2012-08-16 16 views
6

en mi proyecto, la lógica de negocios todo en el servicio de aplicaciones, el servicio de dominio solo alguna entidad, ¿quién puede decirme o darme un ejemplo para mostrar cómo agregar lógica empresarial al servicio de dominio en el diseño controlado por el dominio? ¡muchas gracias!Cómo agregar lógica de negocios al servicio de dominio en el diseño controlado por el dominio?

ACTUALIZACIÓN

escribo un solutation sencillo, este solutation es un sistema de votación, la parte principal solutation es:

enter image description here

Vote.Application.Service.VoteService.cs:

namespace Vote.Application.Service 
{ 
    public class VoteService 
    { 
     private IVoteRepository _voteRepository; 
     private IArticleRepository _articleRepository; 

     public VoteService(IVoteRepository voteRepository,IArticleRepository articleRepository) 
     { 
      _voteRepository = voteRepository; 
      _articleRepository = articleRepository; 
     } 

     public bool AddVote(int articleId, string ip) 
     { 
      var article = _articleRepository.Single(articleId); 
      if (article == null) 
      { 
       throw new Exception("this article not exist!"); 
      } 
      else 
      { 
       article.VoteCount++; 
      } 

      if (IsRepeat(ip, articleId)) 
       return false; 

      if (IsOvertakeTodayVoteCountLimit(ip)) 
       return false; 

      _voteRepository.Add(new VoteRecord() 
      { 
       ArticleID = articleId, 
       IP = ip, 
       VoteTime = DateTime.Now 
      }); 

      try 
      { 
       _voteRepository.UnitOfWork.Commit(); 
       return true; 
      } 
      catch (Exception ex) 
      { 
       throw ex; 
      } 
     } 

     private bool IsRepeat(string ip, int articleId) 
     { 
      //An IP per article up to cast 1 votes 
      //todo 
      return false; 
     } 

     private bool IsOvertakeTodayVoteCountLimit(string ip) 
     { 
      //An IP per day up to cast 10 votes 
      //todo 
      return false; 
     } 
    } 
} 

Vote.Domain.Contract.IVoteRepository.cs:

namespace Vote.Domain.Contract 
{ 
    public interface IVoteRepository 
     : IRepository<VoteRecord> 
    { 
     void Add(VoteRecord model); 
    } 
} 

Vote.Domain.Contract.IArticleRepository.cs:

namespace Vote.Domain.Contract 
{ 
    public interface IArticleRepository 
     : IRepository<Article> 
    { 
     void Add(VoteRecord model); 

     Article Single(int articleId); 
    } 
} 

Vote.Domain.Entities.VoteRecord:

namespace Vote.Domain.Entities 
{ 
    public class VoteRecord 
    { 
     public int ID { get; set; } 

     public DateTime VoteTime { get; set; } 

     public int ArticleID { get; set; } 

     public string IP { get; set; } 
    } 
} 

Vote.Domain.Entities.Article:

namespace Vote.Domain.Entities 
{ 
    public class Article 
    { 
     public int ID { get; set; } 

     public string Title { get; set; } 

     public string Content { get; set; } 

     public int VoteCount { get; set; } 
    } 
} 

Quiero mover el registro de negocios en application.service a Domain.service (actual no en este proyecto), ¿quién puede ayudarme? ¿cómo hacerlo es razonable? ¡muchas gracias!

+0

¿Puede proporcionar algunos ejemplos de los objetos de su dominio? – casablanca

+0

@casablanca He actualizado mi pregunta – artwl

+0

¿Qué significa IP? ¿Hay alguna relación entre Article y VoteRecord? Por favor, publique el artículo de la clase –

Respuesta

7

DDD se centra en cómo diseñar modelos de dominio que se ajusten a los requisitos, el esquema en la base de datos no importa demasiado.

Si su entidad de dominio es solo propiedad, parece que está violando el Anemic Model anti-pattern. La lógica empresarial debe estar en entidades de dominio. Entonces, en su caso, para evitar la fuga de lógica de negocios al servicio de aplicaciones. Puede tener un nuevo modelo llamado Cliente, por ejemplo, para almacenar Ip u otras propiedades si es necesario.

Para tener una comprensión más fácil, si el Cliente excede los límites en el día, este método debe estar en la clase Cliente. Similar con el método IsRepeated.

Por lo tanto, el objeto de dominio debería ser:

public class Client 
{ 
    public string Ip { get; set; } 
    // More properties if needed 

    public List<Vote> Votes { get; set; } 

    public bool ExceedLimitInDay() 
    { 
    } 
} 

public class Vote 
{ 
    public int Id { get; set; } 
    public DateTime VoteTime { get; set; } 
    public Article Article { get; set; } 
    public Client { get; set; } 
} 

public class Article 
{ 
    public int Id { get; set; } 
    public string Title { get; set; } 
    public string Content { get; set; } 

    public List<Vote> Votes { get; set; } 

    public bool IsRepeated(string ip) 
    { 
     return Votes.Select(v => v.Client.Ip == ip).Any();  
    } 
} 

Nota: Si no es necesario crear una nueva tabla de clientes, simplemente trazarlo en la tabla de voto. En cuanto a las propiedades VoteCount, no es necesario porque se puede recuento basado en la lista de voto

+2

+1 poner la lista de votos en el artículo es el enfoque correcto. Evitaría tener una referencia retrospectiva al artículo en votación, ya que crea una referencia circular; de ser necesario, esto se puede buscar a través de un repositorio, por ejemplo. 'Artículo article = repository.FindArticleByVote (vote)'. – casablanca

0

De mirando el Servicio de Aplicaciones yo diría que es apenas un servicio de aplicación, ya es un poco de un Servicio de dominio en el sentido de que captura alguna lógica de dominio (en lugar de tomar la entrada del modelo de vista y mapearla en las entidades). Sin embargo, tiene problemas mayores:

Sus agregados están desactivados. Desea aplicar dos invariantes alrededor de una dirección IP emitiendo un voto sobre un artículo (una IP solo puede votar una vez por artículo, una IP puede emitir hasta 10 votos por día). Ninguno de los dos nombres son adecuados (artículo, voto) para rastrear esto.

ArticleVotes puede ser una buena opción para rastrear y hacer cumplir los votos emitidos en un artículo por ips individuales, mientras que IPVotesPerDate podría rastrear el número de votos emitidos por una dirección IP individual por día. Es posible que pueda mover ArticleVotes en el agregado del artículo si el número total de votos es lo suficientemente bajo (y puede mantener el rendimiento donde lo desee). IPVotesPerDate podría doblarse en VotesPerDate si la cantidad total de IP que vota día a día es baja.

En pocas palabras, el volumen de votación y de IP dictará el rendimiento de sus agregados. Esto podría forzarlo a remodelarlos para acomodar los números de rendimiento que busca. Lo mejor que puede hacer es buscar esos números para saber en qué dirección proceder.

A partir de ahí, debería ser obvio que el comportamiento deseado podría incorporarse a los agregados que mencioné. Por lo tanto, la necesidad de un servicio de dominio podría desaparecer. Digo que sí, porque el caso de uso sigue siendo una votación por IP sobre un artículo. Como tal, puede requerir cierta coordinación entre los agregados, por ejemplo, la introducción de un servicio de dominio.

+0

Si el número de ips y votos es alto. ¿Cómo lo diseñarás? –

+0

Considero que los invariantes son falsos, solo acepto todas las escrituras y deduplicar después de los hechos. –

+0

¿Qué quieres decir con deduplicate? ¿Qué hay de la creación de un servicio de dominio como VotingService donde puede verificar las invariantes antes de aceptar el voto? Es realmente lo que el código OP, simplemente moverlo a la capa de dominio. –

1

Creo que el voto y el artículo son un agregado. No sé mucho sobre su dominio, pero supongo que cada voto solo es importante para un artículo determinado. Los votos no se compartirán entre artículos, por lo que se los debe tratar como miembros de la agregación y no se deben tratar como entidades de todo el dominio.

En mi opinión, el artículo sería la entidad raíz del Agregado y el Voto sería una entidad miembro dentro. Aplicando este "patrón" puede encapsular toda la lógica de negocios dentro.

Puede tener un AddVote (...) dentro de su artículo, o alguna lógica de negocios como esta.

Entonces usted se estará preguntando ... "Ok ... ¿pero qué hay de la persistencia?". Dado que está definiendo su Artículo-Voto como un Agregado, entonces los trataría juntos. Si realiza operaciones CRUD para un Artículo, al mismo tiempo realizará estas operaciones en sus miembros Agregados (votos). Por lo tanto, es posible que necesite un repositorio para el artículo agregado, que se ocupará de los votos del artículo.

Espero que esto tenga sentido para usted. Elija la mejor opción según su dominio.

Cuestiones relacionadas