- 28
- 159 417
Dave Leeds
Приєднався 18 вер 2022
Applying the State Pattern in Kotlin
When our objects behave differently in different states, then it can be helpful to apply the State Pattern. Today, we'll look at code that could benefit from the State Pattern, we'll apply a traditional State Pattern from the classic Gang of Four Design Patterns book, and then we'll see how we can modernize it and reduce boilerplate by using some of Kotlin's language features.
✨ New to Kotlin? Start your journey here: typealias.com/start/
... or pick up the new Leanpub Edition for offline access and more! book.typealias.com/
🚀 Get the inside scoop on everything I'm working on - join my new email newsletter!
Sign up here: newsletter.typealias.com/
📺 Watch Episode #1 of the TypeAlias Show Livestream:
ua-cam.com/users/liveS_JKbmN_A8o
📚 Chapters
00:00 Introduction
00:16 Example Code
02:16 Classic State Pattern
06:50 Modernized State Pattern in Kotlin
11:58 Wrap-up
Correction:
11:03 Inside the `println()` on line 13, I should have printed `$it` instead of `$email`.
✨ New to Kotlin? Start your journey here: typealias.com/start/
... or pick up the new Leanpub Edition for offline access and more! book.typealias.com/
🚀 Get the inside scoop on everything I'm working on - join my new email newsletter!
Sign up here: newsletter.typealias.com/
📺 Watch Episode #1 of the TypeAlias Show Livestream:
ua-cam.com/users/liveS_JKbmN_A8o
📚 Chapters
00:00 Introduction
00:16 Example Code
02:16 Classic State Pattern
06:50 Modernized State Pattern in Kotlin
11:58 Wrap-up
Correction:
11:03 Inside the `println()` on line 13, I should have printed `$it` instead of `$email`.
Переглядів: 4 955
Відео
Applying the Decorator Pattern in Kotlin
Переглядів 4,4 тис.Місяць тому
The Decorator Pattern allows us to augment the behavior of an object - without the object itself knowing about it! In this video, we'll start with code that could benefit from this pattern. Then we'll apply the Decorator Pattern using the classic approach as outlined in the original Gang of Four book. Finally, we'll modernize the pattern using some of Kotlin's language features. ✨ New to Kotlin...
Applying the Strategy Pattern in Kotlin
Переглядів 6 тис.Місяць тому
The strategy pattern is one of my favorites from the original Design Patterns book. In this video, we'll see why the strategy pattern is helpful, we'll apply the pattern in Kotlin, and then we'll see how we can use some of Kotlin's language features to put a more modern spin on it. ✨ New to Kotlin? Start your journey here: typealias.com/start/ ... or pick up the new Leanpub Edition for offline ...
Coroutines: Concurrency in Kotlin
Переглядів 10 тис.Місяць тому
In this presentation, I give an overview of coroutines in Kotlin, including the basics of coroutines, how they can be used for concurrency and parallelism, and how structured concurrency helps ensure coroutines are cleaned up in response to cancellations and exceptions. The content for this presentation is largely based on chapter 20 of Kotlin: An Illustrated Guide, which you can read online he...
Kotlin Code Reuse: Composing like you're Inheriting
Переглядів 9 тис.2 місяці тому
The classic Design Patterns book introduced the principle of favoring composition over inheritance. In this video, we'll explore what the authors meant by this principle, we'll consider the characteristics that are affected by it, and we'll look at an underrated Kotlin feature that can change our perspective on it! ✨ New to Kotlin? Start your journey here: typealias.com/start/ ... or pick up th...
7 Features in Kotlin's Standard Library that You Might Have Overlooked
Переглядів 7 тис.2 місяці тому
Are you still using the Java API when you don't have to? Are you rewriting functions that are already in the standard library? In this video, I cover seven features in Kotlin's standard library that you might have missed or forgotten about. 🕙 What days and times work best for you for a livestream? forms.office.com/r/9vpuJv0PMq ✨ New to Kotlin? Start your journey here: typealias.com/start/ ... o...
Reified Type Parameters
Переглядів 3,8 тис.3 місяці тому
Learn what happens to type arguments when our Kotlin code is compiled, and how we can step around certain type erasure problems with reified type parameters. 📽️ Inline, Crossinline and Noinline video: ua-cam.com/video/T9sAlxqYFYc/v-deo.html ✨ New to Kotlin? Start your journey here: typealias.com/start/ ... or pick up the new Leanpub Edition for offline access and more! book.typealias.com/ 🚀 Get...
The Essence of Coroutines
Переглядів 10 тис.3 місяці тому
In Kotlin and other languages, coroutines are often seen as just async/await. But the essence of coroutines is much simpler and easier to understand. In this video, I'll boil down coroutines to their most fundamental properties.
Looking Forward to Kotlin 2.0
Переглядів 17 тис.4 місяці тому
The Kotlin 2.0 release candidates are coming along. Let's learn what 2.0 is all about, and explore some of the updates that I'm most looking forward to! K2 Compiler Performance Benchmarks: blog.jetbrains.com/kotlin/2024/04/k2-compiler-performance-benchmarks-and-how-to-measure-them-on-your-projects/ K2 Performance Metrics Project: github.com/Kotlin/k2-performance-metrics K2 Compiler Migration Gu...
Three Simple Rules for Subtypes
Переглядів 2,5 тис.4 місяці тому
Inheritance, declaration-site variance, and type projections are all based on three simple rules for subtypes. Once you understand those three rules, you can reason your way through inheritance and generic variance. In this video, we'll learn what those three rules are, and then see how they apply to a variety of Kotlin language features! ✨ New to Kotlin? Start your journey here: typealias.com/...
Inline Functions: inline, crossinline, and noinline
Переглядів 5 тис.5 місяців тому
Most of us understand the basics of what it means to inline a function, but in Kotlin, there are some nuances that affect how you can use lambdas that are passed to them. In this video, we'll cover the basics of inline functions, and then learn about those nuances - and how we can use crossinline and noinline to get the behavior that we want. ✨ New to Kotlin? Start your journey here: typealias....
Every Kind of Class in Kotlin
Переглядів 11 тис.5 місяців тому
Kotlin offers many different kinds of classes, and in this video, we're gonna look at all of them - regular classes, nested classes, inner classes, data classes, inline value classes, enum classes, sealed classes, and annotation classes! By the end of this video, you'll understand these different kinds of classes and when to consider using each one. ✨ New to Kotlin? Start your journey here: typ...
Type Projections... and why they work!
Переглядів 3,7 тис.6 місяців тому
Let's dive into the world of Kotlin's type projections! We can't always use the `in` or `out` modifiers in a generic class, but don't sweat it - we can still get the generic subtypes we want! This video shows how you can use type projections to get generic subtyping - even for types that are in library code! In less than 9 minutes, you'll learn both how you can use them and why they work. 📘 Kot...
New HexFormat Tooling in Kotlin 1.9
Переглядів 1,9 тис.7 місяців тому
New HexFormat Tooling in Kotlin 1.9
A Tour Through Konsist with Igor Wojda
Переглядів 2,2 тис.10 місяців тому
A Tour Through Konsist with Igor Wojda
Intro to Collection Builders in Kotlin
Переглядів 4,4 тис.Рік тому
Intro to Collection Builders in Kotlin
Easy SharedPreferences with Delegated Properties in Kotlin
Переглядів 8 тис.Рік тому
Easy SharedPreferences with Delegated Properties in Kotlin
5 Fun Ways to Use Extension Functions in Kotlin
Переглядів 12 тис.Рік тому
5 Fun Ways to Use Extension Functions in Kotlin
Peek Behind the Scenes of TypeAlias.com - Dave Leeds on Kotlin
Переглядів 1,3 тис.2 роки тому
Peek Behind the Scenes of TypeAlias.com - Dave Leeds on Kotlin
This validator class is nice, maybe an episode about how to create a generic validator as it is something we do often in code.
That camera quality, voice and background. Wow
Hey, thanks so much, Ronny! Glad you're happy with the production quality!
best kotlin channel. Any plans to add inline, crossinline, noinline, reified material to your book?
Hey, Hameed! Thanks so much! For the book, the objective was to get the reader to the point where he or she could be productive with Kotlin day-to-day, so I've intentionally left out some of the things that are mainly concerned with optimization (value classes are another feature that I love, but just didn't quite fit the objective, so I left them out). So, they won't be included in the Illustrated Guide - however, I'll still be writing (and drawing!) about Kotlin features as standalone articles on the website, and if there's enough interest in that topic, I'd be happy to write that one!
I have been struggling for a long time for what is coroutines,until I see your explanation.Thanks that helps me alot
That's fantastic! I'm so glad you found it helpful!
Having used emacs for a while, I use the navigation shortcuts from it since they also work in the terminal. Ctrl-p/n/f/b. There are many others like kill and yank for cut and paste that also work in the terminal.
Hey, that's great, Robert! Emacs is another one that I always felt had a good reputation among the more hardcore, elite developers, but I never got too far with it myself. Neat idea to use its navigation shortcuts since they also work in the terminal! I do sometimes get tripped up when trying to navigate in another app. 😅
What a great explanation
you really2 mastering of kotlin, always 2 step ahead. 🥶
I loved the intro
Hey, thanks so much, Mario! Took a while for me to finish all the animation, but I'm happy with how it turned out. =)
Hotkeys I got used to from Isabelle/JEdit are alt+left and alt+right for backwards and forwards in history. It goes over file boundaries as well. It's not as good as the version in JEdit, but it is very useful.
Settings -> Editor -> General -> Smart Keys -> 'Use "CamelHumps" words' enables the mode persistently so you wouldn't need to remember a dedicated shortcut
Nice! See you at KotlinConf!
Thanks so much Anton! Looking forward to seeing you there!
Whoa, didn't know about the double ctrl + up/down for multiple carets, I've been always setting my own shortcuts for that I've always seen people use it and never found it in the shortcut settings, so I thought it's a macOS-only thing or something :P Guess it's time to use the default one instead! (note that on Linux, I can hold the Ctrl key after the second press for as long as I want, it doesn't deactivate)
Hey, that's great! And I'm glad to hear that there's no timeout for the Ctrl key on the second press on Linux. I think I'd use that shortcut more if that were the case - I'll check Mac and see whether it happens there, too.
@@typealias Yeah, it would be annoying if it disactivated. Hope to meet you in KotlinConf btw!
Yeah, sounds great! Looking forward to seeing you there!
Your book is great, completely recommended for anyone who wants to learn quickly and clearly, from the basics.
Hey, thanks so much, Renato! I'm really glad to hear that you've enjoyed the book!
awesome content! thanks
Hey, Dave. Thanks for explaning and optimising codes using kotlin. And also motivating to follow Design Patterns during development. But I have a question, in Android there is a BaseActivtiy or BaseClasses generally we do use it and it is Anti-pattern. But over there we implement AutoLogout and LoadingLiveData logic over there to show progress bar for all screens. Well progress bars can be implemented by all the activities or fragment but how about the AutoLogout, if we implement in All activities then there is a boiler plate code all over the activites and if we miss to include it in some activity then what.. Even thought for AutoLogout Service but that thing also needs to be started or stopped onActivity resume and stop. If you could share some optimisation for this as well that will be really great. Thanks in Advance. Love your content.
Why user is pasted in method, not to the constructor?
More design patterns please
You got it! 👍
I
I really like how this code looks after your refactoring. But I see one potential drawback. Before to create a concrete implementation of FormField you just needed to call the constructor and the validator is built-in. Now you need to make sure that you pass an appropriate validator for your field, and from my opinion this is error-prone, especially in the production. We might solve this problem by introducing a Factory or something similar combined with your refactoring but, again, we will get more code. What do you think?
Hey Ilian, thanks for reaching out! I think I understand what you're getting at - the earlier approach had an actual type (e.g., EmailValidator vs. UsernameValidator) whereas by the end, they're all just the same type - (String) -> Boolean, and we'd have to be careful to use the right validator on the right kind of value. If we want the compiler to enforce that, I'm thinking we could still keep the latter approach, but might consider using simple value classes for the types, and generics for the validators. Maybe something like this: ``` interface Value { val value: String } @JvmInline value class Email(override val value: String) : Value typealias Validator<T> = (T) -> Boolean val emailValidator: Validator<Email> = { it.value.contains("@") && it.value.contains(".") } class FormField<T : Value>(val name: String, val value: T, private val validator: Validator<T>) { fun isValid() = validator(value) } fun <T : Value> Validator<T>.optional(): Validator<T> = { it.value.isEmpty() || this(it) } ``` I only included the value class for Email in the code here, but same idea for the Username and Password. This wouldn't add too much code, and having strong types for those values would usually be a good idea anyway!
@@typealias Thank you VERY much for the detailed answer.
Thank you so much for the great talk! One of the best explanations of coroutine concepts I've seen out there!
Hey, thank you so much, Yan! I appreciate that!
Such a great explanation. Great job, Dave, as always!.
Hey Dave. Great seris 👍I think you should cover Visitory as well. I've talked about it here at GDG a while ago ua-cam.com/video/i7dHrLej2bg/v-deo.html
Thanks for the inspiring video. I would like to see the Chain of Responsibility pattern next. I came up with a few implementation variants and would like to see your version.
Thanks, Peter! Yeah - I had played with Chain of Responsibility implementations recently, but I wasn't as happy with my ideas for it at the time, so I moved on to other patterns. I'll pull up my notes for it and see if I can look at it with a fresh perspective!
I liked it very much. I would add naming parameters in the lambda for clarification. enum class UserState( val signUp: User.(email: String) -> Unit, ....
wow that was awesome! thanks for sharing!
loving the design pattern series!
Thanks, Fabiano! I'm glad it's resonating so well with everyone!
Excellent presentation! It would be great if you could do something about context receivers and compare them with typeclasses
Thanks so much! I'll add that to my running list of video ideas!
I think your approach is much better than the standard approach; it is concise, well packed and more understandable even for beginners.
Thanks so much, Mike! I really appreciate that!
great content as usual
You’re awesome 🎉 I haven’t learned a new language this fast, ever before! You sir are great at explaining! Keep this up!!
Oh wow, that's really great to hear - really glad that you're picking it up so quickly! I'll keep at it!
Mind blown by all your design pattern videos so far. The format of these videos is really good: take a real life code scenario, refactor the code to use the pattern, followed by some crazy kotlin. And all this in about 12 minutes! Loving it!
Thanks so much, Tony! It sounds like the format is working well for everyone, so I'll keep at it!
I thought i am too good at kotlin but now 🥲
Loving your videos. Keep them coming! Personally, I would have used a sealed class/interface instead of the enum. Main reason being, you can separate each implementation in its own file (if the number of enums keeps increasing you end up with a huge file)
Thanks, Mankin! Yes, that's a good point. I think also as you start getting more distance between each enum entry, they start to feel less optimal as a choice. With the 5-parameter constructor that I had at the end of the video, they started spreading out a bit, but at least they did all fit on a single screen. But like you said, if we were to add a few more entries, it could start to become more difficult to keep up with them!
This was oddly satisfying, felt like a TLC show for developers :)
Hey, thanks Zeynep! I'm glad you enjoyed it! 🙂
Very nice. Good review of the State Pattern and how Kotlin can uniquely implement it. Thanks for posting this
Great video, can you show shortcuts toasts, like in presentation mode? TY
Thanks - I've had a lot of requests to show shortcuts lately! My keyboard shortcuts are very customized, but most people are particularly interested in how to edit with multiple carets, so I'm going to cover that at the upcoming livestream. 👍
This is AMAZING! Regarding 7:19: if we want a more flexible code structure than the rigid enum class, but we still want an exhaustible type, we can of course make the state a sealed interface or sealed class instead!
Yes, thanks Arthur! I probably should have just done that in the video - I can't think of any reason not to make the interface sealed here. 👍
awesome!!! Thanks Just need one more step -> logout and change state from AUTHENTICATED to ANONYMOUS
Yes, good thinking, Pavlo! 👍
For me personally "state" - is something that holds data & state's name is the marker aka description of action that must executed for each of them. For this particular scenario seems like state can also execute some logic (which in real life will not be as just printing some debug line) and that makes state itself a lot more complex thing that possibly requires a dependency to other classes --> a lot of business logic happening inside. I would think of something more appropriate for execution, like StateManager/StateHandler/etc that will execute business logic for each state change
Maybe the term "state" here is closer to the term "state machine" than "object state"
While working on this video, I did feel like there's a bit of irony in that these state objects hold literally no state of their own. Yes - we basically made a finite state machine, and that's the sense of the word being used here. Maybe the term "State Pattern" was more intuitive back when the GoF book was written (I was just a high school kid writing QBasic at that point), but I can definitely see how it could be a confusing term these days!
nicee
My ocd is kicking in on my code 😂
There certainly is something nice about having all that code line up like that! 🙂
A topic for future videos would be how to do state transitions (ex. from unverified to authenticated) and deal with unsupported operations (ex. anonymous can't edit a profile)
Transitions should be as simple as swapping the instance of state in the context. Unsupported operations should probably fail with IllegalStateException, a convenient way to throw it is to call the "fun error(message: Any): Nothing" function from the Kotlin standard library.
I'm currently writing C# in my day job and I wish I could end up with code similar to your final Kotlin version yet C# does not support "top level functions". Another thing to keep in mind is that in your class based version you could instantiate the same validator even tough it makes no sense since as you said they have no state at all. You most likely want to use `object` rather than `class` if you want to keep the class based approach.
Great video! but I have a question, why use objects instead of classes?
You certainly can use a class if you like! Even in the GoF Design Patterns book, they mention a lot of flexibility in how you can implement this one. If you've got states that have no instance variables of their own, you might prefer to keep them as singletons, as we're doing here, to avoid the cost of instantiating the additional objects for each user - the book points out that when we do that, the states are also very similar to flyweights from the Flyweight Pattern. For cases where that's not as important - which, these days, might be most cases - you can just instantiate a new state object each time, which would clean up the function signatures (because you wouldn't have to pass the user object for each operation).
@@typealias thanks for explaining!
Waiting for all design petters videos from you!
You want all of the design patterns in a single video? That might end up being a pretty long video! 🙂
@@typealias ofc not in single video. One design pattern per video is great
Haha, okay gotcha! I'll keep at it, then - only about 20 videos to go! 🙂 I actually might end up having to do a single round-up video for a few of the "leftover" patterns that wouldn't really warrant their own videos. Like - singleton wouldn't take too long to explain. And for some of the others, Kotlin doesn't add much. Anyway, thanks for clarifying!
@@typealias omfg this is my dream to see these videos! Thank you so much! Can't wait!
Now add another function to the interface and you didn't accomplish anything with this pattern
Well, adding another function would require us to revisit each of the state objects - I think that's what you're getting at. Even then, though, I would find it easier to manage the smaller, more focused functions that are grouped by state rather than large functions that are each trying to juggle different implementations for multiple states. (But if I'm misunderstanding your point, let me know!)
You're a gem for Kotlin learning
Really nice
Thanks A couple of "PR" comments.. :D - you ve got a bug in the end in the anonymous signup function - you are printing `email` from the receiver instead of `it`, so it will print null.. - when declaring lambdas like (String) - Unit, its better to keep the names of params, i.e. (email: String) -> Unit instead of stripping it - otherwise it becomes hard to read I would agree - thats a bit too far of a refactoring :)
Ahhh, yes you're right! Thanks for catching that. Should be printing `it` instead. 😅
I also prefer typed parameters in lambda for other developer's sanity.
Explicitly writing the lambda parameters is always an option, of course. It all depends on the team's conventions, or in case of solo projects, the developer's preferences.
@@ArthurKhazbs Absolutely, you project your rules, but here we are educating people, it seems :) and when I see such in the code: `val editProfile: (String) -> Unit` - how am I supposed to understand what would be passed here? And in this case I see at least 2 solutions - either name it `(email: String) -> Unit` or use tiny type - `value class EmailAddress(val email: String)` - then its inferred in the type what will be passed.
Thank you. My heart started to ache a bit when you used semicolons🙃It definitely looks nice when the code is complete, but I can see how hard would it be to maintain the logic when it's written in one line)
Yeah! I almost never use semicolons... In this case, at a glance it looks like it might be part of the println() statement, so it'd be easy to miss what's happening!