.Create() がインスタンス化できない場合、空のオブジェクト、null を返すか、例外をスローする必要がありますか?
-
13-09-2019 - |
質問
次のようなコードを使用して、アプリケーション内の任意のオブジェクトをインスタンス化できるようにしたいと考えています。
SmartForm smartForm = SmartForm.Create("id = 23");
Customer customer = Customer.Create("id = 222");
私は現在、そのオブジェクトが存在しない場合に Create() が何を返すべきかを議論しています。
Create() が 空のオブジェクト, この場合、これは一種の「ヌル パターン」であり、そのオブジェクトをアプリケーションに渡してメソッドを呼び出すことができるため、このモデルを使用したプログラミングが便利で簡単になります。
Create() が返った場合 ヌル, そうすると、インスタンス化のたびにオブジェクトが null に等しいかどうかをチェックする必要があり、プログラミングは少し面倒になりますが、より明示的になります。これの問題は、null のチェックを忘れると、null をチェックしていないことに気づかずにアプリケーションが長時間動作し、その後突然壊れてしまう可能性があることです。
if Create() 例外をスローします, 基本的に null を返すのと同じですが、インスタンス化ごとに try、next、finally ブロックを作成する必要があるため、プログラミングがさらに面倒になりますが、さまざまなタイプの例外をスローできます (null ソリューションではスローできません)。 UI 上の深刻なエラーをより明示的に処理できるようにバブルアップする可能性があるため、try/catch コードの肥大化は発生しますが、これが最も堅牢な解決策だと思います。
ということのようです 軽さと堅牢さのトレードオフ. これらの方針に沿って決定を下した経験のある人はいますか その決定によりどのような点でメリットやデメリットが生じましたか?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestFactory234.Models
{
public class SmartForm : Item
{
public string IdCode { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int LabelWidth { get; set; }
public SmartForm() { }
private SmartForm(string loadCode)
{
_loadCode = loadCode;
TryToInstantiateFromDatabase();
}
public static SmartForm Create(string loadCode)
{
SmartForm smartForm = new SmartForm(loadCode);
if (!smartForm.IsEmpty())
{
return smartForm;
}
else
{
return null;
}
}
}
}
解決
これは、依存して - 何かが確かに間違っているので、それが失敗した場合は、その例外は、プログラミングは、の容易になります。の - あなたは、各呼び出しの周りのtry / catchを書いていない、あなただけの例外バブルアップをしましょう。例外をスローするのヌル/空白の戻り値をチェックしていることを比較し、<全角>。
これはIMO、ArgumentException
を使用するために適切な時期のように聞こえます。
あなた自身がのtry / catch「肥大化」を作成見つけた場合は、あなたが本当にただ彼らにバブルアップをさせるのではなく、例外をキャッチする必要がある理由を見てみましょう。
他のヒント
、その後、あなたはそれが有効だと仮定進みます - またはそれは空白だかいないかどうかを確認するために入念なテストのいくつかの種類を行う必要があります。それはnullを返した場合、あなたは常にnullをチェックする必要があります(そしておそらくそれは大丈夫です)。これが起こると想定されていないように、あなたのコードが設計されていることを仮定して - 私はそれが例外をスローすることを好むだろう。これは、通常のシナリオの場合は、NULLがより良い選択かもしれません。
デフォルトの動作は、インスタンスを作成する場合は、例外的な行動は、作成に失敗することがある - >例外
あなたはEmptyObjectで何をしますか?これは本当に感じる作る - あなたはまだそれを周りに渡すことができると言いますか?方法は、あなたがそれらを呼び出すときに、何をしますか?
たぶん、あなたは、第二の TryCreate()のメソッドを実装する必要があります。
私は例外バリアントを実装するだろうが、それはあなたが必要とする動作に依存ます。
あなたのサンプルコードは、「負荷を試しDBから」メソッドを呼び出し、作成規則は、<のhref =「http://www.castleproject.org/activerecord/index.html」のrel = "nofollowをnoreferrerのようにたくさん見えます「>城のActiveRecord のオブジェクト。なぜ、取得/作成、データベースの操作を分離フレームワークが作業を行えるよう、その慣習に依存しない?
[ActiveRecord("Forms")]
public class SmartForm : Item
{
[PrimaryKey("Id")]
public string IdCode { get; set; }
[Property]
public string Title { get; set; }
[Property]
public string Description { get; set; }
[Property]
public int LabelWidth { get; set; }
}
あなたはこのようなインスタンスを作成/取得
SmartForm entity = ActiveRecordMediator<SmartForm>.Find(1);
SmartForm otherEntity = ActiveRecordMediator<SmartForm>.FindFirst(/* criteria */);
のインスタンスを見つけるために利用可能な他の方法がたくさんあります。 //:私はあなたがActiveRecordののデフォルトの<のhrefは= "HTTPことを見つけると思いますapi.castleproject.org/html/M_Castle_ActiveRecord_ActiveRecordBase_1_FindAll.htm "のrel = "nofollowをnoreferrer" するについて> <のhref = "http://api.castleproject.org/html/M_Castle_ActiveRecord_ActiveRecordBase_1_FindFirst_1.htm" のrel =" nofollowをnoreferrer 「>投げの例外は、にnullを返す、またはコレクションの場合、 、空のコレクションは、非常に一貫してうまく実装されています。
、あなたはより良い列挙ではなく、文字列を渡すことになる。
それは作成が失敗する可能性があることを予見できるのですが、アプリケーションのコードの多くは、それは、あなたが本当に、成功するか、例外をスローする必要がありますどちらか1つ作成方法の2つのバージョンを実装する必要があります動作することを期待しようとした場合これの他には、例外をスローする以外の手段で予想される障害を示し、そしておそらく(例えばCpuIsOnFireException)を予想していないだけの障害のために、発信者が例外をスローする必要があります。これを行うための一般的なパターンは、TryCreate方法は、バイrefの引数に作成された引数を格納し、成功を示すブール値を返すことです。それが合否の状態(それが失敗した理由について、すなわち何もない)以外のものを示すのない手段を提供していないので、私は、本当にそのパターンが好きではありません。私は新しいものまたはnullのいずれか「試す」関数の戻り値を持っている方が良いかもしれないと思うが、失敗の理由を示すことによって、参照引数を持っています。このアプローチは、暗黙の型(C#で、例えば「VAR」キーワード)をより有効に利用することが可能になることに注意してください。