0

I am trying to apply Robert Martin's Clean Architecture on my .NET project. In one of chapters about boundary, it talks about that database interface should reside in business logic component rather than database component. In a way that interface is in business logic and implementation is in database. One of interfaces I use, is IRepository.

If I move repository interfaces to business logic, then I have to move definition of database entities into the business logic which does not seem to be correct. Maybe repository interfaces should not use database entities directly? What is the correct way? I am confused.

8
  • 1
    Do you happen to use the Entity Framework in C#? It uses the term "Entity" differently than Domain Driven Design does, which can cause confusion here. In a Clean/Onion/Hexagonal architecture the inner business logic defines entities and interfaces for external connectors, but not database schemas or models. The Repository may use whatever it wants internally to achieve persistence. This is in contrast to typical layered architectures where the business logic depends on models defined in a data layer, and often reuses the database models as business-logic entities.
    – amon
    Commented Jun 18 at 10:59
  • 2
    @afshar screwdrivers make poor hammers. Frameworks want everything to know and use them. The HOCy architectures don't want to know the database exists. Commented Jun 18 at 11:36
  • 3
    You need IRepository in business, and its implementation in database layer. The consequence is that database entities (orm objects) should live in database layer. And you should have domain objects that you map them to entities through repository. In which case the natural question is: why do you need Entities to begin with? And the point is: you don't. Ultimately ORMs suck. Nowadays I do exactly that with raw sqls. Faster, cleaner, simpler. As long as you know sql of course.
    – freakish
    Commented Jun 18 at 14:25
  • 1
    The problem is Entity Framework doesn't play well with the repository pattern. It is a repository pattern itself, so adding an extra one on top leaves you with these extra 'entities' hanging around doing nothing
    – Ewan
    Commented Jun 19 at 9:20
  • 1
    I think using the dbcontext as repository is the way MS intended. But its not a solution I would recommend for larger projects. You can test by spinning up an in memory or containerised db
    – Ewan
    Commented Jun 21 at 11:40

1 Answer 1

3

Repository interfaces are defined in the business logic component so the business classes can declare what their data access needs are. Remember that these are just interfaces — contracts for behavior. The actual implementation of those interfaces should be kept in the outer most shell of clean architecture. This allows you to swap out implementations if, say, your CEO suddenly gets a really, really good deal on SQL Server and suddenly you need to switch from Oracle, or maybe the technology ecosystem in which your system lives needs to utilized web services or microservices. The dependency points from the outer shell in clean architecture towards the inner circles. This is the intended direction of dependencies in clean architecture.

An entity in Entity Framework, your object relational mapper, means something different than what entity means in clean architecture:

Entities encapsulate Enterprise wide business rules. An entity can be an object with methods, or it can be a set of data structures and functions. It doesn’t matter so long as the entities could be used by many different applications in the enterprise.

Source: The Clean Architecture, Clean Coder Blog

The emphasis here is that entities in clean architecture are part of your "business logic component." An "entity" in Microsoft Entity Framework can mean the same thing provided you spend the time to properly craft your data mappings. Many developers create an anemic domain model with Entity Framework, because it is easy and fast. And then there is no good place to put "business logic" so we go hunting for a suitable place, ultimately landing on a "service layer" or "more of essentially the same classes but in a different architectural layer." I think this might be the root cause of your question.

If classes are mapped in Entity Framework as an anemic domain model, then all you have created is data transfer objects used between your application and a relational database. Now things won't fit neatly into the layers of clean architecture, and, thus, the need for this question.

Entity Framework does allow you to map classes and properties with private setters, which helps maintain encapsulation, but this isn't perfect. I've not found a perfect bridge between a relational data model in the database and a behavior data model in an object oriented language. So, it comes down to compromise.

  • Spend the extra time and effort crafting your data mappings so Entity Framework entities are not just big, dumb DTOs between your application and the database. They can contain business logic and maintain some amount of encapsulation.

  • Accept that your business model will not a pure domain model. Some of the details of your data mappings will surely leak through. In my opinion, this is fine as long as you can still swap out your data layer with minimal effort.

Remember that all of the software architectures have a few common goals in mind:

  • Invert the directions of dependencies so you can swap out the infrastructure of your application when you need to. Note that this is not necessarily "easy", but it should feel "possible."

  • Promote testability. A testable application can be changed.

  • Help developers organize large and complex code bases.

  • Manage complexity.

  • And (unfortunately) to sell books and lecture tickets.

    This isn't a judgement on any one architecture. It's just an observation I've had over the years. It seems a few big names draw some variation of onion architecture, give it a different name and then sell a book.

So, whatever you chose, keep the main goals of all these architectures in mind, and accept that those architectures are an ideal which does not reflect reality. Don't be afraid to compromise on the ideals.

Once you map your database to business classes in Entity Framework, you are free to put those types in the signatures of your repositories, because your Entity Framework Entities are also Clean Architecture Entities. Your business classes and repository interfaces live within the same layer, which allows for the direction of dependencies that plays well with clean architecture.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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