Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Some Questions about structuring domain-driven-design namespaces

I have some general questions about framework design.

I am building an API for an iPhone application in C#.NET (framework 3.5), & SQL 2008 (using LINQ). I have followed the Domain-Driven-Design pattern (in a book) and have the following folder structure:

Core
- DataAccess
--Impl
-Domain
-Impl

Core is my core API library - my DLLs. DataAccess contains the data access interfaces DataAccess.Impl contains the repositories (LINQ to the DB) Domain contains most of my data types and properties. Impl contains my services (i.e. AccountService.cs, EmailService.cs)

Now, as an exercise, I have added a Windows Service to this project and am attempting to call functionality from the DLLs in this service. MY QUESTION IS, what layer should I be exposing to other applications and what should stay hidden?

  • Should the service classes from the Impl folder be what programmers see?
  • Or the Repositories from DataAccess.Impl?
  • Or, should i just lay it all out for the programmers to see? As it looks now, this seems sort of confusing.

When I started reading about DDD I was assuming that the repositories would be hidden and accessed by the service classes, but I am finding I need to call functionality from both in my client. Have I designed this wrong?

My other question has do do with namespace naming. When the Windows Service calls functionality from my core library, I have to do my includes as such:

using Company.Product.ProductCore.Core.DataAccess.Impl 
using Company.Product.ProductCore.Core.Domain 
using Company.Product.ProductCore.Core.Impl

This seems wordy. Looking at Microsoft's DLLs, they seem to keep with a two-tier convention - (System.Linq, System.Text, etc). Having Company.Product.ProductCore.Core.Impl seems messy and doesn't really tell the programmer what this namespace does (but it is what was suggested by the example I read). Is there a best practice here?

Your suggestions (and any examples) are seriously appreciated.

Thanks.

like image 535
Peter Avatar asked Dec 04 '10 18:12

Peter


2 Answers

The domain is definitely not what you're looking for, in my opinion, neither is your data access layer.

In my humble opinion, what would have to be exposed is not yet there, that is, a static class, let's say, if we consider the Façade design-pattern, which exposes your library subsystems features and functionalities.

alt text

The Façade design pattern explained:

  1. Façade Design-Pattern - (Gang of Four);
  2. Facade pattern (Wikipedia).

So in the end, what is your code supposed to do? Just expose what is necessary, which you ought to know, since you're the only one to know about the system you're developing.

In short, I often use the Façade pattern so that I can isolate my classes, implementations and several related subsystems under the hood of a façade. Let's consider we are a brand new car dealer. This façade will be the great windows which let you see the cars exposed in the show room. You got to think of what this façade exposes. Does it expose only cars?

In my opinion, this façade exposes cars, which you will be able to buy, to borrow money to buy, to repair the car, to buy other related accessories, etc. The accessories are then to be exposed, but only what needs to. The same with the other items such as the car. That is, you might want to expose an interface only, and keep the implementation for yourself, so that through you façade, when you got to return an ICar or an IAccessory, you have to instantiate them through your implementation object class, then return the interface instance through your façade. That said, the user doesn't need to know what is going on under the hood, but only that if he wants a car, he has to order it through your façade. Just like you won't go buy a Mazda 3 to Mercedes Benz. You'll work with the right façade. Then again, the different car dealers might only be subsystems, hence some kind of factories. Then you ask the façade for a car with this and that specifications, and the façade should know what ICar instance to return to exchange for what you're asking it to provide you with.

Hope this helps anyway! =)

like image 70
Will Marcouiller Avatar answered Nov 09 '22 02:11

Will Marcouiller


If I'm not mistaken, you are asking two questions:

  1. How to structure a DDD application?
  2. What about those long namespace names?

My answer is rather lengthy - I took the liberty of splitting it into two anwsers.

This is an answer to the second question:

2. What about those long namespace names

I don't think long namespace names are necessarily messy. IMHO what looks messy in your names are:

  • the repeating of the words "Product" and "Core"
  • The use of the general term "Impl"

A first improvement could be:

// The Domain objects go here;
MyCompany.MyProduct.Core.Domain;  
// DataAccess interfaces go here:
MyCompany.MyProduct.Core.DataAccess;
// a Linq implementation of the DataAcces interfaces go here:
MyCompany.MyProduct.Core.DataAccess.LinqImpl; 
// The Core service go here:
MyCompany.MyProduct.Core.Services;
// Some general purpose infrastructure goes here (e.g. emailing code)
Mycompany.MyProduct.Infra;

Furthermore, I find that the use of a commercial product name (such as MyProduct) in the code structure is bad (what if marketing chooses a different name?); I like to use the name of logical subsystems instead. Let's assume your building car rental system. Then CarRental will be considered the core functionality of this app. Then I'd use the following namespace structure (Serra is the name of my company):

// For classes Customer, Account, Car
Serra.CarRental.Domain;    
// I use Dao as a general abbreviation for "Data Access Objects"
// Dao interfaces go here:
Serra.CarRental.Dao;     
// Linq implementation for Dao interfaces  
Serra.CarRental.Dao.Linq;
// For Services specific to the car rental domain: 
// AccountService and RentalService and CarAvailabilityService
Serra.CarRental.Services;  
// For UI objects (not relevant in you situation?)
Serra.CarRental.UI;
// general service code; ignorant of the CarRental domain (e.g. an EmailService)
Serra.Infra.Service;       
like image 39
Marijn Avatar answered Nov 09 '22 02:11

Marijn