patterncsharpModerate
Onion Architecture
Viewed 0 times
onionarchitecturestackoverflow
Problem
After doing a whole bunch of research on Onion Architecture, I have made an attempt at implementing this in a new system that we are developing.
We have the Layers as per below:
Domain.Entities - All the domain models are kept here.
Base Entity
Company Entity
Domain.Interfaces - I have a bunch of generic interfaces programmed here.
```
namespace Domain.Interfaces
{
public interface IReadRepository where TEntity : class
{
IQueryable All ();
TEnti
We have the Layers as per below:
- Domain
Domain.Entities
Domain.Interfaces
- Infrastructure
Infrastructure.Data
Infrastructure.DependencyResolution
Infrastructure.Interfaces
Infrastructure.Logging
- Services
Services.Interfaces
- Tests
Tests.Core
- Web
Web.UI
Domain.Entities - All the domain models are kept here.
Base Entity
namespace Domain.Entities
{
public class BaseEntity
{
public virtual Guid ID { get; set; }
public virtual DateTime DateCreated { get; set; }
public virtual DateTime? DeletedDate { get; set; }
public override bool Equals (object obj)
{
if (obj == null)
return false;
var t = obj as BaseEntity;
if (t == null)
return false;
if (ID == t.ID)
return true;
return false;
}
public override int GetHashCode ()
{
int hash = GetType ().GetHashCode ();
hash = (hash * 397) ^ ID.GetHashCode ();
return hash;
}
}
}Company Entity
namespace Domain.Entities
{
public class Company : BaseEntity
{
public virtual string Name { get; set; }
public virtual IEnumerable Users { get; set; }
public virtual IEnumerable Branches { get; set; }
public virtual IEnumerable Departments { get; set; }
public class CompanyCollection : List
{
}
}
}Domain.Interfaces - I have a bunch of generic interfaces programmed here.
IReadRepository
IReadWriteRepsitory
IUnitOfWork
IWriteRepository
IReadRepository```
namespace Domain.Interfaces
{
public interface IReadRepository where TEntity : class
{
IQueryable All ();
TEnti
Solution
Let me know if I went wrong somewhere. This is the first time I set up an application with a proper architecture.
I'm afraid there is no such thing as general "proper" architecture. Relevant architecture is the one that enables/assists developers in implementing new functionality or adjusting your solution to new requirements.
In your implementation I don't see the reason to define your own logging and repository/UoW patterns:
Note that the series of articles "Refactoring toward frictionless & odorless code" actually show how you can move the transaction/session management to infrastructure level, leaving your business logic clean an tidy.
And a couple of small comments:
I'm afraid there is no such thing as general "proper" architecture. Relevant architecture is the one that enables/assists developers in implementing new functionality or adjusting your solution to new requirements.
In your implementation I don't see the reason to define your own logging and repository/UoW patterns:
- logging - there is NLog/log4net/whatever, why abstract from them? Even if you may want to switch the implementation, use
Common.Logging. All these frameworks do not (and should not) use dependency injection, so havingILoggingServiceinjected will only make your life harder.
- repository/UnitOfWork pattern - It's a long-running discussion between those who think repository is a must, and those who see it as a redundant layer that only makes your life harder, and leads to leaked abstractions in all but most simple scenarios. I'm in the latter camp, so here are a couple of links from one of the NHibernate core devs:
- Repository is the new Singleton
- Refactoring toward frictionless & odorless code: The baseline
- Refactoring toward frictionless & odorless code: Hiding global state
- Refactoring toward frictionless & odorless code: Limiting session scope
- Refactoring toward frictionless & odorless code: A broken home (controller)
- Refactoring toward frictionless & odorless code: The case for the view model
- Refactoring toward frictionless & odorless code: Getting rid of globals
- Refactoring toward frictionless & odorless code: What about transactions?
Note that the series of articles "Refactoring toward frictionless & odorless code" actually show how you can move the transaction/session management to infrastructure level, leaving your business logic clean an tidy.
And a couple of small comments:
- I don't see any reason to have
public class CompanyCollection : List {}
Repository- why do youreturn trueinUpdatemethods? If there is a failure - throw exception, notreturn false.
IConfigService/ConfigServicebreaks Open/Closed principle, as would need to edit this class (add properties) whenever a new configuration parameter is needed. Classes that require configuration should expect specific configuration values in constructor instead of consuming the generalIConfigService. Inject these parameters at the DI registration time. If you need a dynamic configuration which can be changed during software execution - then some sort ofIConfigServicecan be implemented, but I would suggest to have a generalT GetValue(string configName)in this case.
Context
StackExchange Code Review Q#83261, answer score: 10
Revisions (0)
No revisions yet.