私は、一連のインターフェイスを実装することでユーザーがシステムを拡張できるようにするソフトウェアに取り組んでいます。
私たちが行っていることの実行可能性をテストするために、私の会社は、ユーザーが行うのとまったく同じ方法でこれらのクラスにすべてのビジネス ロジックを実装することにより、「独自のドッグ フードを食べます」。
すべてを結び付け、拡張可能なクラスで定義されたロジックを使用するいくつかのユーティリティ クラス/メソッドがあります。
ユーザー定義関数の結果をキャッシュしたい。どこでこれを行う必要がありますか?
それはクラス自体ですか?これは、多くのコードの重複につながる可能性があるようです。
これらのクラスを使用するのはユーティリティ/エンジンですか? その場合、何も知らされていないユーザーがクラス関数を直接呼び出しても、キャッシュのメリットが得られない可能性があります。
サンプルコード
public interface ILetter { string[] GetAnimalsThatStartWithMe(); }
public class A : ILetter { public string[] GetAnimalsThatStartWithMe()
{
return new [] { "Aardvark", "Ant" };
}
}
public class B : ILetter { public string[] GetAnimalsThatStartWithMe()
{
return new [] { "Baboon", "Banshee" };
}
}
/* ...Left to user to define... */
public class Z : ILetter { public string[] GetAnimalsThatStartWithMe()
{
return new [] { "Zebra" };
}
}
public static class LetterUtility
{
public static string[] GetAnimalsThatStartWithLetter(char letter)
{
if(letter == 'A') return (new A()).GetAnimalsThatStartWithMe();
if(letter == 'B') return (new B()).GetAnimalsThatStartWithMe();
/* ... */
if(letter == 'Z') return (new Z()).GetAnimalsThatStartWithMe();
throw new ApplicationException("Letter " + letter + " not found");
}
}
LetterUtilityはキャッシングを担当する必要がありますか? ILetterの個々のインスタンスはそれぞれ必要ですか? 他に完全にできることはありますか?
この例を短くしようとしているので、これらのサンプル関数はキャッシュを必要としません。しかし、(new C()).GetAnimalsThatStartWithMe()
実行するたびに 10 秒かかるこのクラスを追加することを検討してください。
public class C : ILetter
{
public string[] GetAnimalsThatStartWithMe()
{
Thread.Sleep(10000);
return new [] { "Cat", "Capybara", "Clam" };
}
}
私は、ソフトウェアを可能な限り高速にすることと、維持するコードを減らすこと (この例では結果を にキャッシュすることLetterUtility
) と、まったく同じ作業を何度も行うこと (この例では、 を使用するたびに 10 秒待機すること) の間で戦っていることに気づきましたC
。