La Regola 9 di Object Calisthenics è davvero praticabile nella vita reale?

6

Recentemente ho letto di Object Calisthenics e sono bloccato sulla Regola 9.

Il mio tipico approccio al codice (io sono uno sviluppatore C # .NET) è quello di modellare i dati come classi POCO che esistono solo per rappresentare schemi di dati. Inevitabilmente questo significa un insieme di proprietà esposte con getter e setter. Queste classi implementano pochi, o più spesso no, metodi. Sono oggetti stupidi e in genere esistono a un livello basso nella mia architettura di soluzione. Hanno una responsabilità singolare: modellare i dati strutturati, ad es. una riga della tabella del database.

Dove ho bisogno di funzioni logiche, introdurrò queste come classi di servizio dedicate in un livello aziendale (o servizio). Queste classi osservano anche il principio della responsabilità unica, affrontando ciascuna una specifica esigenza aziendale. Ad esempio, potrei avere una classe Customer e una classe CustomerRepository caricata con la lettura e la scrittura in un archivio dati persistente. Questo CustomerRepository implementerà un contratto IRepository per assicurarmi di poterlo iniettare come dipendenza, deriderlo nei test ecc.

Con questo modello, inevitabilmente il mio Customer deve esporre le sue proprietà tramite getter e setter (" espellere le budella direttamente in faccia "!) in modo che il repository possa mapparlo su una tabella di database o altro.

Quindi la mia domanda è: perché un devoto di oggetti calisthenici vedrebbe questo così sbagliato? In tutti gli esempi che ho visto, gli autori mantengono le proprietà private e introducono funzioni logiche direttamente alla classe che, secondo il mio punto di vista, rompono la singola responsabilità e potrebbero potenzialmente condurre a classi vaste, ingombranti e non testabili.

Quindi, la Regola 9 è davvero praticabile nella vita reale? In una delle poche spiegazioni dettagliate che ho trovato l'autore sembra discutere contro se stesso definendo una classe Account , rendendo il Balance privato quindi introducendo metodi come Withdraw per incapsulare non solo la proprietà ma qualsiasi logica che funzioni con quella proprietà. Bene, ma cosa succede se il requisito aziendale richiede al programmatore di scrivere il saldo del conto in un'interfaccia utente? Come si può osservare la regola 9 in questo caso?

    
posta getsetcode 02.10.2017 - 19:23
fonte

2 risposte

6

Il suo principale n. 9 è errato. Gli oggetti hanno bisogno di getter e setter da utilizzare nella maggior parte delle applicazioni di vita reale. Tuttavia, dovrebbero essere utilizzati il meno possibile .

La visualizzazione delle proprietà di un oggetto a un utente finale richiederà getter.

Per consentire a un utente finale di modificare le proprietà di un oggetto occorrono setter.

Un livello di persistenza richiederà getter e setter per salvare l'oggetto sul disco e leggerlo di nuovo.

Un costruttore avrà bisogno di setter.

Una regola migliore sarebbe:

Altre entità logiche all'interno del livello dominio non dovrebbero usare getter e setter di un'altra entità se possono essere praticamente evitate

Ora ci sono alcuni soluzioni per evitare l'uso di getter e setter nelle eccezioni di cui sopra, ma sono eccessivamente complessi per la maggior parte delle situazioni.

Il tuo approccio alla progettazione di oggetti ha i suoi problemi ed è l'altro estremo. In pratica stai facendo programmazione funzionale in un linguaggio OO senza adeguate funzionalità funzionali. Tuttavia, questo è un argomento per un'altra discussione.

Vedi la risposta di Ben, è fantastico: Come si evita getter e setter?

    
risposta data 02.10.2017 - 19:49
fonte
3

Dal link che hai fornito:

In this case, you could keep the getScore() as you may want to display it somewhere on the UI, but keep in mind that setters should not be allowed.

Quindi, nel tuo esempio in cui il saldo del conto verrebbe mostrato su un'interfaccia utente, il getBalance () sarebbe appropriato da conservare.

Dato il tuo attuale modello di scrittura delle classi POCO, potresti non essere in grado di riconciliare i due. Potrebbe essere necessario modificare un po 'il design per compensare la mancanza di setter. O semplicemente renditi conto di quale sia lo spirito della Regola 9, e cioè di impedire che qualsiasi oggetto distrugga il tuo oggetto. Dato che la tua classe esiste solo per mappare le informazioni dal DB, questa sembra essere una preoccupazione marginale.

    
risposta data 02.10.2017 - 19:42
fonte

Leggi altre domande sui tag