Open9

Domain-Driven Design with Golang読書メモ

ta.toshiota.toshio

1 A Brief History of Domain-Driven Design

Three pillars of DDD

Ubiquitous language

Strategic design

Tactical design

Adoption of DDD

When should you use DDD?

scorecardを例示

Further reading

Design a DDD-oriented microservice by Microsoft (2022); available at https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/ddd-oriented-microservice

Find Your Business Domains to Start Refactoring Monolithic Applications by Amazon Web Services (AWS) (2022); available at https://aws.amazon.com/blogs/mt/find-your-business-domains-to-start-refactoring-monolithic-applications/

Apply Domain-Driven Design to microservices architecture by IBM; available at https://www.ibm.com/garage/method/practices/code/domain-driven-design/

ta.toshiota.toshio

2 Understanding Domains, Ubiquitous Language, and Bounded Contexts

Setting the scene

Domains and sub-domains

もうひとつの考え方は、ビジネスの世界だ。ドメイン駆動設計という言葉を読むたびに、ビジネス問題駆動設計と読み替えることができるだろう。

Ubiquitous language

Benefits of ubiquitous language

Bounded contexts

Open Host Service

https://github.com/PacktPublishing/Domain-Driven-Design-with-GoLang/blob/main/chapter2/open_host.go

Anti-corruption layer

https://github.com/PacktPublishing/Domain-Driven-Design-with-GoLang/blob/main/chapter2/anti_corruption.go

ta.toshiota.toshio

3 Entities, Value Objects, and Aggregates

cover the following topics

What is an entity, and how should I use it?
What are some common pitfalls when designing entities, and how can I avoid them?
What is a value object, and how should I use it?
What is the aggregate pattern, and how should I use it?
How do I discover aggregates?

Working with entities

へー

import "github.com/Rhymond/go-money"
// We use a specific money library as floats are not good ways to represent money.
...
   startingPrice money.Money

Generating good identifiers

A warning when defining entities

Anemic models

A note on object-relational mapping

Working with value objects

不変性と副作用のない関数の原則に従うことで、私たちはバリュー・オブジェクトを推論しやすくし、ユニットテストを書きやすくした。複数の異なる入力と予測可能な出力で、非常にシンプルなテストを書くことができる。これは、システムの長期的なメンテナンスに役立つだろう。

How should I decide whether to use an entity or value object?

このオブジェクトを不変のものとして扱うことは可能か?
そのオブジェクトはドメイン概念を測定、数値化、記述するものですか?
その値によって、同じ型の他のオブジェクトと比較できますか?

これらの質問に対する答えがすべてイエスなら、バリュー・オブジェクトはあなたのユースケースに適しているでしょう。

The aggregate pattern

aggregateの例として、注文、チーム、walletを紹介していた

Discovering aggregates

Designing aggregates

Aggregates beyond a single bounded context

ta.toshiota.toshio

4 Exploring Factories, Repositories, and Services

  • The factory pattern – we will discuss what it is and when it is useful
  • The repository pattern – we will walk through some examples to help you understand how they differ from database tables
  • Services – we will look at domain services, application services, and infrastructure services and the difference between them all

Introducing the factory pattern

Entity factories

エンティティ ファクトリ関数を設計する場合、ファクトリ関数に構造体の ID を生成させるか、または ID をパラメータとして渡すかを決定する必要があります。どちらの方法でもかまいませんが、よほどの理由がない限り、ファクトリ関数にIDを生成させることをお勧めします。

Implementing the repository pattern in Golang

リポジトリレイヤーで陥りがちな間違いの1つに、データベーステーブルごとに1つの構造体を作成するというものがあります。これは避けるべきです。代わりに、集約ごとに1つの構造体を作成するようにします。次の図に、その概要を示します

Understanding services

Domain services

before
https://github.com/PacktPublishing/Domain-Driven-Design-with-GoLang/blob/main/chapter4/domain_service_before.go

after

https://github.com/PacktPublishing/Domain-Driven-Design-with-GoLang/blob/main/chapter4/domain_service_after.go

Having this logic in a single-domain service means that if other clients want to implement our behavior, they can use our service, and our business invariants will be automatically enforced.

Domain services are perfect for when we need to compose domain logic in a stateless manner.

stateless -> infrastracture層を使うものはstateful?

Application services

⭐⭐

アプリケーション・サービスは、他のサービスやリポジトリを構成するために使用される。アプリケーションサービスは、様々なモデルの間で行われるトランザクション保証を管理する役割を担う。アプリケーション・サービスにはドメイン・ロジックを含めるべきではありません(これは前のセクションで説明したように、ドメイン・サービスに属します)。

通常、アプリケーション・サービスは非常に薄い。アプリケーション・サービスは調整のためだけに使われ、他のロジックはすべてアプリケーション・レイヤーの下のレイヤーに押し込まれる。通常、セキュリティ上の懸念もこのレイヤーで扱う。

https://github.com/PacktPublishing/Domain-Driven-Design-with-GoLang/blob/main/chapter4/booking_application_service.go

ta.toshiota.toshio

5 Applying Domain-Driven Design to a Monolithic Application

What a monolithic application is, as well as in what situation you may want to build one
How to build an entire domain-driven monolith from scratch
How to identify that your existing application might benefit from applying domain-driven design

https://github.com/PacktPublishing/Domain-Driven-Design-with-GoLang/tree/main/chapter5

What do we mean when we say monolithic application?

Setting the scene

Getting started with our CoffeeCo system

Implementing our product repository

https://github.com/PacktPublishing/Domain-Driven-Design-with-GoLang/blob/main/chapter5/internal/purchase/purchase.go

このようにするのは、購入アグリゲートを Mongo の実装から切り離すためです。他のすべてのドメインモデルもデータベースモデルから切り離す必要があります

Adding an infrastructure service for payment handling

Paying with CoffeeBux

Adding store-specific discounts

ta.toshiota.toshio

6 Building a Microservice Using DDD

Learn what a microservice is, and how it differs from a monolithic application
Learn at a high level when you and your company may benefit from considering a microservice-based architecture
Build another service from scratch, using the ports and adaptor pattern, as well as the anti-corruption layer pattern

https://github.com/PacktPublishing/Domain-Driven-Design-with-GoLang/tree/main/chapter6

What do we mean by microservices?

What are the benefits of microservices?

What are the downsides of microservices?

Should my company adopt microservices?

Setting the scene (again)

Building a recommendation system

Next, we are going to define an interface for the partnerships system:

type Option struct {
   HotelName     string
   Location      string
   PricePerNight money.Money
}
type AvailabilityGetter interface {
   GetAvailability(ctx context.Context, tripStart time.Time, tripEnd time.Time, location string) ([]Option, error)
}

ここで、私たちがインターフェイスとパートナーシップの実装をまったく結びつけていないことに注目してほしい。私たちは、境界のあるコンテキストからドメイン言語を使い、合理的で賢明なインターフェースとは何かを定義した。これは長い目で見れば、新しいパートナーシップ・システムへの移行をより簡単にするために大いに役立つだろう。

Revisiting the anti-corruption layer

https://github.com/PacktPublishing/Domain-Driven-Design-with-GoLang/blob/main/chapter6/recommendation/internal/recommendation/adapter.go

Exposing our service via an open host service

ta.toshiota.toshio

7 DDD for Distributed Systems

What do we mean by a distributed system?
What are CQRS and EDA?
What is event sourcing?
What is a message bus?
How can we best deal with failure?

What is a distributed system?

CAP
Consistency, Availability, Partition tolerance

一貫性:すべての読み取りが最新の情報を受け取るか、エラーになる。
可用性:すべてのリクエストはエラーでないレスポンスを受け取るが、最新の情報を受け取れない可能性がある。
パーティション耐性: ネットワーク上の問題(パケットの廃棄など)が発生しても、システムは稼動し続ける。ここで障害が発生した場合、システム設計者は次のどちらかを選択しなければならない

  • オペレーションをキャンセルし、可用性を低下させるが、一貫性を確保する。
  • 操作を続行することで、可用性は確保できるが、一貫性が失われるリスクがある。

CAP theorem and databases

Distributed system patterns

CQRS

EDA

Dealing with failure

Two-phase commit (2PC)

準備段階:各サブシステムに、私たちが完了させたい仕事量をこなせるかどうかを確認する。
完了フェーズ:各サブシステムに、先ほど約束した作業を行うように指示する。

The saga pattern

What is a message bus?

Kafka

RabbitMQ

NATS

ta.toshiota.toshio

8 TDD, BDD, and DDD

https://github.com/PacktPublishing/Domain-Driven-Design-with-GoLang/tree/main/chapter8

Discuss and give examples of TDD and BDD using Go
Talk about how TDD and BDD can be used alongside DDD to make your systems more resilient and maintainable

TDD

Run the test we just wrote – it should fail (and we should expect it to)

Write as little code as possible to pass the test

Refactoring

https://github.com/PacktPublishing/Domain-Driven-Design-with-GoLang/blob/main/chapter8/cookies_test.go

BDD