最近の就職の面接で、私は [〜#〜] solid [〜#〜] -についての質問に答えることができませんでした。それは本当に私を悩ませます。私は2、3日分の調査を行いましたが、まだ満足のいく要約を作成していません。
インタビューの質問は:
SOLID原則に厳密に従っていると私が言った.Netプロジェクトを見るとしたら、プロジェクトとコード構造の観点から何を期待できますか?
私は少し悩みましたが、実際には質問に答えず、爆撃しました。
この質問にどのように対処できたでしょうか?
S =単一責任の原則
したがって、よく整理されたフォルダ/ファイル構造とオブジェクト階層が表示されると思います。機能の各クラス/部分は、その機能が非常に明白であることを示す必要があり、そのタスクを実行するロジックのみを含む必要があります。
数千行のコードを含む巨大なマネージャークラスを見た場合、それは単一の責任が守られていなかったことを示しています。
O =開閉原理
これは基本的に、既存の機能への影響を最小限に抑える、または変更を必要としない新しいクラスを通じて新しい機能を追加するという考えです。
オブジェクトの継承、サブタイピング、インターフェース、抽象クラスを多く使用して、機能の設計と実際の実装を分離し、他のバージョンに影響を与えずに他のバージョンを一緒に実装できるようになると思います元の。
L =リスコフ置換原理
これは、サブタイプを親タイプとして扱う機能に関係しています。適切に継承されたオブジェクト階層を実装している場合、これはC#のボックスから出てきます。
一般的なオブジェクトをベースタイプとして扱い、サブタイプ自体をインスタンス化して操作するのではなく、ベース/抽象クラスでメソッドを呼び出すコードが見られると思います。
I =インターフェース分離の原則
これはSRPに似ています。基本的に、機能のより小さなサブセットをインターフェースとして定義し、それらを使用してシステムを分離したままにします(たとえば、FileManager
はファイルI/Oを処理する単一の責任を持つかもしれませんが、特定のメソッド定義を含むIFileReader
およびIFileWriter
を実装できますファイルの読み取りおよび書き込み用)。
D =依存関係の逆転の原則
再び、これはシステムを分離した状態に保つことに関係しています。おそらく、Unity
やNinject
などのソリューション、またはAutoFacServiceLocator
などのServiceLocatorシステムで使用されている.NET Dependency Injectionライブラリの使用に目を光らせているでしょう。
多くの小さなクラスと、依存性注入を伴うインターフェースがいたるところにあります。おそらく大きなプロジェクトでは、IoCフレームワークを使用して、これらすべての小さなオブジェクトのライフタイムを構築および管理するのに役立つでしょう。 https://stackoverflow.com/questions/21288/which-net-dependency-injection-frameworks-are-worth-looking-into を参照してください
SOLIDの原則に厳密に従っている大きな.NETプロジェクトは、必ずしもすべての人と協力するのに優れたコードベースを意味するわけではありません。インタビュアーが誰であるかによっては、 SOLIDの意味を理解し、かつ/または独断的に設計原則に従っていることを確認すること。
確かに、あなたがしっかりしているためには、あなたは従う必要があります:
[〜#〜] s [〜#〜]責任の原則が1つであるため、1つのことだけを行う小さなクラスが多数あります。
[〜#〜] o [〜#〜]ペンで閉じた原理。これは通常、.NETでは依存関係の注入で実装され、Iも必要ですと下のD ...
[〜#〜] l [〜#〜]iskovの置換の原則は、c#でワンライナーで説明することはおそらく不可能です。幸いにも、それに対処する他の質問があります。 https://stackoverflow.com/questions/4428725/can-you-explain-liskov-substitution-principle-with-a-good-c-sharp-example
[〜#〜] i [〜#〜]インターフェース分離原理は、オープン/クローズの原理と連携して機能します。文字通り従うのであれば、少数の「大きな」インターフェースではなく、多数の非常に小さなインターフェースを優先することを意味します。
[〜#〜] d [〜#〜]依存関係の反転の原則高レベルのクラスは低レベルのクラスに依存してはならず、どちらも抽象化に依存している必要があります。
私が日々の仕事でSOLIDを支持しているショップのコードベースに見られると期待するいくつかの基本的なこと:
多くのアダプターパターンと複合パターン-ある目的のために開発された依存関係のプラグインをわずかに合理化するために、多くのアダプターパターン(別のインターフェイスの機能に「パススルー」することによって1つのインターフェイスを実装するクラス)の使用を期待しますその機能性も必要とされるさまざまな場所。使用するファイル名を指定する手段を公開するようにインターフェイスを更新すると、コンソールロガーをファイルロガーに置き換えるだけの簡単な更新で、LSP/ISP/DIPに違反します。代わりに、ファイルロガークラスは追加のメンバーを公開し、アダプターは新しいものを非表示にすることでファイルロガーをコンソールロガーのように見せるため、これらすべてをスナップするオブジェクトだけが違いを知る必要があります。
同様に、クラスが既存のものと同様のインターフェースの依存関係を追加する必要がある場合、オブジェクト(OCP)の変更を回避するために、通常の答えは複合/戦略パターン(依存関係インターフェースを実装し、他の複数のクラスを消費するクラス)を実装することですそのインターフェースの実装。さまざまな量のロジックを使用して、クラスが1つ、一部、またはすべての実装に呼び出しを渡すことができます)。
SOLIDの「O」が「役に立たず、よく理解されていない」という Jon Skeetの議論 でそれらをそらし、Alistair Cockburnの「保護されたバリエーション」とJoshについて話してもらいます。 Blochの「継承のための設計、またはそれを禁止する」。
スキートの記事の短い要約(元のブログ投稿を読まないで彼の名前を落とすことはお勧めしませんが!):
OPは、「この質問にどのように対処できたでしょうか?」面接を行うシニアエンジニアとして、私は箇条書きのリストからガタガタできる人よりも、さまざまなコードデザインスタイルの長所と短所についてインテリジェントに話すことができる候補者に計り知れないほど興味があります。
別の良い答えは、「まあ、それは彼らがそれをどれだけよく理解しているかに依存します。もし彼らが知っているすべてがSOLID流行語である場合、継承の乱用、依存性注入の乱用を期待しますフレームワーク、100万の小さなインターフェース。いずれも製品管理との通信に使用されるドメイン語彙を反映していません...」
これには、さまざまな時間で答えることができる方法がいくつかあるでしょう。しかし、これは「SOLIDの意味を知っていますか?」」の方に沿っていると思います。したがって、この質問に答えることは、ポイントに到達し、プロジェクトに関してそれを説明することになるでしょう。
したがって、次のように表示されます。
これは素晴らしい質問ですが、面接は難しい質問だと思います。
SOLIDの原則は、クラスとインターフェース、およびそれらの相互関係を実際に管理します。
この質問は、実際にはfilesに関連するものであり、必ずしもクラスではありません。
簡単な観察または私が与える答えは、一般に、インターフェースのみを保持するファイルが表示されることであり、多くの場合、慣習として、それらは大文字のIで始まるということです。さらに、ファイルにはコード(特にモジュール、アプリケーション、またはライブラリ内)が重複しておらず、そのコードはモジュール、アプリケーション、またはライブラリ間の特定の境界を越えて慎重に共有されます。
Robert Martinは、このトピックについて Designing Objected Oriented C++ Applications using the Booch Method のC++の領域で説明しています(上のセクションを参照)凝集性、閉鎖性、再利用性)および Clean Code 。