¿Por qué las clases de datos se consideran un olor a código?

18

Este artículo afirma que una clase de datos es un "olor a código". La razón:

Es normal cuando una clase recién creada contiene solo unos pocos campos públicos (y tal vez incluso un puñado de captadores / establecedores). Pero el verdadero poder de los objetos es que pueden contener tipos de comportamiento u operaciones en sus datos.

¿Por qué está mal que un objeto contenga solo datos? Si la responsabilidad principal de la clase es representar datos, ¿no agregaría métodos que operan en los datos que rompan el Principio de Responsabilidad Única ?

Sipo
fuente
1
Esto dependerá en gran medida de las características del lenguaje. En Python, por ejemplo, no hay distinción entre el "campo" y sus accesores, a menos que haga todo lo posible para escribir Java en Python .
jscs
1
Creo que tener algunas clases de datos solamente no es un olor de código per se, pero si la mayoría de las clases son así, entonces estamos hablando del antipatrón de "dominio anémico" en.wikipedia.org/wiki/Anemic_domain_model
Tulains Córdova
1
No veo cómo esta pregunta es un duplicado. La otra pregunta es sobre el uso de clases de datos en OO, mientras que esta es sobre las desventajas de las clases de datos, temas completamente diferentes.
Milos Mrdovic
Es posible que desee leer esta respuesta en stackoverflow, que está mucho más diferenciada que la respuesta más votada aquí que postula la inferioridad del modelo de dominio rico y la presenta como un hecho comprobado. stackoverflow.com/questions/23314330/…
McLovin

Respuestas:

31

No hay absolutamente nada de malo en tener objetos de datos puros. El autor de la pieza, francamente, no sabe de qué está hablando.

Tal pensamiento surge de una vieja y fallida idea de que el "verdadero OO" es la mejor manera de programar y que el "verdadero OO" se trata de "modelos de datos enriquecidos" en los que se mezclan datos y funcionalidad.

La realidad nos ha demostrado que en realidad lo contrario es cierto, especialmente en este mundo de soluciones de subprocesos múltiples. Las funciones puras, combinadas con objetos de datos inmutables, son una forma demostrablemente mejor de codificar.

David Arno
fuente
1
Solo quería agregar que los objetos de datos puros pueden ser invaluables para modelar relaciones, validación, control de acceso / cambios.
Adrian
2
Aunque es bueno si esas funciones puras que solo toman una instancia del objeto de datos inmutable como argumento se implementan como métodos en el objeto de datos.
RemcoGerlich
77
Si la función toma un argumento de ese tipo de datos, ya está acoplada a los datos.
RemcoGerlich
44
Votación negativa porque esto es incorrecto o, en el mejor de los casos, una cuestión de opinión. En un lenguaje OO, generalmente tiene sentido que un objeto contenga tanto los datos (¡que aún pueden ser inmutables!) Como los métodos que actúan sobre él. Las funciones puras y los datos separados son excelentes en otros paradigmas de lenguaje, pero si está haciendo OO, hágalo completamente.
Marnen Laibow-Koser
3
La realidad nos ha mostrado muchas cosas. -1 para la opinión dogmática de "todos los demás han fallado". Además, el autor no dice que los objetos de datos puros sean "incorrectos", solo que son un "olor a código" y dignos de ser interrogados. Solo lamento tener un voto negativo para mi país. :-)
user949300
7

No hay absolutamente nada de malo en tener objetos de datos puros. El autor tiene una opinión no compartida por los desarrolladores de software que conozco.

Especialmente para el mapeo de bases de datos, en general tiene clases de entidad que solo contienen los campos almacenados en la base de datos y captadores y establecedores. Wikipedia Hibernate (marco)

La idea del agujero de los beans Java utilizados por muchas herramientas / frameworks se basa en clases de datos llamadas beans que solo contienen campos y los captadores y establecedores relacionados. Wikipdia JavaBeans

Fazit:
Si alguien afirma que algo es 'malo' o 'huele a código', siempre debe buscar las razones dadas. Si las razones no te convencen, pregúntale a alguien más por mejores razones o una opinión diferente. (Como hiciste en este foro)

MrSmith42
fuente
El autor no dice que los objetos de datos puros sean "incorrectos". Dicen que los objetos de datos puros son un "olor a código", lo que significa que debe pensar dos veces antes de usarlos.
user949300
1
@ user949300, pareces confundido. Si el autor se refiere a ellos como un olor a código, entonces indica que podría haber algo mal con ellos. Como son ampliamente reconocidos en estos días como una muy buena práctica, claramente no son un olor a código. Por lo tanto, MrSmith42 es correcto: no hay absolutamente nada de malo en ellos.
David Arno
4

Un buen argumento por Martin Fowler:

"Tell-Don't-Ask es un principio que ayuda a las personas a recordar que la orientación a objetos se trata de agrupar datos con las funciones que operan en esos datos. Nos recuerda que, en lugar de pedir datos a un objeto y actuar sobre esos datos, en cambio, debería decirle a un objeto qué hacer. Esto alienta a mover el comportamiento a un objeto para que vaya con los datos ".

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

Curtis Yallop
fuente
1
El problema aquí es que Fowler restringe artificialmente "decir no preguntar" al cambiar las funciones de pedir un alcance más amplio a solo preguntar el alcance del objeto. Todavía están preguntando. "Decir, no preguntar" puede, de hecho, ir un paso más allá al decir realmente esas funciones a través de sus listas de argumentos. Y así llegamos a objetos de datos y funciones separadas (en cuanto a datos) siendo la verdadera implementación de "tell don't ask". Entonces, en lugar de ser un buen argumento para la afirmación de que las clases de datos son un olor a código, de hecho demuestra lo contrario.
David Arno
2
@DavidArno Te estás olvidando de la encapsulación y la ocultación. Le dice a un objeto que ejecute un método miembro, y el método miembro va al recuadro negro del objeto y hace lo que sea necesario para obtener la respuesta. Si le pregunta a un objeto desde afuera, no tiene acceso a su estado privado, por lo que el objeto expone más estado del que es sabio o el autor de la pregunta tiene que saltar más aros de los necesarios. No veo por qué alguna vez "pedirías" un objeto en un entorno OO. (Otros paradigmas de programación pueden requerir diferentes enfoques, por supuesto.)
Marnen Laibow-Koser
2
@DavidArno Por supuesto, puede pasarlo bazcomo parámetro a un método estático, pero para hacer eso, primero debe preguntarle al objeto. Quizás en un paradigma de programación donde los métodos eran primarios (como, por ejemplo, la programación funcional) esto tiene sentido, pero en un entorno OO, absolutamente no lo hace, porque los objetos son primarios y deben contener tanto los datos como las funciones para actuar sobre ellos. Su afirmación de que eliminar el método del objeto ha aumentado la encapsulación también es exactamente al revés , por lo que puedo decir, porque significa que ahora ha bazaparecido fuera del objeto.
Marnen Laibow-Koser
1
@ MarnenLaibow-Koser, no pretendo "estar haciendo OO". Escribo código y utilizo buenas técnicas para hacerlo. Si esas técnicas provienen del paradigma funcional, o del paradigma OO, o del paradigma de quién da una maldita maldición, no me interesa. Escoger un paradigma y apegarse a él lo más posible es puro dogma. Es malo. Es ridículo. Te sofoca y da como resultado un código inferior. No lo hagas
David Arno
1
@DavidArno Por el contrario, si te comprometes completamente con un paradigma (cualquier paradigma decente, no solo OO), obtienes poderosas abstracciones de alto nivel y un código lógicamente consistente y mantenible. No digo que esto sea dogmático, sino más bien pragmático. He visto y mantenido demasiado código que aparentemente se produjo con una actitud como la suya, donde el autor realmente no se comprometió con la coherencia lógica del sistema que se está utilizando. Es difícil de entender, difícil de mantener y difícil de modificar. Ningún paradigma es perfecto, pero generalmente una mezcla (a menos que se considere cuidadosamente) es más difícil de entender.
Marnen Laibow-Koser
2

Lo que debe comprender es que hay dos tipos de objetos:

  • Objetos que tienen comportamiento . Estos deben abstenerse de dar acceso público a la mayoría / cualquiera de sus miembros de datos. Solo espero muy pocos métodos de acceso definidos para estos.

    Un ejemplo sería una expresión regular compilada: el objeto se crea para proporcionar un cierto comportamiento (para hacer coincidir una cadena con una expresión regular específica y para informar las coincidencias (parciales)), pero la forma en que la expresión regular compilada funciona no es del usuario negocio.

    La mayoría de las clases que escribo están en esta categoría.

  • Objetos que en realidad son solo datos . Estos deberían declarar a todos sus miembros públicos (o proporcionar el conjunto completo de accesores para ellos).

    Un ejemplo sería una clase Point2D. No hay absolutamente ninguna invariante que deba garantizarse para los miembros de esta clase, y los usuarios deberían poder acceder a los datos a través de myPoint.xy myPoint.y.

    Personalmente, no uso mucho esas clases, pero supongo que no hay un código más grande que haya escrito que no use tal clase en alguna parte.

Ser competente con la orientación a objetos incluye darse cuenta de que existe esta distinción y aprender a clasificar la función de una clase en una de estas dos categorías.


Si codifica en C ++, puede hacer esta distinción explícita utilizando classpara la primera categoría de objetos y structpara la segunda. Por supuesto, los dos son equivalentes, excepto que eso classsignifica que todos los miembros son privados por defecto, mientras que structdeclara a todos los miembros públicos por defecto. Cuál es exactamente el tipo de información que desea comunicar.

cmaster - restablecer monica
fuente
1
Una explicación para el
voto negativo
Gracias por la respuesta. Odio cuando la gente rechaza sin motivo. Si tiene un problema con una respuesta, explique por qué .
Sipo