Composizione e chiamata dei metodi di parte

4

Qual è il giusto concetto di chiamare metodi di parti in composizione?

Ho una classe

class Body{
   Arm arm;
}

class Arm{
   public void waveArm(){}
   Finger finger
}

class Finger{
   public void moveFinger(){}
}

E voglio invocare moveFinger (). Qual è il modo corretto per farlo? È

Body b;

b.arm.finger.moveFinger()

O dovrei creare wrapper, ad es.

Body::moveFinger(){ arm.moveFinger();}
Arm::moveFinger(){ finger.moveFinger();}
b.moveFinger()

Usando la prima, possiamo ottenere un concatenamento molto lungo.

Comunque usando il secondo metodo, per ogni nuovo metodo dovrei creare molti wrapper (fino a n dove n è la profondità dell'albero delle parti - o come chiamarlo).

Qual è il modo corretto o come scegliere tra questi due?

    
posta trolkura 06.01.2018 - 14:38
fonte

2 risposte

2

Non parli con il braccio di una persona e digli di muovere un dito. Il braccio appartiene a una persona quindi parli con la persona. Ma non chiedi a una persona di darti il braccio in modo da poter muovere un dito su di esso. Né diresti a una persona direttamente come muovere le singole dita: sarebbe un modo molto inefficiente per fare qualcosa di utile. Quello che fai è parlare con la persona sul livello di astrazione appropriato e dire qualcosa come "fammi un sandwich". La persona capirà come spostare le braccia, le gambe e le dita per risolvere quel compito.

Il punto è che non dovresti aver bisogno di parlare con i singoli componenti di una composizione dall'esterno. Parli con l'unità nel suo complesso e il modo in cui è composto internamente è un dettaglio di implementazione. Se hai bisogno di parlare direttamente con un componente interno, allora qualcosa non va nel design.

Ora, se entri nel corpo della persona e vedi come il cervello comunica con le dita, noterai che il cervello può inviare segnali diretti a ogni singolo muscolo. Dal punto di vista del cervello, braccia e dita sono sullo stesso livello di astrazione stesso , quindi non è proprio un modello appropriato per dire che le dita sono sottocomponenti del braccio.

Tradurre ciò nei principi di progettazione: se hai una composizione, non devi parlare direttamente con le singole parti dall'esterno. I metodi esposti dovrebbero essere operazioni nel complesso. Se hai veramente bisogno di parlare con parti specifiche, probabilmente la composizione non dovrebbe essere stata utilizzata in primo luogo, dal momento che non puoi incapsulare le parti.

Creare wrapper che inoltrano un messaggio dall'intero a una parte specifica è solo un inganno - hai ancora un cattivo design, anche se riduci la quantità di punti.

    
risposta data 04.11.2018 - 22:31
fonte
1

b.arm.finger.moveFinger() viola la legge di Demeter , poiché apparentemente stai esponendo la struttura interna di body .

Ma la prima domanda che dovresti porci è che tratti veramente body come una borsa dati, una struttura? Probabilmente ha qualche problema quando si ottiene un arm ? Eventuali decorazione o stato essere coinvolto? Di ', potresti avere un braccio predefinito, un braccio strong, un braccio infortunato, ecc.? Il comportamento è ricco, componibile e modificabile. La struttura è statica Quindi, se decidi di considerare body come un oggetto responsabile di fornire un arm in qualche modo , che non è una rivelazione di struttura, è un comportamento. In questo caso b.arm().finger().moveFinger() andrebbe bene e non costituirebbe una violazione della legge summenzionata.

    
risposta data 07.01.2018 - 11:35
fonte