クリーンアーキテクチャとドメイン駆動設計の関係性を整理してみる

組み合わせると高い保守性が実現できる

読み終えるまでの目安: 15分

目次

はじめに

この記事では、クリーンアーキテクチャとドメイン駆動設計 (DDD) の関係性について、私なりの考えをまとめる

結論から言うと、これら 2つは相互に補間し合う関係だと感じた

私はこの記事の執筆中、まさにソフトウェア設計に関する悩みを抱えており、それを解決したくてこれらを学んでいる
まだ実践できるほどのレベルには達していないものの、当初のモヤモヤはかなり解消しつつある

この 2つの考え方を学んだことで、“ソフトウェア設計” の要素を分解して考えることができるようになった
設計を考えるための視点が増えたり、より細部まで見えるようになったり…

つまり、ソフトウェア設計に関して、よりよい問いを立てられるようになったと思う

⚠️ なお、注意事項がいくつかあるため、先に示しておく

  • この記事ではクリーンアーキテクチャと DDDの詳細までは説明しない
    あくまで私なりに重要だと思った要素をかいつまんで紹介するに留める
  • 私はまだこれら 2つを勉強している最中なので、誤った記述や曖昧な表現などがあるかもしれない

私の主観だが、この 2つのテーマに関しては、常にマサカリが飛び交っていそうな印象がある…
言及するのには少し勇気がいるが、私がスッキリできる程度にアウトプットしておく

対象読者

以下のいずれかに当てはまる人

  • ソフトウェア設計について学びたいが、どうアプローチすればいいのかわからない人
  • 実装の途中で「あれ、この処理どこに書くのがいいんだろう…」と悩むことがある人
  • クリーンアーキテクチャもドメイン駆動設計も聞いたことがあるが、よく知らないという人

設計の悩み

私がどういうモチベーションでこれらを学んだのかを整理しておく

以前の開発合宿をきっかけに、久々にプライベートでプロダクトを開発していた
それなりにアクティブにコードを書いており、日進月歩で実装も進んでいた

普通はこういうとき、プロダクトはどんどん地に足がついていくものなのだろう
しかし、私の場合は日に日に不安が大きくなっていった

「設計、これでいいのかな…?」

ソフトウェア開発とは、問題解決そのものをソフトウェアで表現することだと思うのだが、脳内に「もっと最適な表現 (== 設計) があるのではないか」というモヤモヤがずっとあった
設計に対し、「なんかうまくできないな、わからないな」というぼんやりとした苦手意識があり、それを晴らしたい

そこで、有名な設計手法・プラクティスであるクリーンアーキテクチャと DDDにヒントを求めてみた

よい設計とは

一般的に、よい設計とは変更が容易なものだとされる
そういったものはよく “保守性が高い” とかいわれたりする

それに加えて、理解が容易であることも重要だといわれることがある
私はそれに共感していて、自分の作るソフトウェアもそうしていきたい

ここで取り上げるクリーンアーキテクチャも DDDも、こういった保守性を追求した結果として生まれたものだと思う

クリーンアーキテクチャの概要

基本的な考え方

クリーンアーキテクチャの考え方には、一貫して主張し続けている原則がある

それは、

  1. 抽象と具体を分ける
  2. 抽象が具体に依存しないようにする

ということである

ここでの “抽象” とは、そのソフトウェアが従う普遍のルールである
X/Twitterでいうと、ユーザやポスト/ツイートという概念はこれにあたる

“具体” とは、それをどのような技術で実現するかという実装の詳細である
GUIの実装に何を使うかとか、DBに何を使うかとか…

これらが守られていれば、たとえば使う DBを変えたいとき、具体のほうだけを変更すればいい
また、抽象から開発を始めれば、たとえばどんな HTTPクライアントを使うかといった詳細の決定を先送りにできる

原則を実現するためのアーキテクチャ

さて、先述の原則を実現するために、ボブおじさんこと Robert C. Martin氏が提唱したのがこの “クリーンアーキテクチャ” である

出典: https://nrslib.com/clean-architecture-old/

Enterprise Business Rules

円の中心のレイヤで、最も抽象度の高いもの
ここで定義されるものはエンティティとよばれる
X/Twitterでいうと、ユーザやポスト/ツイートなどのクラスはエンティティとなる

そして外側にいくほど具体、つまり実装の詳細を扱う要素となる

Application Business Rules

中心より一歩外側へいったレイヤで、ユースケースを実装する
つまり、エンティティを組み合わせて問題解決のロジックを書くところ
フォローしているユーザのリストを出すとか、検索してヒットしたポスト/ツイートのリストを出すとか、そういった一連の流れが当てはまる

Interface Adapters

ユースケースからひとつ外側にいったところ
DBとのやりとりをしたり、UIのために情報を成形したりといった処理を担う

Frameworks & Drivers

最も外側のレイヤ
DBそのものとか入出力の UIとかが当てはまる

依存の方向は外側から内側にと決まっている

原則の 2つめは「抽象が具体に依存しないようにする」であった
図の矢印が依存の方向を示している

具体のほうが抽象に従い、抽象のほうは具体の存在を意識しない・知らないという状態にする
循環参照も NG

これによって変更の影響を最小に抑える

以上がクリーンアーキテクチャの概要だ

悩みの解像度が上がる

クリーンアーキテクチャの原著を読み、全体像がわかったことで、私の悩みは部分的に解決された

  • 「どれだけ普遍か」という基準で明確にレイヤを分ける
  • そのうえで依存の方向を統一する

これで保守性の高い構成にできるという点は納得できる

しかし、「スッキリした!今すぐリアーキテクトするぞ!」とはならなかった
まだ全ての不安が解消されたわけではなかった
というか、これを学んでようやく自身の抱えていた悩みをはっきり認知することができた

クリーンアーキテクチャは「プログラムをクリーンに組み上げる」ための方法論だった
たしかにこれも求めていた情報ではあったが、実は他にも知りたいことがあった

それは「問題をシンプルに解決する」ための考え方
クリーンに作るよりも先に、「その問題をうまく捉えられているか、解決策としてシンプルになっているか」を不安に感じていた

そうして、今まで “ソフトウェア設計” と一括りにしていたものを分解して捉えられるようになった 💡

ソフトウェア設計は

  1. 問題とその解決策をうまくモデリングする
  2. プログラムとしてきれいに構造化する

という 2つのプロセスに分けて考えるとよさそうだ
書いてはみたものの、こうして見ると当たり前のことだなあ… 👀

改めて、今は 1を満たすための情報が欲しい
そこで、次は DDDを学ぶことにした

ドメイン駆動設計

ドメイン駆動設計 (DDD) は、専門知識をしっかり取り入れて、ソフトウェアを問題にフィットさせていく設計手法である
Eric Evans氏によって提唱された

それまであるあるだった「仕様書がおりてきて、ただそれを満たすだけのプログラムを作る」という開発スタイルでは度々手戻りが発生していた
そこで、「もっとそのドメイン (専門領域) に寄り添わなきゃダメだよね」という思想のもと考案されたようだ

ドメインを知り、そこから設計を始める
だからドメイン駆動設計と名付けられたのだろう

モデル

DDDでは “モデル” とよばれるものを用いて問題を表現する

モデルとは、問題解決のために物事の特定の側面を抽象化したもの
「これを表現するために必要な本質ってなんだろう?」を考えて、含める要素を取捨選択するという活動の成果物
取捨選択というのは、たとえば社員のモデルを表すとき、名前は必要だけど出生時の体重は必要ない、みたいな

モデルは一度決めて終わりというわけではなく、継続的に改善するもの
実装をしていくうえでドメインへの理解が深まり、より優れたモデリングができるようになる
(継続的に安心して変更できるように CI/CDを取り入れることが推奨されているらしい)

ドメインはハイコンテクスト

モデルは専門知識を煮詰めてできるものなので、当然ハイコンテクストで理解が難しいものとなる
さらに、そういったモデルの周辺には複雑な業務ロジックも付随してくる

なので、このドメイン知識 (モデルとロジック) をソフトウェア全体に散りばめてしまうと、以下のような弊害が予想される

  • 認知負荷が上がって可読性が下がる
  • 全体の記述量が多くなる

だから分ける

どうやらドメイン知識を点在させると嫌な感じがするというのがわかった

ならば、「ドメイン知識をひとまとめにして、他の処理とレイヤを分けよう」という発想になる
これで、ドメインがいくら複雑でも全体として何をやっているかはわかりやすくなる

おや、”処理のレイヤを分ける” といえば…? 🤔

そう、クリーンアーキテクチャも抽象と具体でレイヤを分けていた

パーツが組み上がる感覚

ここでクリーンアーキテクチャと DDDが繋がる

俯瞰すると、DDDは問題と解決策をうまくモデリングするための考え方
一方でクリーンアーキテクチャは、処理を明確にレイヤで区分し、保守性の高いプログラムにするための考え方だった

これらは親和性が高く、共存し得るもの
お互いに補間し合う関係にあった

こうして関係性が見えてきたことで、

  • ソフトウェア設計を分解して考えることができるようになった
  • それぞれのプロセスでどのようにアプローチすればいいか、どんな手法を活用すればいいかがわかってきた

といった成長を実感している

なお、クリーンアーキテクチャの他にも、処理を明確にレイヤで区分するアーキテクチャは存在する
ここでいくつか名前だけ紹介しておく

  • レイヤードアーキテクチャ
  • オニオンアーキテクチャ
  • ヘキサゴナルアーキテクチャ (ポート&アダプターアーキテクチャ)

最後に

今回解説した 2つの考え方について、それぞれまだ 1冊ずつしか読めていない
他の本でも学ばないといけないと思うし、オブジェクト指向の基礎ももっと身につける必要があると感じている

ちなみに、今回読んだ本は以下の通りだ

勉強をすればするほど自分の無知を知り、勉強したいことが増えていく…
OOCに参加したりもして、また積読も増えた

ドメイン駆動設計の前にオブジェクト指向からかな…
道は遠いなあ笑

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください