Quando si dovrebbe usare la composizione invece di riscrivere la funzionalità?

1

Dire, ho una classe A che ha i metodi m1, m2, m3, m4, m5 .... m100.

Sto facendo un'altra semplice classe B e ho bisogno solo di m2, m3 e m5 in B.

Dovrei utilizzare idealmente le composizioni e inserire un riferimento di A all'interno di B e delegare semplicemente la funzionalità?

o dovrei semplicemente riscrivere [copy = paste] quei 2-3 metodi fuori dalla classe A?

    
posta Amogh Talpallikar 03.10.2013 - 15:33
fonte

1 risposta

1

Idealmente, non tagliare e incollare il codice. La duplicazione della funzionalità porta inevitabilmente a errori in una e una lenta divergenza di hack (è necessario apportare un cambiamento "facile" in uno che conduce a un cambiamento "brutto" nell'altro). La chiave per farlo è quella di rifattorizzarla in modo tale che la bruttezza della classe originale possa essere nascosta nel miglior modo possibile, e un nuovo strato di codice davanti al brutto porti ad "abbandonare sul posto" parti del brutto.

L'obiettivo finale, nonostante la natura "legacy" di A è di asciugare il codice in modo che B e A condividano una classe base comune. Anche se non puoi arrivarci, questa è la destinazione finale.

Il primo passo in questo processo consiste nel rendere quella classe astratta che implementa solo il sottoinsieme di metodi comuni in B e A .

Una volta ottenuto ciò, crei una coppia di classi di implementazione: B e A' . A' è un anti-corruzione layer / wrapper che avvolge A e passa attraverso le chiamate di metodo come appropriate.

(Qui è dove diventa un po 'brutto)

Senza sapere se i 5 metodi (che fanno parte della classe astratta) cambiano lo stato di A in un modo usato dagli altri 20 metodi, può essere difficile considerare la corretta progettazione.

Consente di chiamare tutti i metodi a .. z . I metodi a , e , i , o e u sono quelli che devono essere implementati nella classe B . Se, in A , il metodo a stato modificato usato da b e e - allora è probabilmente meglio che a e e siano entrambi passanti.

D'altra parte, se aeiou non cambia nessuno stato usato dagli altri metodi, possono essere completamente incapsulati all'interno della classe astratta.

Ora, se puoi apportare una modifica al codice legacy - è piuttosto limitato - crea un'interfaccia ( iA ) che definisce il metodo ogni in A che A implementa e A' implementazioni. Uno può quindi refactoring ogni passaggio di A a iA .

Quindi, puoi modificare iA foo = new A() in iA foo = new A'(new A())

Ora hai una classe B che estende la classe astratta, A' che estende la classe astratta e implementa iA che fornisce funzionalità identiche a A . Il codice per aeiou è il più possibile isolato da A in modo che le modifiche ad esso nella classe astratta apportino le modifiche appropriate sia a B che a A' .

    
risposta data 03.10.2013 - 17:19
fonte

Leggi altre domande sui tag