設計原則に関する考察

これらの設計パターン、原則、および手法をすべて発明するのはなぜですか? これがなければ簡単にできて、開発者に良いデザインを教えるだけではないでしょうか? または、このプロセスを形式化し、あるソリューションが別のソリューションよりも明らかに優れているという明確な定量的指標を導入してみませんか?



適切な設計は、若い開発者と若いマネージャーの聖杯です。 彼らは両方とも、 人生、宇宙、およびすべてのそのようなソフトウェア開発の主要な質問に対する答えを見つけることを夢見ています-高品質の設計を短時間で、最小限の労力で達成する方法。



時間が経つにつれて、若い開発者と若いマネージャーの両方が、これが不可能であることを理解するようになります。 「理想的」と「抽象的」という言葉が互いに矛盾しているため、完璧な抽象的なデザインを見つけることは不可能です。 設計とは、パフォーマンスと可読性、シンプルさと拡張性、テストの容易性とソリューションの整合性など、相反する要件間の妥協を常に追求することです。





開発者が常に正しい問題を解決し、風車と戦わないことを考慮しても、どの設計特性がここで重要であるかを「抽象的に」言うことは不可能です。



コードまたは設計の品質を記述する正式な基準があります:メソッドの循環的な複雑さ、継承階層の深さ、クラスまたはモジュールの着信接続と発信接続の数、メソッドの行数、最悪の場合。 これらの定量的指標は有用ですが、それらを所定の境界内に収めることは必要ですが、優れた設計には十分な条件ではありません。 クラスが適切に分割されておらず、サブジェクト領域の重要な抽象化が明らかにされていない場合、デザインがどのような量的特性を持っているとしても、決して良くなることはありません。



正式な基準に加えて、優れた設計という普遍的な概念があります-低結合と高凝集。 これらのプロパティは便利ですが、非公式すぎます。



正式な基準と非公式な基準の間には、 設計原則があります。これは、経験豊富な設計者が依存する一連のルールです。 彼らの目標:設計における「良い点と悪い点」を簡単な言葉で説明すること:「理想的なクラスは、変更の理由を1つだけ( SRP )、最小限のインターフェース( ISP )を持ち、継承( LSP )を正しく実装し、要件を変更すると、カスケードコードが変更されます( OCP )。



Bertrand Meyerの著書「アジャイル!:善、誇大広告、Theい」では、設計原則とは何かについて十分に明確な定義を示しています[Meyer2014]:



「原則とは、ソフトウェア開発の一般的な見解を表現する方法論的なルールです。 良い原則は、 抽象的であり、改ざん可能です。 抽象性は原則を慣行と区別しますが、反証性は原則を公平性と区別します。 抽象とは、原則が特定の慣行ではなく普遍的な規則を記述するべきであることを意味します。 反証可能性とは、合理的な人が原則に同意できないことを意味します。 彼らの正しい心の誰もが提案された原則に異議を唱えないなら、このルールは有用ですが、興味深いものではありません。 ルールが原則であるためには、あなたの意見に関係なく、反対の見方をしている人々がいると仮定する必要があります。



設計レベル







開発者は、プロとしてのキャリアを通じて、設計原則などのツールを所有するいくつかの段階を経ます。



最初の段階では、若い開発者はまだ抽象的な原則に達していないが、代わりに、高品質のソリューションを取得できるようにする一連の具体的なプラクティスを探しています。 「一連のステップ、明確なフォローを聞きたいので、望みどおりの結果が得られます!」 この段階では、開発者は他の人のソリューションをコピーするのが得意であり、説明が抽象的すぎるか、自分のケースに絶対にふさわしくない場合は深刻な問題に直面します。



第2段階では、開発者は特定のプラクティスの基礎にあるもの、および設計原則が必要なものを確認し始めます。 「ええ、このクラスはベースに移動し、ビジネスロジックが含まれているため、SRPに違反しています。 彼には変更の2つの明確な理由があることがわかりました!」



レベルが増加したにもかかわらず、原則またはパターンの最も頻繁な使用が不適切であるのはこの段階です。 特定のクラスがこの原則に違反していることを証明するのは簡単ですが、開発のこの段階では、この違反がいつ正当化されるのか、いつ正当化されないのかは必ずしも明らかではありません。



第3段階では、開発者(またはアーキテクト)に才能があり、特定の設計原則が解決するように設計されている問題をかなり明確に理解します。 その定義により原則は明確であるため、経験豊富な開発者は、いつ違反が正当化されるか、いつ違反するか、いつ設計修正を行うかを理解しています。



この段階では、原則はアプリケーションの設計を制御するのではなく、コミュニケーションの役割を果たすようになります。「クラスがやりすぎです。つまり、SRPに違反しています! このクラスには2種類のクライアントがあり、ISPに違反しています!」





武道では、スキルの3つの段階を区別するのが習慣です:syu、ha、およびri( Shu、Ha、Ri )。 最初のステップは、マスターの動きのみを繰り返す学生です。 第二段階では、生徒は規則から自由になり始め、いつ従うべきか、従わないかを決め始めます。 3番目の段階では、ルールは消え、学生はマスターになり、これらのルールを自分で作成できます。 同じモデルですが、ソースがわずかに異なりますが、アメリカ文化ではDreyfus Modelと呼ばれています。



設計原則の役割



設計原則の適用には価格があります。 SRPに応答するようにクラスを小さなコンポーネントに分割すると、ロジックが複数のクラスに分散し(凝集度が低い)、パフォーマンスが低下する場合があります。



オープンクローズド原則の違反は、下位互換性の問題によって正当化される場合があります。 継承は常にサブタイプの関係を決定するとは限らないため、Liskの置換原理は無視できます。 後方互換性または使いやすさのために、インターフェイスが厚くなる場合があります。 また、依存関係の反転はカプセル化を簡単に損ない、完全な脳のOOPにつながる可能性があります。



原則を効果的に使用するには、彼らが実際に解決する問題と、それが今あなたに関係があるかどうかを知る必要があります。 通常、原則の関連性は、複雑さが増すか、変更のコストが増加するにつれて増加します。 アプリケーションの中核となるビジネスロジックは、他の世界から分離すべきものの一例です。 一般にアクセス可能なクラスには、外部との接続を最小限に抑え、簡単なことを簡単に許可する必要があります。 モジュールのジャンクションにあるクラスは、他のクラスよりもよく考えてください。



優れた設計を実現し、設計原則を有効に活用するための鍵は、反復的な設計アプローチです。 初期の段階では、サブジェクト領域についてほとんど理解していないため、モジュールを役割に分割するだけです。インフラストラクチャを個別に、ロジックを個別に。 同時に、クラスとモジュールの関係の数は厳密に制限されているため、クラスの自律性と副作用の最小化により設計が容易になります。



アプリケーションが開発されると、デザインは不要なパッチで大きくなりすぎ、主題領域の理解が向上します。 大規模なリファクタリングを避け、開発中にデザインを変更しようとしています。 変更を加える前に、質問に答えようとします。なぜこれを行うのですか? 現在のソリューションが特定の設計原則に違反しているということだけである場合、変更を行う前に、本当に問題があるかどうかを理解する必要があります。



長い目で見た私の変化の主な原動力は、複雑さが増したことです。 頭の中で決定を維持できないとすぐに、それをナビゲートするのが難しいか、どこで変更を加えるかが明確ではないので、それを改善する方法を考える時が来ました。



「クラスが複雑すぎて、 SRPに違反しているので、2つに分割します。 継承階層に関する情報はモジュール全体に広がっており、おそらくファクトリの背後に隠す価値があります。 隠れた依存関係が豊富にあるため、クラスをテストすることはできませ 。今度は、クラスの依存関係を強調します。



同時に、原則やパターンが過剰設計の世界に私を導いたかどうかを常にチェックしています。変更を加えた後、設計は容易になりましたか? 本当に存在しない問題を解決していますか? 私は時期尚早の一般化のネットワークに入りませんでしたか? 問題の合理的な解決策を見つける前に、いくつかの反復を実行する必要がある場合があります。



設計原理





設計原則の人気は、あなたとあなたのチームを簡単に欺きます。 原則とパターンへの過度の愛は、過剰なエンジニアリングと過度の複雑さとして現れます。 しかし、これを知っていれば、アプリケーションコードに原則の過度の愛がどのように現れるかを準備し、予測することができます。



Anti - SRP-あいまいな 責任の原則 。 クラスは多くの小さなクラスに分割され、その結果、ロジックは複数のクラス/モジュールに分散されます。



OCP防止 -工場工場の原則 。 設計は一般化されており、拡張可能であるため、抽象化のレベルが多すぎます。



Anti - LCP- 理解できない継承の原則。 原則は、地元のチーフアーキテクトの経験と見解に応じて、過剰な量の継承または完全な不在のいずれかで現れます。



ISP -1000のインターフェイスの原則。 クラスインターフェイスは非常に多くのコンポーネントに分割されているため、すべてのクライアントで使用するには不便です。



Anti-DIP-意識の反転またはDI脳 の原理 インターフェイスは各クラスに割り当てられ、バンドルはコンストラクターを介して渡されます。 ロジックがどこにあるかを理解することはほとんど不可能になっています。



All Articles