Perché le classi di dati sono considerate odore di codice?


18

Questo articolo afferma che una classe di dati è un "odore di codice". La ragione:

È una cosa normale quando una classe appena creata contiene solo pochi campi pubblici (e forse anche una manciata di getter / setter). Ma il vero potere degli oggetti è che possono contenere tipi di comportamento o operazioni sui loro dati.

Perché è sbagliato che un oggetto contenga solo dati? Se la responsabilità principale della classe è quella di rappresentare i dati, non aggiungerebbero i metodi che operano sui dati infrangendo il principio di responsabilità singola ?


1
Questo dipenderà fortemente dalle caratteristiche del linguaggio. In Python, ad esempio, non c'è distinzione tra il "campo" e i suoi accessori, a meno che tu non esca dal tuo modo di scrivere Java in Python .
jscs,

1
Penso che avere alcune classi solo dati non sia un odore di codice in sé, ma se la maggior parte delle classi è così, allora stiamo parlando
dell'antipasto

1
Non vedo come questa domanda sia duplicata. L'altra domanda riguarda l'uso delle classi di dati in OO, mentre questa riguarda gli aspetti negativi delle classi di dati - argomenti completamente diversi.
Milos Mrdovic,

Potresti voler leggere questa risposta su StackOverflow che è molto più differenziata rispetto alla risposta più votata qui che postula l'inferiorità del modello di dominio avanzato e la presenta come un fatto provato. stackoverflow.com/questions/23314330/...
McLovin

Risposte:


31

Non c'è assolutamente nulla di sbagliato nell'avere oggetti dati puri. L'autore del pezzo francamente non sa di cosa sta parlando.

Tale pensiero deriva da una vecchia, fallita, idea che "vero OO" è il modo migliore per programmare e che "vero OO" è tutto su "modelli di dati ricchi" in cui si mescolano dati e funzionalità.

La realtà ci ha mostrato che in realtà è vero il contrario, specialmente in questo mondo di soluzioni multi-thread. Le funzioni pure, combinate con oggetti dati immutabili, sono un modo dimostrabilmente migliore per codificare.


1
Volevo solo aggiungere che gli oggetti di dati puri possono essere preziosi per le relazioni di modellazione, la convalida, il controllo dell'accesso / modifiche.
Adrian,

2
Anche se è bello se quelle funzioni pure che prendono solo un'istanza dell'oggetto dati immutabile come argomento sono implementate come metodi sull'oggetto dati.
Remco Gerlich,

7
Se la funzione accetta un argomento di quel tipo di dati, è già accoppiata ai dati.
Remco Gerlich,

4
Downvoting perché questo non è corretto, o nella migliore delle ipotesi una questione di opinione. In un linguaggio OO, di solito ha senso avere un oggetto contenente sia i dati (che possono essere ancora immutabili!) Sia i metodi che agiscono su di esso. Funzioni pure e dati separati sono fantastici in altri paradigmi linguistici, ma se stai eseguendo OO, esegui OO completamente.
Marnen Laibow-Koser,

3
La realtà ci ha mostrato molte cose. -1 per l'opinione dogmatica "gli altri hanno fallito". Inoltre, l'autore non dice che gli oggetti di dati puri siano "sbagliati", solo che sono un "odore di codice" e degni di essere interrogati. Mi dispiace solo di avere un voto negativo da dare al mio paese. :-)
user949300

7

Non c'è assolutamente nulla di sbagliato nell'avere oggetti dati puri. L'autore ha un'opinione non condivisa dagli sviluppatori di software che conosco.

Soprattutto per la mappatura del database in generale si hanno classi di entità che contengono solo i campi memorizzati nel database e getter e setter. Wikipedia Hibernate (framework)

L'idea del buco dei bean Java utilizzati da molti strumenti / framework si basa su classi di dati chiamate bean che contengono solo campi e relativi getter e setter. Wikipdia JavaBeans

Fazit:
se qualcuno afferma che qualcosa è "cattivo" o "odore di codice", dovresti sempre cercare i motivi indicati. Se i motivi non ti convincono, chiedi a qualcun altro per motivi migliori o opinioni diverse. (Come hai fatto in questo forum)


L'autore non afferma che gli oggetti dati puri siano "sbagliati". Dicono che gli oggetti dati puri siano un "odore di codice", il che significa che dovresti pensarci due volte su come usarli.
user949300,

1
@ user949300, sembri confuso. Se l'autore si riferisce a loro come un odore di codice, allora indica che potrebbe esserci qualcosa di sbagliato in loro. Poiché sono ampiamente riconosciuti in questi giorni come un'ottima pratica, chiaramente non hanno un odore di codice. Quindi MrSmith42 ha ragione: non c'è assolutamente nulla di sbagliato in loro.
David Arno,

4

Un buon argomento perché di Martin Fowler:

"Tell-Don't-Ask è un principio che aiuta le persone a ricordare che l'orientamento agli oggetti riguarda il raggruppamento di dati con le funzioni che operano su tali dati. Ci ricorda che invece di chiedere un oggetto per i dati e agire su tali dati, noi dovrebbe invece dire a un oggetto cosa fare. Questo incoraggia a spostare il comportamento in un oggetto per andare con i dati. "

https://martinfowler.com/bliki/TellDontAsk.html


1
Il problema qui è che Fowler limita artificialmente il "dire non chiedere" cambiando le funzioni dal chiedere un ambito più ampio al solo chiedendo l'ambito dell'oggetto. Stanno ancora chiedendo. "Dillo a non chiedere" può infatti essere fatto un passo avanti raccontando veramente quelle funzioni attraverso i loro elenchi di argomenti. E così arriviamo agli oggetti dati e alle funzioni separate (per quanto riguarda i dati) essendo la vera implementazione di "dire non chiedere". Quindi, piuttosto che essere un buon argomento per l'affermazione che le classi di dati sono un odore di codice, in realtà dimostra ulteriormente il contrario.
David Arno,

2
@DavidArno Stai dimenticando l'incapsulamento e il nascondiglio. Dici a un oggetto di eseguire un metodo membro e il metodo membro va nella casella nera dell'oggetto e fa tutto il necessario per ottenere la risposta. Se chiedi a un oggetto dall'esterno, non hai accesso al suo stato privato, quindi l'oggetto espone più stato di quanto non sia saggio, oppure il richiedente deve saltare attraverso più cerchi del necessario. Non vedo perché mai "chiedi" un oggetto in un ambiente OO. (Naturalmente, altri paradigmi di programmazione potrebbero richiedere approcci diversi.)
Marnen Laibow-Koser,

2
@DavidArno Naturalmente puoi passare bazcome parametro a un metodo statico, ma per farlo, devi prima chiederlo all'oggetto. Forse in un paradigma di programmazione in cui i metodi erano primari (come, diciamo, la programmazione funzionale) questo ha senso, ma in un ambiente OO, assolutamente no, perché gli oggetti sono primari e dovrebbero contenere sia i dati che le funzioni per agire su di esso. La tua affermazione che la rimozione del metodo dall'oggetto ha aumentato l'incapsulamento è anche esattamente all'indietro , per quanto posso dire, perché significa che ora sei bazapparso all'esterno dell'oggetto.
Marnen Laibow-Koser,

1
@ MarnenLaibow-Koser, non pretendo di "fare OO". Scrivo codice e utilizzo buone tecniche per farlo. Che tali tecniche provengano dal paradigma funzionale, o dal paradigma OO, o dal paradigma di chi diavolo non mi interessa. Scegliere un paradigma e attenersi ad esso nel modo più completo possibile è puro dogma. È cattivo. È ridicolo. Ti soffoca e si traduce in codice inferiore. Non farlo
David Arno,

1
@DavidArno Al contrario, se ti impegni completamente in un paradigma (qualsiasi paradigma decente, non solo OO), ottieni potenti astrazioni di alto livello e codice logicamente coerente e gestibile. Non sto dicendo che questo sia dogmatico, ma piuttosto pragmatico. Ho visto e mantenuto troppi codici apparentemente prodotti con un atteggiamento come il tuo, in cui l'autore non si è realmente impegnato nella coerenza logica del sistema in uso. È difficile da capire, difficile da mantenere e difficile da modificare. Nessun paradigma è perfetto, ma generalmente una miscela (se non attentamente considerata) è più difficile da capire.
Marnen Laibow-Koser,

2

Quello che devi capire è che ci sono due tipi di oggetti:

  • Oggetti che hanno un comportamento . Questi dovrebbero astenersi dal dare accesso pubblico alla maggior parte / a qualsiasi dei loro membri dei dati. Mi aspetto solo pochi metodi di accesso definiti per questi.

    Un esempio potrebbe essere una regex compilata: l'oggetto viene creato per fornire un determinato comportamento (per abbinare una stringa a una regex specifica e per segnalare le corrispondenze (parziali)), ma modo in cui la regex compilata fa il suo lavoro non è nessuno dei attività commerciale.

    Molte classi che scrivo appartengono a questa categoria.

  • Oggetti davvero giusti dati . Questi dovrebbero semplicemente dichiarare pubblici tutti i loro membri (o fornire il set completo di accessori per loro).

    Un esempio sarebbe una classe Point2D. Non esiste assolutamente alcun invariante che deve essere garantito per i membri di questa classe e gli utenti dovrebbero poter accedere ai dati tramite myPoint.xe myPoint.y.

    Personalmente, non uso molto tali classi, ma immagino non ci sia un pezzo di codice più grande che ho scritto che non usi tale classe da qualche parte.

Diventare abili con l'orientamento agli oggetti include rendersi conto che esiste questa distinzione e imparare a classificare la funzione di una classe in una di queste due categorie.


Se si codifica in C ++, è possibile rendere esplicita questa distinzione usando classper la prima categoria di oggetti e structper la seconda. Naturalmente, i due sono equivalenti, tranne classper il fatto che tutti i membri sono privati ​​per impostazione predefinita, mentre structdichiarano tutti i membri pubblici per impostazione predefinita. Qual è esattamente il tipo di informazioni che vuoi comunicare.


1
Una spiegazione per il downvote sarebbe interessante ...
cmaster - reintegrare monica il

Grazie per la risposta. Lo odio quando le persone riducono il voto senza motivo. Se hai un problema con una risposta, spiega perché .
Sipo,
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.