型を使用したC#では、すべて問題ありません

タイプコントロールの強化:典型的なC#-プロジェクトのどこに、弱い型付けの未承諾要素がありますか? 」という記事を読んだ後、 「このアプローチの誤りと、誰もそれに注意を払っていないという事実に非常に驚きました。



投稿の著者は、特定のリポジトリからオブジェクトが作成された参照型を返すメソッドは、何らかの方法で、返されたオブジェクトがnullでないことを保証するべきだと考えています。 さらに、1つの例では、彼は契約を使用していますが、これは原則と矛盾しています。 このアプローチの誤りを明らかにしたいと思います。



特定のリポジトリからオブジェクトを取得するGetItem



メソッドがあり、作成者によると、オブジェクトがnullにならないことを保証する必要があります。



 public Item GetItem(int itemId) { return dataAccessor.getItemById(itemId); }
      
      







目的のオブジェクトがリポジトリにない場合、 dataAccessor



はnullを返します。これはクライアントに渡され、nullの値をチェックせずにNullReferenceExceptionを受け取ります。 それでは、どうしてこれが起こらないことを保証できますか?



メソッド内でnullチェックを絞り込み、オブジェクトが見つからない場合は例外をスローできます。 ただし、これを使用して、NullReferenceExceptionの名前を、たとえばItemNotFoundExceptionに変更します。 さらに、クライアントはこのメソッドにアクセスするたびにtry-catchブロックを追加する必要があります。 クライアントライターは非常に満足しています。



別のオプションは、メソッドに事後条件を追加することです。 このように:



 public Item GetItem(int itemId) { Contract.Ensures(Contract.Result<Item>() != null); return dataAccessor.GetItemById(itemId); }
      
      







ここではすべてが非常に悪くなり、世界の子猫の数が少なくなります。 契約を読んだ後は、誰でもこのメソッドが提供された識別子とともにオブジェクトを常に返すことを理解する必要があります。 しかし、それは不可能です。 メソッドは、このIDを持つオブジェクトがリポジトリ内にあることを保証できません。 そのため、貧しい仲間を助け、すべての問題をクライアントにプッシュするための前提条件を追加する必要があります。



 public Item GetItem(int itemId) { Contract.Requires(dataAccessor.GetItemById(itemId) != null) Contract.Ensures(Contract.Result<Item>() != null); return dataAccessor.GetItemById(itemId); }
      
      







楽しいですね。 リポジトリからオブジェクトを取得するには、まずリポジトリからオブジェクトをプルする必要があります。何のためにリポジトリからオブジェクトをプルする必要があるのですか...



真実は、 スプーンがないということです;誰もリポジトリ内のオブジェクトの存在を保証することはできません 。 オブジェクトの存在を保証する唯一の方法は、オブジェクトを作成し、そのリンクをつまむことです。 他のすべては悪い設計です。 データアクセス層は、リポジトリからオブジェクトを取得し、クライアントに渡す必要があります。 彼はオブジェクトの不在を処理する方法を知らず、それが悪いかどうかさえ知りません。 これはロジックレベルが担当します。



可視領域外のオブジェクトの存在を保証できないことは、上記のリンクの記事にある2番目のアイデアにつながります。 参照型にnull許容コンテナを使用します。 言い換えると、null許容参照です。 オイルはオイルです。 このパターンの人気について学ぶのは奇妙でした。



参照型はnullを参照する場合があります。 ある参照型を別の参照型に固定し、HasValueプロパティをコンテナに追加する理由は明らかに私には明らかではありません。 HasValueを確認するには? このチェックなしでオブジェクトのコンテンツへのアクセスを妨げるものは何ですか? 不平等によりnullをチェックしないように不注意にできます。 さらに、このパターンは役に立たないだけでなく、有害でもあります。 次のコードを見てください。



 public Maybe<Item> SomeMethod() { var mbItem = GetMbItem(); if(mbItem.HasValue) { var item = mbItem.Value; ModifyItem(ref item); } return mbItem; }
      
      







ModifyItemメソッドがオブジェクトを置き換えた場合、SomeMethodメソッドは古いオブジェクトを含むコンテナーを返します。 後で移動して、このバグを探してください。



一般的に、私はその記事に示されている慣行が有害だと感じています。 C#でnull参照をチェックするための標準ツールがあり、NullReferenceExceptionを許可しないように注意する必要があります。 このためにシステムを複雑にする必要はありません。 リポジトリを操作するときは、データの整合性を監視する必要があり、これから逃げることはありません。 リポジトリ内に存在する必要があるオブジェクトがない場合、それははるかに悪くなります。



All Articles