Por que as classes de dados são consideradas um cheiro de código?

18

Este artigo afirma que uma classe de dados é um "cheiro de código". O motivo:

É normal quando uma classe recém-criada contém apenas alguns campos públicos (e talvez até um punhado de getters / setters). Mas o verdadeiro poder dos objetos é que eles podem conter tipos de comportamento ou operações em seus dados.

Por que é errado um objeto conter apenas dados? Se a principal responsabilidade da classe é representar dados, não adicionaria métodos que operam com os dados violem o Princípio de Responsabilidade Única ?

Sipo
fonte
1
Isso vai depender muito dos recursos do idioma. No Python, por exemplo, não há distinção entre o "campo" e seus acessadores, a menos que você faça o possível para escrever Java no Python .
JSCs
1
Eu acho que ter apenas algumas classes de dados não é um cheiro de código em si, mas se a maioria das classes é assim, estamos falando do antipadrão de "domínio anêmico" en.wikipedia.org/wiki/Anemic_domain_model
Tulains Córdova
1
Não vejo como essa pergunta é duplicada. As outras perguntas são sobre o uso de classes de dados no OO, enquanto esta é sobre as desvantagens das classes de dados - assuntos inteiramente diferentes.
Milos Mrdovic 18/05/19
Você pode ler esta resposta no stackoverflow, que é muito mais diferenciada do que a resposta votada aqui, que postula a inferioridade do modelo de domínio rico e a apresenta como um fato comprovado. stackoverflow.com/questions/23314330/…
McLovin 28/03

Respostas:

30

Não há absolutamente nada de errado em ter objetos de dados puros. O autor da peça, francamente, não sabe do que está falando.

Esse pensamento decorre de uma idéia antiga e falida de que "verdadeiro OO" é a melhor maneira de programar e que "verdadeiro OO" tem tudo a ver com "modelos de dados ricos", onde se misturam dados e funcionalidade.

A realidade nos mostrou que, na verdade, o oposto é verdadeiro, especialmente neste mundo de soluções multithread. Funções puras, combinadas com objetos de dados imutáveis, são uma maneira comprovadamente melhor de codificar.

David Arno
fonte
1
Só queria acrescentar que objetos de dados puros podem ser inestimáveis ​​para modelar relacionamentos, validação, controlar acesso / alterações.
Adrian
2
Embora seja bom se essas funções puras que usam apenas uma instância do objeto de dados imutável como argumento forem implementadas como métodos no objeto de dados.
RemcoGerlich
7
Se a função usar um argumento desse tipo de dados, ela já estará acoplada aos dados.
RemcoGerlich
4
Voto negativo, porque isso está incorreto ou, na melhor das hipóteses, uma questão de opinião. Em uma linguagem OO, geralmente faz sentido que um objeto contenha os dados (que ainda podem ser imutáveis!) E os métodos que atuam sobre ele. Funções puras e dados separados são ótimos em outros paradigmas de linguagem, mas se você estiver fazendo OO, faça OO completamente.
Marnen Laibow-Koser
3
A realidade nos mostrou muitas coisas. -1 para a opinião dogmática de saber tudo "os outros falharam". Além disso, o autor não diz que objetos de dados puros estão "errados", apenas que são um "cheiro de código" e merecem ser questionados. Lamento apenas que tenho um voto negativo a dar pelo meu país. :-)
user949300 26/03
7

Não há absolutamente nada de errado em ter objetos de dados puros. O autor tem uma opinião não compartilhada pelos desenvolvedores de software que conheço.

Especialmente para mapeamento de banco de dados, em geral, você tem classes de entidade que contêm apenas os campos armazenados na base de dados e nos getters e setters. Wikipedia Hibernate (estrutura)

A idéia básica dos Java beans usados ​​por muitas ferramentas / estruturas é baseada em classes de dados chamadas beans que contêm apenas campos e os getters e setters relacionados. Wikipediadia JavaBeans

Fazit:
Se alguém afirma que algo é 'ruim' ou 'um cheiro de código', você deve sempre procurar os motivos apresentados. Se os motivos não o convencerem, pergunte a alguém por outros motivos ou uma opinião diferente. (Como você fez neste fórum)

MrSmith42
fonte
O autor não diz que objetos de dados puros estão "errados". Eles dizem que objetos de dados puros são um "cheiro de código", o que significa que você deve pensar duas vezes antes de usá-los.
user949300 26/03
1
@ user949300, você parece confuso. Se o autor se refere a eles como um cheiro de código, ele indica que pode haver algo errado com eles. Como hoje em dia são amplamente reconhecidos como boas práticas, eles claramente não são um cheiro de código. Assim, MrSmith42 está correto: não há absolutamente nada de errado com eles.
David Arno
4

Um bom argumento por Martin Fowler:

"O Tell-Don't-Ask é um princípio que ajuda as pessoas a lembrar que a orientação a objetos trata de agrupar dados com as funções que operam nesses dados. Isso nos lembra que, em vez de solicitar dados a um objeto e agir sobre esses dados, em vez disso, deve dizer a um objeto o que fazer. Isso incentiva a mudar o comportamento para um objeto para acompanhar os dados ".

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

Curtis Yallop
fonte
1
O problema aqui é que Fowler restringe artificialmente o "diga não pergunte", alterando as funções de pedir um escopo mais amplo para apenas perguntar o escopo do objeto. Eles ainda estão perguntando. O "dizer não perguntar" pode, de fato, dar um passo adiante, dizendo verdadeiramente essas funções por meio de suas listas de argumentos. E assim chegamos a objetos de dados e funções separadas (em termos de dados), sendo a verdadeira implementação do "tell don't ask". Portanto, em vez de ser um bom argumento para a alegação de que as classes de dados são um cheiro de código, na verdade prova o contrário.
David Arno
2
@DavidArno Você está esquecendo o encapsulamento e a ocultação. Você diz a um objeto para executar um método de membro, e o método de membro entra na caixa preta do objeto e faz o que for necessário para obter a resposta. Se você perguntar a um objeto de fora, não terá acesso ao seu estado privado e, portanto, o objeto expõe mais estado do que o sensato, ou o solicitante precisa pular mais argolas do que seria necessário. Não vejo por que você "pergunta" a um objeto em um ambiente OO. (Outros paradigmas de programação podem exigir abordagens diferentes, é claro.)
Marnen Laibow-Koser
2
@DavidArno Claro que você pode passar bazcomo parâmetro para um método estático, mas para fazer isso, primeiro você precisa pedir ao objeto. Talvez em um paradigma de programação em que os métodos sejam primários (como, por exemplo, a programação funcional), isso faça sentido, mas em um ambiente OO, absolutamente não, porque os objetos são primários e devem conter os dados e as funções para agir sobre ele. Sua afirmação de que a remoção do método do objeto aumentou o encapsulamento também é exatamente ao contrário , pelo que sei, porque significa que agora você bazaparece fora do objeto.
Marnen Laibow-Koser 27/03
1
@ MarnenLaibow-Koser, não pretendo "fazer OO". Eu escrevo código e uso boas técnicas para fazer isso. Se essas técnicas vêm do paradigma funcional, do paradigma OO ou do paradigma de quem dá a mínima, não me interessa. Escolher um paradigma e segui-lo o mais completamente possível é um dogma puro. Isso é ruim. É ridículo. Isso o sufoca e resulta em código inferior. Não faça isso.
David Arno
1
@DavidArno Pelo contrário, se você se comprometer totalmente com um paradigma (qualquer paradigma decente, não apenas OO), obterá abstrações poderosas de alto nível e código logicamente consistente e sustentável. Não estou dizendo que isso seja dogmático, mas sim pragmático. Vi e mantive muito código que aparentemente foi produzido com uma atitude como a sua, onde o autor realmente não se comprometeu com a consistência lógica do sistema que está sendo usado. É difícil de entender, difícil de manter e difícil de modificar. Nenhum paradigma é perfeito, mas geralmente uma mistura (a menos que seja cuidadosamente considerada) é mais difícil de entender.
Marnen Laibow-Koser 27/03
2

O que você precisa entender é que existem dois tipos de objetos:

  • Objetos que possuem comportamento . Eles devem abster-se de dar acesso público à maioria / a qualquer um de seus membros de dados. Espero apenas muito poucos métodos de acesso definidos para esses.

    Um exemplo seria uma regex compilada: O objeto é criado para fornecer um determinado comportamento (para corresponder uma cadeia de caracteres a uma regex específica e relatar as correspondências (parciais)), mas como a regex compilada faz seu trabalho não é do usuário. o negócio.

    A maioria das aulas que escrevo estão nessa categoria.

  • Objetos que são realmente apenas dados . Eles devem apenas declarar todos os seus membros públicos (ou fornecer o conjunto completo de acessadores para eles).

    Um exemplo seria uma classe Point2D. Não existe absolutamente invariável que precise ser garantido para os membros dessa classe, e os usuários devem poder acessar os dados apenas via myPoint.xe myPoint.y.

    Pessoalmente, não uso muito essas classes, mas acho que não escrevi um pedaço maior de código que não use essa classe em algum lugar.

Tornar-se proficiente na orientação a objetos inclui perceber que essa distinção existe e aprender a classificar a função de uma classe em uma dessas duas categorias.


Se você codificar em C ++, poderá explicitar essa distinção usando classa primeira categoria de objetos e structa segunda. Obviamente, os dois são equivalentes, exceto que isso classsignifica que todos os membros são privados por padrão, enquanto structdeclara todos os membros públicos por padrão. Qual é exatamente o tipo de informação que você deseja comunicar.

cmaster - restabelece monica
fonte
1
Uma explicação para o
voto negativo
Obrigado pela resposta. Eu odeio quando as pessoas votam sem motivo. Se você tiver algum problema com uma resposta, explique o motivo .
Sipo