3 Clean Code Hacks I Bet You Didn't Know (Kotlin & Android)

Поділитися
Вставка
  • Опубліковано 15 жов 2024

КОМЕНТАРІ • 86

  • @nymexe
    @nymexe 11 місяців тому +59

    Typealiases are great, but I think using inline value classes would be a better approach

    • @Marcix456
      @Marcix456 11 місяців тому +2

      Could You elaborate on that?

    • @johanramaroson
      @johanramaroson 11 місяців тому

      I agree

    • @GrahamFirst
      @GrahamFirst 11 місяців тому +7

      I think one advantage there would be typechecking, which I don't believe you would get with a typealias.
      What I mean by this is that IIUC using a typealias, a parameter of type "PhotoAlias" would actually accept any String (or whatever the primitive type is). With an inline value class, it's actually a new type, rather than an alias.
      Inline value classes also offer constructors/initializers for additional semantics, validation etc.
      In most cases, this is achieved without any overhead, meaning as with a typealias, at runtime you really just have a String (in this example, or whatever primitive type).
      So tl;dr it's a more robust, powerful and flexible option, and there shouldn't be any performance penalty, so I don't really see any reason NOT to use an Inline Value Class over a typealias, unless I'm missing something (which is quite possible 😅).
      Happy to learn by being corrected if I'm wrong or missing something. Inline value classes are new and TBH I haven't actually used them yet, but I think they're a great feature and I'm looking forward to using them shortly in a personal project where they are quite applicable.
      kotlinlang.org/docs/inline-classes.html

    • @vibovitold
      @vibovitold 11 місяців тому

      @@GrahamFirst typealiases, to me, should only be used locally (so i wouldn't rely on them for the scenario Philipp shows, i tend to agree with you in that sense).
      i find them great mostly for resolving occasional naming conflicts - eg. you are using kotlin.Result and some custom Result type alongside, and you don't want to always write the fully qualified kotlin.Result or com.myapplication.utils.Result to distinguish between them.
      creating an inline value class just for that purpose would be an overkill.
      so - to me - they're not interchangeable. it's apples and oranges. they serve different purposes and aren't meant as replacements for eachother.
      speaking of kotlin.Result, Result.success is actually an inline value class. so if you've got a failure, it's a specific class, but if you've got Result.success(true) (for example), it's actually just "true" coated with syntax sugar. there are some edge cases where it can lead to surprising results, eg. if you're using Mockito, you're not mocking some kotlin.Result property (so it stays null), but the compiler actually "thinks" it's a success, because it will treat it as Result.success(null).

    • @mikegehard6402
      @mikegehard6402 2 місяці тому +1

      @@GrahamFirstgreat explanation!

  • @armandoavila4615
    @armandoavila4615 11 місяців тому +8

    Didn't know about the partition function, pretty cool, thank you!

  • @ernestguevara5968
    @ernestguevara5968 11 місяців тому +14

    The hack 2 was really helpful! I'm really relying most on Pairs, than creating another data class for it. Now it will be more readable

    • @GrahamFirst
      @GrahamFirst 11 місяців тому

      Agreed! And keep in mind you could use even more specific names than key/value for even greater readability.

    • @vibovitold
      @vibovitold 11 місяців тому

      destructuring declarations are nice, but relying on Pairs a lot is probably an anti-pattern in its own right.
      eg. if you have two values like (name, id), and if you implement it as a class, then you can always look for all the usages of "ThisClass.name" in the codebase.
      but if you're using a Pair, you cannot, because it will only find you the occurrences of Pair.first or Pair.second, and that might include lots of unrelated results from irrelevant contexts.
      or if you've got a Pair to represent name and id, and both are Strings, but then you realize you actually need to revert the order of name and id (id should be "first", name should be "second", because of some Map conversion), you've got no type safety when refactoring. you may forget about some place where it should be reversed, because both are of String type.
      so the code that will mistakenly use id as a name and vice versa is going to run and compile without any issues. this wouldn't happen if you had a normal class with expliitly named properties.

    • @arjun1194
      @arjun1194 11 місяців тому

      i dont like the 2nd hack. it can be achieved in a better way with a simple if else

  • @dzjxn1988
    @dzjxn1988 10 місяців тому

    It really blown my mind. I thought I've known everything. Thank you! 🎉

  • @AkhmadjonAkbarov-hi6wn
    @AkhmadjonAkbarov-hi6wn 2 місяці тому

    thank you for useful video. I have reduced a bunch of code in my project by only change sharedpreference

  • @safionweb
    @safionweb 11 місяців тому

    Amazing background, Phillip.

  • @mehrzweck_mandala
    @mehrzweck_mandala 10 місяців тому

    Bitte, bitte - mehr davon. Diese Art von Content ist großartig! (Please, please - more of the same. This kind of content is great)!

  • @danielbojcobos4015
    @danielbojcobos4015 9 місяців тому

    Hello, this video is really instructive. Would you mind to do one video going deeper abaout the 'delegates'?
    Your channel is awesome, thank you!

  • @amzpakistani3186
    @amzpakistani3186 11 місяців тому +5

    Hey Philipp, excellent work. I've been learning a lot from your videos, the explanation and implementation is great. I am relatively a beginner and now I am gonna learn network, APis and stuff. I came across your tutorials about Retrofit and Rest API but they are 2 years old now. So are they still relevant?

    • @amzpakistani3186
      @amzpakistani3186 11 місяців тому +1

      @sackhaarspalter Ohh alright, I was actually confused which one to learn, thanks for help.

    • @ChrisAthanas
      @ChrisAthanas 11 місяців тому

      @sackhaarspalteryes ktor for multi platform, and retrofit for classic android

  • @davrukin
    @davrukin 8 місяців тому

    In Hack 3, I would remove the "val" from context so you don't hold onto it and bring in a memory leak, since context is only used to create the SharedPreferences object. Also, I would maybe put the Context extension function in a companion object of the delegate, but that is probably stylistic.

  • @21Kikoshi
    @21Kikoshi 7 місяців тому +1

    1. Typealias
    2. Destructing
    3. Delegates

  • @TiagoDvl
    @TiagoDvl 11 місяців тому

    Loved this one. Thanks again Philipp!

  • @mateusbauer7299
    @mateusbauer7299 11 місяців тому

    Excellent. Greetings from Brazil.

  • @swaminathbera6407
    @swaminathbera6407 7 місяців тому

    You are amazing, loved the hack3

  • @vladislavmelnikov5452
    @vladislavmelnikov5452 11 місяців тому

    Thank you! Would like to see more!

  • @TenthMeli
    @TenthMeli 8 місяців тому

    what theme are you using for android studio? looks super clean and that logcat cat is cuteeee

  • @gilsonjuniorpro
    @gilsonjuniorpro 11 місяців тому +1

    Lol, this hacks exploded my mind, excellent video, thank you!

  • @calixtoandrade996
    @calixtoandrade996 11 місяців тому

    nice video
    the third is a great one
    thanks for sharing!

  • @arielapp9469
    @arielapp9469 11 місяців тому

    are you spying on me or something?
    your videos always point to the exact problems I keep facing in my work.
    that's awesome.

  • @mohamadrezamehrjou9553
    @mohamadrezamehrjou9553 10 місяців тому

    Thank you Philipp 🤩

  • @TheBlackManMythLegend
    @TheBlackManMythLegend 11 місяців тому

    not bad not bad cool tricks. improved readibility

  • @prasannadeshpande4435
    @prasannadeshpande4435 11 місяців тому

    Another great video. Thanks.

  • @SyncImpl
    @SyncImpl 8 місяців тому

    good tips, thanks

  • @wazzzupmissionz
    @wazzzupmissionz 11 місяців тому

    Don't forget to mention: when you use "by" keyword, compose compiler will recognize state as written, thus function will recompose, even if it just pass state to inner compose function

  • @UnrealTubeShorts
    @UnrealTubeShorts 11 місяців тому

    Love from INDIA ❤

  • @517Amit
    @517Amit 11 місяців тому

    All of them were good hacks. I liked the Getter and Setter idea.

  • @thkorkem
    @thkorkem 11 місяців тому

    Delegate example is so useful 👌

  • @andrewairman7658
    @andrewairman7658 11 місяців тому

    Wow, thanks a lot for these tips

  • @omerokumus1
    @omerokumus1 11 місяців тому

    Typealiases are cool, however, the reader may think PhotoUrl is another class and get confused. Another approach using typealias that I'd prefer is explicitly making PhotoUrl is a typealias of string by PhotoUrl to PhotoUrlStr or better off, write a wrapper class that;
    data class PhotoUrl(value: String) // You can use another naming for value property tho
    Of course, those are my opinions

    • @vibovitold
      @vibovitold 11 місяців тому

      Inline classes fall somewhere in between those two
      btw it should be val value: String actually ; ) (i know you're just illustrating the idea)

  • @rrrdriguez_
    @rrrdriguez_ 11 місяців тому +1

    Hey man! Great suggestions, but I got one question regarding the third hack.
    Following your example, if I used this property delegate for a shared preference inside a view model for example, how would we test this view model? How could we mock the property delegate so the test is unit and we can avoid using roboelectric or something similar?

    • @PhilippLackner
      @PhilippLackner  11 місяців тому +1

      Either way, you'd have a separate class which implements your preferences. That class is injected in your VM and can be replaced for testing there

    • @vibovitold
      @vibovitold 11 місяців тому

      a ViewModel shouldn't deal with shared preferences directly AT ALL, because they are an Android concept, tied to the platform.
      they require access to Context.
      ideally a ViewModel should be unaware and independent of Android SDK.

  • @nicholasferrara8028
    @nicholasferrara8028 11 місяців тому

    Can we get a video about uploading a photo to the back end and returning a url?

  • @nischalshrestha2611
    @nischalshrestha2611 11 місяців тому

    Sir, Could you please tell me, how long it takes to build an app by learning from scratch using Kotlin and Jetpack compose
    ?.........Just tell me the time please!....

    • @vibovitold
      @vibovitold 11 місяців тому

      it takes 64 days.

  • @riyupapa39
    @riyupapa39 11 місяців тому

    Wow!!! typealias is very useful!!!!!

  • @hammadnaseem8852
    @hammadnaseem8852 11 місяців тому

    Can we get data from firebase synchronizely in kotlin.can you make videos on it

  • @jimpauloovejera2599
    @jimpauloovejera2599 11 місяців тому

    great stuff!

  • @mkc0321
    @mkc0321 10 місяців тому

    awesome tips

  • @David-zb8br
    @David-zb8br 11 місяців тому

    hey philipp what happened to your newsletter? i suddenly stopped getting emails from you

  • @Otabek001uz
    @Otabek001uz 11 місяців тому

    very good, it's very amazing!!!!!!!!!

  • @micortes89
    @micortes89 8 місяців тому

    How about if return type of first example is an uri?

  • @imSagarMalhotra
    @imSagarMalhotra 11 місяців тому

    Third one was helpful

  • @mitulsheth
    @mitulsheth 11 місяців тому

    It's very helpful

  • @parashyadav9721
    @parashyadav9721 11 місяців тому

    Hello bro, I used to watch your video from very early. I did a lot of research but still i am not able to find a solution to my query.
    I found a strechable ui in some of the professional app. For example consider the new playconsole app , it includes q strchable ui which make user feel that this is end of the screen. I saw this behaviour as defult after android 12 but in android 9 or 8 it does not.
    But still the app shows that strechable ui in android 9. Can you help me how to get so .
    Is this happening because playconsole is made using flutter ???
    Hope you answer my question 😊

  • @karomatullo_apk
    @karomatullo_apk 11 місяців тому +1

    What about datastore ? Can we do like this with datastore?

    • @PhilippLackner
      @PhilippLackner  11 місяців тому +1

      I don't think the setter and getter can be a suspend function which would be needed for that. You could keep a runBlocking in that property delegate, but it's not ideal IMO since that would not make it clear that it's a blocking call and should be executed on a thread

  • @germenwong
    @germenwong 11 місяців тому

    I liked it bro!!!

  • @GrahamFirst
    @GrahamFirst 11 місяців тому

    Why return a Result rather than just a String (in the first example)?

    • @vibovitold
      @vibovitold 11 місяців тому

      Because Result allows you to return an error if the operation fails.

    • @GrahamFirst
      @GrahamFirst 11 місяців тому

      @@vibovitold Why not just throw an exception?

    • @sgstudioofficial
      @sgstudioofficial 11 місяців тому

      @@GrahamFirstbecause exceptions are for exceptional circumstances. Inability to upload a photo is not an exceptional occurrence. Failure is just an alternative success.

  • @John-qt6qk
    @John-qt6qk 11 місяців тому

    Thanks

  • @tuvirusfury
    @tuvirusfury 11 місяців тому

    Hello Philipp, i got something that i find weird with Unit Tests and Jacoco, using the Result API does not cover me the 100% for some reason (a path o branch to test, but unclear) anyone or you could have an idea why, and maybe explain this?

    • @vibovitold
      @vibovitold 11 місяців тому

      Doctor, my tummy is aching for some reason, do you have any idea why?

  • @verofero
    @verofero 9 місяців тому

    amazing

  • @Nick-cx4rs
    @Nick-cx4rs 11 місяців тому

    only use typealias for long java class names like : class ProjectContractChargingPeriodAccountReferenceVM :D :D

    • @vibovitold
      @vibovitold 11 місяців тому

      or naming conflicts, like if you have to use two classes which happen to have the same name, but come from different packages, in the same file/class.
      typealias is a nicer alternative to using a fully qualified name (including a possibly lengthy package path).

  • @DanielJohnGay
    @DanielJohnGay 7 місяців тому

    Cool!

  • @buslovskiy
    @buslovskiy 11 місяців тому

    Great hacks!

  • @alex_aleluia
    @alex_aleluia 5 місяців тому

    Muito bom !

  • @robchr
    @robchr 11 місяців тому

    Humble brag, I knew all of these hacks.

  • @icodethis
    @icodethis 11 місяців тому

    goat

  • @scottbiggs8894
    @scottbiggs8894 5 місяців тому +1

    Hack #1 & #2 : Some programmers will do ANYTHING to avoid properly documenting their code. Sigh.
    Hack #3: Is this *really* easier than using the standard sharedPreferences? Perhaps it IS if you're doing lots and lots of sharedPrefs reading and writing. But wait--why are you doing lots of sharedPrefs reading and writing? That alone is quite inefficient--code that should be re-thought.
    This has all the code smell of someone showing off all their esoteric knowledge of hidden details of kotlin instead of someone who truly wants their code to be understood by the next batch of programmers to look at it (and as usual, they are almost always the people with the least experience and the least ability to follow such subtle code tricks).

  • @andriiyakubenko148
    @andriiyakubenko148 11 місяців тому

    nice hack3

  • @saeedmoradi6858
    @saeedmoradi6858 11 місяців тому

    Philipp plz build music player with content resolver and clean arch. If anyone think that will be so cool then like my comment 😄😄😄

  • @asshinichi
    @asshinichi 11 місяців тому +1

    code push in git

  • @warTag68
    @warTag68 11 місяців тому

    Hack 1 is useless, better to use a separate data class