3 Clean Code Hacks I Bet You Didn't Know (Kotlin & Android)
Vložit
- čas přidán 19. 05. 2024
- In this video, you'll learn about 3 clean code hacks that make your code easier, more readable and understandable.
💻 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
00:00 - Hack 1
01:40 - Hack 2
04:22 - Hack 3
Typealiases are great, but I think using inline value classes would be a better approach
Could You elaborate on that?
I agree
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
@@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).
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
Agreed! And keep in mind you could use even more specific names than key/value for even greater readability.
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.
i dont like the 2nd hack. it can be achieved in a better way with a simple if else
Especially the third hack is really useful! Thanks M8!
Glad it helps!
now im seeing the video
in the fist hack
thanks for not spoiler me
Loved this one. Thanks again Philipp!
Didn't know about the partition function, pretty cool, thank you!
It really blown my mind. I thought I've known everything. Thank you! 🎉
You are amazing, loved the hack3
nice video
the third is a great one
thanks for sharing!
Bitte, bitte - mehr davon. Diese Art von Content ist großartig! (Please, please - more of the same. This kind of content is great)!
Thank you! Would like to see more!
Amazing background, Phillip.
Thank you Philipp 🤩
Wow, thanks a lot for these tips
Another great video. Thanks.
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.
Delegate example is so useful 👌
1. Typealias
2. Destructing
3. Delegates
Lol, this hacks exploded my mind, excellent video, thank you!
Excellent. Greetings from Brazil.
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?
Retrofit wont be further developed. I switched to ktor due to its Multiplatform feature
@@_zantetsuken_ Ohh alright, I was actually confused which one to learn, thanks for help.
@@amzpakistani3186 No problem! Both are fine but ktor is more powerful and i asked myself the same question like you.
@@_zantetsuken_yes ktor for multi platform, and retrofit for classic android
good tips, thanks
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
great stuff!
awesome tips
It's very helpful
Third one was helpful
are you spying on me or something?
your videos always point to the exact problems I keep facing in my work.
that's awesome.
what theme are you using for android studio? looks super clean and that logcat cat is cuteeee
Love from INDIA ❤
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
Inline classes fall somewhere in between those two
btw it should be val value: String actually ; ) (i know you're just illustrating the idea)
All of them were good hacks. I liked the Getter and Setter idea.
very good, it's very amazing!!!!!!!!!
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?
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
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.
Thanks
not bad not bad cool tricks. improved readibility
Wow!!! typealias is very useful!!!!!
I liked it bro!!!
amazing
How about if return type of first example is an uri?
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 😊
Can we get a video about uploading a photo to the back end and returning a url?
hey philipp what happened to your newsletter? i suddenly stopped getting emails from you
Can we get data from firebase synchronizely in kotlin.can you make videos on it
Hello, this video is really instructive. Would you mind to do one video going deeper abaout the 'delegates'?
Your channel is awesome, thank you!
Muito bom !
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!....
it takes 64 days.
Great hacks!
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?
Doctor, my tummy is aching for some reason, do you have any idea why?
only use typealias for long java class names like : class ProjectContractChargingPeriodAccountReferenceVM :D :D
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).
What about datastore ? Can we do like this with datastore?
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
Why return a Result rather than just a String (in the first example)?
Because Result allows you to return an error if the operation fails.
@@vibovitold Why not just throw an exception?
@@GrahamFirstbecause exceptions are for exceptional circumstances. Inability to upload a photo is not an exceptional occurrence. Failure is just an alternative success.
goat
Humble brag, I knew all of these hacks.
nice hack3
code push in git
Philipp plz build music player with content resolver and clean arch. If anyone think that will be so cool then like my comment 😄😄😄
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).
Hack 1 is useless, better to use a separate data class
Cool!