Evita getter e setter, visualizzando le informazioni dell'utente

11

Sfondo

Sto leggendo il "Clean Code book" e, in parallelo, sto lavorando su oggetti calisthenic come Kata come il conto bancario, e sono bloccato su quella regola:

La nona regola degli oggetti calisthenic è che non usiamo getter o setter.

Sembra abbastanza divertente, e sono d'accordo con questo principio. Inoltre, a pagina 98-99 di Clean Code, l'autore spiega che i getter / setter rompono l'astrazione e che non dobbiamo chiedere il nostro oggetto, ma dobbiamo dire al nostro oggetto.

Questo ha perfettamente senso nella mia mente e sono pienamente d'accordo con questo principio. Il problema viene in pratica.

Contesto

Ad esempio, sto avendo un'applicazione in cui devo elencare alcuni utenti e visualizzare i dettagli dell'utente.

Il mio utente è composto da:

-> Name
   --> Firstname --> String
   --> Lastname --> String
-> PostalAddress
   --> Street --> String
   --> PostalCode --> String

problema

Come posso fare, o cosa posso fare per evitare i getter quando ho solo bisogno di visualizzare una semplice informazione ( e devo confermare che non ho bisogno di operazioni extra su quel particolare campo ) per visualizzare il valore di Firstname in un supporto di output (casuale) semplice?

Ciò che mi viene in mente

Una soluzione è:

user.getName().getFirstName().getStringValue()

Che è terribilmente terribile, infrange molte regole degli oggetti calisthenic e infrange la legge Demeter.

Un altro sarebbe qualcosa di simile:

String firstName = user.provideFirstnameForOutput();
// That would have called in the user object =>
String firstName = name.provideFirstnameForOutput();
// That would have called in the name object =>
String firstName = firstname.provideFirstnameForOutput();

Ma non mi sento a mio agio con questa soluzione, che sembra solo essere una "accessoria di ordine superiore" come bypassare getter / setter standard con un metodo che mira solo a far corrispondere la legge Demeter ...

Qualche idea?

    
posta mfrachet 24.01.2017 - 09:28
fonte

2 risposte

15

Il malinteso comune sull'idea di evitare getter e setter è di evitarli ovunque, il che è impossibile quando si arriva alla superficie della propria architettura che interagisce con l'utente.

Dovresti evitare di usare getter e setter nella parte di business logic della tua applicazione, dove gli oggetti dovrebbero essere protetti utilizzando gli aggregati che forniscono il contesto, ei metodi dovrebbero fungere da comandi.

Per evitare getter e setter potresti progettare una soluzione simile alla programmazione reattiva , implementando il sistema di reporting attraverso entità osservabili, ma questo complica estremamente l'architettura e non ha senso nel livello CRUD della tua applicazione, anche se il design è veramente buono per le interfacce utente.

Se dovresti considerare l'utilizzo di getter / setter dipende interamente dalla parte dell'applicazione a cui stai lavorando attualmente. Se la tua preoccupazione è l'interfaccia utente che usa getter è completamente soddisfacente, per la logica aziendale, dove si dovrebbe eseguire una parte di un codice basato su un valore recuperato tramite un getter, non tanto (questo urla che la logica avrebbe dovuto essere effettivamente incapsulata all'interno la classe su cui stai chiamando il getter).

Inoltre, la legge di demeter non riguarda il conteggio dei punti, ma semplicemente lo smantellamento di una classe che fornisce il contesto utilizzando i getter della classe per ottenere i suoi componenti a cui non si dovrebbe avere accesso da solo.

Se ritieni che la tua interfaccia utente stia andando troppo in profondità nei tuoi modelli di business, puoi pensare all'introduzione di modelli di visualizzazione affinché il tuo sistema sia responsabile della trasformazione di parti specifiche dei modelli in rappresentazioni visive.

    
risposta data 24.01.2017 - 12:03
fonte
2

Una direzione da considerare sarebbe quella di fornire una funzione di membro di formattazione di stringa generica, piuttosto che fornire l'accesso ai dati non elaborati. Qualcosa del genere:

String lastName = user.formatDescription("$(Lastname)");
String fullName = user.formatDescription("$(Lastname), $(Firstname)");
String abbreviated = user.formatDescription("$(FnAbb). $(LnAbb).");

Vedete, con questo approccio, non siete limitati a fornire solo i dati completi così come sono, potete fornire i mezzi per trasformare i dati in modi convenienti e significativi. Ad esempio, potresti dover giocare dei trucchi con il caso dei personaggi:

String accountName = user.formatDescription("$(firstname).$(lastname)");

Potresti anche definire alcuni formati comunemente usati, possibilmente complessi una volta, quindi potresti dire, per esempio

String fullAddress = user.formatDescription(User.kAddressFormat);

La bellezza di questo approccio è che mantiene le singole stringhe interne alla classe User , mentre in realtà fornisce significativamente più funzionalità al codice chiamante. Tuttavia, il lato negativo è che devi implementare il meccanismo di template entro formatDescription() che sarà composto da poche righe di codice.

In quanto tale, questo potrebbe essere un completo esagerazione: non dimenticare mai che i principi di programmazione sono solo linee guida. E ogni volta che seguire un altro principio viola il principio KISS, è meglio farlo semplicemente nel modo più semplice. Quindi, a meno che tu non abbia almeno qualche bisogno di un membro di formattazione, non mi preoccuperei di implementarlo per semplicità, usando l'approccio basato sull'accessorio.

    
risposta data 24.01.2017 - 10:04
fonte

Leggi altre domande sui tag