2012-05-04 19 views
15

An interesting thread surgió cuando escribí esta pregunta en este momento. Sin embargo, no creo que responda mi pregunta.¿Puede un "modelo de dominio enriquecido" violar el principio de responsabilidad única?

He estado trabajando mucho con .NET MVC3, donde es deseable tener un modelo anémico. Ver modelos y editar modelos es mejor que nada como contenedores de datos estúpidos que puedes pasar de un controlador a una vista. Cualquier tipo de flujo de aplicaciones debería provenir de los controladores, y las vistas manejan las preocupaciones de UI. En MVC, no queremos ningún comportamiento en el modelo.

Sin embargo, tampoco queremos lógica comercial en los controladores. Para aplicaciones más grandes es mejor mantener el código de dominio separado e independiente de los modelos, vistas y controladores (y HTTP en general para el caso). Entonces, hay un proyecto separado que proporciona, antes que nada, un modelo de dominio (con entidades y objetos de valor, compuestos en agregados de acuerdo con DDD).

He hecho algunos intentos para pasar de un modelo anémico a uno más rico en el código de dominio, y estoy pensando en renunciar. Me parece que tener clases de entidades que contienen datos y comportamiento viola el SRP.

Tomemos como ejemplo un escenario muy común en la web, componiendo correos electrónicos. Dado algún evento, es responsabilidad del dominio componer un objeto EmailMessage dado un EmailTemplate, EmailAddress y valores personalizados. La plantilla existe como una entidad con propiedades y el usuario proporciona valores personalizados como entrada. Digamos también por el argumento de que la dirección FROM de EmailMessage puede ser provista por un servicio externo (IConfigurationManager.DefaultFromMailAddress). Teniendo en cuenta estos requisitos, se parece como un modelo de dominio rico podría dar la EmailTemplate la responsabilidad de componer la EmailMessage:

public class EmailTemplate 
{ 
    public EmailMessage ComposeMessageTo(EmailAddress to, 
     IDictionary<string, string> customValues, IConfigurationManager config) 
    { 
     var emailMessage = new EmailMessage(); // internal constructor 
              // extension method 
     emailMessage.Body = this.BodyFormat.ApplyCustomValues(customValues); 
     emailMessage.From = this.From ?? config.DefaultFromMailAddress; 
     // bla bla bla 
     return emailMessage; 
    } 
} 

Este fue uno de mis intentos de modelo de dominio rico. Sin embargo, después de agregar este método, era responsabilidad de EmailTemplate contener las propiedades de los datos de la entidad y redactar los mensajes. Tenía alrededor de 15 líneas, y parecía distraer a la clase de lo que realmente significa ser una EmailTemplate, que, IMO, solo almacena datos (formato de sujeto, formato del cuerpo, archivos adjuntos y direcciones opcionales desde/respuesta a))

Terminé refaccionando este método en una clase dedicada, cuya única responsabilidad es componer un mensaje de correo electrónico dados los argumentos anteriores, y estoy mucho más feliz con él. De hecho, estoy empezando a preferir los dominios anémicos porque me ayuda a mantener las responsabilidades separadas, haciendo que las clases y las pruebas de unidad sean más cortas, más concisas y más centradas. Parece que hacer que las entidades y otros objetos de datos "carezcan de comportamiento" puede ser bueno para separar la responsabilidad. ¿O estoy fuera de pista aquí?

+1

Un modelo de dominio enriquecido debe ser rico solo lo suficiente para el contexto donde sea relevante. –

Respuesta

19

El argumento a favor de un modelo de dominio rico en lugar de un modelo anémico depende de una de las propuestas de valor de OOP, que mantiene el comportamiento y los datos uno al lado del otro. El beneficio principal es el de la encapsulación y la cohesión que ayuda a razonar sobre el código. Un modelo de dominio enriquecido también se puede ver como una instancia del patrón information expert. Sin embargo, el valor de todos estos patrones es en gran medida subjetivo. Si es más útil para usted mantener separados los datos y el comportamiento, que así sea, aunque también podría considerar a otras personas que mirarán el código. Prefiero encapsular todo lo que puedo. El otro beneficio de un modelo de dominio más rico en este caso sería la posibilidad de hacer ciertas propiedades privadas. Si una propiedad solo se utiliza con un método en la clase, ¿por qué hacerlo público?

Si un modelo de dominio enriquecido infringe SRP depende de su definición de responsabilidad. Según SRP, una responsabilidad es una razón para cambiar, que a su vez requiere una definición. Esta definición generalmente dependerá del caso de uso en cuestión.Puede declarar que la responsabilidad de la clase de plantilla es ser una plantilla, con todas las implicaciones que surgen, una de las cuales es generar un mensaje desde la plantilla. Un cambio en una de las propiedades de la plantilla puede afectar el método ComposeMessageTo, lo que indica que tal vez se trata de una responsabilidad única. Además, el método ComposeMessageTo es la parte más interesante de la plantilla. A los clientes de la plantilla no les importa cómo se implementa el método o qué propiedades están presentes en la clase de plantilla. Solo quieren generar un mensaje basado en la plantilla. Esto también vota a favor de mantener los datos al lado del método.

+0

Excelente respuesta, gracias. – danludwig

0

Bueno, depende de cómo quiera verlo.

Otra forma es: "¿Puede el principio de responsabilidad única violar un modelo de dominio enriquecido?"

Ambas son directrices. No hay ningún "principio" en ninguna parte del diseño de software. Sin embargo, hay buenos diseños y malos diseños. Ambos conceptos se pueden usar de diferentes maneras para lograr un buen diseño.

Cuestiones relacionadas