假设我有一个域类:
public class Country
{
string name;
IList<Region> regions;
}
public class Region
{
string name;
IList<City> cities;
}
etc.
我希望以树的形式在GUI中对此进行建模。
public class Node<T>
{
T domainObject;
ObservableCollection<Node<T>> childNodes;
}
public class CountryNode : Node<Country>
{}
etc.
如何自动检索区域等的国家/地区列表更改的区域列表更改?
一种解决方案是在域类上实现INotifyPropertyChanged并更改IList&lt;&gt;到ObservableCollection&lt;&gt;,但这感觉有点不对,因为为什么我的域模型有通知更改的责任?
另一种解决方案是将责任放在GUI /表示层上,如果某个操作导致向Region添加Region,则表示层应将新国家/地区添加到CountryNode.ChildNodes和域CountryRegions。
对此有何想法?
答案 0 :(得分:2)
将INotifyPropertyChanged滚动到解决方案中是将事件实现到模型中的一部分。从本质上讲,事件本身并不符合DDD的口头禅。事实上,这是埃文斯暗示的事情之一,他早期的材料已经遗漏了。我不记得究竟在哪里,但他确实在这个视频中提到过它; What I've learned about DDD since the book
就其本身而言,阻止事件模型在域中实际上是合法的,因为它引入了域与系统中其他代码之间的分离。您所做的只是说您的域名有能力通知有关各方事情已发生变化。然后,订户有责任采取行动。我认为,混淆的地方在于您只使用INotifyPropertyChanged实现来中继回事件接收器。然后,该事件接收器将通过已注册的回调通知任何订户已发生“某事”。
然而,话虽如此,你的情况是“边缘”场景之一,事件并不适用于所有这些。您希望在列表本身更改时查看是否需要重新填充UI。在工作中,我们当前的解决方案使用ObservableCollection。虽然它确实有效,但我并不喜欢它。另一方面,发布列表中的一个或多个项目已更改的事实也存在问题。例如,您如何确定列表的熵以最好地确定它已更改?
因此,我实际上认为这不是域的关注。我不认为您所描述的内容将是域所有者的要求,而是应用程序体系结构的工件。如果您在更改之后查询域中的服务,它们将正确返回,并且应用程序仍然是不合适的。在这个领域,这个领域的世界里面没有任何实际的错误。
所以,我可以通过几种方式看到这一切。最低效的方法是直接针对模型轮询更改。您还可以考虑使用某种标记来指示列表是脏的,尽管不使用域模型这样做。再一次,不是那个干净的解决方案。但是,您可以在域外应用这些原则,以提出可行的解决方案。
如果您有某种共享缓存机制,即分布式缓存,您可以实现JIT缓存/逐出方法,其中插入和更新将使缓存无效(即逐出缓存的项目)并且后续请求将加载然后,你可以将一个标记放入缓存本身,这表明可以识别出重建项目的时间。例如,如果您有一个包含区域ID的列表的缓存项,则可以存储它与JIT一起使用的DateTime。然后,应用程序可以跟踪它具有的JIT版本,并且仅在发现版本已更改时才重新加载。你仍然需要轮询,但它消除了将责任放入域本身,如果你只是轮询一小部分数据,那么每次重建整个事情要好。
此外,在建立一个完整的解决方案之前。解决域名所有者的疑虑。他/她/他们可能完全可以接受你只是在某个地方有一个“刷新”按钮或菜单项。这也是关于妥协的,我相当肯定大多数域名所有者会偏好核心功能而不是某些类型的问题。
答案 1 :(得分:2)