5 に答える
コードの重複とは、ブロック、ステートメント、または一般的なメンバー宣言のグループ化の重要な繰り返しを指します。言語のキーワード、識別子、パターンなどの繰り返しについては言及していません。そうでなければ、ポリモーフィズムを実現することはできません。
提供する例は、特定のクラスの動作を変更せずに拡張する方法を示していないため、実際にはオープン/クローズの原則を示していません。オープン/クローズの原則は、バリアントの動作が必要になるたびに新しいクラスを作成することです。これは、テンプレートメソッドパターンとともに継承を使用して実現できます(つまり、サブクラスでオーバーライドされて目的の/新しい動作を実現する基本クラスの抽象メソッドまたは仮想メソッドを呼び出す)が、ストラテジーパターンを使用した合成を使用してより頻繁に示されます(つまり、バリアントの動作をクラスにカプセル化し、それを閉じた型に渡して、達成された全体的な動作を決定するために使用します)。
あなたの例から、継承を通じてOCPを達成しようとする方針に沿って考えていたようですが、ベースレポートフォーマッターから始めて、サブタイプとのインターフェイスを確立し、特定のレポートのさまざまなタイプのフォーマットを示すことは、実際には良いスタートです。構成を通してOCPを示しています。構成ベースのアプローチでOCPを実証するために必要なのは、フォーマッターを消費するクラスです...ReportWriterと言います。
public class ReportWriter : IReportWriter
{
Write(IReportData data, IReportFormatter reportFormatter)
{
// ...
var formattedStream = reportFormatter.Format(data, stream);
// ...
}
}
デモンストレーションのために、新しいフォーマッタがどのように動作するかについていくつかの仮定を立てたので、その部分に過度に焦点を当てないでください。注目すべきことは、ReportWriterは、新しいフォーマッターを渡すことを許可することで拡張可能であり、レポートの最終的な作成方法に影響を与えますが、この新しい動作を実現するために必要なコードの変更(つまり、ifステートメントの存在、切り替え)のために閉じられることです。複数のフォーマット方法を実現するためのステートメントなど)。
オープン/クローズの原則はコードの重複を引き起こさないだけでなく、継承よりも合成を使用して達成された場合、実際には重複を減らすのに役立ちます。継承階層または戦略クラスを作成する過程で真のコード重複が発生した場合、それは、OCPを達成しようとしているコンテキストに存在する可能性があるという事実とは関係のない因数分解の問題を示しています。
このようなものが機能するはずです。
namespace SOLIDPrinciples
{
public class ReportFormatter {
public virtual void FormatReport() = 0;
}
public class VariableSizeReportFormatter : ReportFormatter {
public void SetSize(String size);
public override void FormatReport() {
Console.WriteLine("implement generic layout routines");
}
}
public class TabloidReportFormatter : VariableSizeReportFormatter {
public override void FormatReport() {
// currently, we just do a tweaked version of generic layout ..
SetSize("11x7");
Super.Format();
Console.WriteLine("RemoveThatColumnWeDontWant");
}
}
}
つまり、次のことを意味します。
- ReportFormatterのクライアントを変更する必要はありません(セットアップを処理する他のメカニズムを想定しています)。
- ジェネリックフォーマット機能の改善を追加して、すべてのレポートを改善できるため、重複したコードがなくなります
- 特定の場合にうまく機能するために必要なものは、その変更を加えるだけです。
重要なのは3番目のポイントです。「原則として、スマートレイアウトルーチンは、コメントによって行が大きすぎて収まらない場合は、日付から年を削除することを知っている必要があります」と言うことができます。しかし、実際にその変更を実装することは悪夢になる可能性があります。それが他のレポートが間違って表示されることを意味する場合は、すべてがどのように機能するかのロジックを変更してから、システム内のすべてのレポートレイアウトを再テストする必要があります...