クリーンアーキテクチャの時代
アーキテクチャはフレームワークではなく、ましてやプロジェクトのディレクトリ構造のことではない。
クリーンアーキテクチャの時代
この記事は、Robert C. Martin(Uncle Bob)によって紹介された「Clean Architecture」を題材に、そのようなアーキテクチャが発想された背景や、解決しようとしている課題、そしてプロダクトへの適用可能性について考察するものです。Clean Architectureそのものを解説することを目的とはしていません。
はじめに
アーキテクチャはフレームワークではなく、ましてやプロジェクトのディレクトリ構造を規定するものでもありません。この点は重要で、誤解してしまうと、アーキテクチャを応用したつもりで用途に合わないフレームワークを導入しただけという結果になりかねません。
この記事はなにか具体的なルールを見出そうとするものではありません。ここで触れるアイデアをもとに、プロダクトや私たち自身との相性を考慮しながら、実践的な取り組みを進めていきましょう。
Architectures are not (or should not be) about frameworks. Architectures should not be supplied by frameworks. Frameworks are tools to be used, not architectures to be conformed to. If your architecture is based on frameworks, then it cannot be based on your use cases.
アーキテクチャはフレームワークのようなものではありません(あるいは、そうあるべきではありません)。アーキテクチャはフレームワークによって提供されるべきではありません。フレームワークは使用すべきツールであり、従うべきアーキテクチャと異なります。もしあなたのアーキテクチャがフレームワークに基づいているなら、それはあなたのユースケースに基づいているとは言えません。
Robert C. Martin, 2017, Clean Architecture: A Craftsman's Guide to Software Structure and Design (以降、注記のない引用はこちらの本から)
時代背景を知る
先に引用した本は2017年に出版されましたが、そのアイデアは著者がそれ以前から展開していたものです。この発想の原点を理解するためには、Web2.0という言葉が生まれた2000年代初頭まで遡る必要があります。
2000年代初頭といえば、XPが認知され、アジャイルソフトウェア開発宣言が出版された時期です。開発と保守との境界が消失し、システムの保守というものが永続的なプロセスになり始めた時代です。
それ以前は、システム開発は設計時点での与件に基づいて行われ、保守は技術的な環境変化への適応し稼働を維持することを目的としていました。しかし、2000年以降は、ダイナミックなビジネス環境へ継続的に適応できるかが重要になりました。
つまり、コンピュータシステムがプロダクトとしての性質を持ち始めたのがこの時代です。システムの保守戦略がプロダクトの成長戦略と言い換えられるようになりました。
ご存知の通り、アーキテクチャは開発と保守の両方に関わる重要な課題です。このような時代背景を踏まえながら、Clean Architectureについて見ていきましょう。
2000年以前の話
2000年以前の保守戦略は構造の保全を基本としていました。開発時に設計された「正しい構造」を保守プロセスの中で維持しつつシステムの寿命を延ばすことに重点が置かれていました。さらに問題が発生した場合はパッチで対応し、システムが機能しなくなった場合は全面的な再構築を行うというアプローチでした。
本書ではこの種の「設計の正しさ」を「自信過剰」と表現しています。(劣化したシステムを一から作り直すというアイデアに対し)
Their overconfidence will drive the redesign into the same mess as the original project.
再設計したとて、エンジニアの自信過剰が元のプロジェクトと同様の混乱を再びもたらすでしょう。
2000年以降の話
Clean Architectureのアイデアは、プロダクトの発案、開発、リリース、そして成長という時間軸を意識しています。そのため、「アーキテクチャ」という言葉から受ける印象とは異なり、変化に対応するための柔軟性を備えています。より正確には、安定した部分と柔軟な部分が共存する構造となっています。
時間軸の導入
プロダクトの成長を考え、ビジネス観点で物事を整理するには、現在から未来への時間軸を意識する必要があります。当然ながら、私たちは未来を完全に予測することはできません。
技術的観点から物事を整理する場合、与件に基づき「どのように作るか」という点だけを考えれば十分かもしれません。しかし、ビジネスの観点も必要となれば、「いつ作るか」「作り続けるか」という要素も同時に考慮しなければなりません。
これはプロダクトの成長という中長期的な時間軸においても、2週間のスプリントという短期間のなかでさえも同じことです。
The composition of the components will likely jitter and evolve with time as the focus of the project changes from develop-ability to resuability.
プロジェクトの焦点が開発の容易さから再利用性に移行するにつれて、コンポーネントの構成は時間とともに揺らぎ、進化していく可能性が高いでしょう。
クリーンアーキテクチャ
クリーンアーキテクチャの特徴を示すオニオン図を見てみましょう。この図は、コンポーネントをレイヤーに整理する際、技術的な性質ではなくビジネス上の性質を基準としています。ビジネスにとって本質的で変化しにくい要素ほど内側に、変化しやすい要素やビジネスと無関係な技術的要素ほど外側に配置されています。
引用: https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
ビジネス観点からの変更可能性を基準として構造を整理することで、環境変化に強いシステムが実現されています。プロダクトとしての成長可能性も実現されているといえます。構造は一時的なスナップショットをもって評価できるものではありません。
There is false or accidental duplication. If two apparently duplicated sections of code evolve along different paths — if they change at different rates, and for different reasons — then they are not true duplicates.
偽のあるいは偶然の重複があります。一見重複しているように見える2つのコードセクションが、異なる経路で進化する場合 — 異なる速度で、異なる理由で変更される場合 — それらは真の重複ではありません。
Appendix
ユースケースとは
本書の中でいうユースケースとは、以下の引用の中で言われるシステムの意図を可視化するための方法論であって、何かの実装方法やコンポーネントの種類ではありません。
The most important thing a good architecture can do to support behavior is to clarify and expose that behavior so that the intent of the system is visible at the architectural level.
優れたアーキテクチャが振る舞いをサポートするために最も重要なことは、システムの意図がアーキテクチャレベルで可視化できるように、振る舞いを明示し公開することです。
主観の必要性
振る舞いの局在性(Locality of Behavior)について、それが原則論とコンフリクトする際の対応について、htmxの著者が興味深いことを述べています。
There is no hard and fast rule, but rather subjective tradeoffs that must be made as software developers.
確固たるルールはなく、むしろソフトウェア開発者として主観的なトレードオフの判断をする必要があります。
Carson Gross, https://htmx.org/essays/locality-of-behaviour/
「主観的な」とは、工学的な手法による単純な評価ではなく、プロダクトの特性を総合的に考慮した上での判断が必要だと解釈できます。
技術的コストの変遷
技術的な正しさを判断する基準の一つはコストですが、この判断基準は常に更新していく必要があります。例えば、tailwindcssのドキュメントには興味深い記述があります。コードの重複に対する解決策として、エディタのマルチカーソル編集機能が紹介されています。この種の重複は、以前であればCSSクラスの作成の動機となっていました。
https://tailwindcss.com/docs/styling-with-utility-classes#using-multi-cursor-editing
ツールを活用してコードの局在性を実現する方が、結果的に保守性の高いコードを生み出せる可能性が高いと言えます。特に現在では、AIの活用も可能になっており、このようなコストに関する考え方を見直す必要があります。