12

私はいくつかのモバイルゲームを開発してきました。これらのゲームはサーバーデータベースからデータを取得します。

私は「タイプ」値を整数識別子として格納し、サーバーからのデータを識別するためにクライアントに列挙型を格納することに慣れています。

例として:データベーステーブル上:

モンスターテーブル:MonsterId(int)、Name(string)、MonsterType(int)

クライアント側のコード:

typedef enum {
    MonsterTypeGround = 1,
    MonsterTypeAquatic = 2,
    MonsterTypeAmphibious = 3,
    MonsterTypeAerial = 4
}MonsterType;

上記のコードはObjective-Cであり、整数値を割り当てることができることに注意してください。しかし、私はC#とC++も使用しています。

しかし、私たちのデータベース担当者は、列挙型はコンパイラのトリックであり、列挙型データ型のようなものはないと言いました。彼は、整数型識別子は値の意味を理解するのを難しくし、クライアント側のコードを見ないと同等のものを知ることができない可能性があり、列挙型は必要があるため適切ではないと主張しました列挙型がサーバー側のIDと同期していること、および代わりに文字列を使用することをお勧めします。

私の質問は:この問題について客観的に正しい答えはありますか?

クライアントコードで列挙型を使用する以外に、サーバーデータベースに整数を使用する代替手段はありますか?

4

2 に答える 2

15

長い答え

あなたのデータベースの人は明らかに間違っています。もちろん、ENUMデータ型のようなものであれば。例で1つ提供しました。そしてMySQLはそれを知っています。そして、多くのプログラミング言語にはENUMのようなものがあります。

しかし、彼はまた、ENUMがコンパイラによって(常に?)最適化されることが多いという点で正しいです。1から4で完全に表すことができる4つの選択肢があるが、コードで識別可能な文字列が読みやすいことがわかります。しかし、コンパイラにはそのような問題はなく、実際には数を気にしません。空中モンスターはタイプ4で、空飛ぶスパゲッティモンスターはタイプ4です。文字列を比較する場合と比較して、CPUがバイトを比較するのは数桁簡単です。

また、彼は、Cコードまたはその他のコードにENUMがあると問題になる可能性があることは正しいです。

  1. 定義(特に順序)を変更する場合は、プログラムと、ライブラリの場合はリンクされているすべてのプログラムを再コンパイルする必要があります。それは苦痛です。
  2. 異なる言語とのインターフェースが必要な場合、それも苦痛になる可能性があります。複数の定義を同期する必要があります。
  3. ENUMの管理は、特に型の削除が面倒です。

文字列を列挙型に変換する関数、またはその逆を使用することで、これを回避できます。

ただし、次のような利点もあります。

  1. モンスタータイプの名前を変更した場合、空中モンスターの名前をフライングモンスターに変更しても、空中モンスターはタイプ4のままになります。数値であるため、データベース内のデータの一貫性が保証されます。文字列を使用する場合、簡単に変換する方法はありません。ええと、検索と置換はコードでは実行されますが、データベースでは実行されません。
  2. 効率的なフォーマットです。それはあなたに10バイトを節約します。私の経験では、数千万のエントリがある場合を除いて、これが問題になることはめったにありません。

TL; DR

いいえ、客観的な答えはありません。

プログラマーの使いやすさが最も重要だと思うなら、文字列がより良い選択肢になるでしょう。コンパイラの最適化が最も重要である場合は、列挙型の方が適しています。

私の意見では、コンパイラーの最適化が重要になることはめったにありませんが、プログラマーの時間はほとんどありません。特定のデータベースを除いて、私自身は主に文字列を使用しています。

そうです、あなたの男にはポイントがあります。

于 2013-02-15T11:05:27.517 に答える
5

さて、ここに行きます..潜在的なdownVote飼料ですが、列挙型は私のお気に入りの1つです..

視点

デザインとコードに最適なものに焦点を合わせます。DBにはその「データ型」がないため、列挙型を使用しませんか?わかった。次に、同じ理由でカスタムクラスを作成しないようにします。それはナンセンスです。

列挙型の良さ

(注:私はC#でコーディングしています)

  1. 問題のドメインの観点から物事を宣言することができます。文字列は文字列ですが、MonsterType列挙型はモンスター(タイプ)です。
  2. 列挙型は本質的に強く型付けされています。未定義の列挙値を使用すると、コンパイルエラーになります。OTOH、文字列のタイプミスは別のデバッグセッションです。
  3. 私は特にswitchステートメントが好きです。theHellOutta整数を打ち負かします:switch(MonsterType)
  4. 列挙型はすべての有効な値を徹底的に定義できます
  5. ドキュメントyになる傾向があります
  6. コード品質エンハンサー-新しいメンバーを追加するには再コンパイルする必要がありますが、それは慎重なことであり、関連するコードの変更を見逃すと、どこかで処理されていない新しい文字列値に対して爆発します(良いことです)。ロジック/処理エラー。デバッグセッションが必要です。
  7. デフォルトはnullではなくゼロです。ヌルの概念が物事を台無しにすることができる方法はおかしいです。それが属するデータベースで「null」を保持します。
  8. プロのコーディングのヒント:常にデフォルトのメンバーを明示的に定義します。再:MonsterType.Unknown = 0。あなたの報酬は、バグが少なく読みやすい、より簡単に書かれたコードになります。あなたのメンテナンスプログラマーはあなたに感謝します。

文字列の悪さ

  1. デフォルト値はnullです。これは、nullと「空の文字列」をめぐる絶え間ない戦いです。私はこのようなばかげた、バグの多いコードを頻繁に見ます:if(string.IsNullorEmpty(myString.Trim()) ...-myStringがnullの場合、プログラムは実行時例外で爆発します。列挙型では発生しません。
  2. 文字列の比較では大文字と小文字が区別されます
  3. タイプミスが発生しやすいエラー
  4. 「文字列」タイプは一般的なものであり、ドメインの観点から問題を表現するのに役立つことはありません。
  5. myString = nullデータベースからフェッチされた設定は、値を持つ変数ではなく、オブジェクトでもありませんが、私たちはそれをそのまま扱うようにしています!

整数の難読化

if (MonsterType == 3)... それはどういう意味ですか?言っ途切れる。

これが実践的な演習です。IDEで、その「3」をクリックして、「定義を検索」するように依頼します。IDEが話すことができれば、「「3」が何を意味するのかを推測するのではなく、問題のドメインで物事を定義してみませんか?」と言うでしょう。

ああ、わかる。どこかで定数の混乱を宣言します。どこか。ああ、神様。列挙型を使用しているふりをしましょう!そして、タイプセーフな値のまとまりのあるセットで作業するよりも楽しいです!

nullは私を狂わせる

C#には、String.Emptyある理由で静的プロパティがあります。値が明示的に(有効な)文字列ではないインスタンス化された文字列オブジェクトを表すために、有効な値(たとえば、スペース)またはnullをハイジャックしないことになります。これはnullと同じものではありません。

nullは、文字通り何も意味しません。それは「離れて、誰も家にいない」という意味です。コーダーは、たとえば「モンスターの種類が不明」という意味を望んでいることがよくありますが、大声で叫ぶ場合は、そのような概念を明示的に定義してください(上記の列挙型のヒントを参照)。このようにnullを使用するIMHOは、デザインに何かが欠けていることを意味します。

nullはコードゾンビです。それは歩き回っていますが、それは何も、死んで、何でもありません。そして、あなたが注意しなければ、それはあなたを噛むでしょう!

「空の」文字列をスペース文字またはnullとして格納することを決定するという終わりのない喜びを体験できます。

スペースは実際には有効な文字列ドメイン値であり、「値なし」の値ではありません。

そして、そのnullと「空の文字列」は実際には同じことを意味するわけではなく、それらを作成しようとすると、「自然な」機能が必要なときに問題が発生します。

そして、手元のタスクに合わせて、string.emptyからnull、spaceに、またはその逆に変換するコードでの絶え間ない混乱。時間の経過とともに、コードはこの点で一貫性がなくなります。

今私を聞いて、後で私を信じてください。

于 2013-02-20T23:41:11.757 に答える