Devo creare interfacce per oggetti di trasferimento dati?


19

È una buona idea o una cattiva idea creare un'interfaccia per gli oggetti di trasferimento dati? Presumendo che l'oggetto sia generalmente mutabile.

Sebbene il mio esempio sia in Java, dovrebbe essere applicabile a qualsiasi altro linguaggio che abbia concetti simili.

interface DataTransferObject  {
    String getName();
    void setName(String name);
}

class RealDataTransferObject  implements DataTransferObject {

    String name;
    String getName() {
        return name;
    } 
    void setName(String name) {
        this.name = name;
    }
}

Naturalmente, questo è un esempio semplificato, nella vita reale potrebbero esserci più campi.

Risposte:


24

La risposta generale è no , perché non si dovrebbe mai aggiungere codice senza avere un motivo specifico e concreto per esso, e non esiste un motivo generale per tale interfaccia.

Detto questo, a volte può esserci una buona ragione. Ma in tutti i casi che ho visto, queste interfacce erano parziali, coprendo solo una o poche proprietà condivise da più classi che volevo usare polimorficamente senza dare loro una superclasse comune. I candidati tipici sono una Idproprietà da utilizzare in una sorta di registro o una Nameproprietà da visualizzare all'utente. Ma può essere utile in ogni caso in cui vuoi che un po 'di codice gestisca tutto ciò che ha una X: basta creare XSourceun'interfaccia che contenga i metodi getX(e, solo se necessario, i setX).

Ma un'interfaccia separata per ogni classe di modello, contenente tutte le proprietà? Non riesco a immaginare una buona ragione per farlo. Una cattiva ragione sarebbe un framework mal progettato che lo richiede; I bean Entity hanno fatto proprio questo, se ricordo bene. Per fortuna sono stati così male che non hanno mai guadagnato molta trazione e sono deprecati da EJB 3.0

Sidenote: si prega di evitare di usare il termine "oggetto valore" per descrivere bean Java con solo getter e setter banali - è in conflitto con la definizione più comune di oggetto valore come qualcosa senza identità che di solito è immutabile. Un termine migliore sarebbe DTO o classe di modello, sebbene in quest'ultimo caso si noti che i modelli di dominio anemico sono considerati antipattern.


3
"i modelli di dominio anemico sono considerati un antipattern" - di Martin Fowler che, in PEAA, ammette di conoscere persone che hanno lavorato in quel modo per decenni "con molto successo". Quindi, suggerisco, meno un anti-pattern e più un non-come-Fowler-like-to-work. Tuttavia, buona risposta, +1.
pdr,

4
@pdr: Fowler potrebbe aver coniato il termine, ma non è affatto l'unico che li considera un antipattern. Non credo che chiunque abbia effettivamente capito OO pensa che sia una buona idea tenere la logica specifica del dominio fuori dal modello del dominio.
Michael Borgwardt,

Grazie per il termine correzione, DTO era la parola che stavo cercando la scorsa notte ma che non ricordavo per la mia vita. Cambiando il nome in giro, le cose avevano più senso dal punto di vista del design.
Archimede Trajano,

@pdr Penso che il modo migliore per dirlo sia che sia un antipasto nel contesto della programmazione OO. Ci sono molti altri paradigmi in cui va perfettamente bene, e potresti persino lavorare con successo in quel modo in un linguaggio OO (semplicemente non sarebbe particolarmente orientato agli oggetti).
Daniel B,

3
@MichaelBorgwardt: sono d'accordo, non è solo in questo. Ma nemmeno le persone non sono d'accordo. Se avessi detto che "i modelli di dominio anemico sono considerati da alcuni come un anti-schema", non avrei detto nulla. Francamente, penso che la tua intera risposta sarebbe comunque migliore senza l'ultimo paragrafo. Il primo tempo avrebbe fatto un commento migliore; la seconda metà non offre nulla a questa domanda.
pdr,

2

La creazione di un'interfaccia è ok, ma NON come funziona il tuo esempio. Dovresti rimuovere il setter dall'interfaccia e andrà bene:

interface ValueObject {
  String getName();
};

Ciò consente molte diverse implementazioni di esso, come il nome può essere recuperato dal database ... Il setter dovrebbe essere in un'interfaccia diversa.


2

Le interfacce definiscono un contratto tra le classi che implementano le interfacce e i loro client. Sono usati come meccanismo di astrazione in modo che i clienti possano manipolare "cose ​​con un determinato comportamento".

Quindi la risposta generale alla domanda "dovrei creare e usare questa interfaccia?" è: Sì, se è possibile associare un (unico) concetto che è semanticamente rilevante per i propri clienti.

Ad esempio, Comparable è una buona interfaccia, perché spiega che le cose possono essere confrontate grazie a uno dei loro metodi, e come cliente sono interessato a trattare oggetti comparabili (ad esempio per ordinarli). A contrario, CoolStuff non è una buona interfaccia se ammetti che gli oggetti fantastici non hanno un comportamento specifico (in effetti, puoi immaginare un software in cui ha senso avere a che fare con oggetti freddi, perché hanno un comportamento comune come un beCool metodo).

Nel tuo caso particolare, credo che la tua interfaccia sia inutile. Chi lo userà, come e quando? Non è possibile creare un'interfaccia per ciascuno dei valori modificabili. Quindi chiediti qual è la proprietà pertinente e interessante dietro i tuoi metodi.

Se quello che vuoi è avere a che fare con oggetti con tutti i loro valori mutabili accessibili attraverso un paio di metodi, dai un'occhiata al concetto di bean Java e al modo in cui puoi forzare le tue classi ad adottare le loro convenzioni.


2

Come ha detto Michael, non aggiungere un'interfaccia a meno che tu non ne abbia una necessità specifica.

Il test è un esempio di una buona ragione. Anche se preferisco usare veri collaboratori se sono solo "oggetti valore" come li chiami tu, per un vero isolamento del test unitario potresti dover creare un oggetto falso per il test, nel qual caso un'interfaccia è abbastanza utile.


1
Le interfacce non sono state necessarie per l'utilizzo di framework beffardi da secoli.
Michael Borgwardt,

Sembra che tu stia sostenendo il monkeypatching. Sono stato su quella strada con Moles in C # e non è carino. Meglio trasmettere i tuoi collaboratori, se possibile.
jhewlett,

1
Sebbene i due framework beffardi che uso Mockito e easyMock non possano deridere le classi finali quando le rendono immutabili.
Archimede Trajano,

1

Se si desidera che questo oggetto abbia una sorta di convalida dei campi in futuro, è necessario incapsularli nelle fasi iniziali.


0

L '"interfaccia per oggetto valore" è ciò che sono abituato a chiamare un accessor.

Ho sperimentato diverse politiche relative ai bisogni degli accessi. Alcune persone sostengono il più possibile, altre vietano quindi di ridurre la quantità di codice da scrivere.

Alcune motivazioni per gli accessori (o l'utilizzo diretto del valore) sono le seguenti:

  • Gli accessori consentono di modificare in seguito la modalità di memorizzazione del valore
  • Accessors consente di aggiungere il registro di accesso quando si desidera eseguire il debug del software (quando si aggiunge una chiamata di registro in un singolo metodo, si acquisisce ogni modifica di valore)
  • Gli accessori sono più in linea con la programmazione degli oggetti, ogni variabile è incapsulata da metodi
  • Gli accessori riducono l'espressività del codice (più SLOC per lo stesso risultato)
  • Gli accessori richiedono un po 'di CPU

Personalmente sostengo di ridurre il numero di accessor e di usarli quando prevedete che il setter (setName) diventerà più di una semplice influenza in seguito.


0

Questo tipo di oggetto valore ha un livello piuttosto basso. Suggerirei di spingerlo in una delle due direzioni: (1) rendere immutabile l'oggetto valore, ovvero, come un valore reale , oppure (2) elevare la mutabilità a una funzione aziendale orientata al dominio di livello superiore, nel senso che dovremmo esporre interfacce in termini di unità di funzionalità rilevanti per il dominio.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.