この記事は、効果的な骨材設計パートI:単一骨材のモデリングの概要です。
エンティティと値オブジェクトを組み合わせて、一貫性の境界を慎重に検討した集計にするのは簡単に思えるかもしれませんが、すべての戦術的なDDDパターンの中で、集計は最も複雑なものの1つです。
いくつかの一般的な質問から始めると役に立ちます。アグリゲートは、密接に関連するオブジェクトを共通のルート(アグリゲートルート)と組み合わせる方法にすぎませんか?もしそうなら、グラフに含めることができるオブジェクトの数に何らかの制限がありますか?あるアグリゲートが別のアグリゲートを参照できるので、これらのリンクを使用してアグリゲートをナビゲートし、特定のアグリゲートに含まれるオブジェクトのデータを変更することは可能ですか?そして、不変量と一貫性の限界は何ですか?最後の質問への回答は、残りの回答に大きく影響します。
アセンブリを誤ってモデル化する方法はたくさんあります。大きすぎるユニットを設計することができます。一方、結果として真の不変量に違反するように、すべての集計を分割することができます。これから説明するように、このような極端な状況を避け、代わりにビジネスルールに注意を払うことが不可欠です。
ProjectOvationアプリケーション開発
例を挙げて集計を見てみましょう。私たちの架空の会社は、スクラム手法に基づいてプロジェクトをサポートするアプリケーションを開発しています。アプリケーションは、従来のスクラムプロジェクト管理モデルに従います。つまり、製品(製品)、製品所有者(製品所有者)、チーム(チーム)、バックログアイテム(バックログアイテム)、計画リリース(計画リリース)、スプリント(スプリント)。スクラム用語は、ユビキタス言語の出発点を形成します。サブスクリプションを購入するすべての組織は、それ自体をテナントとして登録します。これは、私たちの共通言語の別の用語です。
. , DDD . , , DDD . , . , .
? . , . . :
, .
.
.
.
.
.
. , .
:
« » . , , . :
, .
, .
, .
, .
Product . , Product, BacklogItem, Release, Sprint , . . UML- .
public class Product extends ConcurrencySafeEntity {
private Set<BacklogItem> backlogItems;
private String description;
private String name;
private ProductId productId;
private Set<Release> releases;
private Set<Sprint> sprints;
private TenantId tenantId;
...
}
, - . , . , . , , . () , .
:
, , Product c 1 .
BacklogItem . 2.
Release , , Product 1.
. .
. , . . .
. ? , -. , . , .
:
, 2. . ProductId, Product-.
Product. :
public class Product ... {
...
public void planBacklogItem(
String aSummary, String aCategory,
BacklogItemType aType, StoryPoints aStoryPoints) {
...
}
...
public void scheduleRelease(
String aName, String aDescription,
Date aBegins, Date anEnds) {
...
}
public void scheduleSprint(
String aName, String aGoals,
Date aBegins, Date anEnds) {
...
}
...
}
. Product, , – void. :
public class Product ... {
...
public BacklogItem planBacklogItem(
String aSummary, String aCategory,
BacklogItemType aType, StoryPoints aStoryPoints) {
...
}
public Release scheduleRelease(
String aName, String aDescription,
Date aBegins, Date anEnds) {
...
}
public Sprint scheduleSprint(
String aName, String aGoals,
Date aBegins, Date anEnds) {
...
}
...
}
. . , , :
public class ProductBacklogItemService ... {
...
@Transactional
public void planProductBacklogItem(
String aTenantId, String aProductId,
String aSummary, String aCategory,
String aBacklogItemType, String aStoryPoints) {
Product product =
productRepository.productOfId(
new TenantId(aTenantId),
new ProductId(aProductId));
BacklogItem plannedBacklogItem =
product.planBacklogItem(
aSummary,
aCategory,
BacklogItemType.valueOf(aBacklogItemType),
StoryPoints.valueOf(aStoryPoints));
backlogItemRepository.add(plannedBacklogItem);
}
...
}
, . BacklogItem, Release Sprint .
. , , . , , , - . , , .
, . , .
— -, . . , . . . :
, , = 2 b = 3, 5. , 5, . , , .
AggregateType1 {
int a; int b; int c;
operations...
}
, , , - , . , , . , .
. , , . – , , , , . .
( ) . .
, , , . , . . . , , .
: ? , , . , , , , , . - , .
, , ? , (lazy loading). , . , , . , . , , . , .
, 3. 0..* . . , . . , , . .
. , , .
, , «». , , , . , (root entity), / (object value).
, (, ) ? : , . , Product name description. , . , , . -, .
, , , . , , . , , , . , . . - , .
. , . , . , . Order OrderItem . , - , . , .
, , . . , , , .
, . , - . , . , . , , .
, -, , - , . 4. , , , . . , . , , , -.
, , . , , . ?
, , , , . - (eventual consistency) . , , , . , , . . , .