Enumのような値を処理および永続化する最良の方法について、ここでいくつかの質問/ディスカッションを見てきました(例 enumsに適したデータの永続化 、 NHibernateを使用して列挙型を永続化する方法 )、そして私は一般的なコンセンサスとは何かを尋ねたいと思います。
特に:
注:この質問に元々含まれていた説明を回答に移動しました。
私は私の理解を要約しようとしました。修正がある場合は、自由に編集してください。だからここに行く:
コード内
コードでは、列挙型は、言語のネイティブ列挙型(少なくともJavaおよびC#))、または "typesafe enum pattern" のようなものを使用して処理する必要があります。型の安全性を失うため(そしてメソッドなどの正当な入力である値を理解するのが困難になるため)、プレーンな定数(整数など)の使用はお勧めしません。
これら2つのどちらを選択するかは、列挙型に追加する機能の量によって異なります。
特に、少なくともJava enumは別のクラスから継承できません。そのため、スーパークラスに入れたい同様の動作を持つ複数のenumがある場合、Javaのenumは使用できません。
永続的な列挙型
列挙型を永続化するには、各列挙値に一意のIDを割り当てる必要があります。これは整数でも短い文字列でもかまいません。ニーモニックになる可能性があるため、短い文字列が推奨されます(データベース管理者などがデータベース内の生データを理解しやすくなります)。
このアプローチの1つの問題は、正当な列挙値のリストが2か所(コードとデータベース)に存在することです。これは避けるのが難しいため、多くの場合許容できると考えられますが、次の2つの方法があります。
私はあなたの言うことの多くに同意します。ただし、列挙型の永続性について追加したいことが1つあります。DB値からのビルド時の列挙型の生成は受け入れられないと思いますが、実行時チェックは適切な解決策ではないと思います。 3番目の方法を定義します。列挙型の値をデータベースに対してチェックする単体テストを用意します。これにより、「偶発的な」相違が防止され、コードが実行されるたびにデータベースに対して列挙型をチェックするオーバーヘッドが回避されます。
最初の記事は私には元気に見えます。それでも、コメントに基づいて、Java列挙型に関するいくつかのコメントはいくつかのことを明確にする可能性があります。
Javaの列挙型は当然のことながらクラスですが、他のいくつかの言語のように「許可された値のリスト」に関連付けるので、多くのプログラマーはこれを忘れがちです。それだけではありません。 。
したがって、これらのswitchステートメントを回避するために、enumクラスにいくつかのコードと追加のメソッドを配置するのが妥当な場合があります。別の「列挙型の実クラス」を作成する必要はほとんどありません。
ドキュメント化のポイントも考慮してください。データベース内の列挙型の実際の意味をドキュメント化しますか?値(列挙型)を反映するソースコード、または一部の外部ドキュメントで?私は個人的にソースコードを好みます。
速度などの理由でデータベースに列挙値を整数として表示する場合、そのマッピングはJava enumにも存在する必要があります。デフォルトでは文字列名のマッピングを取得し、私はそれに満足しています。各列挙値に関連付けられた序数がありますが、それをコードとデータベース間のマッピングとして直接使用することはあまり明るくありません。なぜなら、その序数は、誰かがソースコードの値を並べ替えると変更されるためです。または、既存の値の間に追加の列挙値を追加するか、一部の値を削除します。
(もちろん、誰かがソースコードで列挙型の名前を変更した場合、デフォルトの文字列マッピングも酸っぱくなりますが、それが誤って発生する可能性は低くなります。必要に応じて、実行時チェックを行うことで、より簡単に保護できます。ここですでに提案されているように、データベースの制約を確認してください。
C#のコード処理では、0値のデリカリングの定義を見逃しています。私はほぼ間違いなく常に最初の値を次のように宣言します:
public enum SomeEnum
{
None = 0,
}
Null値として機能するように。バッキングタイプは整数であり、整数のデフォルトは0であるため、列挙型が実際にプログラムで設定されているかどうかを知ることは、多くの場所で非常に役立ちます。
JavaまたはC#では、コードで常に列挙型を使用する必要があります。免責事項:私の背景はC#です。
値をデータベースに永続化する場合は、各列挙型メンバーの整数値を明示的に定義して、後でコードを変更しても、変換された列挙型の値が誤って変更されず、アプリケーションの動作が変更されないようにする必要があります。
Enum名のリファクタリングから保護するために、値は常に整数値としてデータベースに永続化する必要があります。 Wiki内の各列挙に関するドキュメントを保持し、タイプをドキュメント化するWikiページを指すコメントをデータベースフィールドに追加します。また、Wikiエントリへのリンクを含む列挙型にXMLドキュメントを追加して、Intellisenseから利用できるようにします。
ツールを使用してCRUDコードを生成する場合、生成されたコードオブジェクトが常に列挙型メンバーを使用するように、列に使用する列挙型を定義できる必要があります。
列挙型メンバーにカスタムロジックを適用する必要がある場合は、いくつかのオプションがあります。
私はこれを試していませんが、SQL Server 2005以降では、理論的には、列挙情報を含むデータベースにC#コードを登録し、ビューやその他の構成で使用するために値を列挙型に変換して、 DBAが使用しやすい方法でデータを収集します。
ええと、私の経験では、オプションを(フラグとして)即時メソッド呼び出しに渡す以外の目的で列挙型を使用すると、ある時点でswitch
- ingが発生します。
switch
ステートメント)になる可能性があります。switch
- esを使用することになります)。したがって、機能がもう少し多い列挙型のエンティティの場合、いくつかの点を考慮して、少し時間をかけてクラスとして作成する必要があります。
列挙型へのコード変更で「マジックナンバー」を使用して自分を見つけるたびに。時間の節約に加えて(バグが来ると魔法が消えるので...)それはあなたの目とメモリを節約します(意味のある列挙型はコードをより読みやすく自己文書化します)。あなた自身のコード
Enumのテキスト値をデータベースに格納することは、整数を格納するよりも、必要な追加のスペースと検索速度の低下のため、あまり好ましくありません。数値よりも意味があるという点で価値がありますが、データベースはストレージ用であり、プレゼンテーションレイヤーは物事を美しく見せるためのものです。
Imho、コード部分は:
always列挙には 'enum'タイプを使用してください。そうすると、基本的に多くの景品が得られます。タイプセーフ、カプセル化、スイッチの回避、EnumSet
やEnumMap
などのいくつかのコレクションのサポートとコード明快さ。
永続化の部分については、常に列挙型の文字列表現を永続化し、enum.valueOf(String)メソッドを使用してロードし直すことができます。
私はこれが古いフォーラムであることを知っていますが、データベースに他のものが直接統合されている場合はどうなりますか?例えば。結果のDBがコードの唯一の目的である場合。次に、すべての統合で列挙型を定義します。それらをDBに入れる方が良いでしょう。それ以外の場合は、元の投稿に同意します。