android10 / Android-CleanArchitecture

This is a sample app that is part of a series of blog posts I have written about how to architect an android application using Uncle Bob's clean architecture approach.
Apache License 2.0
15.52k stars 3.32k forks source link

Data layer knows about Domain layer #150

Open CROSP opened 8 years ago

CROSP commented 8 years ago

Hi everyone. I wild about clean architecture, design patterns... I felt a long time ago that I need to design application in another way, found awesome article about Clean Architecture, but have just started to implement it. I have one question about Data and Domain layer. As I understand.

  1. Data layer is responsible for getting data from different places like file, db, cloud ...
  2. Domain is responsible for Use cases. Use cases are verbs used in application like GetUserWithAwesomeAvatarImage or something else. This layer is responsible for creating specific request to data layer, data layer support crud operations only, all application specific logic should be handled on domain layer

There is also one important rule that dependency arrow should only point from upper layer to lower but not vice versa, but in example provided by author there dependency pointing from Data to Domain. Maybe I am wrong, but I thought that it should point from Domain layer to Data.

For example create all repository stuff on data layer but domain layer will just consume repository from data layer, for example using dependency injection.

Please explain this.

Trikke commented 8 years ago

The exact same question has already been answered here.

CROSP commented 8 years ago

@Trikke really thank you for your explanation. I feel the same like the guy that started that topic, I have read your explanation several time but still a little it confused . Can you please answer to my one question. Why does model proposed by @android10 is better than described by @andrewjohnson90. What are the benefits of such architecture ? I would be very grateful for answer.

Trikke commented 8 years ago

@andrewjohnson90 did not describe any model in that thread. He just literally asked the same question as you and had some confusions about the setup of the project vs the architectural ideas.

CROSP commented 8 years ago

@Trikke Thanks for answer.

All in all, I think I got an idea, I was confused as well as a lot of user developers, because of standard 3-layer architecture and approaches like MVC.
Let me describe how do I understand this. In case of CleanArchitecture we have another model.

  1. First of all UseCase ring/layer is the core of our app, it should not be dependent on any specific implementation and operates only with interfaces and abstract classes. All dependencies should be injected using dependency injection tool like Dagger2.
  2. All other layers are pointing to the UseCase layer or being pointed by UseCase layer. For example Presenter points to UseCase to get use cases and respond to user actions (buttons, lists ...). In turn Use Case layer points to abstract repository in order to get required data. DataLayer is outer most ring of the architecture.
  3. If user asks for some platform specific data like geolocation, there should be use case GetGeoLocation and in this case Use Case layer points to Infrastructure layer (being discussed in adjacent issue topic) and ask it to get location data.
  4. Rule of thumb is following : the most platform specific dependencies should be on the outermost layer like UI, Database, Framework ...

Am I right or I am still don't understand this approach ?

Thanks.

Trikke commented 8 years ago

  1. Use Case (and other patterns) describe your business logic. This is the core of the app. If i would take your Use Cases and other stuff in that layer, i should be able to exactly tell what your app does. Every rule, every check, every feature. I wouldn't need the other layers to know your app.
  2. If we go outwards, yes, we have all the stuff that accesses your Use Cases and business logic.
  3. As you can see on the diagram, pretty much everything that is "external" to your app exists on the outside layer. But do keep in mind, "external" is a bit of a weird concept. This just means that your app shouldn't depend on a Sqlite database, it should and could (with some work) work just as fine with a text file as database. This is why that kind of stuff is "external" and on the outer layer.
  4. Yes, pretty much. As said in nr 3, this stuff is external. Image if you have a ToDo App with an sql database. If you would have the time and created your Android app architecturally correct, it would be possible to take that ToDo app and strip out the outer layer to make it work on Java Swing with a text file as a database. This is because everything outwards of the green layer is "external".

And just a side note, while nr 4 is possible, it would probably not be the best to follow this example repository if you would ever want to do that. This is because this is a minimal example, and the scope is just to create a correct Android App with Clean Architecture. If you would create a Java ToDo app which would work on multiple Java platforms, the setup would be different in terms of project/gradle setup. But you would still recognise how it works because it would also be based on Clean Architecture.

CROSP commented 8 years ago

@Trikke thank you a lot for you time and explanation, I think I got idea. I felt that app should be based on similar architecture some time ago when I didn't know about clean architecture, so I am so glad that there are a lot of people are interested in this. Please can leave any your contacts or sent me an email crospdevel@gmail.com I have been migrating to clean architecture in my project it is quite complex for the last month, but really had to add new features rather than refactoring architecture, but I think I will end up soon.
And when I finish migration I will share all my experience. Thanks again.

jemshit commented 7 years ago

@Trikke hi, couldn't find right issue to ask question about connection of Domain and Data. I have confusion about this case: if i need token to make api requests, and getting token has some logic: 1) Where does getToken() resides, in Domain or Data? getToken() retrieve String from DB (not api). I feel like i have to put logic in UseCase and DB code in Repository 2) If _methodA in Repository (in Data layer) needs token:

Similar question for cache manager. If i need to get something from cache or Api (which has logic), does that logic resides in UseCase ? Repository will only do CRUD for Api and DB

CROSP commented 7 years ago

@jemshit you are asking a really good question. Such things like authentication, sessions cannot persist on only one layer they are exist on mostly all layers of an application. I had the similar question and it was discussed here https://github.com/android10/Android-CleanArchitecture/issues/151