For the web application (ASP.NET MVC) I'm currently developing, we have the following architecture in place:
Data Access Layer
: Logic for persisting data to an arbitrary dbDomain
: The data modelService Layer
: Business logic (e.g. order processing, account management, etc.)Controller
: Consumes services and provides/receives data to/from the ViewView
: The user interface for the userIn essence, I took the Model
and split it up into the DAL
, Service Layer
and Domain
. I felt that stuffing all the logic within the Model
made my code overly complicated. Furthermore, I felt that it let me express my business logic cleanly without making the controller do too much work.
My question then is: What is this type of architecture called?
As a secondary question: Does this type of architecture make sense? If not, am I doing something wrong?
The types that will be discussed here—domestic, religious, governmental, recreational, welfare and educational, and commercial and industrial—represent the simplest classification; a scientific typology of architecture would require a more detailed analysis.
While classical architecture was largely replaced by modernism and contemporary architecture in the 20th century, classical architecture continues to be built in what has been rebranded as "new classical" style.
The Characteristics of 12 Architectural Styles From Antiquity to the Present Day.
You are on the right track about DDD depending on how thin / thick the domain & service layers are. DDD says that the knowledge (i.e. business logic) should be crunched into the domain model. Moving data access concerns to the DAL is in line with DDD, but I think moving business logic out into a Services Layer is not. If you have a thin Domain "data model" layer (mostly for entities) and a thick Services layer (mostly for "business logic"), you may have an anemic domain.
Also, there is technically no "Service Layer" in DDD. There may be an "Application Layer", but it should be thin, and only be responsible for application flow / managing domain class lifetimes. This is essentially what Controllers do in .NET MVC, manage application flow in the context of web http.
If stuffing all of the logic within the Model made your code overly complicated, I'd be interested to hear examples of what you mean by "overly complicated". You could be correctly modeling a complex domain, or there are chances you could have gone to DDD patterns to uncomplicate things. I would say as you have listed it in your question, the arch is not DDD. I would just call it "Layered architecture", but that's because I prefer to use the term "tier" only when talking about physical arch. However, your logical architecture is layered.
I really like that Darin linked to Onion arch in his answer. I'm becoming a big fan of it, and I find it's not exclusive to DDD at all. If your code uses dependency injection to solve interface dependencies with runtime implementations, you may have a form of onion arch. For example, do you define any interfaces in your DAL? Are implementations of those interfaces solved at runtime?
Here is an example of an arch I am starting to use in my new projects. It's a combination of onion + DDD:
API
Project/Assembly: generic interfaces, enums, classes, and extension methods used by all other layers. Need not be separate from Domain, but may.
Domain
Project/Assembly: all entities and business logic. Depends on API
only. Uses DDD patterns like factory, service, specification, repository, etc. Also contains more domain-specific interfaces which are not defined in the API.
Impl
Project/Assembly: implementations of interfaces defined in API
and Domain
. This is where the EF DbContext is implemented, as well as things like logging, email sending, etc. All of these implementations are dependency-injected, so technically you could have several Impl projects / assemblies.
UI
Project/Assembly: This is the MVC project. Controllers consume the domain surface directly, and do not go through an application or service layer. Any interface dependencies in factories, services, repositories, etc, are injected into the domain by the controller using MVC IoC (constructor injection).
I placed an API layer at the very core but you could combine the API and Domain projects into one. Either way, the big meaty part of the onion is the Domain, and it has internal layering. For example Services may depend on Factories, which depend on Repositories, which depend on Entities.
The Impl project is what you see as the "Infrastructure" onion skin in Palermo's diagram. It is at the outer edge along with the UI, and contains no domain-specific knowledge. It knows how to send email, store/retrieve data using EF, etc. If you want, you can have more than 1 of these -- for example 1 Impl for data access, 1 Impl for dealing with mail, etc.
MVC has the Controllers and Views, and concentrates on the UI and web application flow. Anything that requires domain-specific knowledge is delegated out to the domain, and domain classes are constructor injected into the controller. This means any constructor-injected interfaces in domain classes are resolved automatically by the IoC container.
As a final note, programming against interfaces defined in the API and Domain classes means you can unit test the domain project separately from the MVC project.
From a high level, I'd describe it as layered architecture. Describing it as domain-driven design would also look at smaller patterns like aggregate, repository, bounded contexts, etc. I can't tell just from your description.
If the domain layer resides in an assembly/package that doesn't reference any of the others, then it has the core of the Onion Architecture principles, which are:
A concrete thing to look for is if your DataAccess references Domain.
There could be different names depending from which angle you are looking at it. So it's still MVC, it's just that your M is split into multiple layers. It could also be called Multitier architecture (or N-tier architecture). Jeffrey Palermo also used the notion of Onion architecture.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With