6

私のプロジェクトでは、ビジネスロジックはすべてアプリケーションサービスにあり、ドメインサービスは一部のエンティティであり、ドメイン駆動設計でドメインサービスにビジネスロジックを追加する方法を教えてくれるか、例を教えてくれますか?どうもありがとう!

アップデート

私は簡単な解決策を書きます、この解決策は投票システムです、解決策の主要部分は次のとおりです:

ここに画像の説明を入力してください

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

application.serviceのビジネスログインをDomain.service(現在はこのプロジェクトではありません)に移動したいのですが、誰が私を助けてくれますか?どうもありがとう!

4

3 に答える 3

7

DDDは、要件に合うようにドメインモデルを設計する方法に焦点を当てています。データベースのスキーマは、それほど重要ではありません。

ドメインエンティティが単なるプロパティバッグである場合は、貧血モデルのアンチパターンに違反しているようです。ビジネスロジックはドメインエンティティにある必要があります。したがって、あなたの場合、ビジネスロジックがアプリケーションサービスにリークするのを避けるために。たとえば、必要に応じてIpまたはその他のプロパティを格納するために、Clientという新しいモデルを作成できます。

理解を容易にするために、Clientが1日の制限を超えているかどうかを確認するには、このメソッドをClientクラスに含める必要があります。メソッドIsRepeatedと同様です。

したがって、ドメインオブジェクトは次のようになります。

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

注:新しいテーブルClientを作成する必要がない場合は、Voteテーブルにマップするだけです。投票数のプロパティについては、投票リストに基づいてカウントできるため、不要です。

于 2012-08-16T10:32:31.920 に答える
2

Vote と Article は Aggregate だと思います。あなたのドメインについてはよくわかりませんが、各投票は特定の記事にとってのみ重要であると思います。投票は記事間で共有されないため、ドメイン全体のエンティティとしてではなく、集約のメンバーとして扱われるべきです。

私の意見では、Article は Aggregate のルート エンティティであり、Vote は内部のメンバー エンティティです。この「パターン」を適用すると、すべてのビジネス ロジックを内部にカプセル化できます。

記事内に AddVote(...) 、またはこのようなビジネスロジックを含めることができます。

すると、あなたは疑問に思うかもしれません..「わかりました..しかし、永続性はどうですか??」。Article-Vote を Aggregate として定義しているので、それらを一緒に扱います。アーティクルに対して CRUD 操作を実行する場合、同時に、これらの操作をその集計メンバー (投票) で実行することになります。したがって、ArticleAggregate のリポジトリが必要になる場合があります。これは、記事の投票を処理します。

これがあなたにとって意味があることを願っています。ドメインに応じて最適なオプションを選択してください。

于 2012-08-23T14:46:52.183 に答える
0

アプリケーション サービスをざっと見てみると、ほとんどアプリケーション サービスではないと思いますが、(viewmodel の入力を取得してエンティティにマッピングするのではなく) いくつかのドメイン ロジックをキャプチャするという意味で、すでに少しドメイン サービスになっています。ただし、より大きな問題があります。

あなたの集計はオフです。記事に投票する IP アドレスに 2 つの不変条件を適用したいとします (IP は記事ごとに 1 回だけ投票でき、IP は 1 日あたり最大 10 票を投じることができます)。どちらの名詞も、これを追跡するのに適していません (記事、投票)。

ArticleVotes は、個々の ips によって記事に投じられた投票を追跡および実施するのに適している可能性があります。一方、IPVotesPerDate は、1 日ごとに個々の IP アドレスによって投じられた投票数を追跡する場合があります。投票の総数が十分に少ない場合は、ArticleVotes を Article 集計に移動できる可能性があります (そして、必要なパフォーマンスを維持できます)。1 日ごとに投票する IP の総数が少ない場合は、IPVotesPerDate を VotesPerDate に変更できます。

要するに、IP と投票量が集計のパフォーマンスを左右するということです。これにより、求めるパフォーマンス数値に対応するために、それらを改造しなければならない場合があります。あなたの最善の策は、それらの数字を見つけて、どの方向に進むべきかを知ることです.

そこから、私が言及した集合体に望ましい動作をもたらすことができることは明らかです。したがって、ドメイン サービスの必要性がなくなる可能性があります。ユースケースはまだ記事に投票するIPであるため、可能性があると言います。そのため、集約全体で何らかの調整が必要になる場合があるため、ドメイン サービスを導入する必要はありません。

于 2012-08-22T22:29:17.563 に答える