If You're Making These 5 Use Case Mistakes, You Haven't Understood Clean Architecture

  Рет қаралды 23,236

Philipp Lackner

Philipp Lackner

Күн бұрын

Пікірлер: 83
@virajbenade5572
@virajbenade5572 7 ай бұрын
Tomorrow I have interview on kotlin android and today I am spent 8 hours onyour channel ❤❤😂😂
@OlegGolubev_yolo
@OlegGolubev_yolo 7 ай бұрын
gl hf
@ArthurKhazbs
@ArthurKhazbs 7 ай бұрын
Good luck!
@ZeeshanSyed-pq3gq
@ZeeshanSyed-pq3gq 7 ай бұрын
All the best Viraj
@bek_groider
@bek_groider 7 ай бұрын
gl
@robsonalvesdasilva8016
@robsonalvesdasilva8016 7 ай бұрын
GREAT!!! good luck!
@idrios
@idrios 7 ай бұрын
Man I appreciate your channel so much. It feels like Android development changes so much, so quickly but your tutorials are my go-to resource for keeping up with it, above even Google's own Android tutorials
@ParisHilton-b1f
@ParisHilton-b1f 4 ай бұрын
0:45 0:45 0:46 0:46 0:46 0:46 0:46 0:47 0:47 0:47 0:48 0:48 0:48 0:49
@kacetal
@kacetal 7 ай бұрын
For password verification, it is better to send a list of errors to show all the errors at once, rather than one after another.
@BitMavrick
@BitMavrick 7 ай бұрын
Not gonna lie. Properly structured android app is quite hard. As a beginner, I am going through a lot of complexity. Thanks, Philipp, for making videos about such a topic.
@karolkulbaka8577
@karolkulbaka8577 7 ай бұрын
Great overview of why do not use the google clean architecture
@geko1098
@geko1098 7 ай бұрын
This was my first introduction to use cases as code, and I think I got the concept from this video
@kolyakalyzhny
@kolyakalyzhny 7 ай бұрын
Hi, Philipp! Have you ever considered an idea of creating a video on using static types more extensively for enforcing business rules? For example, instead of using a validator use case which returns a boolean, we might, indeed, parse some input into a more structured data: like string to a valid email. Of course, parsing implies errors which should be enumerated by your type system, too. Consider algebraic data types like `Either`, `Validated` etc which are used in Haskell, Scala, Arrow.kt. The approach prevents many bugs at the compile time. I think popularizing such concepts would be of great benefit to the community. Here are some good resources: arrow-kt docs, Scott Wlaschin's talks, blog posts and his book "Domain Modeling made Functional", basic Scala, Haskell design patterns.
@DiegoNovati1
@DiegoNovati1 7 ай бұрын
To avoid the scenario number 3 I make the Domain module a Java library: there is no way to pass Android stuff or use Android libraries in the Domain layer, so it can just be only business logic. For the scenario number 4: all my use cases use loggers and analytics libraries (not directly but by repositories) so that for each use case I collect execution time and, in case of unexpected error, the parameters that created the error. For the scenario number 5: each use case returns an Either monad as result, the left value is the error (implemented as sealed interface) including the UnexpectedError when the data layer raised an unmanaged exception, and the right value is the successful result (NoResult or a Result class, it depends by the use case)
@bitwisedevs469
@bitwisedevs469 7 ай бұрын
I think the formatting part can still be considered business logic as long as it is part of the business requirements? Usually such formatter can be function extension or inside utils. However I also put them in domain model since what I noticed usually is people not adding any logic in the domain model which makes it the so called anemic domain model as well as despite it is more like a UI logic I don’t want to do that formatting again for example in SwiftUI or UIKit with KMM. I think as long as that logic can also be done in platform independent approach then it is safe in the domain layer.
@PhilippLackner
@PhilippLackner 7 ай бұрын
Is something really domain logic if the only place where it makes sense to use it is presentation?
@bitwisedevs469
@bitwisedevs469 7 ай бұрын
@@PhilippLackner it is still part of business requirements thus I think it is still okay to be in domain layer but no need to create use case for that as it will be too overkill. What I want from a domain model is having both formatted version and raw/original value of properties and as of now I see no problem or violation when doing that.
@Ayor88
@Ayor88 7 ай бұрын
I guess you're a good teacher beacause I've watch many (if not all) of your previous videos and I made none of those 5 Use Case mistakes
@niknar266
@niknar266 7 ай бұрын
One thing we're doing at my current project to get a little bit more out of usecases is let them be responsible for wrapping in kotlin Result like the last example to make sure errors are caught in the onFailure and appropriate error event are sent to the presentation later from the viewmodel I have a live template to save me the trouble of writing boilerplate for usecases too :)
@thelegend8990
@thelegend8990 7 ай бұрын
I trust you more than official Android docs. We wish to see more videos like you used to do where you apply all of architectural best practices in a mini project Thank you!
@ilpacolo
@ilpacolo 7 ай бұрын
Amazing video !! i am working as Android dev and this is very helpful
@foivosstamopoulos9709
@foivosstamopoulos9709 6 ай бұрын
Another great video. Thank you so much Philipp!!!
@PedroBarbosaRoman
@PedroBarbosaRoman 7 ай бұрын
I think there is also a space for using use cases containing platform specific libraries. I'm not a big fan of restricting use cases to only pure business logic, because sometimes a use case can do multiple things which depend on platform specific APIs, and so the use case should illustrate that intention through its name and parameters. If in a Multiplatform project we need a different use case from each platform we can then have an "expect" generic named use case (to use in common code) with "actual" implementation use cases that have their own dependencies on each platform.
@lindaporsius
@lindaporsius 7 ай бұрын
Guilty, on all of the mistakes. But since I actually entered a mentorship-program with Philipp, I can at least recognize them and try to improve.
@Alchemist10241
@Alchemist10241 7 ай бұрын
Please make a quick video about how to architect our platform related classes like work manager and services in the clean architecture approach.
@MrMindfullness
@MrMindfullness 5 ай бұрын
I am really excited to watch course material that I have enrolled for. But not sure where to find course I bought. Please help!
@germenwong
@germenwong 7 ай бұрын
Hi Philip, thank you for bringing us how to use biometric technology in Android in the last video. I have really learned a lot, and if possible, I would like to see you introduce how to use speech recognition technology in Android
@زيد_اليماني
@زيد_اليماني 7 ай бұрын
I watched the previous video about the best way to handle errors, and I then touched on the topic of the use case and how to make the view model responsible for displaying the message type to the user. When I glanced at the thumbnail of the clip, I thought there was another bug. 😂
@calixtoandrade996
@calixtoandrade996 7 ай бұрын
excellent video Mr. Lackner Im totally agree with your point!
@santri.awon1
@santri.awon1 7 ай бұрын
recently i searching about usecase and you upload this video
@weslleycampos
@weslleycampos 7 ай бұрын
I prefer use the operator fun invoke in the use cases.
@MajesticNut
@MajesticNut 3 ай бұрын
What can you say about nested use cases?
@martinseal1987
@martinseal1987 7 ай бұрын
I think with your first example this is when you take clean code too far, there is no need for these to be in separate classes just making busy work
@PhilippLackner
@PhilippLackner 7 ай бұрын
Not necessarily, but then don't call it use case if you ask me :)
@martinseal1987
@martinseal1987 7 ай бұрын
@@PhilippLackner yh fair enough, I've never called anything a use case I don't like the concept
@lewi.steven
@lewi.steven 7 ай бұрын
ValidateUserDataUseCase is not even use-case at the first place because use-case is system wide functionality of the application/software (just like when we define use-case in use-case diagram in UML). Do "ValidateUserData" is something that customer can do in the system ? "Login" and "Register" are. With that thought then Login and Register are the use-case class that can call Validator class to validate the request, or or you can have validation logic inside domain entity if you prefer rich domain model.
@martinseal1987
@martinseal1987 7 ай бұрын
So it seems "use case" is just a way to make programmers argue about nothing 🤔
@safionweb
@safionweb 7 ай бұрын
Well explained.
@shadowpenguin3482
@shadowpenguin3482 7 ай бұрын
2:20 the formatting implementation is also really strange. It would be much easier to have a single when expression here with some slight duplication, eg I found this one for file sizes (needs to be slightly adjusted from 1024 to 1000 though) fun fileSizeString(bytes: Double) = when { bytes >= 1 shl 30 -> "%.1f GiB".format(bytes / (1 shl 30)) bytes >= 1 shl 20 -> "%.1f MiB".format(bytes / (1 shl 20)) bytes >= 1 shl 10 -> "%.1f KiB".format(bytes / (1 shl 10)) else -> "$bytes B" }
@nitheeshks7582
@nitheeshks7582 2 ай бұрын
Can u tell how to handle with single line use cases..
@mohannadyoussef8683
@mohannadyoussef8683 7 ай бұрын
Amazing video as always
@george_sigalas
@george_sigalas 7 ай бұрын
6:40 "The domain layer shouldn't contain any references to the data layer" that's where I get confused. Google says that the domain layer is responsible for encapsulating "business logic that is reused by multiple ViewModels" and in the docs it has examples where they use Repositories, which is clearly a data layer component. To me it feels like the domain layer exists solely for bridging the data layer with the rest of the app.
@calixtoandrade996
@calixtoandrade996 7 ай бұрын
a repository is not from the data layer, is from the domain. The implementation of that repository is the data layer
@george_sigalas
@george_sigalas 7 ай бұрын
@@calixtoandrade996 that clears up a lot actually. But why would the graph point to the data layer in the docs? That's so confusing.
@PhilippLackner
@PhilippLackner 7 ай бұрын
The android docs are indeed confusing regarding that. They're not really talking of domain in the sense of DDD (Domain driven design) The idea of this inwards pointing communication is that changes in the data layer don't cause changes in domain and presentation as everything just depends on domain and never data directly
@calixtoandrade996
@calixtoandrade996 7 ай бұрын
What is intended to illustrate is that the domain layer is decoupled from the data layer (since they are two separate layers) and that it is from the Data layer where it obtains the information, so that, if in the future it is decided to change Retrofit for Ktor or some SDK for another, the only one harmed is the Data layer and not the domain, because the domain uses its own entities, abstractions of its repositories and other use cases. Therefore, the Data layer is responsible for mapping/providing the domain entities to the domain, so everything keeps working the same. I think part of the confusion is not differentiating the Data layer from the Data modules/libraries. They are two completely different things, a layer and a library or module. The domain will NEVER implement a data module/library, much less a UI module/library, because those modules depend on the framework. However, the Data and UI MODULES always consume the DOMAIN MODULES (again, the MODULES, not necessarily the LAYER). Of course, how else is Data modules supposed to map the remote/local models to the entities? or how is the viewModel supposed to work with the useCases? So, the architecture is one way because UI calls on domain to get the information (the use cases, not the data sources and much less the repositories implementations), and domain calls on data to get it, but the responsible for implementing the Data modules/libraries is the feature or the app itself. That way, the domain receives the implementation of its abstractions.
@wcman007
@wcman007 7 ай бұрын
Lmao this is like the teacher snitching on common mistakes in the test 😭😭😭
@L4szcZ
@L4szcZ 7 ай бұрын
In example 5 there is easier solution you can change class name from useCase to validator ;)
@mackomako
@mackomako 7 ай бұрын
If you leave it in domain layer it's still wrong. Either you move it to presentation layer or you return Error without string and map it in presentation layer.
@L4szcZ
@L4szcZ 7 ай бұрын
@@mackomako it wasn't in domain as far as I remember and validator shouldnt be in domain btw.
@Mackovitch
@Mackovitch 7 ай бұрын
For usecase #2, one would argue that the formatting of number of followers could be business logic as it pertains to the core of the business features of the app. Also, heavy formatting (almost unlike here) could make the presentation logic convulated (so what would be the best place: in the view model (via a mapper) ? in the UI component directly?) but I do agree that this is for the purpose of the UI and the resulting formatting would find its place in a UI model.
@abada-s
@abada-s 7 ай бұрын
12:28 sometimes creating this abstraction makes all user cases code style be the same but I think it is not the right way to unify the code style
@jimpauloovejera2599
@jimpauloovejera2599 7 ай бұрын
Question: Can we use try-catch inside a use case?
@SensesVI
@SensesVI 7 ай бұрын
I'd think you always should. This way you can catch exceptions and ensure you throw a domain exception instead
@calixtoandrade996
@calixtoandrade996 7 ай бұрын
I do not recommend it, because a single use case would be doing two things: executing its function and also handling the error. Let the error arrive to your viewModel. The error is a UI problem, not a domain problem. What I do is simply add the @Trowhs tag to my use cases so that whoever is going to use it knows in advance that this exception can be thrown. It is the problem of the viewModel or whoever is going to use it how to handle the exception.
@calixtoandrade996
@calixtoandrade996 7 ай бұрын
if you want to throw a domain exception because your service returned something null when it really didn't have to be, then throw your domain exception from there. For example, in remote response the user may be null. Your domain requires that it cannot be null, therefore, if it arrives null from the service, throw your domain exception, for example: return remoteUser ?: throw User.NotFoundException. This way you avoid working with the null user in your datasources, respository and in your use cases, and again, let your viewModel be responsible for handling that error
@jaidynbelbin4863
@jaidynbelbin4863 7 ай бұрын
All good points, but for the last one, how would you recommend handling error messages that come directly from an API response? Sometimes I want to display that exact error message in a dialog, or below a text field or something, as it gives a specific reason why a user action failed, so propagating the message from the Data layer all the way up to the presentation layer, intact. A possible solution could be coordinating with the backend developer to send an error code instead, but sometimes that isn't possible, ie. if the backend is shared with a web application that doesn't use that system. Thanks!
@PhilippLackner
@PhilippLackner 7 ай бұрын
You can extend the error message wrapper with an optional String field for that, it just wouldn't support localization in that case (or at least make it less flexible)
@RonnyBubke
@RonnyBubke 4 ай бұрын
First of all the UseCase suffix is not necessary. Also capsuling a function into a class where no dependencies are needed is also not necessary. Makes it more complex. You should use operator function "invoke" if you need a class for injecting deps and name the class like a function (ValidateEmail). You can call the instance easily like a function ("validateEmail(...)"). Really good readable. Example 2 is wrong IMHO. There is no such thing like the representation layer and a dogmatic assignment. Historically the splitting of View and Logic (Presenter, VM, Controller) was because of testing issues. The View isn't really good testable because of the huge framework which it brings with it. Therefore ALL code, which is testable should be tested and the View should have as less conditions (logic) as possible. It was always the responsibility of the Presenter (VM, Controller) to map the Data from different sources into an format the View can understand (ViewState) and which needs no further mapping/conditions (if possible) to be able to test the logic. I recommend lectures from Kent Beck, Ian Cooper, Robert C Martin (Uncle Bob), Martin Fowler. With the abstractions you are absolutely right. The problem with testing use cases is explained by Ian Cooper (TDD, Where Did It All Go Wrong). You shouldn't test use cases. Test should never know them. Just call the public interface (for instance ViewModel - on...Clicked()) and check for the out coming ViewState. Only external dependencies like a Database or a Http-Layer (Retrofit) should be mocked. I personally use Koin as dependency framework, which allows to override dependencies. Perfect to replace a Retrofit datasource by a mocked one. Install the production Koin Module + Override definitions in the Test. E.g. in the Test you always test the full path and never call implementation details like Usecases or Repositories. Otherwise the Code isn't really tested and refactoring is mostly impossible. Watch Ian Cooper and try to understand him!!! A good indicator you do it wrong is when you use VisibleForTesting annotation. Testing in isolation doesn't mean to test the production classes independent of each other but running the Tests independent of each other ->> Kent Beck You think too much in Layers and belongings. These things are just there to bring order into the code. Technical depth is fine if you have a good feature test coverage. Spaghetti code is fine if your have a good test coverage. If you test like Kent Beck you can refactor each time and the test will tell you if your features are still work. Your code is frozen, when you test each class and it make zero sense. I hope this wasn't to offensive and will bring you to the next level. -> Watch Ian Cooper!!!
@chitye-aung
@chitye-aung 7 ай бұрын
Awesome 🎉❤
@mesutemrecelenk5447
@mesutemrecelenk5447 7 ай бұрын
Thanks phlipp. Can you subscribe a video about unit test.
@Emran.Hejazi
@Emran.Hejazi 2 ай бұрын
If you don't like use cases, then what you like to do for business logic?
@mikec4220
@mikec4220 7 ай бұрын
15:13 "ViewModel should take this enum and map it to the corresponding string resources". I'm not sure this is a good idea, you make your view model dependable on android resources which makes it harder to unit test in isolation.
@karol-lisiewicz
@karol-lisiewicz 7 ай бұрын
Actually, it doesn't affect the testability of a ViewModel. The generated R.string contains only a numeric constant for each resource that you can refer to in your project. This does NOT mean that you need to use Robolectric to test your ViewModels - you still can just unit test them.
@mikec4220
@mikec4220 7 ай бұрын
​@@karol-lisiewicz thanks a lot for your reply, I tried in the past but the solution I came up with was not the most compelling. On another hand this is what the best view model practices on the official android developer site tell us: As they can potentially live longer than the ViewModelStoreOwner, ViewModels shouldn't hold any references of lifecycle-related APIs such as the Context or Resources to prevent memory leaks.
@ErikBongers
@ErikBongers 4 ай бұрын
The most common mistake? Not checking the date of the video. The android api is quite the chameleon. Don't watch tutorials older than a week. They're obsolete.
@saeedmoradi6858
@saeedmoradi6858 7 ай бұрын
Okay but what you use instead usecase???
@Mike-er2ih
@Mike-er2ih 7 ай бұрын
Common sense.
@codewithfelix3940
@codewithfelix3940 Ай бұрын
What happens if a use case has more than one public method
@mohamadshqeer8864
@mohamadshqeer8864 7 ай бұрын
Bro speak about devin
@fpetrovski
@fpetrovski 7 ай бұрын
Easiest solution, just don't use "use cases".
@maximooze3196
@maximooze3196 7 ай бұрын
I only smell religion in this topic here lol
@Tuligarnio
@Tuligarnio 7 ай бұрын
If you do not provide an explanation on why you think so it's not possible to debate about it.
@maximooze3196
@maximooze3196 7 ай бұрын
@@Tuligarnio ok I wont. 🫠
@cbnewham5633
@cbnewham5633 7 ай бұрын
well, a mistake in the first one is requiring a mix of upper, lower and a number and yet having a password min length of 9. There should be no restrictions other than a password length of 10 or 11 - preferably more (i.e.: a pass-phrase). Unmemorable passwords (must have an uppercase letter, a lowercase letter, a number, a special character, and only to be created when there is a full moon) with silly short lengths are far less secure than, say, a lowercase phrase of appropriately long length (which is easily remembered too). Anyway, I'll unpause and see what the mistake is that your are actually pointing out - but these kinds of stupid password requirements really get my goat and I wish developers would quit doing this.
@PhilippLackner
@PhilippLackner 7 ай бұрын
But it's simply not secure to have only a length requirement. If the hashed password db gets leaked, it's super easy to Crack them by just trying every word in the dictionary
MVVM vs. MVI - Understand the Difference Once and for All
18:40
Philipp Lackner
Рет қаралды 48 М.
ЛУЧШИЙ ФОКУС + секрет! #shorts
00:12
Роман Magic
Рет қаралды 25 МЛН
Perfect Pitch Challenge? Easy! 🎤😎| Free Fire Official
00:13
Garena Free Fire Global
Рет қаралды 66 МЛН
Osman Kalyoncu Sonu Üzücü Saddest Videos Dream Engine 275 #shorts
00:29
The ONLY Correct Way to Load Initial Data In Your Android App?
12:27
Philipp Lackner
Рет қаралды 34 М.
Abstraction Can Make Your Code Worse
5:13
CodeAesthetic
Рет қаралды 664 М.
Clean architecture Android - диаграмма Use Case | Чистая архитектура
22:27
The Top 3 Clean Architecture Mistakes in Android
11:25
Philipp Lackner
Рет қаралды 20 М.
🚀 The Clean Architecture (Ian Cooper)
53:05
DevTernity Conference
Рет қаралды 86 М.
FULL Guide to Kotlin's Inline Keyword (inline, crossinline & noinline)
16:35
You Won’t Believe What Excel’s Copilot Can Do! (new updates)
10:37
ЛУЧШИЙ ФОКУС + секрет! #shorts
00:12
Роман Magic
Рет қаралды 25 МЛН