2012-08-16 7 views
6

nel mio progetto, la logica aziendale tutto nel servizio di applicazione, servizio di dominio solo qualche entità, chi può dirmi o darmi un esempio per mostrare come aggiungere business logic al servizio di dominio in Domain-Driven-Design? grazie mille!Come aggiungere la business logic al servizio di dominio in Domain-Driven-Design?

UPDATE

scrivo una semplice solutation, questo solutation è un sistema di voto, la parte principale è solutation:

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; } 
    } 
} 

voglio spostare il Business Log in application.service su Domain.service (non è questo progetto corrente), chi può aiutarmi? come fare è ragionevole? grazie mille!

+0

Puoi fornire alcuni esempi dei tuoi oggetti di dominio? – casablanca

+0

@casablanca ho aggiornato la mia domanda – artwl

+0

Che cosa significa IP? c'è qualche relazione tra articolo e VoteRecord? Si prega di inviare la classe articolo –

risposta

7

DDD si sta concentrando su come progettare modelli di dominio per adattarsi ai requisiti, lo schema nel database non importa molto.

Se l'entità del dominio è solo una proprietà, sembra che si stia violando lo Anemic Model anti-pattern. La logica aziendale dovrebbe essere nelle entità di dominio. Quindi, nel tuo caso, al fine di evitare la logica di business che si perde nel servizio Application. È possibile avere un nuovo modello chiamato Client per esempio per memorizzare Ip o altre proprietà se necessario.

Per facilitare la comprensione, se il client supera i limiti di giorno, questo metodo deve essere nella classe Client. Simile al metodo IsRepeated.

Così, il vostro oggetto di dominio dovrebbe essere:

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: se non è necessario creare nuovo Cliente tavolo, basta mappare in tavola Voto. Per quanto riguarda le proprietà VoteCount, è inutile perché è possibile conteggio in base alla lista di voto

+2

+1 mettere la lista dei voti nell'articolo è l'approccio giusto. Eviterei di avere un riferimento all'articolo in votazione poiché crea un riferimento circolare - se necessario, questo può essere cercato attraverso un repository, ad es. 'Articolo articolo = repository.FindArticleByVote (vote)'. – casablanca

0

Dalla guardando l'Application Service direi che non è certo un Application Service, è già un po 'di un dominio del servizio in percepire che cattura alcune logiche di dominio (al contrario di prendere l'input di viewmodel e mapparlo su entità). Hai comunque problemi più grandi:

I tuoi aggregati sono disattivati. Si vogliono applicare due invarianti attorno a un indirizzo IP che vota un articolo (un ip può votare una sola volta per articolo, un ip può trasmettere fino a 10 voti al giorno). Né i nomi sono una buona misura (articolo, voto) per il monitoraggio di questo.

ArticleVotes potrebbe essere una buona misura per tenere traccia e far rispettare i voti espressi su un articolo da singoli IP, mentre IPVotesPerDate potrebbe tenere traccia del numero di voti espressi da un singolo indirizzo IP su base giornaliera. Potresti essere in grado di spostare i ArticleVotes nell'aggregato articolo se il numero totale di voti è abbastanza basso (e puoi mantenere la performance dove vuoi). IPVotesPerDate potrebbe essere piegato in VotesPerDate se il numero totale di IP che vota su base giornaliera è basso.

In conclusione, l'ip e il volume di votazione determineranno le prestazioni dei vostri aggregati. Questo potrebbe costringerti a rimodellarli per soddisfare i numeri di rendimento che cerchi. Il tuo colpo migliore è di trovare quei numeri per sapere in che direzione procedere.

Da lì dovrebbe essere ovvio che il comportamento desiderato potrebbe essere portato negli aggregati che ho citato. Quindi, la necessità di un servizio di dominio potrebbe andare via. Dico potrebbe, perché il caso d'uso è ancora un ip che vota un articolo. In quanto tale, potrebbe richiedere un certo coordinamento tra gli aggregati, ergo l'introduzione di un servizio di dominio.

+0

Se il numero di IP e voti è alto. Come lo progetterai? –

+0

Ritenerei gli invarianti falsi, accetta solo tutte le scritture e deduplica dopo il fatto. –

+0

Cosa intendi per deduplicazione? Che ne dici di creare un servizio di dominio come VotingService in cui puoi verificare gli invarianti prima di accettare il voto? È in realtà ciò che il codice OP, basta spostarlo sul livello del dominio. –

1

Penso che Voto e articolo siano un aggregato. Non so molto del tuo dominio, ma presumo che ogni voto sia importante solo per un determinato articolo. I voti non saranno condivisi tra gli articoli quindi dovrebbero essere trattati come membri dell'aggregazione e non trattati come entità dell'intero dominio.

A mio parere, l'articolo sarebbe l'entità radice dell'Agregato e il Voto sarebbe un'entità membro all'interno. Applicando questo "modello" si può incapsulare tutta la logica aziendale all'interno.

Si potrebbe avere un componente aggiuntivo (...) all'interno del proprio articolo o una logica aziendale come questa.

Allora potreste chiedervi .. "Ok .. ma per quanto riguarda la persistenza ??". Dato che stai definendo il tuo articolo-voto come un aggregato, allora li tratterai insieme. Se esegui operazioni CRUD su un articolo, allo stesso tempo eseguirai queste operazioni nei loro membri di aggregazione (voti). Quindi potresti aver bisogno di un repository per l'articolo aggregato, si prenderà cura dei voti dell'articolo.

Spero che questo abbia un senso per voi. Scegli l'opzione migliore a seconda del tuo dominio.

Problemi correlati