我在课堂设计中不时碰到这个...当我在对象中有几个相同类型的属性时。举几个例子:
用户有几个地址。我们可以做到
IDictionary<string, Address> Addresses; // Addresses["BusinessAddress"];
或
Address BusinessAddress;
Address ShippingAddress;
产品有相关产品,由不同的笼子。我们可以做到
IDictionary<string, IList<Product>> Related; // Related["Available"];
或
IList<Product> Available;
IList<Product> Required;
用户分配了多个角色。我们可以做到
IList<Role> Roles;
或
bool IsAdmin;
bool IsSales;
那么,什么更好? IDictionary更灵活,因为我们可以轻松地将新地址类别添加到数据库中,甚至无需触及代码。但缺点是我们使用字符串来访问;这总是容易出错。我们可以用单元测试或常量来解决这个问题,比如
public class ProductCategories { public static string Available = "Available"; }
但是,阅读“product.Available”比“product.Related [ProductCategories.Available]”更糟糕。
还有其他一些注意事项,例如,使用ORM(例如NHibernate)更容易/更好地映射。
但问题是,有没有已知的偏好?设计有关此主题的文章和/或书籍?这里的人们经历过现实世界的实践吗?
例如,我们可以结合两个世界......让IList和bool IsAdmin做“返回Roles.Contain(角色(”管理员“));”。但这看起来很难看。
或者,对于IDictionary,我们每种类型的地址不能超过1个;如果我们这样做
IDictionary<string, IList<Address>>
对于我们不需要倍数的简单地址,这很疯狂。但是如果我们使用BillingAddress,ShippingAddress和IList for MultipleAddress,我们可以对我们的地址进行更精细的控制......使用Intellisense等等。
答案 0 :(得分:1)
由于您提及域驱动设计(DDD),the book of the same title包含意图显示接口的指南。拥有域对象的命令绝不是故意揭示的,所以仅仅因为这个原因,我强烈建议不要使用字典。
字典应主要用于公开API,其中调用者可以添加和检索值,或者用于非常通用的基础结构API,您需要能够处理非常灵活的情况。
DDD不是这种情况。想象一下,您没有自己编写类,然后在示例中包含了基于Dictionary的Addresses属性。你怎么知道它包含哪些类型的地址?您必须查看实现代码或阅读文档。
另一方面,如果您同时拥有BusinessAddress和ShippingAddress属性,那么API的消费者可以立即看到可用的内容。
我认为您考虑的灵活性是一种错误的灵活性,因为客户端代码仍然需要知道哪些字典条目可用之后才能使用它们。向类添加新属性就像向字典添加条目一样容易。
如果你真的需要一个Dictionary(或更好的,一个列表),因为有时你需要遍历所有地址(或其他),你可以通过暴露一个只读属性来实现这一点,该属性为两者提供一个枚举器 - 比如这样:
public Address BusinessAddress { get; set; }
public Address ShippingAddress { get; set; }
public IEnumerable<Address> Addresses
{
yield return this.BusinessAddress;
yield return this.ShippingAddress;
}
答案 1 :(得分:0)
这取决于。如果您的应用程序需要允许用户添加地址,那么请务必使用Address
es字典。