web-dev-qa-db-ja.com

代わりに、上記のコンテキストで脆弱なマッピングコードを作成せずに、多くの異なるコンテキストを内部化する巨大な列挙型を処理する方法は?

Ticket_Caseという属性があり、実際のさまざまなユースケースをモデル化する定義済みの値(引数のために、たとえば1から20)があるとします。それらはチケット自体の属性です。

システムの別のコンテキストでは、チケットのケースに基づいて別のメッセージを生成する必要があります。これらの特定のメッセージは、この1つの場所でのみ使用され、他では使用されません。

実用的なソリューションは、ケースをメッセージにマップする巨大なスイッチ/ケース関数を作成することです。実用的ではありませんが、エラーが発生しにくいソリューションは、何らかの方法でメッセージをTicket_Caseオブジェクトに直接添付することです。わかりました。 2つの異なるコンテキストを少し混乱させていますが、それで問題ありません。

しかし、ここでコンテキストの数が増えていると仮定します。それぞれに類似性はあまりないため、コードを再利用することはできません。我々はcouldそれらをすべて特定のTicket_Caseオブジェクトにグループ化しますが、それはそのオブジェクトに多くの責任を負わせます。しかし、他の選択肢は、Ticket_Caseを対応するオブジェクトに変換するために、すべてのコンテキスト境界での巨大なスイッチ/ケースメソッドです。これだけでも、新しいチケットケースが導入された場合、見逃しがちな多くの問題を解決できます。

だから私の質問は、システムのさまざまな場所で正しくても異なる用途を持つこれらの「巨大な列挙型」を、内部で制御できなくなったり、壊れやすいマッピングコードを作成したりせずに処理するための許容できる方法は何ですか?

1
Joe

2次元のメッセージテーブルの概念を導入できます。ここで、次元はユースケース番号であり、コンテキスト番号のようなものです。この「テーブル」は1つのオブジェクトを持つヘルパークラスにすぎず、オブジェクトは起動時に一度初期化できます(または、簡単だと思えば内部で巨大なスイッチケースを使用して実装できますが、これは単なる実装です)詳細)。

次に、パブリックメソッドgetMessage(ContextId id)Ticket_Caseチケットのユースケース番号とコンテキストパラメータに応じて正しいメッセージを返すクラス。このメソッドは、メッセージテーブルのファサードとして機能します。

これはTicket_Caseまるでそれが外部からのメッセージを担当しているかのように見えますが、内部では責任は2つのクラスに分割されています。

4
Doc Brown

ドキュメントの回答に似ていますが、テーブルの代わりに辞書を使用します

TicketCaseMessager : IMessageGenerator
{
    private Dictionary<string,string> messageMap;

    public string GetMessage(Ticket t)
    {
         return messageMap[t.Case] ?? "Unknown Case";
    }    
}

これにより、OOP=の方法でマッピングを切り替えて、必要に応じてテーブルを回避することができます。

ユニットテストを追加して、すべてのTicketCaseが確実に処理されるようにすることができます。

2
Ewan

今回の回答は追加的であるようです。ドキュメントまたはユアンスの回答の拡張として、すべてのチケットケースとすべてのコンテキストを通過するユニットテストを追加し、メッセージがデフォルトの不明なメッセージ(「不明なケース」またはnullなど)の場合は失敗します。 )。

このようにして、誤って除外されていないものがないことを確認します。

1
mtj

DocとEwanの答えの代わりに、各コンテキストで異なるオブジェクトを使用し、そのオブジェクトにそのコンテキストに適切な機能を持たせることができます。

オブジェクトは、持っているデータではなく、どのような動作をするかによって定義されるべきではありません。つまり、あるコンテキストでTicketCaseの動作が別のコンテキストと異なる場合、同じdataを参照していても、それらは2つの異なるオブジェクトです。

1