Qual è il vantaggio di avere modelli POCO puri?


15

Qual è il principale vantaggio di avere modelli POCO puri? Ho capito che i modelli dovrebbero essere semplici e puliti, ma tendo a mantenere il mantenimento degli oggetti figlio all'interno delle classi dei modelli. Ad esempio se ho un ClassAe ClassBdefinito come segue:

public class ClassA
{
    public string MyProp { get; set; }
    public IEnumerable<ClassB> Children { get; }

    public void AddChild(ClassB newChild) { /*... */ }
    public void RemoveChild(ClassB child) { /* ... */ }
}

public class ClassB
{
    public string SomeProp { get; set; }
} 

C'è qualcosa di intrinsecamente sbagliato nell'avere i metodi di aggiunta e rimozione? Dovrei invece semplicemente esporre l'elenco e consentire al codice client di aggiungere tutto ciò che passa la responsabilità di semplici convalide dei dati come non null, e non duplicare su un'altra classe?

Qualsiasi aiuto è apprezzato. Grazie.


Rimuoverei i metodi Aggiungi / Rimuovi a meno che non aggiungessero un valore, come tradurre un argomento ClassB null in una versione del modello NullObject dell'oggetto:AddChild(ClassB newChild) => Children.Add(newChild ?? new NullClassB())
Graham,

Se hai mai affrontato il mal di testa delle classi ActiveRecord con centinaia di metodi che potrebbero o meno essere ciò che desideri in un dato momento, penso che sarebbe più facile capire l'appello.
Casey,

Il motivo principale per evitare questo particolare design è perché va contro le linee guida di progettazione .net. È completamente arbitrario, ma le persone si aspettano che la raccolta contenga i metodi mutanti.
Frank Hileman,

@Casey Non sto usando il modello Active Record, il metodo add sta semplicemente facendo qualche piccola validazione dei dati. Il metodo di rimozione è lì perché la raccolta non è esposta, semplicemente aggiungono e rimuovono da un elenco interno. L'ho modificato però per utilizzare un diverso tipo di raccolta che mi consente di eseguire la convalida mentre continuo a utilizzare i metodi Aggiungi / Rimuovi integrati.
Jesse,

Risposte:


42

Le tue due domande non sono correlate.

Qual è il vantaggio di avere modelli POCO puri?

Un POCO puro non dipende da un quadro intraprendente, da una convenzione, da [] cose o intimamente connesso a un oggetto che è allo stesso modo dipendente. In altre parole, il mondo può cambiare completamente attorno a un POCO e continua a fare ciò che fa senza preoccuparsene. Non puoi romperlo aggiornando un framework, spostandolo in un nuovo sistema o guardandolo divertente. Continua a funzionare. Le uniche dipendenze sono le cose che chiede esplicitamente.

POCO non è altro che l'idea di POJO. La J è stata cambiata in una C perché le persone ti guardano in modo strano quando spieghi un concetto che ha Java nel suo nome se quelle persone usano C #. L'idea non dipende dalla lingua. Avrebbero potuto semplicemente chiamarlo Plain Old Objects. Ma chi vuole vantarsi di usare POO?

Lascio che Fowler spieghi le origini:

Il termine è stato coniato mentre Rebecca Parsons, Josh MacKenzie e io ci stavamo preparando per un discorso in una conferenza del settembre 2000. Nel discorso abbiamo sottolineato i numerosi vantaggi della codifica della logica aziendale in normali oggetti Java piuttosto che usare Entity Beans. Ci siamo chiesti perché le persone fossero così contrarie all'utilizzo di oggetti regolari nei loro sistemi e abbiamo concluso che era perché gli oggetti semplici non avevano un nome di fantasia. Quindi ne abbiamo dato uno, ed è stato preso molto bene.

martinfowler.com: POJO

Per quanto riguarda l'altra tua domanda:

C'è qualcosa di intrinsecamente sbagliato nell'avere i metodi di aggiunta e rimozione?

Non mi piace Aconoscere direttamente B. Ma questa è una cosa DIP non una cosa POJO .


Ho avuto la dipendenza diretta Bper semplicità, idealmente entrambi implementerebbero interfacce. Ma Aha ancora un elenco di IInterfaceB. C'è qualcosa di sbagliato nel AddChildmetodo se i bambini sono accoppiati in modo lasco attraverso i riferimenti all'interfaccia?
Jesse il

6
Posso fare tutta una serie di cose sciocche per semplicità. Quello che non mi piace è che A sia a conoscenza di B. A non usa B, quindi non è necessario definire una corretta interfaccia di proprietà A per parlare con B. Per quanto ne so, A è una collezione. Quindi A dovrebbe occuparsi di B attraverso un <T> in modo da non doverne sapere nulla.
candied_orange

2
Ho anche visto "PODO" per "semplice vecchio oggetto dati" per evitare qualsiasi tipo di identificatore del linguaggio nell'acronimo. PODO suona un po 'sciocco (un po' sembra un epiteto che sentiresti su Tatooine, per me), più di POJO o POCO, suppongo, ma significativamente meno sciocco di POO.
KRyan il

2
Mi chiedo quanto sarebbe andata bene la presentazione di Fowler se li avesse chiamati POO?
Oliver,

3

Con Aggiungi e Rimuovi stai implementando Collection<T>funzionalità. Chiediti perché stai usando IEnumerable<T>invece di List<T>qualche altra classe mutabile? Apparentemente non è perché la tua collezione dovrebbe essere di sola lettura.

L'unica ragione a cui riesco a pensare è che vuoi controllare quali metodi di accesso vuoi pubblicare. In tal caso sarebbe meglio creare la propria classe di raccolta, incapsulare un elenco, implementare i metodi di selezione Aggiungi e Rimuovi e implementare IEnumerable<T>. Quindi usalo al posto del IEnumerable<T>tipo di raccolta dei tuoi figli.

Ma mi sembra che List<ClassB>probabilmente ti servirebbe bene.


0

Cosa AddChildaggiunge e RemoveChildrimuove da? Se proviene dal database (o dall'archivio di persistenza di qualunque tipo), hai una specie di Record attivo. Non necessariamente sempre una cosa negativa, ma sicuramente ti avvicina a doverti preoccupare di quadri, convenzioni, dipendenze, ecc., Come menziona @CandiedOrange.

Allo stesso tempo, quale sarebbe il punto di evitare una dipendenza da ClassA a ClassB (o almeno InterfaceB) se sono tutti nella stessa applicazione? Nel dominio del mondo reale che l'applicazione sta modellando, le cose dipendono l'una dall'altra. Gli oggetti del mondo reale che fare hanno collezioni di altri oggetti che "appartengono" a loro. È del tutto appropriato rappresentare quelle relazioni nel tuo codice.

L'unica ragione per cui diventa anche un po 'complicata è perché sembra che tu abbia bisogno di gestire esattamente come una Classe B viene associata e dissociata dalla Classe A. Quindi hai un piccolo comportamento da implementare. Puoi implementarlo all'interno della classe (che è totalmente "legale"; vedi /programming//a/725365/44586 ), oppure puoi avere una sorta di classe separata che contiene quel comportamento. Fai ciò che ha più senso per le tue circostanze individuali.

In ogni caso, POJO / POCO è davvero solo OOP come doveva essere, disadorna e libera. Segui i principi OOP e sarai al sicuro.


In realtà AddChild sta solo verificando la presenza di duplicati e null, e non lo consente neanche. RemoveChild è presente perché per impedire l'aggiunta di backdoor la raccolta viene esposta come IEnumerable. Tuttavia, eseguirà solo la rimozione standard dalla raccolta.
Jesse,

1
Grazie per aver spiegato. Sì, sembra esattamente il tipo di comportamento che dovrebbe essere in un POCO, e sicuramente meglio che semplicemente esporre il tuo IEnumerable sottostante per i chiamanti da modificare o sostituire a piacimento.
John M Gant,

Penso che Active Record sia solo un cattivo modello.
Casey,

1
@Casey, non avrai nessuna discussione da parte mia a riguardo. Ma non direi se qualcuno volesse usarlo. Il punto principale era se Jesse avesse intenzione di utilizzare un modello come Active Record che integra la persistenza con la definizione del modello, avrebbe tutti i problemi evidenziati da CandiedOrange e non si qualificherebbe davvero come POCO, per quello che vale. Ma non è quello che sta facendo comunque.
John M Gant,
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.