2010-04-03 8 views
10

acaba de crear un CAC sobre SO preguntar esto :)En un enfoque DDD, ¿este ejemplo está modelado correctamente?

Asumiendo que este ejemplo simplificado: la construcción de una aplicación web para la gestión de proyectos ...
La aplicación tiene los siguientes requisitos/reglas.

1) Los usuarios deberían poder crear proyectos insertando el nombre del proyecto.
2) Los nombres de los proyectos no pueden estar vacíos.
3) Dos proyectos no pueden tener el mismo nombre.

Estoy usando una arquitectura de 4 capas (interfaz de usuario, aplicación, dominio, infraestructura).
En mi capa de aplicación tengo la siguiente clase ProjectService.cs:

public class ProjectService 
{ 
    private IProjectRepository ProjectRepo { get; set; } 

    public ProjectService(IProjectRepository projectRepo) 
    { 
     ProjectRepo = projectRepo; 
    } 

    public void CreateNewProject(string name) 
    { 
     IList<Project> projects = ProjectRepo.GetProjectsByName(name); 
     if (projects.Count > 0) throw new Exception("Project name already exists."); 

     Project project = new Project(name); 
     ProjectRepo.InsertProject(project); 
    } 
} 

En mi Capa de Dominio, tengo la clase Project.cs y la interfaz IProjectRepository.cs:

public class Project 
{ 
    public int ProjectID { get; private set; } 
    public string Name { get; private set; } 

    public Project(string name) 
    { 
     ValidateName(name); 
     Name = name; 
    } 

    private void ValidateName(string name) 
    { 
     if (name == null || name.Equals(string.Empty)) 
     { 
      throw new Exception("Project name cannot be empty or null."); 
     } 
    } 
} 




public interface IProjectRepository 
{ 
    void InsertProject(Project project); 
    IList<Project> GetProjectsByName(string projectName); 
} 

En mi Capa de infraestructura, tengo la implementación de IProjectRepository que hace la consulta real (el código es irrelevante).


No me gustan dos cosas acerca de este diseño:

1) He leído que las interfaces de repositorio debe ser una parte del dominio, pero las implementaciones no debería. Eso no tiene sentido para mí, ya que creo que el dominio no debe llamar a los métodos de depósito (ignorancia de persistencia), que debería ser una responsabilidad de los servicios en la capa de aplicación. (Algo me dice que estoy terriblemente mal.)

2) El proceso de creación de un nuevo proyecto implica dos validaciones (no nulo ni duplicado). En mi diseño anterior, esas dos validaciones están dispersas en dos lugares diferentes, lo que hace que sea más difícil (yo) ver qué está pasando.

Entonces, mi pregunta es, desde una perspectiva DDD, ¿está modelado correctamente o lo haría de otra manera?

Respuesta

1

Creo que parte de la confusión con (1) es que te falta una capa: inserta una capa de servicio en tu arquitectura y tu problema desaparecerá como magia. Puede poner el servicio y la implementación del repositorio en la capa de servicio, es decir, tiene un servicio que utiliza una implementación concreta del repositorio. Otros servicios son libres de elegir una implementación alternativa del repositorio si así lo desean. Su aplicación es libre de elegir la interfaz de servicio que desee. Habiendo dicho eso, no estoy seguro de que realmente importe en la mayoría de los casos. En casi todas mis aplicaciones tengo un "dominio/capa de datos" que básicamente está arreglado. Podría colocar un repositorio en él o no dependiendo de lo complicada que sea la lógica comercial. Lo mismo con el servicio: simplemente no será necesario si el proyecto no es muy complicado. Si llega a ser así más tarde, siempre puedo refactorizar. Normalmente pongo mi repositorio en el mismo proyecto que mi contexto de datos (usando LINQ) y, si hubiera un servicio, estaría en un proyecto separado (porque típicamente también estaría expuesto como un servicio web).

Con respecto a (2) debe pensar en el problema desde una perspectiva de concurrencia. Su verificación de un nombre duplicado se maneja mejor con una restricción de base de datos si es posible. Creo que esta es la forma más fácil de aplicar esta lógica. Desde luego, puede verificar si hay un duplicado antes de intentar insertarlo, pero a menos que lo haga dentro de una transacción, no puede garantizar que no aparezca otro proceso e insertar uno entre su cheque y su inserción.La restricción de la base de datos resuelve este problema. Al mover el cheque a la lógica de inserción (misma transacción) también se resuelve el problema, pero independientemente de eso, creo que debe estar preparado para manejarlo como un error de inserción así como (o en lugar de) un error de validación.

+0

En cuanto a (1), creo que mi capa de aplicación podría servir al propósito de una capa de servicio, si tuviera otra capa Creo que podría terminar con capas que no tienen sentido o responsabilidades están compartidas entre las capas. Cuando habla de la complejidad del diseño, estoy totalmente de acuerdo con usted. He estado usando un enfoque de 'Patrón de registros activo' para la mayoría de mis aplicaciones, y ese patrón puede parecer más adecuado para resolver este ejemplo. A propósito, dejé este ejemplo simplista, pero estoy intentando aprender a modelar correctamente utilizando un Patrón de repositorio, por eso me inclino por el patrón AR. – Tag

+0

Con respecto a (2), su sugerencia tiene mucho sentido para mí y creo que, de hecho, es la mejor opción en este caso. – Tag

2

El proceso de creación de un nuevo proyecto implica dos validaciones (no nulas ni duplicadas). En mi diseño anterior, esas dos validaciones están dispersas en dos lugares diferentes, lo que hace que sea más difícil (yo) ver qué está pasando.

Proyecto no puede y no debe ser consciente de todos los proyectos de aplicación (artículo en sí mismo no debe ser consciente de todos los demás elementos de la lista), por lo tanto -. Es responsabilidad del servicio de dominio (instead of application service comprobar Evans libro para entender la diferencia exacta).

Hay muchos tipos de validación. Y there can't be universal validation mechanism. DDD solo dice que debe poner la validación de dominio en el modelo de dominio.