web-dev-qa-db-ja.com

開発者が定数を使用できないようにする

開発者がIDまたは名前を指定してNodeReferencesを作成できる1つのソフトウェアシステムがあります。どちらも正常に機能しますが、IDが異なる環境間で同じであるとは限りません。私はドキュメントや会話でIDをハードコーディングしないでください(別の環境にデプロイすると破損するため)ことを強調しましたが、一部の開発者はまだそれらを使用しています。

これは開発環境でのみ機能します。

var level = LevelReference.ById(20);
var node = NodeReference.ByName(level, _patientGuid.ToString());

これはすべての環境で機能します。

var app = ApplicationReference.ByName("Reporting");
var area = AreaReference.ByName(app, "Default");
var level = LevelReference.ByName(area, "Patient");
var node = NodeReference.ByName(level, _patientGuid.ToString());

魅力的なのは、コードの行数が少ないことだけです。 IDの使用自体は悪いことではありませんが(サーバーから返されたIDをキャッシュし、後でそれを使用してルックアップを高速化するなどの有効なユースケースがあるため)、ハードコードされたIDは不適切です。ほとんどの場合、最初のコードは例外をスローしますが、開発者の意図とは異なるオブジェクトの有効なIDである可能性があり、これは非常に悪い問題を引き起こす可能性があります。

コードでそのような定数を使用しないようにする最良の方法は何ですか?理想的には、最初の例のようなコードが表示されたときになんらかのコンパイラエラーをスローするか、少なくとも呼び出しがデータベースに到達する前に例外をスローします。

7
p.s.w.g

不透明なオブジェクト/構造体のint IDを非表示にします。

_var id = level.id;
_

ここでidはそのような構造体です。

このようにして、ById(int)メソッドを削除してById(Id)で置き換えることができ、キャッシュされたIdsを今後も使用できるようにしておくことができます。

また、各参照型に一意のID型を作成して、型の安全性を確保することもできます(そのため、NodeReference.ById(level.id)は実行できません)。

18
ratchet freak

より良いAPIを提供する:

var node = NodeReference.byName("Reporting", "Default", "Patient", _patientGuid.ToString());

または、重要なノードを取得するユーティリティ関数を提供します

var node = NodeReference.byName( theDefaultPatientNode(), _patientGuid.ToString() );

または、列挙型にさまざまなノードがあり、次のようなことをします:

var node = NodeReference.byCategory( REPORT_PATIENT, _patientGuid.ToString() );

この単純なことを行うために、4行のコードを書くことはできません。それ以外の場合は関連オブジェクトをフェッチするのが難しいため、IDを使用しようとしています。だから、もっと簡単に!

21
Winston Ewert

のようなコード

var level = LevelReference.ById(20);

マジックナンバー が含まれているため、コードレビューに合格しないでください。それだけでもそのような慣行を禁止する十分な理由になるはずです。

また、名前付き定数を作成して回避しようとする場合、レビュー担当者は作成者に、番号がすべての展開で正しいことを保証する場所を尋ねる必要があります。

私が正しく理解していれば、それらのIDはデータベースの主キー(ID列)です。この場合の回避策は、コード内の定数を禁止したり追跡したりするのではなく、デプロイメントスクリプトでそれらのキーをランダム化することです。

IDがテストデータ内で同じであることが保証されていないため、開発者にとっての唯一の解決策は、より信頼性の高いもの(あなたの場合は名前)に移行することです。

5

コードレビューで彼らの手を叩いてください。

とはいえ、LevelReference.ById()LevelReference.ByName()の間に実際の違いはありますか?あなたの例では、両方でハードコードされた値を使用しています。

私が取り組んだ1つのコードベースでは、データベースセットアップスクリプトでセットアップされ、列挙値をデータベース値にマップする列挙型を持つ「ハードコード」値を事前定義することで、同様の状況を処理しました。

5
Dave Rager

社会問題の技術的解決策を見つけようとしているようです。コードレビューで呼び出す必要があります。テスト/ステージング環境で何かを行い、ノード番号がneverがクリーンな開発環境に一致することを確認します。インストールごとにランダムな数のガベージ行を挿入し、壊れたものとしてそれを開発に戻します。

人々がこれを回避しようとするならば、あなたは彼らを手放します。

4

Doctor!Doctor!私がこれを行うと痛い!

開発者はAPIを提供したため、APIを誤用しています。 LevelReference.ById()の使用が適切でないと思われる場合は、提供しないでください。あなたがそれを奪うと、彼らはそれを使うのをやめるでしょう:-)

C#について話しているので、ById()[Obsolete]としてマークすることもでき、少なくとも非推奨の警告が表示されます。すべての警告、エラーでコンパイルする人にとって、それは致命的です。

2
Ross Patterson