I’m digging on how to structure projects and so I stumble into Onion Architecture. As to how I understand it, its more on a domain-centered-focus architecture instead of a database-driven type.
I’m looking for some github projects to study and learn more about the architecture, so I found this one https://github.com/chetanvihite/OnionArchitecture.Sample
I’m having hard time understanding:
namespace Domain.Interfaces
{
public interface IUserRepository
{
IEnumerable<User> GetUsers();
}
}
namespace Services.Interfaces
{
public interface IUserService
{
IEnumerable<User> GetUsers();
}
}
namespace Services
{
public class UserService : IUserService
{
private readonly IUserRepository _repository;
public UserService(IUserRepository repository)
{
_repository = repository;
}
public IEnumerable<User> GetUsers()
{
return _repository.GetUsers();
}
}
}
How he use it is by constructor injection.
private readonly IUserService _service;
public HomeController(IUserService service)
{
_service = service;
}
-
Do you always expose a service such as
IUserService
to an app that consumes it? But I noticed,IUserRepository
has the same methods toIUserService
? -
If you say Infrastructure concerns, does it mean or does it involve database? Or not necessarily? if not, what are examples of infrastructure concerns?
P.S. As I’m learning onion architecture, it always, if not always, at least it mention about DDD. So I guess, I’ll be learning DDD also 🙂
3
Q: Do you always expose a service such as IUserService
to an app that
consumes it?
We often do it. Sometimes by inertia others for testing, but most of the time to “draw” boundaries, verticals, etc. It’s a common practice which brings us attractive benefits at a small cost.
Ideally, services orchestrate calls between components of different boundaries so that the consumer doesn’t need to know about these other components. Services are especially relevant in designs in which data and behaviour are drastically decoupled. In such designs, services are the business layer.
Q: But I noticed IUserRepository
has the same methods to
IUserService
?
It sounds like a design flaw to me. It’s over-engineering. They don’t provide any relevant abstraction, there’s nos business logic. The transaction span is as wide as the one beneath the repository.
So, should we allow consumers to know about IRepository
? Yes. If there’s no business logic at all if your domain only provides basic CRUD operations and no business rules are required. Why not? Keep it simple.
Why? Simplicity. Unnecessary complexity makes code hard to maintain, hence expensive. Not only for your customer. It’s also expensive for you.
Q: If you say infrastructure concerns, does it mean or does it involve databases?
Yes, but databases are not the only ones. There could be more.
- access to the email server
- access to the message brokers
- access to queues
- access to remote storage (DBs, File system, etc)
- access to remote devices
- access to indexers
- access to 3rd party services
Think in an assembly line. The goal of the line is to assemble things and to this end, it needs an energy supply. Whatever is supplying the line with energy is considered an infrastructure service. The source of the energy won’t make the assembly line change its goal, but the way it’s supplied could.
So yes, the access to databases can be considered infrastructure concern in onion architectures. Onion architecture considers databases to be remote elements to be communicated with. They are no longer centric and should be possible for us to change them without having to change the domain.
6
Onion architecture means hiding dependencies to infrastructure behind an interface.
All components that use IUserService do not need to know wether the service is implemented using soap, rest, http or anything other infrastructure related.
The actual UserService implementation uses a repository interface IUserRepository as implementation detail. The UserService does not need to know which infrastructure the implementation UserRepository uses (odbc, odedb, mssql-native, ….)
But I noticed IUserRepository has the same methods to IUserService?
This is coincidence.