design patterns - resueltos - Cuánta lógica debe existir en los objetos de su modelo de dominio
modelo de dominio pdf (5)
Acabo de leer esta publicación de Greg Young, donde habla de que Microsoft recomienda patrones con objetos tontos de transferencia de datos. Dio a entender que en la comunidad de Java, las cosas tienden a la otra dirección.
Mi pregunta es ¿cuánta lógica debería haber en los objetos de tu entidad? Nuestra filosofía donde trabajo (C # shop) es que si no puedes serializarlo, no lo pongas en la entidad.
Últimamente, he estado jugando con la idea de crear modelos de dominio que tengan estructura y solo aquellos comportamientos que son 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 de un contexto delimitado . 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 a solo los comportamientos permitidos dentro de un contexto delimitado. Entonces esa podría ser una opción para una respuesta en el medio del camino. :)
El punto principal es cómo uno define la lógica. Para dar algunos ejemplos:
- No categorizaría una función getFullName () en una entidad Person, que solo concatena algunas cadenas, como lógica.
- Cálculo de un valor de artículo de pedido más probablemente calificaría para ser lógica.
- Hacer algunas transacciones de reserva, definitivamente diría que es lógica.
El punto 1 y tal vez 2 me irían a la entidad. Punto 3 no. Entonces yo defino la lógica como:
- cualquier operación que haga algo relacionado con la persistencia (lectura / escritura)
- cualquier operación que involucre cualquier otra entidad (no relacionada directamente, por ejemplo, detalle maestro)
OMI, cualquiera de estas operaciones no pertenece a las entidades.
Ahora, ¿por qué / cuándo no pondría también operaciones de tipo de 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 necesitan ser interpretados de alguna manera antes de que la aplicación pueda utilizarlos (por ejemplo, si depende del usuario actual, el contenido del campo X tiene un significado diferente), eso significa que los datos de la entidad en sí producen cierta lógica.
Por lo que yo entiendo, toda la lógica de negocios relacionada con una entidad debe entrar en esa entidad. Esto consiste en cualquier lógica que defina el comportamiento o la estructura interna de la entidad en función de las reglas comerciales del sistema. Esto no debe incluir lógica de presentación o lógica de persistencia (la excepción obvia es con el patrón de diseño Active Record) pero debe incluir cosas tales como validación de datos, relaciones de entidad, máquinas de estado y otras cosas que definen cómo se comporta la entidad en términos del real- cosa del mundo que está tratando de modelar.
La forma en que trato de verlo es tratar de hacer que mis modelos sean lo más reafirmables posible. Siempre trate de pensar en cómo se usaría el modelo si fuera trasladado 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, ¿seguirá comportándose de la misma manera siguiendo las mismas reglas comerciales? Si la respuesta es no, entonces la funcionalidad debe ir en la entidad.
Si los llama sus "objetos del modelo de dominio", supongo que se refiere al patrón del Modelo de dominio de Fowler. http://martinfowler.com/eaaCatalog/domainModel.html
Dada esa suposición, la respuesta a su pregunta es "toda la lógica de negocios", ya que es esencialmente la definición del patrón.
Desafortunadamente, el término "modelo de dominio" parece haberse diluido recientemente para que solo signifique un modelo de objeto de sus datos sin ningún comportamiento.
Si aún no lo ha hecho, le animo a que lea PoEAA y decida dónde cree que pertenece la lógica de dominio en su situación. Si decides un modelo de dominio, te animo a que leas el libro DDD de Evan y aprendas acerca de las diferencias entre las entidades, los objetos de valor y los servicios.
¡Espero que ayude!
Mate,
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 usando código de procedimiento. Hay un tiempo y un lugar para eso.
Ahora el código de procedimiento no tiene lugar en un modelo de dominio. Si desea utilizar un estilo más procedimental que esté bien, utilícelo con algo así como un Módulo de tabla o un patrón de registro activo. No es la falta de OO lo que estoy considerando ser 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 construyendo la capa de dominio (desajuste de impedancia, tiempo de proceso de pensamiento para construir agregados, aislamiento, lenguaje ubicuo, etc.) sin recibir ninguno de los beneficios que la capa de dominio (generalmente capacidad de mantenimiento) proporcionaría. En otras palabras, si bien puede cumplir con sus requisitos funcionales muy bien, termina gastando una gran cantidad de su presupuesto casi sin retorno.
Ahora, para volver a lo que "es el comportamiento", me gustaría centrarme en la pregunta desde un punto de vista orientado a objetos en lugar de un punto de vista "Diseño impulsado por dominio". 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 está encapsulando. En un mundo de OO conductual ideal, el estado nunca estaría expuesto a los comportamientos únicos del objeto. Ponga 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 violació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 el estado de 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 tratar en pruebas con la costura que proporciona el comportamiento que las costuras donde todo el estado está expuesto. La razón de esto es que no necesito duplicar la lógica en mis pruebas. Al código del cliente no le 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, simplemente afirmaríamos que se invocó el método de eliminación en la costura del cliente utilizando un simulacro.
Ahora para volver al título. La cantidad de lógica que debe existir en un objeto comercial es la cantidad de lógica que cae bajo su responsabilidad de encapsular su estado. A veces esto es mucho, a veces no lo es. También hay lugares en los que desea utilizar los servicios ... un buen ejemplo sería coordinar la interacción entre muchos objetos de dominio para un comportamiento determinado, pero incluso aquí el servicio debería llamar comportamientos en los objetos de dominio.
¿Esto ayuda a aclarar un poco las cosas?
Greg