The Top 3 Clean Architecture Mistakes in Android

  Рет қаралды 20,320

Philipp Lackner

Philipp Lackner

Күн бұрын

Пікірлер: 99
@yarn-rdgz
@yarn-rdgz Жыл бұрын
Separating project into features is not a mistake, it's a decision, and has nothing to do with Clean Architecture. Actually, uncle Bob never spoke about that in the book, and this is applied to any architecture you use. I used to always take the feature oriented approach, but in the last project I've been working on, we decided to go with "layer-oriented" because of how coupled the data was. The thing with the feature oriented is that you are splitting your app in mini parts. Ideally, these parts must be independent, so if two features share some logic, where you should put that logic? This absolutely should not go to core/common folder, since this is not something to be shared with the entire app, it's only meant to be shared with these two features. You either go to "mirroring" the data on the other feature, or importing from one feature to another. The price to pay for either of these, in some projects, can be bigger than having these centralized.
@okunevdmitrii
@okunevdmitrii Жыл бұрын
I very like separate project into features-modules, and i think that it is the best way for clear, convenient and easily expandable architecture of Android App) yeap, i have read your comment, and understand that we can use it in any project, not only Android, but i have experience only in Android and KMP) For your problem sharing of data between 2/3/4 (as u want) modules u can use next way: in my project i use 2 modules - api and impl inside feature-modules, all private logic i put in impl module (repositories and usecases implementations, screens, viewModels, uiModels and etc.. Also i put here DI and retrofit Api Interfaces, but it depends on situation and di libraries for example). In Api module i put only data for sharing. For example: UseCases and Repository Interfaces if i need to share it, maybe data layers mappers if need(more often not), maybe sharing constants, domain models for sharing usecases and screen parameters, which i need to get for screen start (for example id of user). In this case any your feature module has dependencies only for api modules of other feature-modules and knows nothing about feature-impl modules. And your Api module is really small and light. And in this way you can implement your feature-api module only in those modules what u need. Also this way help your improve building time, cause u have dependencies only for abstractions or rarely changeble classes as ScreenParams, and it means that u feature-module2 with dependency feature-module2-api will not rebuild after each changes in feature-module2-impl architecture scheme looks like: --feature-module ----api ------data ------domain ------presentation(here presentation layer needs me only for sharing of screen parameters if it's neccesary) ----impl ------data ------di ------domain ------presentation
@Drackmord92
@Drackmord92 Жыл бұрын
@@okunevdmitrii Your approach surely works, but to me it looks hell of a complication! Having all modules having a separate part declaring all their shared classes as interfaces so that they can be injected by DI into sibling modules makes quite hard to figure out how the whole project is structured as it scales. I'm sure most projects can be organised fully in feature modules like Phillip described but in the ones I happened to work, backed provided those very large APIs that returned very interconnected data, and that kind of approach never worked. What I found is best in those situations is just to consider your "app" just the presentation layer, and divide it in feature modules accordingly, with just one module providing shared UI resources. Domain and Data can be while modules that behave like libraries for your UI, data providing repositories that internally manage data sources and domain exposing use cases and models. This also allows me to organise the three layers differently: for example, the division in features that makes sense on the UI level might not be very relevant to the domain layer that could instead group use cases by area of influence, and the data layer could group repositories and data sources around the actual Apis provided by the backend. Forcing a singular organisation vertically for the whole app rarely comes natural.
@yarn-rdgz
@yarn-rdgz Жыл бұрын
​@@Drackmord92 that last approach is just what we've been doing in our last project. But that doesn't mean that if you want to have domain/repositories/all-your-repositories it's a mistake. At the end of the day, it would be exactly the same code (same clean Architecture guidelines), with a very subjective way of organizing how your team edit and visualize it. You can think this as a flatten version of feature oriented, which can be easier to read depending on the team or the project. Don't take me wrong, I will always prefer the feature oriented version, but is not a mistake by any means doing it the other way. Also ​Philipp, keep going with your videos mate, you are doing awesome!
@rickbo5858
@rickbo5858 Жыл бұрын
Tbh, if a 'feature' can operate independently from the other 'feature' u should probably put it in its own module/package. I've never made a native android app but worked with other frameworks (Flutter). Feature is something to figure out for later, because it forces you to think about what will work with what en where. You could say: plan better, but in my experience plans will always change in development because of unforeseen problems. The argument: "it's better because all the related files are grouped together" is non-sense, because with most IDE's you can just click on the import to jump to the source.
@TheMikkelet
@TheMikkelet Жыл бұрын
I tried the feature-approach as well, and I "solved" your problem by having a 'shared' package with data, doman, and presentation. Problem was though, I ended up puttin so much into the shared-package, that it sort of negated the feature-approach lol
@keepgoingman5829
@keepgoingman5829 Жыл бұрын
These mistakes are definitely what developers who study CleanArchitecture at first could do. Thank you so much. this is very useful! Keep going bro!
@PhilippLackner
@PhilippLackner Жыл бұрын
Glad it was helpful!
@pedrolemoz
@pedrolemoz Жыл бұрын
Nice video! Just one thing to note: in the first mistake, I would rather use a custom Regular Expression to validate the email instead of relying on the given implementation. Why? I want to know exactly what's going on. Furthermore, since Regular Expressions are usually part of any programming language, it's safe to use it in the domain layer, as it won't be dependent of anything other than the language itself. About the last mistake, I don't consider it a mistake. It depends of the project size, and the chosen approach. If you are dealing with mono-repo, then it will be an issue. But if you are using multi-repo, micro-frontends, or something like that, you probably will make this mistake, but since everything is very separated, it's not a problem
@TheMikkelet
@TheMikkelet Жыл бұрын
PROPER Regex is incredibly difficult to write and maintain lol (most codebases that do this just go with a contains([@.]]-approach. There's absolutely no shame in using a validator library
@youtubethoughts4273
@youtubethoughts4273 Жыл бұрын
Make a Job scheduler video, How to create jobs and how to control the Jobs
@Akshaykumar-xr9yj
@Akshaykumar-xr9yj Жыл бұрын
Where do i put alarm manager in clean architecture. I have to perform some business logic in broadcast receiver (where should i put broadcast receiver in clean archotecture). can I access usecase in data layer.
@genctasbasi
@genctasbasi Жыл бұрын
Moral of the first 'mistake': "You don't eliminate the complexity, you just push it around" ☺ (I don't mean Philipp obviously, just the saying goes...)
@baharudinmaulana78
@baharudinmaulana78 Жыл бұрын
Yeayyy that good, i learn about clean architecture. But I do that mistake 😢, thank for the knowledge, i hope you always good, i open for feedback ☺️
@RudyStrom
@RudyStrom Жыл бұрын
I also
@АртемВинокуров-ъ7о
@АртемВинокуров-ъ7о 11 ай бұрын
Why ```interface Mapper { fun toDomain(data: Data): DOMAIN fun toData(domain: DOMAIN): DATA }``` is bad solution? If u need to cover 100% unit tests for example.
@adamibraham
@adamibraham Жыл бұрын
Please I need a tutorial about firebase firestore and clean architiecture and retrofit, caching with jetpack compose
@riyupapa39
@riyupapa39 Жыл бұрын
I already did watch this video about 3~4 times. And I forget 3 mistakes again. I watch this video now again.
@kamanchomorgan9655
@kamanchomorgan9655 Жыл бұрын
According second mistake it is not a mistake. For example if you need to write fake mapper for unit test you need this abstraction. And you have 2 implementation.
@PhilippLackner
@PhilippLackner Жыл бұрын
Why would you need a fake mapper?
@kamanchomorgan9655
@kamanchomorgan9655 Жыл бұрын
to test something
@Zeeshan-Syed
@Zeeshan-Syed Жыл бұрын
I just had to use other feature's dependency. Seems like I need to put them in core then.
@lglf77
@lglf77 11 ай бұрын
Can anyone give a tip on how to do 10,000 mathematical calculations without freezing the Android activity screen? I have no idea what to use as a clean architecture if the numeric data comes from a static json.
@koncinar
@koncinar Жыл бұрын
Let's be honest, mistake #1 is only a mistake because Android is designed badly. Ideally you should be able to unit test the original code and shouldn't need to abstract it (like the whole mistake #2 states). In Java days, Pair was super useful class, very generic, but nope, no testability. 👎
@chair_smesh
@chair_smesh Жыл бұрын
If you have only one database within your app, you would put the database in the core directory right?
@mymobile550
@mymobile550 Жыл бұрын
Why do we even have to create a book mapper class ? Just open the body of the data class and write all the related functions in there. Or just simply make an extension function below that class.
@PhilippLackner
@PhilippLackner Жыл бұрын
Extension function is better to keep responsibilities separately
@dhruvreyansh1338
@dhruvreyansh1338 Жыл бұрын
Any example of unit test in MVVM clean architecture with kotlin flow & channels
@breakeract796
@breakeract796 Жыл бұрын
For the second point. I guess you do not know/use MapStruct library. I'm always declare the mapper as an interface and the library gonna generate mapper implementation code for me. interface DtoMapper { fun toDomain(dto: DTO): DOMAIN } @Mapper interface BookMapper: DtoMapper Declare mapper as interface is really effective because the implementation of mapper can be change by business logic/rule anytime. When combination with Dagger we will @provide mapper, it can be injected to many class, I just need to re-provide the mapper implementation.
@samdroid37
@samdroid37 Жыл бұрын
nice
@PhilippLackner
@PhilippLackner Жыл бұрын
Why inject it if you can just make it an extension function to not need to inject it anywhere 😅 you don't gain anything with that interface
@ewomer100
@ewomer100 Жыл бұрын
Isn't #3 the mistake you use in almost all of your long play video tutorials of Clean Architecture?
@paulsoja2732
@paulsoja2732 Жыл бұрын
About mistake #3 - if I have use case which I use in many features? Where I should hold this use case?
@kriisEU
@kriisEU Жыл бұрын
in the core package
@alonshlider4881
@alonshlider4881 Жыл бұрын
7:57 Can you please elaborate on that - what is the difference of testing the usecase layer than for example testing a repository or a viewmodel?
@vasiliychernov2123
@vasiliychernov2123 Жыл бұрын
They exist for different purposes. Repository works with data and that's it. Use-cases contain valuable business logic. As an abstract example, it may get data from one repository, then pass its output to another repository and in the end aggregate it with another data. If use-cases just proxy repository calls, you should reconsider their necessity. View-model maps data from use-cases to UI-friendly structures and receives UI events. These all are different cases for testing. In repository you test correctness of data logic. In use-case you test correctness of business logic. And in view-model you test correctness of presentation logic.
@alonshlider4881
@alonshlider4881 Жыл бұрын
​@@vasiliychernov2123 "In use-case you test correctness of business logic" - so by what you say I see that use-case testing is indeed necessary, which goes against what Philip said in the video
@vasiliychernov2123
@vasiliychernov2123 Жыл бұрын
@@alonshlider4881 Uhm, Philip literally said that use-cases are being tested.
@chauchau0825
@chauchau0825 Жыл бұрын
Not a android developer, but this guy's view on Clean Architecture™, unlike many other random KZbin videos, is correct
@karthikgaddam4
@karthikgaddam4 Жыл бұрын
Hey, just curious why you had to implement the validator in data layer. If I understand correctly, the data layer should only focus on things that deal with raw data. But in this case, validator just takes a string and returns a boolean, which doesn't really deal with data.
@PhilippLackner
@PhilippLackner Жыл бұрын
Data layer deals with SDKs and APIs. The Android SDK is therefore partly data related
@karthikgaddam4
@karthikgaddam4 Жыл бұрын
@@PhilippLackner alright, gotcha!
@kyeiiih4422
@kyeiiih4422 Жыл бұрын
Awesome knowledge Philipp ❤
@Leon-un2ii
@Leon-un2ii Жыл бұрын
Great video as always. I take security very serious so, I would be thankful, if you could do a lock screen app. Maybe with a pin/password/fingerprint? Would be awesome!
@go_better
@go_better Жыл бұрын
Thank you, Philipp. I like your take on clean architecture. I just want to know best practices beforehand to not stumble upon scaling difficulties later on.
@MrSorenstar
@MrSorenstar Жыл бұрын
Thank you so much. I learn something new from you every time
@amirhosseinghafoorian5256
@amirhosseinghafoorian5256 Жыл бұрын
Amazing video, and as I noticed, nowinandroid is also a feature-based modular project and it kind of matches the example 3.
@Shakesbeer1
@Shakesbeer1 Жыл бұрын
Great video whatsoever. Claim about "if there is no second implementation - throw abstraction away" is to strong. You, probably won't have second implementation for that pattern validator. So next to multiple implementations one should always remember about testing and how abstraction make it easier. Second thing I don't agree is that data-domain-presentation does not scale. Just use feature packages inside those layer packages. I have seen both approaches and in wrong hands both could lead to a disaster.
@PhilippLackner
@PhilippLackner Жыл бұрын
Regarding the second thing, that's similar to what I suggested in the video. I was referring to people who use presentation, domain and data packages and then don't use features in these. That's quite common
@Shakesbeer1
@Shakesbeer1 Жыл бұрын
@@PhilippLackner To be absolutely honest your approach kinda better. For me having data-domain-presentation in this order from top to bottom in package manager is more menthal thing, carried from times before clean architecture and even Android development.
@thecoderui
@thecoderui Жыл бұрын
I love you man
@mircodev
@mircodev Жыл бұрын
Many thanks for sharing your experiences from your code reviews. I appreciate it very much.
@ntikomathaba2662
@ntikomathaba2662 Жыл бұрын
Hey Phillip. I just implemented a list-detail view in compose for large screens. Would love to see how you would implement it. There aren't many examples out there
@harshpratapsingh1638
@harshpratapsingh1638 Жыл бұрын
please make a basic video on how to use camerax in compose i am little bit confused
@katou9145
@katou9145 Жыл бұрын
thx :3
@FemiOkedey
@FemiOkedey Жыл бұрын
I like concept explainer videos like these Thank you 😊
@LazyTram911
@LazyTram911 Жыл бұрын
top
@johndominicjasmin
@johndominicjasmin Жыл бұрын
Thanks Philipp
@sheikhchilli7560
@sheikhchilli7560 Жыл бұрын
You said don't abstract usecase. If we want to test the usecase we can use fake repository and test it. Now we will use viewmodel which have usecase as parameter now when we want to test the viewmodel how can I send the usecase Instance. If we make usecase as abstraction we can pass fake usecase. Correct me if I am wrong?
@PhilippLackner
@PhilippLackner Жыл бұрын
Why would you want to pass fake business logic? What's the point? Use cases are always isolated logic, there's zero reasons to abstract that
@sheikhchilli7560
@sheikhchilli7560 Жыл бұрын
​@Philipp Lackner If we didn't abstract usecase then all usecase will be tightly coupled in view model right doesn't it break the DIP principle. Also if we want to test the viewmodel which contains the actual implementation of usecase how you will test it. My suggestion would be to upload a separate video describing this will be helpful for us. Thank-you
@sheikhchilli7560
@sheikhchilli7560 Жыл бұрын
​@@PhilippLacknerIn the context of use cases, it may be necessary to create a mock implementation of a use case in order to test the code that calls it. By creating an interface for the use case and passing in a mock implementation during testing, you can test the code that calls the use case in isolation, without having to worry about the implementation details of the use case itself.
@sheikhchilli7560
@sheikhchilli7560 Жыл бұрын
Any update regarding my query?
@rahul_spawar
@rahul_spawar Жыл бұрын
More videos like this please❤
@emrahc9558
@emrahc9558 Жыл бұрын
Hey Phillip, I agree with you on the first two points but as for your package structure, I personally disagree. Because your package structure can be just as quickly confusing and above all, you should clearly separate the logic from the UI, even within the package. But in the end, it's a personal feeling how you want something to be better organized. I can send you our package structure as a picture on Instagram if you like. It is a mixture of your first and second variant.
@dayakarpuli2307
@dayakarpuli2307 Жыл бұрын
Hi Philipp, Please do full video related to SOLID principles with examples.
@Mogswamp-
@Mogswamp- Жыл бұрын
🔝🔝🔝🔝🔝🔝🔝🔝🔝🔝 *Thanks for watching you have been selected among the lucky winners, inbox* MOGSWAMP 🔝🔝🔝🔝🔝🔝🔝🔝🔝🔝🔝
@denisoluka
@denisoluka Жыл бұрын
Thank you Philip. This was helpful
@denisgithuku8563
@denisgithuku8563 Жыл бұрын
Finna waiting for this.
@Ben-wx1ln
@Ben-wx1ln Жыл бұрын
just amazing as usual
@mustafaammar551
@mustafaammar551 Жыл бұрын
very cool video
@rma1563
@rma1563 Жыл бұрын
is clean architecture absolute necessary? I don't work as an android developer as a job, rather I only develop apps on my spare time. So should I be extra careful with these things? because for me some of these "clean architecture" looks like a lot of extra code for the simplest of things. Is there any performace boast with these methods?
@jarkow
@jarkow Жыл бұрын
It's not necessary, but it's easier to maintain your app and add new features. You won't gain any performance boost though or might be an overkill if your app is very simple.
@rma1563
@rma1563 Жыл бұрын
@@jarkow Thank you
@thousandcranes3045
@thousandcranes3045 Жыл бұрын
It is not. I'm pretty sure even Google says domain layer is optional. If the only thing your use cases do is call 1 method from your repository, then you should throw them away. If you don't even plan to write unit tests, you probably don't even need to abstract your repositories. Clean Architecture is not really a concept from Android, it's used across all domains (iOS, Web, Backend, etc) and it only matters when you have scalability in mind. That said, IMO even on small apps, it's probably still not too good of an idea to put everything in your activities tho...
@PhilippLackner
@PhilippLackner Жыл бұрын
It's definitely not necessary
@khapp7821
@khapp7821 Жыл бұрын
Hi, would you like to make a tutorial about the state holder class and how can we take benefit from the class!
@Mogswamp-
@Mogswamp- Жыл бұрын
🔝🔝🔝🔝🔝🔝🔝🔝 *Thanks for watching you have been selected among the lucky winners, inbox* MOGSWAMP 🔝🔝🔝🔝🔝🔝🔝🔝
@khapp7821
@khapp7821 Жыл бұрын
@@Mogswamp- 🤣🤣
@khapp7821
@khapp7821 Жыл бұрын
@@Mogswamp- @PhilipLackner just see this haha
@VishnuHaridas
@VishnuHaridas Жыл бұрын
In (1) the interface `EmailPatternValidator` is in the domain layer and the implementation is in the data layer. Doesn't that make the data layer depend on the domain layer which creates a circular dependency now? I would keep both the interface and implementation in the data layer itself, under `data/util`. Any other options?
@anegine
@anegine Жыл бұрын
data layer depends on domain layer - it's ok. domain layer doesn't depend on any module (except any other domain layers)
@VishnuHaridas
@VishnuHaridas Жыл бұрын
@@anegine The use-cases in the domain layer can access the repositories in the data layer and now both the domain and data layers are depending both ways right?
@anegine
@anegine Жыл бұрын
@@VishnuHaridas Domain layer MUST NOT depend on data layer. Domain layer contains Repository interface. Data layer contains Repository implementation, which is injected to domain UseCase (with DI / ServiceLocator or any other way).
@VishnuHaridas
@VishnuHaridas Жыл бұрын
@@anegine Oh deja-vu! I have seen similar conversations before when Google introduced the "layered" architecture where domain depends on data layer and not the other way around. I think it will be good to clearly specify that this is not the official "layered" architecture recommendation when making videos on Clean architecture on Android, otherwise new developers can get it mixed up.
@muhammadyaseen7022
@muhammadyaseen7022 Жыл бұрын
👍
@masmmaw
@masmmaw Жыл бұрын
Thank you
@Mogswamp-
@Mogswamp- Жыл бұрын
🔝🔝🔝🔝🔝🔝🔝🔝 *Thanks for watching you have been selected among the lucky winners, inbox* MOGSWAMP 🔝🔝🔝🔝🔝🔝🔝🔝
@boukarradhmoez99
@boukarradhmoez99 Жыл бұрын
Ok that's a good approach but what about the cause when I need Dagger Hilt to inject my repos in my use cases ?
@inertia_dagger
@inertia_dagger Жыл бұрын
if you're going to test your use cases, inject repos as interfaces and mock those interfaces in tests
@boukarradhmoez99
@boukarradhmoez99 Жыл бұрын
@@inertia_dagger First thank you for your answer , Yes that's what im using (interfaces) but i was asking about to add Hilt dependency in the domain Module.
@boukarradhmoez99
@boukarradhmoez99 Жыл бұрын
@PhilippLackner 🤔
@inertia_dagger
@inertia_dagger Жыл бұрын
@@boukarradhmoez99 I didn't understand your question. Rephrase it, please?
@thousandcranes3045
@thousandcranes3045 Жыл бұрын
@@boukarradhmoez99 Repositories are defined as an abstraction so you can have 2 different implementations - 1) the entity, which is the real implementation (which is most likely done in data layer) and 2) usually mocks for your test cases. On Philips' example, he didn't need to create 2 different implementations of a use case, because the the actual implementation of the use case, the business logic itself is what he wants to test. If you're wondering why don't we test the entity of repositories - it's simply because it has direct correlation with data (retrofit responses, rpc calls, room, cache, online configs, whatever) and you don't really care about that in your tests. Another reason is you obviously don't want to actually hit an API on your test cases
@oxitroy
@oxitroy Жыл бұрын
6:10 "An abstraction only make sense if you actually have multiple implementation ... if you only have one implementation you can simply throw it away" I'm really surprised with this clear and direct statement as it goes against DIP principle and as uncle bob and others have said : "Somehow developers think that you should have an interface “only in the case of multiple implementations”. This couldn’t be more wrong. " Interface in clean architecture are aimed to control flow of dependency and they help us in isolating changes, and avoiding to propagate them everywhere. Their only purpose is not to have multiple implementations and even more when working with clean arch. Would love to hear your pov if i misunderstood your statement.
@PhilippLackner
@PhilippLackner Жыл бұрын
In my experience, it very quickly leads to over engineering if you abstract everything while it comes with pretty much no benefit. You either want multiple implementations or really need to abstract stuff to use it in domain
All 17 React Best Practices (IMPORTANT!)
1:46:11
ByteGrad
Рет қаралды 153 М.
Make Objects TICKABLE in C++ for Unreal Engine in 2 Minutes!
2:25
Pobato Tutorials
Рет қаралды 118
💩Поу и Поулина ☠️МОЧАТ 😖Хмурых Тварей?!
00:34
Ной Анимация
Рет қаралды 2 МЛН
Players vs Corner Flags 🤯
00:28
LE FOOT EN VIDÉO
Рет қаралды 78 МЛН
Как подписать? 😂 #shorts
00:10
Денис Кукояка
Рет қаралды 8 МЛН
Make Your Code Clean With the SOLID Principles
18:24
Philipp Lackner
Рет қаралды 99 М.
How to Validate Forms with Clean Architecture (You're Doing it Wrong)
41:08
"Clean Architecture" and indirection. No thanks.
25:06
CodeOpinion
Рет қаралды 43 М.
5 Android Dev Mistakes I've Done in the Past (PLEASE AVOID!)
12:45
Philipp Lackner
Рет қаралды 22 М.
The Value of Source Code
17:46
Philomatics
Рет қаралды 41 М.
💩Поу и Поулина ☠️МОЧАТ 😖Хмурых Тварей?!
00:34
Ной Анимация
Рет қаралды 2 МЛН