2008-08-13

Onion Architecture in Praxis

What is it?

Jeffrey Palermo has coined the pattern onion architecture, so what is it?

Actually it is "just" my default architecture, and has been for some time now. The ideas behind are not new, and it is related to other principles and patterns. Never the less I really like having a name for it, so we have a common understanding of it.

How I use Assemblies and Namespaces

First of I am a bit of a namespace fascist, every namespace in an assembly starts with the root name(The root name is the assembly name part before the first ".").

Assembly: MyDomainCore.dll

Namespaces would be something like: MyDomainCore, MyDomainCore.Something, MyDomainCore.SomethingElse etc.

Also I use folders for namespaces, so that files are located in a folder path that matches the namespace path.

How I use Namespace References

Any namespace can reference another namespace as long as it has another root name.

MyDomainTesting -> MyDomainCore (OK)

Any namespace can reference another namespace with the same root name, as long as the namespace is closer to the root name.

MyDomainCore.Infrastructure -> MyDomainCore (OK)

MyDomainCore -> MyDomainCore.Infrastructure (Not OK)

Visual Studio Solutions, Projects, and folder structure

MyDomain (Solution)

MyDomainCore (Project)

    Infrastructure (Folder)

        Bootstrapping (Folder)

MyDomainApplication (Project) [Reference to MyDomainCore]

MyDomainTesting (Project) [Reference to MyDomainCore and MyDomainApplication]

 

This is the initial setup, from here it can grow to more complex scenarios, like multiple Infrastructure implementations  or multiple applications (web, rich client, web service etc.).

What goes where?

MyDomainCore should only be POCO classes as a model and should not contain references to System.IO, NHibernate, Web or anything other that is remotely infrastructure related. It provides abstractions (abstract classes or interfaces) for Business Services used by the core(think SendEmailService and Repository). Applications Services group together the model for a given user scenario.

MyDomainCore.Infrastructure implements the business services of MyDomainCore. SendEmailService could be implemented as an SmtpSendEmailService. Repository could be implemented as a NHibernateRepository etc. Most Services will also have a stub implementation, like StubRepository and StubSendEmailService.
Classes in MyDomainCore.Infrastructure should in general not use any classes from this namespace, and should be as light as possible in.

MyDomainCore.Infrastructure.Bootstrapping wires the MyDomainCore and MyDomainCore.Infrastructure together, usually with an IOC Container. It can be configured for stub or normal usage.
It is placed in it own namespace so that I cant be referenced from the same name root.

MyDomainApplication when it is a GUI, it parses the raw user input and relays the request to the Application Services, for validation and processing. Its main purpose is to render the UI and to receive user input.

MyDomainTesting contains all automated tests, unit, integration - or as I usually categorize them Fast and Slow.

No comments: