我希望能够使用这种代码实例化我的应用程序中的任何对象:
SmartForm smartForm = SmartForm.Create("id = 23");
Customer customer = Customer.Create("id = 222");
我现在正在讨论如果该对象不存在,Create()应该返回什么。
如果Create()返回空对象,那么这是一种“空模式”,我仍然可以在我的应用程序周围传递该对象并在其上调用方法,这使得使用此模型进行编程既方便又简单
如果Create()返回 null ,那么我需要在每次实例化后检查对象是否等于null,这使得编程更乏味但更明确。这样做的一个问题是,如果你忘记检查null,你的应用程序可能会工作很长时间而你不知道你没有检查null,然后突然中断
如果Create()抛出异常,它基本上与返回null相同,但是通过让你为每个实例创建一个try,next,finally块,使编程变得更加乏味,但你可以抛出各种类型的异常(你不能使用null解决方案),这可能会冒出来,这样你就可以更明确地处理UI上的深层错误,所以我认为这是最强大的解决方案,尽管会产生尝试/捕捉代码膨胀
所以它似乎是轻盈/稳健性权衡。 有没有人有任何根据这些决定做出决定的经验,因为这个决定你遇到了优点或缺点?
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;
}
}
}
}
答案 0 :(得分:6)
这取决于 - 如果它失败是因为某些东西肯定是错误的,那么异常会使编程更容易 - 你不会在每次调用时写一个try / catch,你只是让异常冒出来。将其与检查null /空白返回值进行比较,然后然后抛出异常。
这听起来像是使用ArgumentException
,IMO的正确时间。
如果您发现自己创建了try / catch“膨胀”,请查看为什么您真的需要捕获异常,而不是让它们冒泡。
答案 1 :(得分:2)
如果它返回一个空白对象,那么你将继续假设它是有效的 - 或者必须进行某种精心测试以确定它是否为空白。如果它返回null,你将始终必须检查null(也许这很好)。我希望它抛出异常 - 假设您的代码是为了不应该发生而设计的。如果这是正常情况,那么null可能是更好的选择。
答案 2 :(得分:2)
当默认行为是创建实例时,异常行为将失败并创建 - >例外
你会用EmptyObject做什么?你说你仍然可以传递它 - 这真的有意义吗?当你打电话给他们时,这些方法会做什么?
也许你应该实现第二个 TryCreate()方法。
我实现了Exception-variant,但这取决于你需要的行为。
答案 3 :(得分:1)
您的示例代码调用“从DB尝试加载”方法,并且Create约定看起来很像Castle ActiveRecord对象。为什么不分离Get / Create数据库操作,允许框架完成工作并依赖它们的约定?
[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的defaults regarding throwing exceptions,返回null,或者在集合的情况下,是一个空集合,非常一致且实现得很好。
答案 4 :(得分:0)
如果要创建表单工厂,最好传递枚举而不是字符串(当然,除非代表插件架构)。
答案 5 :(得分:0)
如果可以预见创建可能会失败,但很多应用程序代码会期望它能够正常工作,那么你真的应该实现两个版本的创建方法,其中一个应该成功或抛出异常,并且其他的应该通过除抛出异常之外的某些方式指示预期的失败,并且仅针对调用者可能没有预料到的失败抛出异常(例如CpuIsOnFireException)。执行此操作的常见模式是让TryCreate方法返回指示成功的布尔值,将创建的参数存储到by-ref参数。我真的不喜欢这种模式,因为除了传递失败状态之外,它没有提供任何指示任何东西的方法(即没有关于它失败的原因)。我认为让“try”函数返回new或null返回可能会更好,但是有一个by-ref参数指示失败的原因。请注意,此方法可以更好地使用隐式类型(例如C#中的“var”关键字)。