DDD 与集合一起
假设我有一个域类:
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<> 。到 ObservableCollection<>,但这感觉有点错误,因为为什么我的域模型有责任通知更改?
另一个解决方案是将该责任放在 GUI/表示层上,如果某些操作导致将区域添加到国家/地区,则表示层应将新国家/地区添加到 CountryNode.ChildNodes 和域 Country.Regions。
对此有什么想法吗?
suppose I have a domain classes:
public class Country
{
string name;
IList<Region> regions;
}
public class Region
{
string name;
IList<City> cities;
}
etc.
And I want to model this in a GUI in form of a tree.
public class Node<T>
{
T domainObject;
ObservableCollection<Node<T>> childNodes;
}
public class CountryNode : Node<Country>
{}
etc.
How can I automatically retrieve Region list changes for Country, City list changes for Region etc.?
One solution is to implement INotifyPropertyChanged on domain classes and change IList<> to ObservableCollection<>, but that feels kinda wrong because why should my domain model have resposibility to notify changes?
Another solution is to have that responsibility put upon the GUI/presentation layer, if some action led to adding a Region to a Country the presentation layer should add the new country to both the CountryNode.ChildNodes and the domain Country.Regions.
Any thoughts about this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
将 INotifyPropertyChanged 滚动到解决方案中是在模型中实现事件的一部分。从本质上讲,事件本身并不违背 DDD 的口号。事实上,这是埃文斯暗示的他早期材料中缺失的事情之一。我不记得具体在哪里,但他在这段视频中提到了; 自这本书以来我对 DDD 的了解
就其本身而言,事件模型在该领域中实际上是合法的,因为它引入了领域与系统中其他代码之间的解耦。您所做的只是说您的域有能力通知感兴趣的各方某些事情已经发生了变化。因此,订户有责任据此采取行动。我认为混乱之处在于您仅使用 INotifyPropertyChanged 实现来中继回事件接收器。然后,该事件接收器将通过注册的回调通知任何订阅者“某事”发生了。
然而,话虽如此,您的情况是三项赛不太适用的“边缘”场景之一。您正在查看当列表本身发生更改时是否需要重新填充 UI。在工作中,我们当前的解决方案使用 ObservableCollection。虽然它确实有效,但我不喜欢它。另一方面,发布列表中的一个或多个项目已更改的事实也是有问题的。例如,您将如何确定列表的熵以最好地确定它已更改?
因此,我实际上认为这不是该领域所关心的问题。我不认为您所描述的内容是域所有者的要求,而是应用程序体系结构的产物。如果您在进行更改后查询域中的服务,它们将正确返回,并且应用程序仍然会不同步。此时此刻,领域世界内实际上并没有任何问题。
因此,我可以通过几种方法来实现这一目标。最低效的方法是持续轮询直接针对模型的更改。您还可以考虑使用某种标记来指示列表是脏的,尽管不使用域模型来执行此操作。再说一遍,这并不是一个干净的解决方案。但是,您可以在域外应用这些原则来提出可行的解决方案。
如果您有某种共享缓存机制,即分布式缓存,您可以实现 JIT 缓存/逐出方法,其中插入和更新将使缓存无效(即逐出缓存的项目),后续请求会将它们加载回然后,您实际上可以在缓存本身中放入一个标记,该标记将指示可识别该项目何时被重建的信息。例如,如果您有一个包含区域 ID 列表的缓存项,则可以将其 JIT 化的日期时间与其一起存储。然后,应用程序可以跟踪它所具有的 JIT 版本,并且仅在发现版本已更改时才重新加载。您仍然需要轮询,但它消除了将该责任放入域本身,如果您只是轮询较小的数据,那么这比每次都重建整个数据要好。
另外,在构建完整的解决方案之前。解决域名所有者的疑虑。他/她/他们可能完全可以接受您只在某处有一个“刷新”按钮或菜单项。这也是一个妥协的问题,我相当确定大多数域名所有者都会优先考虑核心功能而不是某些类型的问题。
Rolling INotifyPropertyChanged into a solution is part of implementing eventing into your model. By nature, eventing itself is not out of line with the DDD mantra. In fact, it is one of the things that Evans has implied that has been missing from his earlier material. I don't remember exactly where, but he does mention it in this video; What I've learned about DDD since the book
In and of itself, impelemnting an eventing model is actually legitimate in the domain, because of the fact it introduces a decoupling between the domain and the other code in your system. All you are doing is saying that your domain has the capability of notifying interested parties in the fact that something has changed. It is the responsibility of the subscriber, then, to act upon it. I think that where the confusion lies is that you are only using an INotifyPropertyChanged implementation to relay back to an event sink. That event sink will then notify any subscribers, via a registered callback, that "something" has happened.
However, with that being said, your situation is one of the "fringe" scenarios that eventing does not apply all that well to. You are looking to see if you need to repopulate a UI when the list itself changes. At work, the current solution that we have uses an ObservableCollection. While it does work, I am not a fan of it. On the flip side, publishing a fact that one or more items in the list have changed is also problematic. For example, how would you determine the entropy of the list to best determine that it has changed?
Because of this, I would actually consider this to not be a concern of the domain. I do not think that what you are describing would be a requirement of the domain owner(s), but rather an artifact of the application architecture. If you were to query the services in the domain after the point that the change is made, they would return correctly and the application would still be what is out of step. There is nothing actually wrong inside the world of the domain at this momeent in time.
So, there are a few ways that I could see this being done. The most inefficient way would be to continually poll for changes directly against the model. You could also consider having some sort of marker that indicates that the list is dirty, although not using the domain model to do so. Once again, not that clean of a solution. You can apply those principles outside of the domain, however, to come up with a working solution.
If you have some sort of a shared caching mechanism, i.e. a distributed cache, you could implement a JIT-caching/eviction approach where inserts and updates would invalidate the cache (i.e. evict the cached items) and a subsequent request would load them back in. Then, you could actually put a marker into the cache itself that would indicate something identifiable as to when that item(s) was/were rebuilt. For example, if you have a cache item that contains a list of IDs for region, you could store the DateTime that it was JIT-ed along with it. The application could then keep track of what JIT-ed version it has, and only reload when it sees that the version has changed. You still have to poll, but it eliminates putting that responsibility into the domain itself, and if you are just polling for a smaller bit of data, it is better than rebuilding the entire thing every time.
Also, before overarchitecting a full-blown solution. Address the concern with the domain owner. It may be perfectly acceptable to him/her/them that you simply have a "Refresh" button or menu item somewhere. It is about compromise, as well, and I am fairly sure that most domain owners would have a preference of core functionality over certain types of issues.
关于事件 - 我见过的最有价值的材料来自 Udi Dahan 和 Greg Young。
这里可以找到我渴望尝试的一种很好的事件实现。
但首先要了解这是否真的有必要,正如约瑟夫建议的那样。
About eventing - most valuable material I've seen comes from Udi Dahan and Greg Young.
One nice implementation of eventing which I'm eager to try out can be found here.
But start with understanding if that's really necessary as Joseph suggests.