In questo esempio, in che modo il polimorfismo è migliore delle due chiamate di funzioni [design ATM]?

2

Quindi ho finalmente iniziato a leggere Progettare il software orientato agli oggetti e il mio ago è bloccato in un piccolo ma punto importante. Capisco che l'esempio che sto per presentare potrebbe sembrare un po 'fuori contesto, perché è stato sviluppato nel libro negli ultimi capitoli, ma credo che l'idea generale sia davvero semplice e farò del mio meglio per fornire contesto ovunque io possa. Riguardo a me, sono uno sviluppatore junior che insegna a me stesso, quindi spero che mettere questa domanda qui porterà a qualche discussione fruttuosa.

Bene, finalmente abbiamo eliminato i preliminari.

Il sistema sto parlando di un bancomat (ATM), che dobbiamo modellare in termini di software orientato agli oggetti. La discussione riguarda le classi di input che raccoglieranno input numerici dall'utente. Vengono identificati due possibili casi: la raccolta di numeri di account, importi, ecc. E la raccolta del PIN, che deve essere reso in modo diverso (il PIN viene visualizzato come un campo password).

Quindi gli autori hanno definito due classi diverse: Form e SecureForm, quest'ultima derivante dal precedente.

Ora ecco una sezione del libro (discutendo dell'utilità di SecureForm) che mi crea problemi:

The intended distinction between Form and SecureForm is whether user input is echoed literally or symbolically (perhaps with an X). This can be done by invoking two different messages: getValue() and getSecureValue(), but the sender [the class making the request] would have to test to determine which message to send. This could lead to maintenance difficulties. It is better to use polymorphism; that is, to have one message that invokes different methods depending on the class of object to which it is sent. For this reason we keep SecureForm [that is, don't discard it from our design].

La parte in corsivo non ha senso per me. Cosa dovrebbe provare l'oggetto chiamante? Forse per il tipo di input richiesto, ma poi a me non sembra fare la differenza se usi il polimorfismo o meno. Considera i seguenti due esempi ipotetici:

//inside doTransaction function of WithdrawalTransaction

//example 1
form = new Form();
pin = form->getSecureValue();

//example 2
form = new SecureForm();
pin = form->getValue();

Difficilmente mi sembra diverso, e non un "incubo di manutenzione" da nessuna misura.

Mi sento come se ci fosse qualche sottigliezza che mi manca qui, ma mi sfugge. Sarò molto grato se qualcuno mi può aiutare a decifrare l'intento dell'autore, e ancora meglio se alcuni esempi possono essere forniti.

Spero che non manchi alcuna informazione critica dal mio post. Se c'è, per favore fai notare e aggiungerò ulteriori dettagli.

    
posta dotslash 19.11.2015 - 17:03
fonte

2 risposte

5

L'interpreto significa che mentre potresti avere un SecureForm che implementa sia un getValue che un getSecureValue , non dovresti perché diventa un problema di manutenzione.

In altre parole, in questo modo, il chiamante dovrebbe fare una distinzione nel codice su come chiamare l'istanza di SecureForm , facendo attenzione a non chiamare getValue ma getSecureValue se questo è ciò che si desiderava.

Finiresti con codice come questo ovunque nel tuo programma:

String value;
if (form instanceof SecureForm) {
  value = ((SecureForm)form).getSecureValue();
} else {
  value = form.getValue();
}

Dovendo sapere di che tipo si tratta è molto un anti-pattern. Il polimorfismo True non significa caring come viene implementato getValue . Se hai bisogno di chiamare getValue AND getSecureValue in SecureForm , allora non stai facendo qualcosa di giusto (e probabilmente non dovresti strutturare il tuo codice in questo modo in quel caso). SecureForm può chiamare getSecureValue internamente, ma un'istanza di Form dovrebbe essere intercambiabile con qualsiasi altra istanza, a parte il principio di Listkov.

    
risposta data 19.11.2015 - 17:20
fonte
1

Proprio in quell'esempio di 4 righe ci sono molte cose che sono una pratica subdolamente cattiva. Il chiamante sa molto sull'implementazione di fondo del callee e il callee sa un po 'troppo su come le cose stanno chiamando a questo. Idealmente queste due cose non dovrebbero sapere l'una dell'altra.

Una grande forza del polimorfismo è che i dettagli di come o cosa sono nascosti al chiamante perché non gli interessa o non hanno bisogno di saperlo. Anche implementare le implementazioni per obbedire a un contratto (interfaccia) renderà più semplice il chiamante. Conoscenze intime non necessarie portano a un accoppiamento stretto non necessario che può portare a un incubo di manutenzione.

    
risposta data 19.11.2015 - 17:44
fonte

Leggi altre domande sui tag