Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement a maintainable and loosly coupled application using DDD and SRP?

The reason for asking this question is that I've been wondering on how to stitch all these different concepts together. There are many examples and discussions on i.e. DDD, Dependency Injection, CQRS, SOA, MVC but not so many examples on how to put them all together in a flexible way.

My goal:

  1. Develop modules that with little or no modification can stand on their own
  2. Changing or reworking the UI should be as easy as possible (i.e. the UI should do as little as possible, and be "stupid"
  3. Use documented patterns and principles

To make it easier to ask a concrete question, the main arcitecture now looks like this:

Employee management example

The example shows how to add a note to an employee. Employee Management is one bounded context. Employee has several properties, among those an ICollection<Note>.

The bound context is in my understanding the logic place to seperate code. Each BC is a module. Most of the time I find each of them can warrant their own UI if needed (i.e. some modules might be made available for Windows phone).

The Domain holds all business logic.

The infrastructure holds repository implementation, and services to send mail, save files and utilities that does not belong in the domain. I'm thinking of making some of the common service feautures that I have to use in several domains (like send e-mail) as a sort of an API that I could reference to save some code implementing the same things across several BC's.

The query layer holds all Querys except GetById that I need in the repository to fetch an object. The query layer can query other persistence instances, and will probably need to change some for each UI.

The Wcf or Web Api is kind of my Application layer, it might belong in infrastrucure and not on the outside. This service also sets up the dependencies, so all UI need to do is to ask for information and send commands.

The process starts with the blue arrows. Read the model since that has most of the information.

In step 1 the EmployeeDto in this example is just some of employee properties to show the user information about the employee they need to make a note on (like a note about new experience or something like that).

So, the questions are:

  1. Does implementing a layered arcitecture like this really involve so much mapping, or have I missed something?
  2. Is it recommended (or even smart) to use a Wcf service to run the main logic like this (it practically is my Application Service)
  3. Are there alternatives to Wcf without having my domain objects in my UI layer?
  4. Is there anything wrong with this implementation. Any fall pits to look out for?

  5. Do you have any good examples to recommend looking at that can help me to understand how all these concepts are supposed to work together.

Update: I've read through most of the articles now (quite a bit of reading) except for the paid book (requires a bit more time to do). All of them are very good pointers, and the way of thinking of the Wcf of more as an adapter seems to be a good answer to question 2. JGauffins work on his framework is also very interesting if I'm planning to go the that route.

However, as mentioned in some of the comments beneath I feel some of the examples tends towards recommending or implementing event and/or command sourcing, message buses and so on. To me it is overkill to plan for that level of scaling right now. As many business applications this is a "large" (in terms of an internal application, think max a few thousand) number of users working on a large set of data, not a highly collaborative domain in the sense of needing to implement event and command queues often assosiated with CQRS to cope with that.

Based on the answers below, the approach I'll start with will be based on the model above and the answers like this:

  1. I'll just have to cope with mapping. Thoe pros outweighs the cons.

  2. I'll pull application services back to the infrastructure and consider Wcf as an "adapter"

  3. I'll use command objects and send to application service. Not polluting my domain with domain objects.

  4. To keep complexity down I try to manage without event/command sourcing, message buses etc for now.

In addition I just wanted to link to this blog post by Udi Dahan about CQRS, I think things like this keeps complexity down unless they are really needed.

like image 940
cfs Avatar asked Nov 27 '12 20:11

cfs


2 Answers

  1. There is a trade-off between mapping and layers. One reason certain mappings exist is because appropriate abstractions aren't available or feasible. As a result, it is often easier to just explicitly map between layers than trying to implement a framework that infers the mappings, but I digress; this hinges on a philosophical discussion of the issue.

  2. The WCF or WebAPI service should be very thin. Think of it as an adapter in a hexagonal architecture. It should delegate everything to an application service. There is conflation of the term service which causes confusion. Overall, the goal of WCF or WebAPI is to "adapt" your domain to a specific technology such as HTTP. WCF can be thought of as implementing an open host service in DDD lingo.

  3. You mentioned WebAPI which is an alternative if you want HTTP. Most importantly, be aware of the role of this adapting layer. As you state, it is best to have the UI depend on DTOs and generally the contract of a service implemented with WCF or WebAPI or anything else. This keeps things simple and allows you to vary implementation of your domain without affecting consumers of open host services.

  4. You should always be on the lookout for needless complexity. Layering is a trade-off and sometimes it can be overkill. For example, in an app that is primarily CRUD, there is no need to layer this much. Also, as stated above, don't think of WCF services as being application services. Instead, think of them as adapters between a transport technology and application services. In turn, think of application services as being a facade over you domain, regardless of whether your domain is implemented with DDD or a transaction script approach.

  5. What really helped me understand is the referenced article on the hexagonal architecture. This way, you can view your domain as being at the core and you layer things around it, adapting your domain to infrastructure and services. What you have seems to already follow these principles. A great, in-depth resource for all of this is Implementing Domain-Driven Design by Vaughn Vernon, specifically the chapter on architecture.

like image 61
eulerfx Avatar answered Nov 03 '22 15:11

eulerfx


Does implementing a layered architecture like this really involve so much mapping, or have I missed something?

Yes. The thing is that it's not the same object. It's different representations of the same object, but specialized for each use case. A view model contains logic to update the GUI, a DTO is specialized for transfer (might get normalized to ease transfer). etc. etc. They might look the same, but they really aren't.

You could of course try to put all adaptations into a single class, but that would not be very fun to work with when your application grows.

Is it recommended (or even smart) to use a Wcf service to run the main logic like this (it practically is my Application Service)

You need some kind of networking layer. I wouldn't let all client applications touch my database. It would create a maintenance nightmare if you mess with the database schema (if some of the clients still run the old version).

By using a server it's much easier to maintain version differences.

Do note the a WCF service definition should be treated as constant once being used. Any changes should be defined in a new interface (for instance MyService2).

Are there alternatives to Wcf without having my domain objects in my UI layer?

You could take a look at my framework. Start post: http://blog.gauffin.org/2012/10/writing-decoupled-and-scalable-applications-2/

Is there anything wrong with this implementation.

Not that I can see. Looks like you have a pretty good grasp of the concepts and how they should be used.

Any fall pits to look out for?

Don't try to be lazy with the queries and commands. Don't make them a bit more generic to fit several use cases. It will come back and bite you when the application grows. Smaller classes is easier to maintain.

Do you have any good examples to recommend looking at that can help me to understand how all these concepts are supposed to work together.

The my linked blog post and all other articles in that series.

like image 2
jgauffin Avatar answered Nov 03 '22 16:11

jgauffin