私は、依存関係注入を使用しているときに、自分のインタフェースと具象クラスとの間に1対1の関係があることを認めています。インターフェイスにメソッドを追加する必要があるとき、私はインターフェイスを実装するすべてのクラスを壊してしまいます。インタフェースまたはクラスによる依存注入
これは簡単な例ですが、自分のクラスの1つにを注入する必要があるとしましょう。
public interface ILogger
{
void Info(string message);
}
public class Logger : ILogger
{
public void Info(string message) { }
}
このような1対1の関係を持つことは、コードの匂いのように感じます。クラスを作成し、単一のクラスだけのインターフェイスを作成するのではなく、テストでオーバーライドするためにInfo
メソッドを仮想としてマークすると、1つの実装しかないので、潜在的な問題はありますか?これらの各クラスが漏れやすい抽象化を作成することになり、特定のプロパティやメソッドを持っている場合は
public class SqlLogger : Logger
{
public override void Info(string message)
{
// Log to SQL
}
}
が、私はベースを抽出することができます:私は別の実装を必要と
public class Logger
{
public virtual void Info(string message)
{
// Log to file
}
}
場合、私はInfo
メソッドをオーバーライドすることができますクラス:
public class Logger
{
public virtual void Info(string message)
{
throw new NotImplementedException();
}
}
public class SqlLogger : Logger
{
public override void Info(string message) { }
}
public class FileLogger : Logger
{
public override void Info(string message) { }
}
私が今まで別のメソッドを追加したい場合は、私はexisを破るないので、私は抽象として基本クラスをマークしなかった理由は、実装例です。たとえば、FileLogger
にDebug
メソッドが必要な場合は、既存のSqlLogger
を破損することなく、ベースクラスLogger
を更新できます。
また、これは簡単な例ですが、私はインターフェイスを好むべきですか?
_私が抽象クラスとして基底クラスをマークしなかったのは、別のメソッド_Hmを追加したければ抽象クラスに実装を含めることができるからです。 Debugメソッドを抽象Loggerクラスに追加することができます。 –
既存の実装を破ることは、再利用可能なライブラリを作成する場合にのみ問題になります。あなたですか?あるいは単にビジネスアプリケーションのラインを書いていますか? – Steven
それは問題の範囲ではありませんが、継承は過大評価されています。 'SqlLogger'は' SqlLogPersistenceStrategy'を使った具体的な 'Logger'です。ほとんどの場合、コンポジションは継承よりもはるかに優れています。あなたの問題についても、ISPはどうですか? 'ILogInfo'、' ILogError'など – plalx