4

In the Clean Architecture, Uncle Bob defines Entities as enterprise-wide business rules and Interactors (Use Cases) as application-specific business rules. Also, he describes that Interactors are responsible for the "dance of the entities", and in the diagrams the Interactor -> Entity relation is shown as direct, without boundaries.

What I don't seem to understand is that in order to test an Interactor, I would inadvertently test code from the Entity, as they seem to be coupled together.

There are some projects that implement the Clean Architecture which do not hold logic inside the Entities, only data.

So, should Entities:

  • hold only data,
  • be another Boundary or
  • be tested with the Interactors or
  • something else?
2

If you're only holding data in your Entities your domain model will become anemic, because the encapsulation is broken and the behaviors are all defined outside the entity, far from where the data are declared.

The whole point of the Clean Architecture (and the Hexagonal Architecture, Onion Architecture, etc.) is to promote the Dependency Inversion Principle, the D in the SOLID acronyme. To do that, the outer layers need to depend on the the inner layers, not the opposite. That's why it's not only ok but necessary that your interactors depend on your entities. But your entities should not depend on your interactors.

Testing interactors means testing a whole use case, so that's totally intended to execute the code in your entities !

  • I think this might need to be a bit more accurate. While I do not know clean architecture. I think that while you might execute entities code, you will only write and executes tests which will check that your applications rules are correctly implemented. Of course if you're also happens to be developping also the entities layer, you will test business rules, but not in the same place than your application specific ones. – Walfrat Dec 18 '18 at 16:52
  • But what if the Entity that is being used in my Interactor is using others entities? This might become troublesome to test the Interactor, as its dependencies cannot be mocked. – Fernando Toigo Dec 18 '18 at 19:43
  • @FernandoToigo You're supposed to access your entities only via the aggregate root. Entities can access their value objects to delegate some behaviors, you never need to mock your entities since that's what you want to test. Maybe you're struggling with what to test in the first place. – Pierre Criulanscy Dec 19 '18 at 9:01
  • @FernandoToigo And, by the way, you're not supposed to access other entities directly from your entity. You declare dependencies between your entities through their identifiers. Yes, it leaks some technical details, but it's better than depending directly on your entities, because in that case, you're tied to a specific type of persistence, and you entities are going to be lazy loaded via some kind of ORM, defeating the purpose of DDD (but some people advocates for this practice, so it's up to you). – Pierre Criulanscy Dec 19 '18 at 9:12
  • @PierreCriulanscy I want to test every unit independently and I don't want to have unit tests of various interactors failing because of changes on an specific entity. I want just the unit tests of the changed entity to fail (along with integration tests). About your second comment, I see a bigger problem with that. I don't think your entity class (which holds business logic) should be the class that is going to be serialized. You probably need another class for that (which in turn should have agnostic identifiers). – Fernando Toigo Dec 19 '18 at 11:13
0

Architectural patterns are not meant to be followed religiously. Like any other pattern in software, they are well tested and defined solutions for specific problems, but flexible enough to be adapted. Answering your questions:

So, should Entities:

  • hold only data,

It depends on your domain. Sometimes, you need Entities that are capable of transforming or updating their state. On the other hand, you might only need a data representation of a given concept, with no state at all (e.x.: data classes in Kotlin). On Android, for instance, it is pretty common to have an anemic model, and that is OK because it fits the domain most of the times.

  • be another Boundary

Again, depends on your domain. Interactors already serve as a boundary between Entities and the rest of your system, and if you don't need to reuse your Entities anywhere else outside your application, you don't need the extra effort and/or complexity involved in isolating them (assuming that their state, if existent, is well encapsulated). Don't add complexity where you don't need it :)

  • be tested with the Interactors

You guess it - depends on your domain. If you have specific code in your Entities that you want to make sure works, sure, unit test it. However, you should not refrain from testing your Interactors along with your Entities because 1) integration tests are nice, 2) interactors are pretty useless if they don't work well with your Entities, so you might as well make sure of that and 3) since you'll probably mock out repositories and mappers, you'll get a good feeling of how your robust your whole domain layer is.

Long story short, as long as you understand the context of the problem you're solving, you don't need to bother that much with how you apply clean architecture. Use it as a guide, of course, but do it in a way that feels right or makes sense to you, learn from it, and refactor it later if needed.

  • 1
    But for using clean architecture as a guide, you first need to implement it religiously at least once ;) – Fabio Dec 18 '18 at 16:28
  • Thanks for your response. I understand that it might depend on the domain, and I agree with you. But it seems bad to leave the Entity and Interactor coupled with each other, because then the unit tests on the Interactors are going to be fragile, as any change in an Entity can make them fail. – Fernando Toigo Dec 18 '18 at 20:05
  • @Fabio: I don’t agree with you :p I’ve used clean architecture concepts like having use cases or following the dependency rule without implementing the whole thing. – Ricardo Costeira Dec 19 '18 at 0:46
  • @Fernando when unit testing, you only want to test that specific “unit” of code, mocking out the dependencies. So in this case you would either mock out the entities or do integration tests instead, which would then possibly (and correctly, since that’s their purpose) fail when the entities’ behavior changes. – Ricardo Costeira Dec 19 '18 at 0:53
  • @RicardoCosteira So in the case o mocking out the entities, they would become like a boundary to the interactor that uses it, right? I think this should be the default behaviour, as the layers become more independent that way. Of course, it is not necessary to do this in cases where there is only a single usage of said Entity, bud I think it is a good practice. – Fernando Toigo Dec 19 '18 at 10:59

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.