43

我对软件开发非常陌生。我认为分层架构是减少面向对象软件开发过程中出现的复杂性的好方法,更不用说保持代码的组织性了。

我有兴趣了解领域驱动设计方法,并且我遇到了一些问题来让自己了解它(当然,初学者级别的)。
这里是 -

我想构建一个应用程序来将人员相关数据保存在数据库中并在 WPF 中显示人员详细信息DataGrid(我知道,DDD 绝对不适合这种规模的应用程序,而只是为了让像我这样的业余爱好者保持简单)。所以,我创建了一个域类“Person”,比如——

    public class Person
    {
        public Person(dataType paramA)
        {
            this.PropertyA = paramA;
        }

        private dataType _fieldA;
        public dataType PropertyA
        {
            //encapsulates _fieldA    
        }

        public dataType PropertyX
        {        
            //some code that manipulates private field    
        }

        private dataType MethodPQR(dataType param)
        {        
            //some code    
        }
    }

现在,我对 DDD 的理解说架构(它的最简单版本)应该如下(如果我错了,请纠正我) -
在此处输入图像描述

笔记:

  1. 我希望DataGrid绑定到一些ObservableCollection,以立即反映任何类型的变化。

  2. 这是一个 WPF 应用程序,但不一定是 MVVM 模式,我故意想使用后面的代码。

我的问题是——

  1. 什么样的代码属于Application Layer

  2. 我的猜测是,我绝对不应该将ObservableColletion我的域对象(即Person)绑定ItmsSourceDataGrid. 那么我应该从域对象中提取什么类型的对象,以及如何提取?

  3. 为了保持两者之间的脱钩Presentation LayerDomain Layer可能有一个像never instantiate domain objects directly in the presentation layer. 那有哪些non-direct方法呢?

  4. 如果代码隐藏与该对话,Application Layer那么应该与该Application Layer对话Data Repository吗?但是,如果需要某种与数据访问无关的域访问可能不在此应用程序中,但可能会发生,对吗?)在那种情况下,应该是谁(子X层/模块)谈?Domain LayerApplication Layer

我知道我的问题是非常业余的水平,但它们确实是从我面临的问题中提出的问题,以获得清晰的画面。因此,如果有人有时间,将不胜感激。

编辑:我不确定是否Data Repository应该参考Domain Model.

4

1 回答 1

52

就更“经典”的 DDD 而言,是的,域对象通常不允许在域之外的任何地方。但表示层不使用领域对象也不是绝对的规则。例如,Naked Objects 代表了直接使用领域对象的一种思想流派。我自己主要坚持不直接使用域对象的哲学,所以我不熟悉他们建议的所有实践,我个人认为直接绑定到域对象是不明智的,但是......只要坚持请注意,并非每个人都将此视为一项要求。

如果您不允许域本身之外的域对象,您通常会使用 DTO 或数据传输对象,它们只是具有属性的类,而此类 DTO 类没有域行为。DTO 通常准确地反映域模型结构,但并非必须如此。

业务逻辑应该在域模型中实现,因此应用层中的大部分内容都涉及协调各种服务,通常是将数据传入和传出客户端应用程序。许多人为此使用某种形式的 SOA 或至少是 Web 服务。这些调用存储库,但也需要其他组件(例如汇编程序)获取从存储库调用返回的域对象并将属性值复制到 DTO,然后可序列化并返回给调用者。调用者通常是演示者或控制器,但如果您不使用 MVC 或 MVP,调用者仍将位于表示层。反向行程更复杂 - UI 可能会发回代表更新的 DTO 或代表要添加的新对象的 DTO。

至于领域层的“非数据访问”,有几个典型的例子。大多数人通常将您可能认为的“X”组件称为域服务。域服务与应用程序服务的不同之处在于它接近域模型和实际业务逻辑的存在。

例如,如果一个应用程序涉及某种下订单,实际上有两个问题 - 下订单和订单履行。应用程序服务协调将制定订单放置所需的数据传输到 UI,然后返回用户希望放置的订单。但这只是调解数据传输,这就是应用程序服务结束的地方。然后可能需要域服务来应用业务规则并构建实际履行该订单所需的其他域对象。

总的来说,我发现这是一个有用的概念或隐喻,可以应用于许多场景 - 应用程序服务仅在请求提交方面促进某种类型的请求。另一方面,域服务有助于实际的请求实现

除了面向数据之外,我遇到或可以轻松想象的唯一“访问”模式是面向过程的功能。这并不是在每个应用程序中都会遇到,但在某些领域很普遍。例如,在我工作的医疗保健领域,您可能需要包含管理临床数据和临床过程的重要元素的应用程序。我通过不使该过程强调成为我的域模型的一部分并为此使用不同的工具来解决这个问题。

OOP 技术不太适合实际流程本身,它们对于向流程提供数据和从流程捕获数据很有用。毕竟,面向对象也主要是面向名词的。对于实时流程管理,您需要“面向动词的编程”而不是“面向名词的编程”。工作流工具是“面向动词”的工具,可以补充数据密集型和流程密集型应用程序的领域驱动模型。我做了很多涉及 C# DDD 模型和 Workflow Foundation 模型的工作,但同样只需要某些类型的应用程序。许多典型的业务应用程序只需要域模型和服务。

最后,DDD 最重要的方面不是任何技术或架构。它的真正核心围绕着无处不在的语言以及与领域专家的互动(在我看来是直接互动),以提炼出关键的领域知识。(我认为大多数声称做 DDD 的公司都没有,因为很多公司拒绝让业务和开发直接交互,但那是另一个话题......)它是领域知识的提取和合并,而不是任何真正将 DDD 与传统 OOP 分开的技术,这就是 DDD 的真正价值所在。

编辑

就存储库的使用而言,该图是正确的。通常,应用层总是通过域对象的存储库。首先,您必须能够将数据带到应用程序中,并且大多数应用程序还需要一定程度的查询能力。

领域层 OTOH 通常不存储库交互。通常,您希望领域模型是自包含的并与任何特定技术分离,即它应该代表“纯领域知识”。持久性本质上与某种特定技术紧密耦合,因此一般来说,人们努力使他们的领域模型摆脱任何持久性实现。您有存储库,但您通常不想在域模型中调用存储库方法。

在领域模型本身中,对象要么作为新对象(可以直接实例化或通过工厂实例化)获得,要么通过遍历关联获得。有时在创建新对象时,将所需的所有内容传递给构造函数是不切实际的,因此这是您可能需要在域模型本身内进行某种数据访问的一种情况。通常人们所做的是通过接口传入数据服务,以便可以为域模型提供数据访问,但仍与数据层实现分离。但在大多数情况下,域对象与已经实例化的其他域对象进行交互和交互。

于 2011-05-05T12:11:20.193 回答