Pregunta

Acabo de leer esta publicación por Greg Young, donde está hablando de que Microsoft recomienda patrones con objetos de transferencia de datos tontos. Él dio a entender que en la comunidad Java, las cosas tienden a la otra dirección.

Mi pregunta es ¿cuánta lógica debería haber en sus objetos de entidad? Nuestra filosofía donde trabajo (tienda C #) es que si no puede serializarlo, no lo coloque en la entidad.

¿Fue útil?

Solución

Matt,

Diría que su tienda está escribiendo un código de procedimiento. Quiero dejar en claro que no hay nada de malo en que muchos sistemas grandes (incluidos muchos en los que he trabajado) se hayan escrito utilizando código de procedimiento. Hay un momento y un lugar para ello.

Ahora el código de procedimiento no tiene cabida en un modelo de dominio. Si desea utilizar un estilo de procedimiento más adecuado, utilícelo con algo como un Módulo de tabla o un patrón de Registro activo. No es la falta de OO lo que considero tan destructivo en la orientación, sino el uso de un modelo de dominio con lógica de procedimiento.

Esto hace que uno gaste una gran cantidad de recursos en la construcción de la capa de dominio (falta de coincidencia de impedancia, tiempo de proceso pensado para construir agregados, aislamiento, lenguaje ubicuo, etc.) sin recibir ninguno de los beneficios que la capa de dominio (generalmente mantenibilidad) de lo contrario proporcionar. En otras palabras, si bien puede cumplir con sus requisitos funcionales, terminará gastando una gran cantidad de su presupuesto casi sin retorno.

Ahora para volver a lo que es "comportamiento" Me gustaría centrarme en la pregunta de un Orientado a Objetos en lugar de un "Diseño Dirigido por Dominio" punto de vista. Un objeto generalmente encapsulará algún estado y generalmente expondrá algunos comportamientos.

reiteración rápida: encapsular el estado, exponer el comportamiento

Entonces, ¿qué comportamientos debe tener un objeto? En pocas palabras, deberían ser los comportamientos que operan sobre el estado que encapsula. En un mundo de OO conductual ideal, el estado nunca estaría expuesto a los comportamientos del objeto solamente. Poner tácticamente en el código si comenzamos a ver código como:

Customer c = GetCustomerFromRepository();
c.Status = CustomerStatuses.Deleted;
c.LastUpdated = DateTime.Now;
c.UpdatedBy = GetCurrentUser();
CustomerRepository.Save(c);

Tenemos una infracción de SRP ... Este código es un código que debería ser un comportamiento del objeto del cliente porque la " Responsabilidad " del objeto del cliente es.

Encapsular estado sobre un cliente y exponer comportamientos.

Como tal, podemos ver que sería mejor tener un método Customer.Delete (). (sí, este es un mal ejemplo, lo sé ...)

Ahora también llegaríamos a esto usando TDD. Es mucho más fácil para nosotros lidiar en las pruebas con la costura que proporciona el comportamiento que las costuras donde está expuesto todo el estado. La razón de esto es que no necesito duplicar la lógica en mis pruebas. El código del cliente no importa cómo funciona una eliminación ... solo le importa que el cliente exponga el comportamiento. Como tal, en nuestras pruebas en lugar de afirmar que c.State == CustomerStates.Deleted y c.UpdatedBy == GetCurrentUser (), etc., etc., simplemente afirmaríamos que el método de eliminación se invocó en la costura del cliente mediante un simulacro.

Ahora para volver al título. La cantidad de lógica que debe estar en un objeto comercial es la cantidad de lógica que recae bajo su responsabilidad de encapsular su estado. A veces esto es mucho, a veces no lo es. También hay lugares donde desea utilizar los servicios ... un buen ejemplo sería coordinar la interacción entre muchos objetos de dominio para un comportamiento dado, pero incluso aquí el servicio debería llamar a comportamientos en los objetos de dominio .

¿Ayuda esto a aclarar un poco las cosas?

Greg

Otros consejos

Si los está llamando sus "objetos de modelo de dominio" entonces supondré que te estás refiriendo al patrón del modelo de dominio de Fowler. http://martinfowler.com/eaaCatalog/domainModel.html

Dado ese supuesto, la respuesta a su pregunta es "toda la lógica de negocios". ya que esa es esencialmente la definición del patrón.

Desafortunadamente, el término "modelo de dominio" parece que se ha diluido recientemente para que solo signifique un modelo de objeto de sus datos sin comportamiento.

Si aún no lo ha hecho, le animo a leer PoEAA y decidir dónde cree que pertenece la lógica de dominio en su situación. Si decide un modelo de dominio, le animo a leer el libro DDD de Evan y conocer las diferencias entre entidades, objetos de valor y servicios.

¡Espero que eso ayude!

Últimamente, he estado jugando con la idea de crear modelos de dominio que tengan estructura y solo aquellos comportamientos que sean universales para ese modelo (es decir, comportamientos que pueden usarse en múltiples contextos delimitados) con métodos de extensión para el comportamiento específico para Un contexto acotado. Esto mantiene los modelos de dominio cerca de un DTO (para aquellos que les gusta eso) y restringe el uso de ese modelo de dominio solo a los comportamientos permitidos dentro de un contexto acotado. Entonces esa podría ser una opción para una respuesta a mitad de camino. :)

El punto principal es cómo se define la lógica. Para dar algunos ejemplos:

  1. No categorizaría una función getFullName () en una entidad Person, que solo concatena algunas cadenas, como lógica.
  2. Calcular un valor de artículo de pedido probablemente calificaría para ser lógico.
  3. Hacer algunas transacciones de reserva, definitivamente diría que es lógico.

El punto 1 y tal vez 2 irían a por mí a la entidad. Punto 3 no. Entonces defino la lógica como:

  • cualquier operación que haga algo relacionado con la persistencia (lectura / escritura)
  • cualquier operación que involucre a cualquier otra entidad (no directamente relacionada, por ejemplo, master-detail)

OMI, cualquiera de estas operaciones no pertenece a entidades.

Ahora, ¿por qué / cuándo no pondría también operaciones de tipo punto 1 y 2 en una entidad? Es una situación bastante rara, pero no lo haría, tan pronto como los datos almacenados en la entidad necesiten ser interpretados de alguna manera antes de que la aplicación pueda usarlos (por ejemplo, si depende del usuario actual, el contenido del campo X tiene un significado diferente), lo que significa que los datos de la entidad producen cierta lógica.

Hasta donde yo entiendo, toda la lógica de negocios relacionada con una entidad debe ir a esa entidad. Consiste en cualquier lógica que defina el comportamiento o la estructura interna de la entidad en función de las reglas de negocio del sistema. Esto no debe incluir la lógica de presentación o la lógica de persistencia (la excepción obvia es con el patrón de diseño de Active Record) sino que debe incluir cosas como la validación de datos, las relaciones entre entidades, las máquinas de estado y otras cosas que definen cómo se comporta la entidad en términos de la realidad cosa del mundo que intenta modelar.

La forma en que trato de verlo es tratando de hacer que mis modelos sean lo más valiosos posible. Siempre trate de pensar cómo se usaría el modelo si fuera a ser portado a un sistema diferente donde el código del cliente (o el código que usa la entidad) puede ser diferente. Si la funcionalidad no es parte de la entidad, ¿se comportará de la misma manera siguiendo las mismas reglas comerciales? Si la respuesta es no, entonces la funcionalidad debería ir en la entidad.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top