web-dev-qa-db-ja.com

Djangoおよびドメイン駆動設計

ドメイン駆動設計アプローチについて混乱しています。ネット上の情報源から、それはあなたのDomain ObjectsおよびDatabase Objectsしかし、2つの違いを理解できません。

例として、DjangoチュートリアルのPollsの例 code を見てみましょう。2つのモデルPollsChoiceがあります。

これらは domain level objectsまたはdatabase level objects

ORMでDDDが必要ですか?

はいの場合、ORMでDDDアプローチを使用する必要がある良い状況を提供できますか

たとえば、これはモデルです

class Polls(models.Model):
    question = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

私が人々が書いているDDDアプローチコード

class PollService(object):
    def __init__(self, poll_repository):
        self.poll_respository = poll_respository

    def update(self, poll_id):
        poll = self.poll_respository.fetch_by_id(poll_id)
        poll.question += '?'
        self.poll_respository.update(poll)

#assume that the following code works?
class PollRepository():

    def __init__(self, db):
        self.db = db

    def update(self, poll):
        try:
            self.db.session().add(poll)
            self.db.session.commit()
        except Exception:
            self.db.session.rollback()

これは正しいアプローチですか?ここには冗長なコードがたくさんありますが、Pollsはドメインレベルのオブジェクトであり、データベースと直接通信すべきではないと人々は言っていますか?

DDDには常にDDDレポジトリが付属していますか? ORMがあるのにDDDリポジトリが必要な理由

別のアプローチ

views.py
def update_poll(poll_id):
    poll = models.Polls.objects.get(poll_id)
    poll.question += '?'
    poll.save()

このアプローチの何が問題になっていますか?

16
Anubhav Agarwal

アクティブレコードパターン

Djangoは、この Django Design Philosophy ページで説明されている Active Record Pattern の使用に合わせて調整されています。

2番目の例はこのパターンに従います-モデル自体には、そのプロパティ、動作、およびデータアクセスが含まれています。

さらに多くの動作をモデルにプッシュすると、このパターンをよりDDDのような方法で使用できます。例えばあなたの例では、パターンをより効果的に使用するには、行を折り返すことになります

poll.question += '?'

pollオブジェクトの意図を明らかにするメソッドで、update_pollメソッドは:

views.py
def update_poll(poll_id):
    poll = models.Polls.objects.get(poll_id)
    poll.add_question()
    poll.save()

これには、ビジネスロジック(モデルにプッシュされる)をアプリケーションフローロジック(update_poll 方法)

ただし、add_questionだけではなく、メソッドの意図または目的を実際に示す名前を使用することをお勧めします。

ただし、これを行っても、純粋なDDDではなく、アクティブレコードパターンを使用しています。

「ORMでDDDが必要ですか?」

DDDとORMは異なる問題を解決しようとしています。 ORMは、よりオブジェクト指向の方法でデータベースのセットのようなレコード指向の世界を抽象化する便利な方法を提供します。

DDDは、コードで複雑な現実世界の状況をモデル化するのに役立つアプローチです。

多くのDDDシステムはORMを使用して、データベースからの取得および永続化のインフラストラクチャの問題を解決します(さまざまな理由でORMをリポジトリにラップする場合があります)が、DDDの焦点はドメインモデルと、検討中のドメインの適切なモデル化にあります。

したがって、あなたの例では、ビジネスロジックが比較的単純であるため、DDDの利点を確認することは困難です。

アプローチの言語にとらわれない概要と、それが価値を追加する状況については、DDDの信頼できるソースを読むことをお勧めします ドメイン駆動設計by Eric Evans

更新

あなたが尋ねる:

ORMでDDDを使用することが理にかなっている1つの良い例を教えてください

そして

ORMを使用する場合、DDDリポジトリは必要ないと思います

ORMを使用する場合、ORMはリポジトリリポジトリです。モデルを要求すると、モデルが返されます。それがリポジトリの目的です。人々がそれを「リポジトリ」と呼ばれるクラスにラップするとき、それは通常、彼らがいくつかのことの一つをしたいからです。

  1. ユニットテストを簡素化するためにモックリポジトリを注入することを簡単にします
  2. 特定のormテクノロジーを抽象化し、サービスやドメインに手を加える必要なく、後でORMを変更する柔軟性を提供する

この リポジトリパターンの概要 は、dddリポジトリパターンの別の優れた説明を提供します。

17
Chris Simon

ポールハレットは、すべてを彼の美しく完全な記事にまとめました: https://phalt.github.io/post/Django-api-domains

そして、ここの例: https://github.com/phalt/Django-api-domains

簡単に言えば:

Djangoのスタイルガイドは古い

チュートリアルから完全なドキュメントまでのドキュメントは、DjangoがHTMLをレンダリングしてWebブラウザーに配信するモデルビューコントローラーの世界について話します。

これについて何かが奇妙なことに私を驚かせました-私は2012年以来Djangoで作業しており、それを使用してHTMLを一度だけレンダリングすることを覚えています。 Djangoでの私の時間のほとんどすべて、およびDjangoが会議で話題になっているのを見てきましたが、常にAPIを提供することでした(通常、Django REST Framework )フロントエンドプロジェクトに。これが、今日のDjangoの事実上の標準であると私は主張します。ドキュメントは現在人気のあるユースケースでは古くなっています。これは一般的にDjangoで見られる傾向です。プロジェクトは、実行方法および非同期の適切な処理方法を最新化しようとしています。そろそろDjangoが開発者にも提案するデザインパターンを再考する時がきたのではないでしょうか。

私の差し迫った問題に戻ります。チームがソフトウェアをより適切に整理できるように、私はコミュニティから優れたスタイルガイドを見つけることに着手しました。 Domain Driven Resign、境界付きコンテキストの利点について読んだところ、使用しようとしたHacksoftの素敵なスタイルガイドを見つけました。これは素晴らしかったです!ここのドキュメントは非常に健全で、小規模なプロジェクトや小規模な企業に最適です。

しかし、それを使った実験中に、いくつかの理由で目的に適さないことがわかりました。つまり、ビジネスロジックがモデルに生きることを奨励されているという事実です。 Djangoもこれを推奨しており、基本的にはアクティブなレコードパターンです。非常に大規模なチームでの経験では、ビジネスロジックをモデルに関連付けたままにしておくと、開発者はmodels.pyを大量のコードで埋めることができます。これにより、開発者が同時に1つのファイルで作業することが非常に困難になります。単一のファイルがドメイン内の複数の問題(プレゼンテーション、データ、コントローラーなど)を所有する場合、他のすべての問題もファイルに吸い込まれる傾向があることは言うまでもありません。

8
adilnaimi

DDDおよびDjangoに関するいくつかの例が必要な場合、これは https://dry-python.org/static/slides/ddd-toolkit-2.html スライドを使用してdry pythonツールが役立つかもしれません。

また、サンプルプロジェクトを確認してください https://github.com/dry-python/tutorials/tree/master/Django/example

1
auvipy