列挙に特別な値「ALL」を含めることは良い習慣ですか?


11

私はマイクロサービス環境で新しいサービスを開発しています。これはRESTサービスです。簡単にするために、パスが/ historyBooksであるとしましょう

そして、このパスのPOSTメソッドは、新しい履歴ブックを作成します。

歴史書が歴史の1つ以上の時代をカバーしていると仮定しましょう。

簡潔にするために、人間の歴史の次の時代しかないと仮定しましょう。

  • 古代
  • ポストクラシック
  • モダン

私のコードでは、それらをで表現したいと思いenumます。

メソッドの本体(ペイロード)はJSON形式であり、フィールド名を含める必要がありますeras。このフィールドは、eraこの本で扱う値のリストです。

本体は次のようになります。

{
  "name": "From the cave to Einstein - a brief history review",
  "author": "Foo Bar",
  "eras": ["Ancient", "Post Classical", "Modern"]
}

この特定のサービスでは、ビジネスロジックは次のとおりです。
入力に時代が指定されていない場合、この本はすべての時代を網羅していると見なされます。

APIレビューでは、すべての時代が網羅されていることを明示的に示すために、時代の列挙に
別の値を含めることを提案しましたALL

長所と短所があると思います。

長所:

明示的な入力

短所:

リスト内の2つの項目が提供されている場合、と言うALLAncient-アプリケーションから取得されますでしょうか?これでALL他の値が上書きされるはずですが、それは新しいビジネスロジックです。

特定の時代を対象とする書籍のクエリを実行する場合、すべての時代を対象とする書籍をどのように表現しますか?場合ALLも(同じロジックを使用して)出力に使用され、それが解釈する消費者の責任だALLとは["Ancient", "Post Classical", "Modern"]

私の質問

新しいALLものを持つことは、まったく持たないことよりも混乱を引き起こすと思います。

どう思いますか?このALL値を追加しますか、それなしでAPIを保持しますか?


7
原子時代を追加したいと決めた場合はどうなりますか?「すべて」の時代をカバーする本は魔法のように新しいコンテンツを取得しますか?本の内容について嘘をつき始めますか?すべてを更新しますか?いくつかの本がすでに原子時代についてのコンテンツをすでに持っている場合、それは重要なことです。
8ビットツリー

回答:


13

呼び出し元アプリケーションで使用可能な紀元が使用可能かどうかによって異なります。おそらく、それらはユーザーが興味のあるものを選択できるようにするためのものです。その場合、「すべて」オプションを提供するのはフロントエンドの問題です。私なら、「すべて」オプションではなく、すべての時代のリストを送信することになります。そうでない場合は、「ALL」オプションが必要であり、フロントエンドが理解できない時代から物事を取り戻すリスクを実行します。

あなたが指摘するように、他のオプションを使用したALLは、競合する要求を取得できることを意味します。さらに考慮すべき点は、「ALL」を渡すと、他のすべての列挙型が包含ではなく除外になることです。それはある種の理にかなっていますが、明らかにUIは複雑すぎるだけかもしれません。

TL; DR; ほとんどの場合、「すべて」はUIの優れた点であり、サービスレベルで同じことをあいまいさなく達成できるため、実行しないでください。


6

入力に時代が指定されていない場合、この本はすべての時代を網羅していると見なされます。

これと、特別な「すべて」のケースがあることは悪いことです。可能な場合、APIは明示的にする必要があります。「何も実際にはすべてを意味しない」などの特別なケースがあるということは、APIを使用する人もすべての特別なケースを知っている必要があることを意味します。

特殊なケースは、ユーザー入力が有効かどうかの検証、およびリクエストの適切な処理の両方の点で、より複雑なコードにつながることもよくあります。


1

カテゴリ変数については、同じレベルにワイルドカード「すべて」を入れないようにします。

期間には2レベルの検索条件があるようです。

  1. ブール値、is_selective?
  2. セット、特定のカテゴリの分離

呼び出し元は、(false、無視)または(true、{'ancient'、 'modern'})を指定できます。

または、空のセットをワイルドカードとして解釈することもできます。これは、非選択を示します。

特定のケースでは、いくつかの有名な値に離散化された連続変数年があり、実際に必要なのは区間演算を行うことです。したがって、クエリは(開始、終了)範囲の年を受け入れ、enumはそのような属性を便利に提供できます。


1

tl; dr
実装のローカルデータ構造に関する実際の質問について、私はあなたの結論に同意します。すべての時代の特別な値は避けてください。ただし、特にエンドユーザーUIとシリアル化されたペイロードデータは異なる場合があります。

ローカルデータ構造

これを型システムの観点から見てみましょう。基本的に列挙型は、@ JHによる回答ですでに指摘されているように、特定のカテゴリ(列挙子)の分離したセットを定義する型です。列挙型の変数は、これらのカテゴリの1つを正確に保持します。列挙子の値のコレクションを表現する場合は、2番目のタイプが必要です。

// C++-inspired pseudo-code
enum Era { ancient, post_classical, modern };
using Eras = Collection<Era>;

all列挙子は、それが一緒にこれらの2種類のマッシュのでノー行くではありません。これは単一のカテゴリではなく、可能なすべてのカテゴリのコレクションです。

厳密に実用的なレベルでは、あらゆる種類の特別な値を扱うと実装が複雑になり、エラーが発生する可能性が高くなります。どこでも特別なケースにするか、実際の意味に合わせてアンパックする必要があるからです。ああ、すべての可能な列挙子の明示的なコレクションについてはどうでしょう。これをいつどこで特別なall値にまとめる必要がありますか?それはまったく崩壊すべきですか?

私が好むアーキテクチャは、コード内のすべての時代を表現しないことです。これにはall列挙子が含まれますが、すべての時代を意味する空のコレクションも含まれます。それはまったく同じ特別な場合で、異なる変装をしています。

リストに2つの項目が提供されている場合、ALLとAncientを言います-アプリケーションから何を取得しますか?[...]

API仕様では、すべての時代マーカーを常に単独で表示する必要があることを指定します。なぜなら、その上に何かを置くことは意味をなさないからです。次に、これを契約違反として拒否します。しかし、それはすべての時代が実装とビジネスロジックの両方を複雑にする方法の良い例です。

主な問題は、特別な値とその背後にある意味との間の変換規則を指定しなければならないことです。そして、あなたとAPIを使用する他のすべての人は、これらのルールを正しく実装する必要があります。私の皮肉屋は誰かがそれを間違えるかどうかの問題ではなく、単にいつなのかを教えてくれます。

シリアル化されたデータ(JSON)

もともと、私はここで"eras"リスト全体に対する読み取り専用クエリとさまざまな役割の変更についてのセクション全体を持っていました。しかし、最終的には、KISSのために削除しました。列挙/コレクションのルールはJSONデータにとって不合理ではないため、物事の一貫性を保つことが最も簡単なソリューションです。

エンドユーザー向けのUI

とにかくUIと基になるデータ構造の間にデータ変換が存在することを想定しています。これはおそらく、何らかのMVC風のアーキテクチャを使用しているためです。そのため、ユーザーにとって最も便利で直感的なものを使用してください。で彼の答え@Markusは、曜日ごとに異なる選択オプションを持つ偉大な例を挙げました。


1

新しいALLを使用すると、まったく使用しないよりも混乱が生じると思います。

はい。

コレクションの観点から考えると、何かのコレクションがあります。そして、そのコレクションのサブセットのみが必要なときはいつでも、要素がこのサブセットの要素と見なされるとき、何らかのフィルター条件を提供する必要があります。そして、ALL何のフィルタが適用されない場合、ない、場合である「filterconditionがありますALL

入力に時代が指定されていない場合、この本はすべての時代を網羅していると見なされます。

私はそれを逆さまにします:この本は特定の時代をカバーしません

これは、クエリの観点からも一貫しています。

紀元が選択されていない場合、すべての書籍が返されます(これには、紀元フィールドが空の書籍も含まれます)。時代が選択されると、選択された時代の書籍のみが返されます。特別な時代のすべての書籍と一般的な書籍を取得することは、どういうわけか予想外のことです。

ALL-カテゴリを追加する唯一のポイントは、ユーザーの利便性のためです。これは、「すべて」ではなく「何も」が選択されていると、よりイライラする可能性があるためです。


0

最近、基本的なスケジューラを実装しました。@ LoztInSpaceで既に述べたように、そのほとんどはUIシュガーです。

ユーザーインターフェースは、オプションの1つを選択するときにユーザーが何を達成するかを完全に明確にする必要があります。

私の場合、選択する平日があります。「すべて」に加えて、「営業日」と「週末」をオプションとして追加しました。各オプションを選択すると、後で使用できるようになります。含める必要のない日は手動で選択解除する必要があります。

技術的には、ユーザーが「平日」を選択した場合、UIには5つのチェックボックスがオンになり、列挙型は「稼働日」の値を使用します。チェックボックスのいずれかにチェックマークが付いていない場合、「就業日」の値は残りの4日間のビットマップに置き換えられます。

オプションの一部を使用してすべてを含めると同時に、何かを除外して競合を回避し、UIがユーザーにとって意味のあるものであることを確認しないでください。

ユーザーが「すべて」に含まれる概念(週のすべての日)を簡単に把握できる場合、または重要ではない場合(Amazonのすべてのカテゴリを検索する場合)


0

ALL列挙を明示的に保持するというアイデアが好きですが、フラグとして設定したいです

const enum = {
    ALL: { value: 0 },
    ANCIENT: { name: 'Ancient', value: 1 },
    POST_CLASSICAL: { name: 'Post Classical', value: 2 },
    MODERN: { name: 'Modern', value: 4 }
}

flagonなどのライブラリを使用するか、すべての値が選択されたときにビット単位の操作で手動で再生する場合は、代わりにALLを使用します。

列挙型の値は常に前の値の2倍でなければならないことに注意してください。また、健全性チェックのために列挙型を削除しないでください。列挙型を無効にして、無効になっているものをすべての一部として常にカウントするようにコードを調整できます。

代わりにNONEフラグがあり、後でビジネスが変更された場合に備えて、NONEが使用されたときにクライアントが何をすべきかをクライアントに決定させます。

この実装が採用される場合、enunsを渡す代わりに、選択された値の合計を代わりに渡します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.