SOLIDは、OOPを本当に理解していると思う人を批判します
©Kuryashkinビクター
私は6年間、SOLIDの原則に精通してきましたが、昨年になってようやく、その意味が理解されました。 この記事では、これらの原則について簡単に説明します。 実装のためのプログラミング言語の最小要件について説明します。 私が理解するのに役立つ資料へのリンクを提供します。
一次資料
ソリッドロバートマーティン(ボブおじさん)の原理を発明した。 当然、彼の作品で彼はこのトピックを扱っています。
本「C#でのアジャイル開発の原則、パターン、および手法」2011。 私が見た記事のほとんどは、この特定の本に基づいています。 残念ながら、原則のあいまいな説明を提供し、その人気を大いに受けました。
ビデオサイトcleancoders.com 。 ボブおじさんは、指で冗談を言って、原則が正確に何を意味し、それをどのように適用するかを説明します。
2017年の本「Clean Architecture」。 SOLID原則に準拠したブリックから構築されたアーキテクチャについて説明します。 構造的でオブジェクト指向の関数型プログラミングを定義します。 私が今まで見た中で最高の固体原理の説明が含まれています。
必要条件
SOLIDは、OOPのコンテキストで常に言及されます。 動的な多型の便利で安全なサポートが登場したのは、OOP言語であったためです。 実際、SOLIDのコンテキストでは、OOPは動的なポリモーフィズムを指します。
ポリモーフィズムにより、 異なるタイプに同じコードを使用できます。
多態性は、動的と静的に大別できます。
- 動的なポリモーフィズムは、抽象クラス、インターフェース、アヒルのタイピング、つまり 実行時にのみ、コードが機能するタイプが明確になります。
- 静的ポリモーフィズムは、主にテンプレート(ジェネリック)に関するものです。 すでにコンパイル段階にある場合、使用される各タイプに固有のコードは、1つのテンプレートコードから生成されます。
Java、C#、Ruby、JavaScriptなどの通常の言語に加えて、動的なポリモーフィズムは、たとえば
- インターフェイスを使用したGolang
- プロトコルとマルチメソッドを使用したClojure
- 他では、「OOP」言語ではない
原則
固い原則は、モジュールの設計方法、すなわち アプリケーションの構築元のレンガ。 原則の目的は、次のことを行うモジュールを設計することです。
- 変化に貢献する
- 分かりやすい
- 再利用可能
SRP:単一の責任原則
モジュールは、1つのアクターのみに責任を持つ必要があります。
古い表現: モジュールには、変更する理由が1つだけ必要です。
多くの場合、次のように解釈されました。 モジュールには1つの義務のみが必要です。 そして、これは原則を知る上での主な誤りです。 すべてが少しトリッキーです。
各プロジェクトで、人々は異なる役割(役者)を演じます:アナリスト、インターフェイスデザイナー、データベース管理者。 当然、一人が一度に複数の役割を果たすことができます。 この原則では、たった1つの役割がモジュールの変更を要求できるという事実について話しています。 たとえば、特定のビジネスロジックを実装するモジュールがあり、アナリストのみがこのモジュールの変更をリクエストできますが、DBAやUXはリクエストできません。
OCP:オープンクローズドプリンシプル
ソフトウェアアーティファクトは、拡張のために開かれ、修正のために閉じられる必要があります。
古い表現: クラスの動作を変更せずに拡張できるはずです。
これは間違いなくst迷につながる可能性があります。 クラスを変更せずに動作を拡張するにはどうすればよいですか? 現在の定式化では、Robert Martinはアーティファクトの概念を使用しています。 jar、dll、gem、npmパッケージ。 動作を拡張するには、動的多態性を使用する必要があります。
たとえば、アプリケーションは通知を送信する必要があります。 依存関係の反転を使用すると、モジュールは通知インターフェイスのみを宣言し、実装は宣言しません。 したがって、アプリケーションのロジックは1つのdllファイルに含まれており、インターフェイスを実装する通知を送信するクラスは別のファイルにあります。 したがって、ロジックを使用してモジュールを変更(再コンパイル)することなく、さまざまな方法で通知を送信できます。
この原則はLSPとDIPに密接に関連しており、これらについては後で検討します。
LSP:リスコフ代替原理
置換可能な複雑な数学的定義があります。ベース型を使用する関数は、ベース型のサブタイプを知らなくても使用できる必要があります 。
違反の典型的な例。 次のインターフェイスを実装する基本クラスStackがあります:length、push、pop。 また、追加されるアイテムを複製するDoubleStackの子孫があります。 当然、DoubleStackクラスはStackの代わりに使用できません。
この原則には面白い結果があります。 エンティティをモデル化するオブジェクトは、これらのエンティティの関係を実装する必要はありません 。 たとえば、整数と実数があり、整数は実数のサブセットです。 ただし、doubleは、カマキリと指数の2つの整数で構成されます。 intがdoubleから継承された場合、面白い画像が取得されます。親には2人の子が含まれています。
Generics. , Shape
Circle
Rectangle
. Foo(List<Shape> list)
. , List<Circle>
List<Shape>
. , . , , list
, rectangle
. list
Circle
.
ISP: The Interface Segregation Principle
Make fine grained interfaces that are client specific.
Java, C# . .
DIP: The Dependency Inversion Principle
Depend on abstractions, not on concretions.
- . .
- . .
? ? , . /, . .. , BD, , . , - — .
? , .. import, require .. runtime .
Logic, , . ISender, Logic. , ConcreteSender, ISender. , Logic ConcreteSender. runtime, , Logic ConcreteSender.
“ , ?”.
. , , , Postgresql, — ElasticSearch. . , , , .. , . , . , , , , .
SOLID , , — Agile Manifesto.
SOLID .
SOLID .