域驱动设计-应该如何组织层?

问题描述 投票:34回答:1

我对软件开发非常陌生。我认为分层体系结构是减少面向对象软件开发过程中出现的复杂性的一种好方法,更不用说使代码井井有条了。

我有兴趣学习域驱动设计方法,并且遇到了一些问题,无法自我介绍(当然,是初学者级的)。这是-

我想构建一个应用程序,将与人相关的数据保存在数据库中,并在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对话?但是,如果需要某种与[[not数据访问相关的域访问(可能不在此应用中,但是可能会发生,对吗?),在那种情况下,那个X家伙(子层)是谁? / module)Domain Layer应该与之对话的内容?

我知道我的问题是非常业余的,但实际上,这些问题是我为了清楚地了解所面临的问题而提出的。因此,如果有人有时间,我们将不胜感激。

EDIT:我不确定Application Layer是否应具有Data Repository的引用。

domain-driven-design repository code-organization project-organization layer
1个回答
39
投票
就更“经典”的DDD而言,是的,通常不允许在域外的任何地方使用域对象。但是,在表示层中不使用域对象并不是绝对的规则。例如,“赤裸对象”代表一种思想流派,其中直接使用领域对象。我本人主要坚持不直接使用域对象的哲学,因此我对它们建议的所有实践都不熟悉,我个人认为不建议直接绑定到域对象,但是...请记住并非每个人都将此视为要求。

如果不允许域对象超出域本身,通常将使用DTO或数据传输对象,它们是仅具有简单属性的类,没有域行为。 DTO通常可以准确地反映域模型的结构,但不必如此。

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

就域层的“非数据访问”而言,有几个典型示例。大多数人通常将您可能想到的“ X”组件称为域服务。域服务与应用程序服务的区别在于它与域模型的相似性以及实际业务逻辑的存在。

例如,如果应用程序涉及某种类型的订单下达,则实际上存在两个问题-订单下达和订单履行。 Application Services中介将制定订单放置所需的数据传输到UI,然后返回用户希望放置的订单。但这仅是中介数据传输,这就是Application Services的终点。然后可能需要域服务来应用业务规则并构造实际完成该订单所需的其他域对象。

通常,我发现这是一个可以应用于许多场景的有用概念或隐喻-应用服务仅根据请求

submission促进某种请求。另一方面,域服务有助于实际请求完成

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

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

最后,DDD最重要的方面不是任何技术或体系结构。它的真正核心围绕着无处不在的语言以及与领域专家的互动(在我看来,DIRECT与之互动)中,以提取出关键的领域知识。 (在我看来,大多数声称进行DDD的公司并不是因为如此多的公司拒绝允许业务和开发直接进行交互,但这是另一个主题...)这是领域知识的提取和整合,而不是任何领域的知识。实际上将DDD与常规OOP分开的技术,DDD的真正价值就在此出现。

编辑

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

域层OTOH通常不会与存储库进行交互。通常,您希望域模型是独立的并与任何特定技术分离,即它应该表示“纯域知识”。持久性与某种特定技术本质上紧密地联系在一起,因此通常人们会努力使自己的域模型不受任何持久性实现的约束。您有存储库,但通常不想在域模型中调用存储库方法。

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

© www.soinside.com 2019 - 2024. All rights reserved.