3

I am developing a C# application following DDD and Onion Architecture concepts, but I cannot realize how to separate the code:

  1. I want it separated by modules -bounded contexts- (i.e. Sales; Suppliers; Clients)
  2. and I want it separated by layers (i.e. Core; Services)

It comes to mind doing the following: one project per layer and one folder (with an unique namespace) per module. For example:

Project Core

  • Folder Sales
  • Folder Suppliers
  • Folder Clients

Project Services

  • Folder Sales
  • Folder Suppliers
  • Folder Clients

However, I think I could do it reverse: one project per module and one folder per layer.

I dont know if there are more approaches.

Thank you.

Franco
  • 479
  • 3
  • 11
  • Separation boundaries are really defined by inter-operability. There are elements of "Sales" and "Clients" that are shared, for instance, such as the client itself. Generally when I approach DDD projects, I don't worry about these hard boundaries at the start and organize as I go. DDD concepts are to promote flexibility for change, so it plays into the narrative of the purpose, so to speak. – MutantNinjaCodeMonkey Dec 01 '15 at 21:25
  • So you start by creating a unique model, and later iteratively refinining and separating it just when it's neccesary? – Franco Dec 01 '15 at 22:20
  • 2
    Yes. Exactly. DDD is very designed to be iterative in it's approach. The odds of you hitting it out of the park the first time are pretty slim. Not necessarily because you didn't model correctly, but because you'll learn things from those supplying specifications that force change as you go. – MutantNinjaCodeMonkey Dec 02 '15 at 00:00
  • 1
    I generally initially organize my DDD projects as follows (layers/projects): Application - Used by client code or services that expose client code; Persistence - Database implementation (EF, nHibernate, etc); Domain - Contains domain objects. Doesn't know about persistence or Application. Also hosts repository-defining interfaces; Services - Code that doesn't really belong to the domain (such as vendor APIs), but is used by application layer; – MutantNinjaCodeMonkey Dec 02 '15 at 00:08
  • 1
    Depending upon the complexity and scope of the project, there are more layers. Sometimes the services don't live all under one project. Sometimes I need something to expose remoting (such as WebApi or WCF). Sometimes I store DTOs in a separate layer. – MutantNinjaCodeMonkey Dec 02 '15 at 00:10
  • Ok, so you start with "high level" architectural boundaries, like Core and Services, and later create "harder" boundaries, like Sales and Purchases (I don't know if that is the correct word) as you go learning about the domain. Now one unrelated question comes from what you explain: the Application layer is composed by WebAPI code that could return JSON objects to the clients? Does this mean that your MVC layer is totally disconnected and cannot make use of the Entities defined in the Core for binding in Views? (that would mean I have to create ViewModels for each View) – Franco Dec 02 '15 at 01:38
  • 1
    I generally have an application layer that has no knowledge of how it's used by the clients. A webapi/mvc layer will wrap those calls. And if there is a presentation layer in the solution (a web site), that will call the application layer methods too. – MutantNinjaCodeMonkey Dec 02 '15 at 03:52
  • 1
    I think you're asking if it's okay to use the domain objects in the other layers. That's kind of a religious question. ;) Some developers are fine with exposing them in the application layer. In my experience, especially when they're bound to a persistence solution like EF, I tend to prefer to only expose DTOs out of the application layer. That way the whole transaction is encapsulated and only relevant data comes out of the calls. – MutantNinjaCodeMonkey Dec 02 '15 at 03:57
  • 1
    If you want independent deployability of your modules, second option is the way to go. – guillaume31 Dec 02 '15 at 08:05
  • @MutantNinjaCodeMonkey _"That way the whole transaction is encapsulated and only relevant data comes out of the calls_" I think that is something with which I will be fine. Thank you for your precise answers :). – Franco Dec 02 '15 at 14:06

2 Answers2

5

One approach that works well in VS is the following:

  • Create one project per module. This is a natural approach, because you have explicit dependencies between projects.
  • Use Solution Folders to group the projects into layers. You can prefix the layer with a number, so that it shows up in order within visual studio. Note that solution folders are virtual, i.e. not visible in the file system, but that is usually not a concern.
theDmi
  • 17,546
  • 6
  • 71
  • 138
  • So you would have, for example, Core/Sales, Core/Suppliers, Application/Sales, Application/Suppliers, Infraestructure/Sales, Infraestructure/Suppliers? – Franco Dec 02 '15 at 14:30
  • @Franco If `Sales` and `Suppliers` are different BCs (which I assume based on your question), then this is a good structure. If they are however separate applications (frontends) to the same BC, then make a single domain module. Also, infrastructure will probably be one module in that case. – theDmi Dec 02 '15 at 14:33
  • I edited the question to clarify that modules are BCs, thanks. I like your approach, but there won't be a lot of assemblies in the entire solution? I don't know if nowadays that is an actual problem to worry about. – Franco Dec 02 '15 at 14:44
  • It's a trade-off, but a few assemblies (like 10 - 20) don't hurt at all. But decide on the trade-off for yourself! Overall, I like this answer as a general guideline: http://stackoverflow.com/a/568789/219187 – theDmi Dec 02 '15 at 15:00
  • Very useful, I just wanted to know that in advance. – Franco Dec 02 '15 at 15:32
3

Based on the last DDD project i did i came to the following:

  • 1 project for your domain model. (per bounded context) Since in a DDD it's important everyone speaks the same language/model make this into 1 project.

  • Use solution folders to separate layers, (like theDmi mentioned)

  • Start with 1 project in each layer and refactor as needed. Assuming some kind of agility in your approach there is no need to lay out your whole project structure in advance. Just like you can refactor classes, refactor projects. Keep the following in mind

1) Does have a project have their own reason to exist. For example a car has a reason to exist, i can buy one, replace one etc. An engine part has no reason to exist on it's own. I never buy it unless i have the matching car.

2) Avoid the "Too few classes in this namespace" warning from code analysis. If i have only a few type of cars within each brand (and don't deal with many individual car parts) put a whole brand into a single project

3) Does looking at a single project hierarchy fit within a screen (or 2) in your solution explorer. As soon as you start searching for aclasses you know that exist within a project then consider splitting the project. For example cars can be separated by brand.

Let the complexity of your solution grow as your project grows. Although i've seen solutions with 100 project i've rarely seen it work. The same goes for projects with more than 100 (maybe a bit more for projects) classes.

If you keep it between those you are probally safe.

Update Look at a code map of your projects. If it tells a meaningfull story then you are good. If it doesn't try to figure out what needs to change.

Batavia
  • 2,497
  • 14
  • 16