フォーム読み込み中
ソフトバンクアドベントカレンダー、クリスマス当日の最終日! 25日目の記事です。
皆さんこんにちは。データ基盤戦略本部の牧野 颯太です。私は普段、分散コンピューティング基盤の研究開発プロジェクトにおいて、研究成果を統合するWebアプリケーション/ソフトウェアの開発に携わっています。また、このプロジェクトは、NEDO公募を通じて採択された研究開発テーマの中で実施されています。
さて、本稿は先日公開させていただいた『大規模研究開発PJのSystem Integrationチームに加入して実施した施策 前編』の続編となります。
前編を読んでいただいていない方は、こちらを先に読んでいただくと、より楽しめるかなと思います。
前編では私が所属しているチーム「System Integrationチーム」が抱えている課題と、それに対する施策の1つを紹介させていただきました。
本稿では、課題の対策として実施した、クリーンアーキテクチャを導入について深堀りしていこうと思います。
まずは課題を思い出してみます。
でしたね。
プログラムが一枚岩になっているから、テストが実装し辛い(課題1)し、並行して作業にも入れない(課題2)のでした。
まず、結論からお話しすると、ソフトウェアアーキテクチャとして、クリーンアーキテクチャを導入した結果、開発者はテストを実装しやすくなったし、レイヤーごとに実装にタスクに着手することができるようになってハッピー!という風になりました。
画面の向こうの皆さんがどういうこと?ってなっている気がするので、順を追って説明していこうと思います。
まず、ソフトウェアにおけるアーキテクチャとは何なのか?そして、アーキテクチャにはどんな目的が含まれているのかを考えてみます。
Robert C. Martin氏著の『Clean Architecture 達人に学ぶソフトウェアの構造と設計』という超有名な書籍がありますが、この書籍には次のように記載してありました。
アーキテクチャの主な目的は、システムのライフサイクルをサポートすることである。優れたアーキテクチャがあれば、システムを容易に理解・開発・保守・デプロイできる。最終的な目的は、システムのライフサイクルタイムコストを最小限に抑え、プログラマの生産性を最大にすることである。
そう、アーキテクチャの目的には、保守が含まれているんです。当然の話ではあるのですが、ソフトウェアは作って終わりではありません。商用サービス開発だったら、お客様が使い始めてからが本番です。研究開発PJだってステークホルダーが見ている大事なデモの時に動かないでは困りますよね。
クリーンアーキテクチャを表す超有名な図です。書籍『Clean Architecture 達人に学ぶソフトウェアの構造と設計』を読むと次のような5つのアーキテクチャ/特性を単一の実行可能なアイデアに統合したものがクリーンアーキテクチャであると説明がされていました。
アーキテクチャは特定のフレームワークやライブラリに依存しておらず、ツールとして利用できる。
ビジネスルールは、UI、データベース、ウェブサーバー、その他の外部要素がなくてもテストできる。
UIは、システムの他の部分を変更することなく、簡単に変更できる。
特定のDBに依存せず、他のDBに置き換えることができる。
ビジネスルールは、外部のインターフェースについて何も知らない。
これを見て、気付いた方もいらっしゃるのではないでしょうか。そうです、私が最初にあげていた課題、「テスタビリティが低い」理由はプログラムが一枚岩だったからなのですが、その一枚岩のプログラムには、ビジネスルール、データベース都合、Web都合など多様な都合が含まれており、複雑に絡まってしまっていたのです。
私達が取り組んでいる研究開発PJは、商用サービス開発と比べて新技術/新ソフトウェアの導入のハードルが低いのですが(そこが本質であるとも言える気がします)、裏を返せばより柔軟に変化に対応する必要があるとも言えます。
また、シーズベースの研究開発では想定するビジネスルールも、時々刻々と変化していきます。そういった意味でもビジネスルールとその他の都合がソフトウェア上で疎結合になっていることが重要だと強く感じています。
さて、ここからは実際にクリーンアーキテクチャをどのように実装していったのかをお話ししていきます。
チームメンバーと相談したり、業務委託先からアドバイスをいただいて検討した結果、次のようなディレクトリ構造になりました。
.
├── adapter
│ ├── db
│ │ └── gateway
│ └── web
│ ├── controller
│ └── presenter
├── app
├── cmd
├── config
├── domain
│ ├── entity
│ └── repository
├── infra
│ ├── db
│ └── web
│ ├── middleware
│ └── router
├── pkg
└── usecase
└── interactor
この構造により、以下のメリットが得られました。
テスタビリティの向上:
ドメイン層やユースケース層を他の層から切り離し、依存元の層のIFを実装することで、依存性の注入が可能になり、ユニットテストがしやすくなった。
ドメイン層のテストでは外部のデータベースやAPIに依存する必要がなく、ドメイン層に閉じてテストをすることができるようになった。
作業の並行性の向上:
各レイヤーが独立しているため、複数の開発者が異なるレイヤーに同時に着手できるようになった。
クリーンアーキテクチャを導入することによって、各層をバラバラに扱えるようになったため、チケットの切り方も変化しました。
例えば以下のようにチケットを切ることができます。
チケット-XXX1:各層のIF実装
各層に対して、依存している層のIFを実装をする
チケット-XXX2:usecase層の実装
ドメイン層を利用して具体的なアプリケーションロジックを実装
チケット-XXX3:adapter層の実装
Web/APIコントローラーとリポジトリの実装
チケット-XXX4:domain層の実装
ビジネスロジックのコア部分であるエンティティやサービスを実装
チケット-XXX5:infra層の実装
フレームワークや外部ライブラリに依存する部分の実装
このように切ったチケットと前編で紹介したshort-lived feature branches版のトランクベース開発と組み合わせることで作業並行性の観点で凄まじい威力を発揮します。
ソフトウェアアーキテクチャの導入によるレイヤーの分割とブランチ戦略の導入による効果を組み合わせた結果、以下の効果がありました。
テスタビリティの向上:
一部の層に変更を加えても他の層に影響を与えにくく、回帰テストが楽になった。
効率的な作業分担:
レイヤーごとに責務が明確になり、複数人での開発がスムーズに進行するようになった。
変化に強い設計:
ビジネスルールや外部依存を分離したことで、要件変更や技術変更に柔軟に対応できるようになった。
これにて、ソフトバンクアドベントカレンダーは終幕です!テックブログは続きますので、ぜひ引き続きごらんください。
ここまで読んでいただいた皆様にBigな感謝を!
条件に該当するページがございません