这似乎没有成为很多细节上的领域驱动设计的一个组成部分,是如何以及为什么你应该从你的界面分离你的域模型。 我试图说服我的同事,这是一个很好的做法,但我似乎没有要发出很大的进展...
他们使用了输入这些产品的介绍和界面层取悦域实体。 当我认为对他们,他们应该使用显示器型号或DTO的绝缘从界面层领域层,他们反驳说,他们没有看到在做类似的商业价值,因为现在你有一个UI对象保持以及原来的域对象。
于是我找了一些具体的原因,我可以用它来支持这一行动。 特别:
- 为什么我们不应该在我们的表现层使用域对象?
(如果答案是显而易见的一个,“脱钩”,那么请解释为什么这是很重要的在这方面) - 我们是否应该使用其他物体或构造我们的域对象从接口隔离?
Answer 1:
很简单,原因是执行和漂移的一个。 是的,你的表现层需要了解你的业务对象能够正确地代表他们。 是的,最初它看起来像有很多的两种类型的对象的实现之间的重叠。 问题是,随着时间的推移,事情变得两侧增加。 表述方式的变化,并表示层演变的需求,包括事情是完全独立的业务层的(颜色,例如)。 同时,你的域对象随时间而改变,如果你没有从你的接口适当脱钩,在运行通过使看似良性改变你的业务对象搞砸了你的界面层的风险。
就个人而言,我认为接近事情的最好办法就是通过严格执行界面范式; 也就是说,你的业务对象层暴露出那就是它可以与沟通的唯一途径的接口; 没有实施细则(即域对象),该接口被暴露。 是的,这意味着你必须实现在两个位置域对象; 你的界面层,并在你的BO层。 但是,重新实现,虽然它可能最初看起来像是额外的工作,有助于强制脱钩,将节省的工作吨在未来的某一时刻。
Answer 2:
我有这个挣扎自己。 在有些情况下一个DTO是有道理的presentaton使用情况。 比方说,我想表现出下降的公司在我的系统中来,我需要他们的id的值进行绑定。
好吧而不是加载可能需要订阅或谁知道还有什么引用一个CompanyObject,我可以发回一个DTO的名称和编号。 这是一个良好的使用恕我直言。
现在再举一个例子。 我有代表估算的对象,这个估计可能是由劳动力,设备等,可能有很多是由内搭所有这些项目,总结起来,用户定义的计算(每估计可能是与不同类型的不同计算)。 为什么我要到这个对象模型的两倍? 为什么不能我只是有我的UI枚举计算并显示出来?
我一般不使用DTO的我的域名层与我的UI隔离。 我使用他们到我的领域层从边界那是我无法控制的隔离。 有观点认为,有人会把导航信息在他们的业务对象是荒谬的,不污染您的业务对象。
有观点认为,有人会把验证他们的业务对象? 嗯,我说这是一件好事。 你的UI不应该有唯一的责任,以验证您的业务对象。 业务层必须尽自己的验证。
为什么你会把UI生成代码在busienss对象? 在我来说,我有产生从用户界面UI代码seperatley单独的对象。 我有我的渲染业务对象转换为XML sperate对象,你必须单独的层,以防止这种类型的污染是如此陌生的我,因为为什么你会甚至把HTML生成代码的业务对象的想法...
编辑当我觉得有点多,有些情况下UI信息可能会在域层属于个案。 而这可能会云你所谓的域层,但我曾在一个多租户应用程序,它有非常不同的行为都UI外观和功能的工作流程。 根据各种因素。 在这种情况下,我们有一个表示租户及其配置的域模型。 其形态发生包括UI信息(标签对例如通用域)。
如果我要设计我的对象,使他们持久化,我应该也有复制的对象? 请记住,如果你想添加一个新的领域,现在你有两个地方添加它。 也许这如果您使用DDD提出了另一个问题,都坚持实体域对象? 我知道,在我的例子他们。
Answer 3:
你对你保持SQL你的ASP / JSP页面的同样的理由这样做。
如果你只保留一个域对象,在介绍和领域层使用,那么这一个目标很快得到单片。 它开始包括UI验证代码,UI导航代码和UI生成代码。 然后,你很快就会加入所有的业务层的方法,最重要的是。 现在,您的业务层和用户界面都混出来的,所有的人都在域实体层瞎搞。
你想重用在其他应用程序,漂亮的UI控件? 好了,你必须用这个名字,这两种模式,而这些表18创建数据库。 你还必须配置Hibernate和Spring(或者你选择的框架)做业务验证。 哦,你还必须包括这些85其他非关联类,因为它们在业务层,这恰好是在同一个文件中引用。
Answer 4:
我不同意。
我认为最好的方法是先从领域对象在表示层,直至它的意义否则什么。
流行的看法相反,“域对象”和“值对象”可以愉快地共存于表示层。 这是做到这一点的最好办法 - 你得到两全其美,减少重复(和样板代码)与域对象的利益; 和剪裁和跨请求使用值对象的概念的简化。
Answer 5:
我们使用相同的模式在服务器上的用户界面。 而且这是一个痛苦。 我们有一些一天重构它。
该问题主要是因为域模型需要被切成小块,以便能够序列化,而无需引用整个数据库。 这使得它更难的服务器上使用。 重要环节缺失。 有些类型也不可序列化,不能被发送到客户端。 例如“类型”或任何泛型类。 他们需要的是不通用的,类型需要转移的字符串。 这种序列化产生额外的属性,它们是多余的,令人困惑。
另一个问题是,在UI实体真的不适合。 我们使用数据绑定和许多实体有大量的冗余特性仅用于UI目的。 此外,还有很多“BrowsableAttribute”和其他实体模型。 这是非常糟糕的。
最后,我认为这是早晚的事情,其方式是更容易。 有可能通过它只是工作正常,并在那里是没有必要再写DTO模式的项目。
Answer 6:
答案取决于你的应用规模。
简单的CRUD(创建,读取,更新,删除)应用程序
对于基本的CRUD应用程序,你没有任何功能。 在实体顶部添加DTO woudl是在浪费时间。 这会增加复杂性,而不增加可扩展性。
中等复杂的非CRUD应用程序
在这种规模的应用,你将有哪些具有真正lifeclycle和与之相关的一些业务逻辑的几个实体。
在这种情况下添加的DTO是几个原因是一个好主意:
- 表示层可以看到哪些实体具有领域的唯一子集。 您封装实体
- 后端和frontent之间无联结
- 如果你有内部的实体商业方法,但不是在DTO然后添加的DTO是指外部的代码不能毁了你的实体的状态。
复杂的企业应用程序
单一的实体可能需要呈现的多种方式。 他们每个人都需要不同的字段集。 在这种情况下,你会遇到同样的问题在前面的例子再加上需要控制每个客户端可见字段的量。 具有单独的DTO为每个客户端将帮助你选择什么应该是可见的。
Answer 7:
这是关于依赖性大部分。 该组织的核心功能结构有其自身的功能要求,以及用户界面应该使人们能够修改和查看核心; 但核心本身不应该被要求以适应UI。 (如果需要发生,它通常是指示的核心不是财产而设计的。)
我的会计系统具有结构和应该模型我公司的经营内容(数据)。 该结构是真实的,不管我用什么样的会计软件的存在。 (不可避免的给定的软件包中包含结构和自身利益的内容,但面临的挑战的一部分,最大限度地减少这方面的开销。)
基本上一个人有工作要做。 在DDD应符合工作的流程和内容。 DDD的目的是使所有的明确需要被完全和独立完成的广告尽可能的作业。 然后,UI希望有助于获得尽可能透明地进行,因为高效地工作。
接口是关于所规定的正确地建模,并且不变功能核心的输入和视图。
Answer 8:
该死的,我发誓这说的持久性。
不管怎么说,这是同样的事情多了一个实例:尔格的法律说一个模块应保守秘密,而这个秘密是可以改变的要求。 (鲍伯马丁有一个规则,就是这另一个版本。)在这样的系统中, 演示可以独立域名的更改。 比如,例如,保持价格在欧元,并在公司办公室使用法语,但想以价格以美元与普通话文字的公司。 域是相同的; 演示可以改变。 因此,最大限度地减少了系统的脆性 - 也就是说,必须改变以实现要求的改变事物的数量 - 你分开的关注。
Answer 9:
您的演示文稿可能会引用您的域层,但应该没有直接从你的UI绑定到你的域对象。 域对象不用于UI的使用,因为他们往往是,如果设计得当,周围的行为,而不是数据表示为主。 应该有UI和域之间的映射层。 MVVM,或MVP,是一个很好的模式。 如果您尝试直接绑定您的UI到域,你会probalby创造了很多头疼的自己。 他们有两个不同的目的。
Answer 10:
也许你是不是概念化足够宽泛的UI层。 可以考虑这样的反应的多种形式(网页,语音应答,印有字母等)方面和多国语言(英语,法语等)的条款。
现在,假设该电话呼叫系统语音引擎从运行的网站(也许视窗)的计算机上(例如苹果)一个完全不同类型的计算机上运行。
当然,很容易落入陷阱“那么在我的公司,我们只关心英语,在LAMP运行我们的网站(Linux操作系统,Apache,MySQL和PHP)和每个人都使用Firefox的相同版本的”。 但是,我们在5年或10年?
Answer 11:
也参见在下文中,我认为部分“层之间的数据传播”呈现令人信服的理由:
http://galaxy.andromda.org/docs/andromda-documentation/andromda-getting-started-java/java/index.html
Answer 12:
有了这样“工具的帮助价值喷油器 ”和表示层“映射器”与视图工作时的概念,它更容易理解每一段代码。 如果你的代码一点点,你不会看到立即的优势,但是当你的项目变得越来越多,你会很高兴,而与视图工作给没有进入服务的逻辑,库了解视图模型。 视图模型是一项长期的工程在反腐败层和值得其重量的广阔天地另一个后卫金。
为什么我看到使用视图模型没有优势的唯一理由是,如果你的项目足够小和简单有直接绑定到模型中的每个属性的看法。 但是,如果在未来的危机中,在视图中的需求变化和某些控件将不会被绑定到模型上,你没有一个视图模型的概念,你将开始在很多地方增加补丁,你会开始有遗留代码你会不会升值。 当然,你可以做一些重构来变换视图,视图模型视图模型的,并按照YAGNI原则,同时不增加代码,如果你不需要它,但为我自己,它更是我必须遵循添加最佳实践表示层仅暴露视图模型对象。
Answer 13:
下面是一个真实的例子,为什么我觉得它很好的做法,从视图中单独的域的实体。
几个月前,我创建了一个简单的用户界面,通过一系列的3个仪表显示氮,磷,钾的土壤样品中的值。 每个计有红色,绿色和红色部分,也就是你既可以拥有过少或过多的每个部件的,但有一个安全的绿色水平在中间。
没有太多的想法,我建模为这些3种化学成分和一个单独的数据表提供数据我的业务逻辑,包含关于各3例(其中正在使用哪一个测量单元,即摩尔或百分比)所接受的级别的数据。 然后我模仿我的UI使用一个非常不同的模式,这种模式是关心规标签,值边界值和颜色。
这意味着,当我后来不得不表现出12个组件,我只是映射额外的数据转换成12新规的视图模型,他们出现在屏幕上。 这也意味着,我可以轻松地重复使用厚度控制,并让它们显示其他数据集。
如果我有直接耦合这些仪表进入我的域实体,我不会有任何的上面的灵活性和未来的任何修改将是一个头疼的问题。 我已经在建模的UI日历时遇到非常类似的问题。 如果有一个日历约会变红的要求时,有与会者10+,那么企业的逻辑来处理这应该留在业务层和用户界面中的所有日历需要知道的是,它已经被指示变成红色,它不应该需要知道为什么。
Answer 14:
唯一合理的理由加入通用和特定领域的语义之间的附加映射是,你必须是基于广义的(但可映射)(获得)的代码(工具)现有机构的语义从您的域的语义不同。
结合一组正交的功能结构域框架(如ORM,GUI,工作流程等)中使用时域驱动的设计工作得最好。 总是记住,这是仅在外层邻接该域的语义需要暴露。 通常,这是前端(GUI)和持久性的后端(RDBM,ORM)。 任何有效的设计,中间层可以而且应该域不变。
文章来源: Why should I isolate my domain entities from my presentation layer?