サーバー上で常に実行され、サービスバスからメッセージを受信するコンソールアプリケーションをリファクタリングする必要があります。
現時点では、着信メッセージを解析するだけで、プロパティに基づいて、switchステートメントを使用して、さまざまな関数のいずれかを呼び出します(現時点では約70、常に増加します)。問題の1つは、関数が失敗した場合に再試行されないことです。 1つの巨大なswitchステートメントの醜さは言うまでもありません。
これを修正するためにコマンドパターンを使用することに傾いています( https://scottlilly.com/c-design-patterns-the-command-pattern/ )が、pub/subも検討しましたこれらの関数を処理するパターン。
この状況に最適なアーキテクチャパターンは何か知っていますか?
この質問にC#
のタグを付けたので、質問に対する言語固有の回答を提供します。 C#とBCLには、コマンドパターンの組み込みバージョンであるデリゲートの辞書が用意されています。持っているのではなく、例えば:
SomeType Foo(MessageType message)
{
switch (message.Id)
{
case "Id1" : return HandleId1();
case "Id2" : return HandleId2();
...
}
}
あなたはそれを
private readonly Dictionary<string, Func<SomeType>> _handlers =
new Dictionary<string, Func<SomeType>>
{
["Id1"] = HandleId1,
["Id2"] = HandleId2,
...
};
...
SomeType Foo(MessageType message) => _handlers[message.Id]();
サービスバスを既に使用している場合、アプリを多数のアプリに分割し、メッセージキューをタイプごとのキューに分割します。
これにより、アプリは1種類のメッセージのみを処理し、メッセージを個別にスケーリングして、再デプロイせずに新しいタイプを追加できます。
失敗したメッセージを再試行するためにサービスバスエラーキューを使用できます
@David Arnoの答えは私がすることですが、1つだけ違いがあります。デリゲートは使用しませんが、コマンドオブジェクトを使用します。したがって、次のようなものになります。
Dictionary<string, ICommand> _handlers = new Dictionary<string, ICommand>();
どこ
public interface ICommand
{
void Execute();
}
次に、次のようにnullオブジェクトを実装できます。
public NullCommand : ICommand
{
public void Execute()
{
}
}
コードは次のようになります。
ICommand GetCommand(string id)
{
ICommand retVal = null;
if (!_handlers.TryGet(id, out retVal))
{
retVal = new NullCommand();
}
return retVal;
}
これにより、所有権が明確になり、テスト容易性が向上します。