域驱动设计-应该如何组织各层? [英] Domain Driven Design - how the layers should be organized?

查看:88
本文介绍了域驱动设计-应该如何组织各层?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm very much new to software development. I think layered architecture is a great way to reduce the complexities that arise in the process of object oriented software development and, not to mention, to keep your code organized.

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

I'm interested to learn about Domain Driven Design approach and I've run into some problems to get myself introduced to it (of course, beginner level ones).
Here it is -

我想构建一个应用程序,以将与人相关的数据保存在数据库中,并在WPF中显示人的详细信息DataGrid(我知道,DDD绝对不适用于如此规模的应用,而只是为了使业余爱好者保持简单像我这样的).因此,我创建了一个域类"Person",例如–

I want to build an application to save person related data in database and display person details in a WPF DataGrid (I know, DDD is definitely not for the apps of such scale, but just to keep things simple for an amateur like me). So, I created a domain class "Person", something like –

    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的理解是,该体系结构(最简单的版本)应如下所示(如果错了,请纠正我)-

Now, my understanding of DDD says the architecture (the simplest version of it) should be as follows (please, correct me if I'm wrong) -

注意:

  1. 我希望将DataGrid绑定到某些ObservableCollection,以立即反映任何类型的更改.

  1. I want the DataGrid to be bound to some ObservableCollection, to reflect any kind of changes instantly.

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

It's a WPF application but not necessarily be in MVVM pattern and I deliberately want to use the code behind.

我的问题是-

  1. Application Layer属于哪种代码?

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

My guess is, I should definitely not bind an ObservableColletion of my domain object (i.e. Person) as the ItmsSource of the DataGrid. What type of object then I should extract from the domain object, and how?

为使Presentation LayerDomain Layer之间保持解耦,可能存在类似never instantiate domain objects directly in the presentation layer的约定.那么non-direct的方法是什么?

To keep a decoupling between Presentation Layer and Domain Layer probably there's a convention like never instantiate domain objects directly in the presentation layer. What are the non-direct approaches then?

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

If the code-behind talks to the Application Layer then should the Application Layer talk to the Data Repository? But what if some kind of domain access is needed which is not data access related (may be not in this app, but it may occur, right?) In that scenario, who's that X guy (sub-layer/module) in Domain Layer that the Application Layer should talk to?

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

I know my questions are of very much amateur level, but they are questions indeed, raised from problems I'm facing to get a clear picture. So, if anybody has time, any response will be appreciated.

:我不确定Data Repository是否应具有Domain Model的引用.

EDIT : I'm not sure if Data Repository should have a reference of Domain Model.

推荐答案

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

Speaking in terms of more "classical" DDD, yes domain objects are typically not allowed anywhere outside of the domain. But it is not an absolute rule that domain objects are not used in the presentation layer. For example Naked Objects represents a school of thought where domain objects are used directly. I myself adhere mostly to a philosophy where domain objects are not used directly, so I am not familiar with all the practices they suggest, I personally would think binding to a domain object directly would be ill advised, but ... Just keep in mind not everyone views this as a requirement.

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

If you do not allow domain objects outside of the domain itself, you would typically use DTO or Data Transfer Objects which are simple property only classes that do not have domain behaviors. DTOs often mirror the domain model structure exactly but do not have to.

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

Business logic is supposed to be implemented in the domain model, so much of what is in the application layer is involved with coordinating various services, typically to bring the data to and from the client applications. Many people use some form of SOA or at least web services for this. These call the repositories but also require other components such as assemblers to take the domain objects returned from repository calls and and copy the property values into DTOs, which are then serializable and returned to the caller. The caller is often a presenter or controller but if you are not using MVC or MVP the caller would still be in the presentation layer. The reverse trip is more complex - the UI may send back DTOs that represent updates or DTOs that represent new objects to be added. Mediating these back and forth activities is primarily the purpose of the application layer.

关于域层的非数据访问",有几个典型示例.大多数人通常将您可能会想到的"X"组件称为域服务.域服务与应用程序服务的区别在于它与域模型的接近性以及实际业务逻辑的存在.

As far as "non-data access" of the domain layer, there are a couple of typical examples. Most people usually refer to the "X" component you may be thinking of as a Domain Service. A Domain service differs from an Application Service by it's proximity to the domain model and the presence of actual business logic.

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

For example, if an application involves some kind of order placement, there are actually two concerns - order placement and order fulfillment. Application Services mediate the transfer of the data needed to formulate an order placement to the UI and then return the order that the user wishes to place. But that is only mediating data transfer and that is where Application Services end. A Domain Service may then be needed to apply business rules and construct additional domain objects that are needed to actually fulfill that order.

总的来说,我发现这是一个适用于许多场景的有用概念或隐喻-应用服务仅根据请求 submission 简化了某种请求.另一方面,域服务有助于满足的实际要求.

In general I find that to be a useful concept or metaphor that can be applied to many scenarios - an Application Service facilitates a request of some sort, in terms of the request submission only . A Domain Service on the other hand facilitates the actual request fulfillment.

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

The only other mode of "access" other than data oriented I have encountered or can readily imagine is process oriented functionality. This is not encountered in every application but is prevalent in certain fields. For example in healthcare where I work you may want applications that incorporate significant elements of managing both the clinical data as well as the clinical process. I solve this problem by not making that process emphasis a part of my domain model and using different tools for that instead.

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

OOP techniques are not well suited for an actual process itself, they are useful for providing data to and capturing data from a process. Object oriented is after all also primarily noun oriented. For real time process management you need "verb oriented programming" more than "noun oriented programming". Workflow tools are "verb oriented" tools that can be complementary to Domain driven models for applications that are both data intensive and process intensive. I do a lot of work that involves both C# DDD models and Workflow Foundation models, but again this is only needed for certain types of applications. Many typical business apps only require domain models and services.

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

Finally the most important aspect of DDD is not any technique or architecture. The real heart of it revolves around the Ubiquitous Language and interaction with (in my strong opinion DIRECT interaction with) domain experts to distill out critical domain knowledge. (Most companies that claim to do DDD in my opinion do not because so many companies refuse to allow the business and development to interact directly, but that is another topic... ) It is the extractions and incorporation of domain knowledge, rather than any technique that actually separates DDD from conventional OOP and that is where the real value of DDD arises.

编辑

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

As far as repository use goes, the diagram is correct. Typically the application layer always goes through a repository for domain objects. First of all you have to be able to bring data to the application, and most applications also need some level of query ability.

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

The domain layer OTOH usually does not interact with repositories. Typically you want the domain model to be self contained and decoupled from any specific technology, i.e it should represent "pure domain knowledge". Persistence is inherently tightly coupled to some sort of specific technology, so in general people strive to make their domain models free of any persistence implementation. You have repositories but you typically do not want to call repository methods in the domain model.

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

Within the domain model itself objects are obtained either as new objects (which may be instantiated directly or through a factory) or else reached by traversing associations. Sometimes when creating a new object it is impractical to pass everything needed into a constructor, so this is one case where you might need some sort of data access within the domain model itself. Usually what people do is pass in a data service via an interface so that the domain model may be provided with data access but remains decoupled from the data layer implementation. But for the most part domain objects act and interact with other domain objects that are already instantiated.

这篇关于域驱动设计-应该如何组织各层?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆