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

Sdílet
Vložit
  • čas přidán 1. 06. 2024
  • In this video, you will learn that if you are making these 5 use case mistakes, then you have not understood Clean Architecture!
    💻 Let me be your mentor and become an industry-ready Android developer in 10 weeks:
    pl-coding.com/drop-table-ment...
    ⭐ Courses with real-life practices
    ⭐ Save countless hours of time
    ⭐ 100% money back guarantee for 30 days
    ⭐ Become a professional Android developer now:
    pl-coding.com/premium-courses/
    Get my FREE PDF about 20 things you should never do in Jetpack Compose:
    pl-coding.com/jetpack-compose...
    Regular programming advice on my Instagram page: / _philipplackner_
    Join my Discord server:
    / discord
  • Věda a technologie

Komentáře • 74

  • @virajbenade5572
    @virajbenade5572 Před 2 měsíci +58

    Tomorrow I have interview on kotlin android and today I am spent 8 hours onyour channel ❤❤😂😂

  • @kacetal
    @kacetal Před 2 měsíci +16

    For password verification, it is better to send a list of errors to show all the errors at once, rather than one after another.

  • @karolkulbaka8577
    @karolkulbaka8577 Před 2 měsíci +2

    Great overview of why do not use the google clean architecture

  • @BitMavrick
    @BitMavrick Před 2 měsíci +5

    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.

  • @idrios
    @idrios Před 2 měsíci +2

    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

  • @foivosstamopoulos9709
    @foivosstamopoulos9709 Před měsícem

    Another great video. Thank you so much Philipp!!!

  • @calixtoandrade996
    @calixtoandrade996 Před 2 měsíci

    excellent video Mr. Lackner
    Im totally agree with your point!

  • @ojo_lali_ngaji
    @ojo_lali_ngaji Před 2 měsíci +4

    recently i searching about usecase and you upload this video

  • @mohannadyoussef8683
    @mohannadyoussef8683 Před 2 měsíci

    Amazing video as always

  • @geko1098
    @geko1098 Před 2 měsíci

    This was my first introduction to use cases as code, and I think I got the concept from this video

  • @safionweb
    @safionweb Před 2 měsíci

    Well explained.

  • @ilpacolo
    @ilpacolo Před 2 měsíci

    Amazing video !! i am working as Android dev and this is very helpful

  • @niknar266
    @niknar266 Před 2 měsíci

    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 :)

  • @Ayor88
    @Ayor88 Před 2 měsíci

    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

  • @germenwong
    @germenwong Před 2 měsíci

    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

  • @kolyakalyzhny
    @kolyakalyzhny Před 2 měsíci

    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.

  • @Alchemist10241
    @Alchemist10241 Před 2 měsíci

    Please make a quick video about how to architect our platform related classes like work manager and services in the clean architecture approach.

  • @chitye-aung
    @chitye-aung Před 2 měsíci

    Awesome 🎉❤

  • @DiegoNovati1
    @DiegoNovati1 Před 2 měsíci +1

    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 Před 2 měsíci +2

    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  Před 2 měsíci

      Is something really domain logic if the only place where it makes sense to use it is presentation?

    • @bitwisedevs469
      @bitwisedevs469 Před 2 měsíci

      @@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.

  • @Mackovitch
    @Mackovitch Před 2 měsíci

    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.

  • @MrMindfullness
    @MrMindfullness Před 14 dny

    I am really excited to watch course material that I have enrolled for. But not sure where to find course I bought. Please help!

  • @martinseal1987
    @martinseal1987 Před 2 měsíci +4

    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  Před 2 měsíci +4

      Not necessarily, but then don't call it use case if you ask me :)

    • @martinseal1987
      @martinseal1987 Před 2 měsíci +1

      @@PhilippLackner yh fair enough, I've never called anything a use case I don't like the concept

    • @lewi.steven
      @lewi.steven Před 2 měsíci +6

      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 Před 2 měsíci +1

      So it seems "use case" is just a way to make programmers argue about nothing 🤔

  • @lindaporsius
    @lindaporsius Před 2 měsíci

    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.

  • @jaidynbelbin4863
    @jaidynbelbin4863 Před 2 měsíci

    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  Před 2 měsíci

      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)

  • @PedroBarbosaRoman
    @PedroBarbosaRoman Před 2 měsíci

    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.

  • @solokiller5883
    @solokiller5883 Před 2 měsíci

    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. 😂

  • @weslleycampos
    @weslleycampos Před 2 měsíci +1

    I prefer use the operator fun invoke in the use cases.

  • @george_sigalas
    @george_sigalas Před 2 měsíci +1

    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 Před 2 měsíci

      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 Před 2 měsíci

      @@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  Před 2 měsíci +1

      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 Před 2 měsíci

      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.

  • @abada-s
    @abada-s Před 2 měsíci

    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

  • @shadowpenguin3482
    @shadowpenguin3482 Před 2 měsíci

    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"
    }

  • @thelegend8990
    @thelegend8990 Před 2 měsíci +1

    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!

  • @jimpauloovejera2599
    @jimpauloovejera2599 Před 2 měsíci

    Question: Can we use try-catch inside a use case?

    • @SensesVI
      @SensesVI Před 2 měsíci

      I'd think you always should. This way you can catch exceptions and ensure you throw a domain exception instead

    • @calixtoandrade996
      @calixtoandrade996 Před 2 měsíci

      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 Před 2 měsíci

      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

  • @wcman007
    @wcman007 Před 2 měsíci

    Lmao this is like the teacher snitching on common mistakes in the test 😭😭😭

  • @mesutemrecelenk5447
    @mesutemrecelenk5447 Před 2 měsíci

    Thanks phlipp. Can you subscribe a video about unit test.

  • @L4szcZ
    @L4szcZ Před 2 měsíci

    In example 5 there is easier solution you can change class name from useCase to validator ;)

    • @mackomako
      @mackomako Před 2 měsíci

      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 Před 2 měsíci

      @@mackomako it wasn't in domain as far as I remember and validator shouldnt be in domain btw.

  • @saeedmoradi6858
    @saeedmoradi6858 Před 2 měsíci +1

    Okay but what you use instead usecase???

  • @mikec4220
    @mikec4220 Před 2 měsíci

    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 Před 2 měsíci

      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 Před 2 měsíci

      ​@@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.

  • @mohamadshqeer8864
    @mohamadshqeer8864 Před 2 měsíci

    Bro speak about devin

  • @fpetrovski
    @fpetrovski Před 2 měsíci

    Easiest solution, just don't use "use cases".

  • @maximooze3196
    @maximooze3196 Před 2 měsíci +5

    I only smell religion in this topic here lol

    • @Elian-Fabian
      @Elian-Fabian Před 2 měsíci +1

      If you do not provide an explanation on why you think so it's not possible to debate about it.

    • @maximooze3196
      @maximooze3196 Před 2 měsíci +1

      @@Elian-Fabian ok I wont. 🫠

  • @cbnewham5633
    @cbnewham5633 Před 2 měsíci

    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  Před 2 měsíci +1

      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