40

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 -

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    
        }
    }

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

Note:

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

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

My questions are -

  1. What kind of codes belong to the Application Layer?

  2. 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?

  3. 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?

  4. 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.

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

atiyar
  • 6,349
  • 6
  • 29
  • 62
  • Application Service can return domain object *[Implementing DDD, page 522]* but should not consume it (client should call application service method to modify the object, but should not modify it directly). – Muflix Aug 11 '19 at 12:46
  • Similar illustration of layers can be found here http://dddsample.sourceforge.net/architecture.html – Muflix Aug 11 '19 at 13:01

1 Answers1

49

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.

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

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 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. The prime purpose of the application layer is mediating these back and forth activities.

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.

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.

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 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.

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.

EDIT

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.

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.

V. S.
  • 804
  • 7
  • 14
Sisyphus
  • 4,007
  • 1
  • 19
  • 15
  • @Sisyphus: +1 for now, for clean & detailed description and ofcourse for your time to enlighten me. But, more questions are gonna come to you way :) – atiyar May 06 '11 at 18:09
  • @Sisyphus: Thanks again.Your suggestion was neat and the example on the difference between the Application Services & Domain Services was very much helpful. Just one more question. Should the Application Layer ever have direct access to the Repository, or it always go through the Domain Layer? I mean, almost always, every request **fulfillment** performs some sort of domain-constraint (validation may be) checkings against any request **submission**, right? Then shouldn’t the Application Layer submit every request to the Domain Layer, and only the Domain Layer have access to the Repository? – atiyar May 07 '11 at 20:07
  • 1
    Because comments are limited I added to my answer. See the EDIT section. – Sisyphus May 08 '11 at 10:51
  • @Sisyphus: My concepts as far totally agrees on your point about the Domain Model, but i was asking if the Application Layer should call some sort of Data Access Service or Validation Checking Service **in the Domain Layer, NOT in the Domain Model**, which in turn checks the domain constraints and then either calls the Repository, or rejects the request. Let's say the Person's FirstName must contain at least 6 characters. Which layer is responsible for performing such domain constraint checkings when the Application Layer is trying to save a Person data to the database? – atiyar May 08 '11 at 21:30
  • 3
    For this example, I would just have the rule in the Person object. No one answer though. Always try to keep entities in valid state. Where to put the logic can vary. A topic of great debate - Google "Validation in DDD" to see opinions/examples. In general, proper assignment of value vs entity, avoiding setters, use of patterns like Factory to create objects and Specification to validate complex conditions are valuable techniques that can make this less problematic. Those techniques can eliminate many basic concerns. But as to how to handle complex validation cases there is no one answer. – Sisyphus May 08 '11 at 23:39
  • Thanks a LOT for your time again. Until next time... :) – atiyar May 09 '11 at 00:04
  • 2
    A final comment. Don't get too caught up in the technical details yet. Doing DDD "strictly by the book" is difficult,requires experience to really even attempt. First DDD project I worked on was before the idea got big. We had Evans to go by, limited experience and at the time little other guidance. We did not distinguish between value and entity objects, aggregates were recognized as concepts in design but not enforced in code. DDD purists would call it crap but we wrote good code and the app benefitted. You can refine your technique as you get more experience. – Sisyphus May 09 '11 at 04:15
  • I'll keep that in mind, especially when objects are even being used around "Naked" (really, i didn't know domain objects can be used in such a way and still be called "domain objects")...thanks again for your time & suggestions, and for sharing valuable thoughts :-) – atiyar May 09 '11 at 04:48