4

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;
}
  1. Do you always expose a service such as IUserService to an app that consumes it? But I noticed, IUserRepository has the same methods to IUserService?

  2. 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
  • 1
    AFAIK onion architecture only covers the separation of UI, Domain (business logic) and Data. It does not say how many middle layers you should have among those. If you feel like creating a service, do so. Nonetheless, if all the user service is doing is hiding the use of user repository, then the service is pretty much useless.
    – Andy
    Apr 19 '16 at 18:14
  • @DavidPacker That's what I also thought about the service. In his code is there any other reason why you'd want to expose service instead of exposing repository directly?
    – Boy Pasmo
    Apr 19 '16 at 18:19
  • Note that asking for off-site resource recommendations such as sample projects is considered off-topic here, so I edited out that subquestion.
    – Ixrec
    Apr 19 '16 at 18:20
9

Q: Do you always expose a service such as IUserService to an app that consumes it?

We usually do. Some times by inertia (we got used to), others for testing, but most of the time to decouple boundaries within the application. It's a common practice which brings us interesting benefits at a small cost (complexity).

Services orchestrate calls between components of different boundaries so that the consumer doesn't need to know about these other components and boundaries. Services are especially relevant in anaemic models where data and behaviour are drastically decoupled. In such designs, most of the logic is located in services, setting the boundaries of the business transactions on this layer.

Q: But I noticed IUserRepository has the same methods to IUserService?

It sounds a design flaw to me. It's a symptom of overengineering and it's telling us -we don't need a user service-. This sort of service doesn't provide us with any relevant abstraction, it's not performing any orchestration and the transaction span is as wide as the one beneath the repository interface. We could still leave the service to set the business transaction scope on this layer rather than the persistence layer, but it wouldn't make the existence of the service less arguable.

So, should we allow consumers to know about IRepository? Yes. Until we need any sort of abstraction between the application and the persistence.

Why? Simplicity. Unnecessary complexity makes code hard to reason about. Code hard to reason is code hard to maintain and hence expensive.

Q: If you say infrastructure concerns, does it mean or does it involve database?

Yes, but databases are not the only. There are more.

  • access to the email server
  • access to the message brokers
  • access to queues
  • access to remote storages (DBs, File system, etc)
  • access to remote devices
  • access to indexers
  • access to 3rd party services

These are processes not tightly related to the domain or the business but still required by the application. Count them as non-functional requirements.

Think in an assembly line. The goal of the line is to assemble things and to this end, it's likely it needs an energy supply. Whatever is supplying the energy is considered an infrastructure service. The source of the supplied energy won't make the assembly line to change its goal, but the way we supply the energy to the line can change it.

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
  • I see. So always expose service even though it contains same method to the repository. Got it. But is there any cases that repository and service does not contain the same method? Do you have any comment on my question #2?
    – Boy Pasmo
    Apr 19 '16 at 18:26
  • The question is why your service has no business? In any service layer is expected to have business. Even if doesn't have, then its business is to be a proxy or a concentrator of repositories, whatever. But you should think in terms of business. What I'm exposing? My data model? My service s? Think in any webservice. Google for example. Do you think google is exposing its data or its business? All these concepts are Facto standards so is open to use'm or not. But it makes a great big deal better to do it.
    – Laiv
    Apr 19 '16 at 18:37
  • Thank you so much. Do you have any comments on this? My question #2. If you say Infrastructure concerns, does it mean or does it involve database? Or not necessarily? if not, what are examples of infrastructure concerns?
    – Boy Pasmo
    Apr 19 '16 at 19:02
  • i have edited my answer. Anyways wait for more opinions ;-). As I said, this subject is open to opinions
    – Laiv
    Apr 19 '16 at 19:13
  • It sounds a design flaw to me. It's a symptom of overengineering To be fair, just becauser you use a service layer doesn't mean that every service has to therefore add functionality to its related repository. For example, there may be additional business logic in the DocumentService and the PictureService (which means they're not just a passthrough for the DocumentRepository and PictureRepository), but the UserService is one that doesn't actually need additional logic and thus looks like a passthrough. If some services has relevant purpose, the service layer has purpose.
    – Flater
    Jun 3 '19 at 10:21
4

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.