3

In Clean Architecture boundaries are interfaces, which I model in Python with abstract classes. The input boundary, which is between the controller and the interactor/use case does not need an interface in my opinion, since it just executes the use cases coming from a "higher level". Is this true?

Other boundaries make sense to me having interfaces, because they decouple from the implementation of my presenter/database/api etc. and because they are called from the use case. If I want to interchange the database for example I just use my interface (my abstract class) in order to implement a new database call.

enter image description here

3 Answers 3

5

While it's true that the controller to interactor boundary isn't helping you invert a dependency, that isn't why it's there. The reason it's there is this:

• High-level modules should not depend on low-level modules. Both should depend on abstractions.

That's from the Dependency Inversion Principle. All it means is that it's nice to have a stable definition of the mini language that the two volatile concrete modules will communicate through. It means they don't have to know about each other. Just about the mini language. A fully abstract class that isn't bound to any destabilizing implementation details satisfies this just fine.

DIP and Clean Architecture are very closely linked. I mapped the Clean Architecture UML onto DIP here

1
  • 1
    In this case, in your understanding, tests in the controller should be done using stubs (Input Boundary(Interface)) or the real Interactor(concrete)? Or both? Aug 1, 2021 at 21:47
2

True. The boundary interface between controller and interactor is not really necessary. If it was not there, the dependency direction would still be correct.

If I were to speculate I would say the boundary interface between controller and interactor is there just for sake of symmetry. As the other boundary interface is necessary to invert the dependency.

It also may be because it makes it possible to create test double for the interactor for the controller, but that is not what this diagram is about.

Also one note : The relationships between the classes do not represent data flow, but compile-time dependencies between the classes, either from usage or from inheritance/implementation. The data and control flows between those classes would look different.

7
  • Then the output boundary abstraction is also unnecessary for the same reason. Is not it? We could extend both boundaries from the controller layer and use Adapter/Proxy Pattern to gain some decoupling between controller input/output and the interactor input/output. What makes me wonder if these interfaces are just a way to keep implementation details away from the business. In other words simplify the business layer and keep the focus on the logic and not on how things are carried from one layer to another.
    – Laiv
    Mar 14, 2019 at 9:13
  • 1
    @Laiv Did you watch Robert C. Martin actually explain the Clean Architecture? youtube.com/watch?v=Nsjsiz2A9mg
    – Euphoric
    Mar 14, 2019 at 9:19
  • Thank you @Euphoric. Just a follow-up question: can you eloborate how the data flows, because I thought it flows from the controller to the presenter via the use case. Is that correct?
    – davidh38
    Mar 14, 2019 at 17:33
  • The graph shows relationships: use, extends, implements, etc... The open arrows are "use", the closed are inheritance or implementation. The double lines are architectural boundaries
    – Laiv
    Mar 14, 2019 at 19:01
  • If I get wrong please correct me but boundary abstraction is for Controller and/or Presenter. By this abstraction, UI can be testable without depending any other layer and, again I think, this is one of main idea of Clean Architecture. Just avoiding High Level modules dependencies to Low Level is not architecture. It is about DiP. Am I wrong ?
    – Engineert
    Mar 15, 2019 at 11:48
0

In my opinion necessity of Input Boundary abstraction depends on Stability metric of component, mentioned earlier in this book.

Stability metric explanation from the book

• Fan-in: Incoming dependencies. This metric identifies the number of classes outside this component that depend on classes within the component.
• Fan-out: Outgoing depenencies. This metric identifies the number of classes inside this component that depend on classes outside the component.
• I: Instability: I = Fan-out / (Fan-in + Fan-out). This metric has the range [0, 1]. I = 0 indicates a maximally stable component. I = 1 indicates a maximally unstable component.

Also definition of The Stable Abstractions Principle(SAP) will be useful in context of the question:

A component should be as abstract as it is stable.

Answer to the question using following explanations:
The harder component to change
=> The more dependent classes from different components it has (the more it's stable)
=> the more abstract it should be
=> the more Input Boundary abstraction necessity

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.