クリーンアーキテクチャを読んでSOLIDの原則についてまとめました。
目次
SOLID原則
SOLID原則は、関数やデータ構造をどのようにクラスに組み込むのか、そしてクラスの相互接続をどのようにするのかといったことを教えてくれます。SOLID原則の目的は以下のような声質を持つ中間レベルのソフトウェア構造を作ることです。
- 変更に強いこと
- 理解しやすいこと
- コンポーネントの基盤として多くのソフトウェアシステムで利用できること
単一責任の原則(SRP: Single Responsibility Principle)
本書では単一責任の原則に違反しているEmployeeクラスの例からその必要性と解決策を提示していました。
給与システムにおけるEmployeeクラスがあり、calculatePay()、reportHours()、save()の3つのメソッドがあります。
それぞれのメソッドは以下の責務を負っています。
- calculatePay():経理部門が規定する。報告先はCFO
- reportHours():人事部門が規定して使用する。報告先はCOO
- save():データベースを管理者が規定する。報告先はCTO
これらのメソッドをひとつのEmployeeクラスに入れると、開発者は全てのアクターを結合することになり、CFOのチームの何らかの操作が、COOチームの使うものに影響を及ぼしてしまうことになります。例えばCFOチームのみが算出方法に手を加える場合が発生した時に、CFOチーム以外の算出方法も変更されてしまい問題が起きます。
解決策
一番わかりやすい解決法として、データを関数から切り離すやり方があります。この場合だと3つのクラスに分けそこからEmployeeDataクラスを使うようにします。EmployeeDataクラスはシンプルなデータ構造のみを保持し、メソッドは含みません。
この方法の弱点として開発者が3つのクラスをインスタンス化して、追跡しなければいけなくなることです。この弱点を解消するのが以下のFacadeパターンです。
EmployeeFacadeクラスは実行したいメソッドを持つクラスのインスタンを生成して処理を委譲するだけのシンプルな構造です。これにより複数をそれぞれインスタンス化して追跡する必要がなくなりなります。
オープン・クローズドの原則(OCP: Open-Closed Principle)
オープン・クローズドの原則は、ソフトウェアの振る舞いは既存の成果物を変更せず拡張できるようにすべきという考え方です。
変更の影響を受けずにシステムを拡張する目的を達成するために、システムをコンポーネントに分割して、コンポーネントの依存関係を階層構造にすることです。そして、上位レベルのコンポーネントが下位レベルのコンポーネントの変更の影響を受けないようにします。
リスコフの置換原則(LSP: Liskov Substitution Principle)
Licenseクラスを例にリスコフの置換原則をみてみます。
LicenseクラスにはcalcFee()メソッドがあり、Billingアプリケーションから呼ばれています。またLicenseの派生型であるPersonalLicenseとBusinessLicenseがあります。これらはそれぞれ異なるアルゴリズムを用いてライセンス料を計算します。
このBillingアプリケーションは2つの派生型に依存していないため、リスコフの置換原則を満たしているといえます。どちらの派生型もLicense型に置き換えることができます。
インターフェイス分類の原則(ISP: Interface Segregation Principle)
インターフェイス分類の原則では必要としないお荷物を抱えたものに依存していると、予期せぬトラブルの元になることがあります。
本書ではシステムSを担当するアーキテクトが、あるフレームワークFをシステムに導入した場合の例として紹介しています。このフレームワークFの作者は、フレームワークを特定のデータベースDのためだけに作っており、SはFに依存しており、さらにFはDに依存していることになります。
FはDの全ての機能を使っているわけはなく、その使っていない部分が変更されてもFは再度不必要なデプロイをすることになります。さらにDの一部の機能に障害が発生すると、それがFやSの障害の原因になってしまう可能性もあります。
依存関係逆転の原則(DIP: Dependency Inversion Principle)
依存関係逆転の原則は、上位レベルの方針の実装コードは下位レベルの詳細の実装コードに依存すべきではなく、逆に詳細側が方針に依存すべきであるという原則です。
ただ依存関係逆転の原則を考える時にはOSやプラットフォーム周りは気にしないことが多いです。変化しないとみなして、こうした具象への依存は許容することにしています。
依存したくないのは、システム内の変化しやすい具象要素です。開発中のモジュールや頻繁に変更され続けているモジュールがその対象になります。