Open rohliq opened 8 years ago
No it is correct. The implementation of the interface resides in the data layer, so that is correct. Because of the inwards dependency rule, a use case from the domain layer can know a UserDataRepository exists through an interface, but can not know (or shouldn't even care) what the concrete implementation is of that UserDataRepository ( be it disk, memory or network ). So the domain defines that a UserDataRepository exists, but it cannot know of the data layer and its implementation.
The reason you think it breaks dependency is because of the flow of control. Look at the following diagram
And this is the accompanying quote by Uncle Bob about crossing those boundaries
At the lower right of the diagram is an example of how we cross the circle boundaries. It shows the Controllers and Presenters communicating with the Use Cases in the next layer. Note the flow of control. It begins in the controller, moves through the use case, and then winds up executing in the presenter. Note also the source code dependencies. Each one of them points inwards towards the use cases.
We usually resolve this apparent contradiction by using the Dependency Inversion Principle. In a language like Java, for example, we would arrange interfaces and inheritance relationships such that the source code dependencies oppose the flow of control at just the right points across the boundary.
For example, consider that the use case needs to call the presenter. However, this call must not be direct because that would violate The Dependency Rule: No name in an outer circle can be mentioned by an inner circle. So we have the use case call an interface (Shown here as Use Case Output Port) in the inner circle, and have the presenter in the outer circle implement it.
The same technique is used to cross all the boundaries in the architectures. We take advantage of dynamic polymorphism to create source code dependencies that oppose the flow of control so that we can conform to The Dependency Rule no matter what direction the flow of control is going in.
I hope this explains things for you.
@Trikke Kudos for such a great explanation!
@android10 happy to help here. You got me interested in proper architecture on android and i've been digging deeper ever since. Seems natural to help a bit with all the questions!
@Trikke good to hear! I really appreciate your help buddy. Sometimes it gets hard to answer all the question and an extra couple of eyes/hands are super useful :)
thanks guys
2015-11-12 13:37 GMT+01:00 Fernando Cejas notifications@github.com:
@Trikke https://github.com/Trikke good to hear! I really appreciate your help buddy. Sometimes it gets hard to answer all the question and an extra couple of eyes/hands are super useful :)
— Reply to this email directly or view it on GitHub https://github.com/android10/Android-CleanArchitecture/issues/65#issuecomment-156093332 .
UseCase output port Interface should be placed in the same UseCase layer, according to the diagram. But the question was about data layer output Interface (UserRepository) being placed in UseCase, which is domain layer.
No name in an outer circle can be mentioned by an inner circle.
But the name 'UserRepository' of outside circle (domain) is mentioned by data - the inner circle. This is imo indeed a case of breaking dependency rule
@ildar2 data is not the inner circle. it does not solve your problem (only provides data), domain layer does and it is where your logic sits. There is no dependency rule break up. :smile:
Hi,
didn't UserDataRepository breaks dependency rules? Class is from data layer but implements userrepository interface which is from domain layer.
thanks rohliq