6

免責事項:このプロジェクトで依存性注入を使用し、インターフェイスベースの設計を全面的に緩く結合したいと思いますが、このプロジェクトでは依存性注入の使用が打ち切られました。また、 SOLIDの設計原則(および一般的な設計パターン)は、私が仕事をしている場所では異質なものであり、私自身もそれらの多くに慣れていません。したがって、この問題に対してより良い設計を提案するときは、それを考慮に入れてください。

これは私が取り組んでいるコードの簡略化されたバージョンであり、そのため、それは不自然に見えるかもしれません。もしそうなら、私はお詫び申し上げます。次のクラスを検討してください。

// Foo is a class that wraps underlying functionality from another 
// assembly to create a simplified API. Think of this as a service layer class,
// a facade-like wrapper. It contains a helper class that is specific to
// foo. Other AbstractFoo implementations have their own helpers.

public class Foo : AbstractFoo
{
    private readonly DefaultHelper helper;
    public override DefaultHelper Helper { get { return helper; } }

    public Foo()
    {
        helper = new Helper("custom stuff");
    }

    public override void Operation1(string value)
    {
        Console.WriteLine("Operation1 using " + value);
    }

    public override void Operation2()
    {
        Console.WriteLine("Operation2");
    }
}

// Helper derives from a default implementation and allows us to
// override it's methods to do things specific for the class that 
// holds this helper. Sometimes we use a custom helper, sometimes
// we use the default one.

public class Helper : DefaultHelper 
{
    private readonly string customStuff;

    public Helper(string value)
    {
        customStuff = value;
    }

    public override void DoSomethingHelpful()
    {
        Console.WriteLine("I was helpful using " + customStuff);
    }
}

これらの2つのクラスが次のように使用されているとします。

    // foo referenced and used in one part of code
    var foo = new Foo();
    foo.Operation2(); // or foo.Operation1();

    // some other point in the program where we don't have a reference to foo
    // but do have a reference to the helper
    helper.DoSomethingHelpful();

しかし、私は今、 ?foo.Operation1のいくつかの実装でも実行する必要があることがわかりました。helper.DoSomethingHelpful();私が考えた潜在的な回避策は次のとおりです。

  1. fooとhelperに双方向の関係を持たせます。DoSomethingHelpfulでfoo.Operation2を呼び出すことができるように
  2. fooにIHelpインターフェースを実装させ、「ヘルパー」コードをfooに移動させます
  3. 委任を使用し、メソッドOperation2をAction<string>委任としてHelperのコンストラクターに渡します。

これらのアプローチはどれも理想的ではないようです(オプション1は好きではないと判断しましたが、後でさらに多くのデリゲートを渡す必要があることがわかった場合、オプション3の保守性について心配しています)。Helperこれは、 /Fooコンボの初期設計に問題があるのではないかと思います。考え?

4

4 に答える 4

3

How about a casual ("uses") relationship:

public class Helper : DefaultHelper 
{
    private readonly string customStuff;

    public Helper(string value)
    {
        customStuff = value;
    }

    public override void DoSomethingHelpful(AbstractFoo foo)
    {
        foo.Operation1();
        Console.WriteLine("I was helpful using " + customStuff);         
    }
}

So you modify the abstract helper to expect a reference to the proper Foo implementation.

于 2012-04-04T14:45:23.413 に答える
1

I think you have what you need. Try not to design for the "just in case I need it later" and don't fix what is not broken. If in the future you need to use Operation1 from your helper, then add it as a dependency on the constructor (as you suggested), or just pass it to the method you are calling. It will depend on the scenario, and you will have it when you actually need something.

EDIT: changed the "Try not to design for the future" as it doesn't seem what I want to say.

EDIT again due changes in the question

You could so something like this:

helper.DoSomethingUsefulWith( foo );

so your helper method will receive the dependency it needs in order to work

于 2012-04-04T14:44:50.533 に答える
1

「これらのアプローチはどれも理想的ではないようです(オプション1は好きではないと判断しましたが、後でより多くの代理人を渡す必要があることがわかった場合、オプション3の保守性について心配しています)。これは私に不思議に思います。 Helper/Fooコンボの初期設計に問題がある場合。」

あなたは正確に正しいです-HelperとFooのデザインに問題があります。最初に説明した基本的なFoo/Helperの関係は問題なく、制御できない他のオブジェクトをラップする必要がある場合の一般的なパターンです。しかし、あなたは言う:

「helper.DoSomethingHelpful();の一部の実装でfoo.Operation1も実行する必要があることがわかった場合はどうなりますか?」

ここで問題が発生します。あなたはFooがヘルパーに依存している関係を説明することから始めました。ここで、ヘルパーがFooに依存している関係について説明します。それはすぐにあなたの依存関係が絡み合っていることを私に教えてくれます。オブジェクト間の依存関係は一方向にのみ進む必要があります。実際、依存性注入はこれに依存しています。

于 2012-04-04T14:46:01.093 に答える
1

私はあなたのすべての解決策が良いと思います。それらは異なる機能を提供するだけです。これらの違いは、現在はそれほど重要ではありませんが、将来的には問題になる可能性があります。

あなたは2番目のものを好みます、そしてあなたの本能はここで最高のガイドです、あなたはあなたのコードの将来について私たちの他の人より多くを知っています。クラスがなくなり、シンプルになったという理由だけで、2番目のソリューションが一番好きです。シンプルなため、後で何か他のことをしなければならない場合でも、多くの作業を捨てる必要はありません。

最初のメソッドでは、さまざまなHelper(IHelper?)インスタンスとサブクラスを使用してゲームをプレイできます。最後の方法は、ヘルパーに多くの柔軟性を追加します。(ヘルパーは必要ないほど多く追加される可能性がありますが、渡すメソッドだけです。)どちらかが将来の推測されていない問題の多くを解決するようであれば、後でそれらを使用するように切り替えることができます。

于 2012-04-04T19:03:02.340 に答える