How many times in your developer career you forget to remove an event listener? Close web socket connection? Unsubscribe from updates from any source? Or you are just to run some cleanup tasks, but every time you should do it manually. In this talk, I will show a new concept “Lifetime”, which will change your mindset about solving the problems above, make it all easy and even automated. I will show how I use it in everyday development and how it makes my application better and secure. I will also show how it improves DX and productivity. And I believe it’s something your team might want to use too.
Less Struggle With Lifetimes
AI Generated Video Summary
The Talk introduces the concept of Lifetime in software development, which is used to handle clean-ups. By using a simple object called Lifetime, engineers can bind clean-up functions and reuse them throughout their applications. Lifetimes can be nested, allowing for the creation of chains and trees to manage dependencies. The Talk also mentions the ability to create different types of lifetimes, such as sequential lifetimes, which can be useful for canceling requests or cleaning up effects from previous iterations.
1. Introduction to Lifetime Concept
Let's get started. Today I'm going to tell you about the Lifetime concept that we use in our applications. LiveTime is a live stream. We're going to show you the same thing, but live stream. This is a piece of code. We have to write all this boilerplate code again and again. But we are engineers and our job is to make manual routine automatic.
Thanks. Thank you. Let's get started. And now, please welcome Igor and Ned. Thank you for having me.
Okay. So, my name is Igor. I'm a software engineer at JetBrains. And today I'm going to tell you about the Lifetime simple, but powerful concept that we use in our applications.
So, to give you some background, I'll show you this piece of content for the slides. This is a slide that you see on the screen. And it's called LiveTime.
So, this is a live stream. So, this is live stream. So, it's an awesome live broadcast. And we're going to show you live stream. So, we're going to show you the same thing, but live stream. Not live stream, live stream. Live stream. Live stream.
So, this is a piece of code. I'm sure you're all familiar with them. And maybe you, as me, were annoyed sometimes and wondering why all of this don't clean up automatically. We have to write all this boilerplate code again and again. Every time we add an event listener or subscription or something similar.
And, yes. I know why we need to do this. We have to try to avoid memory leaks, bugs and sometimes even risk. I'm sure that you all don't want your app to work because something wasn't removed before. But we are engineers and our day-to-day job is to make manual routine to be automatic.
2. 'Lifetime' in Engineering
In our application, Engineer Brains, we use a simple object called Lifetime to handle clean-ups. You write a wrapper around an API, bind the clean-up to Lifetime, and then reuse it everywhere. By calling terminate, all your cleanup functions will be called. Lifetime helps you make your code logic more scalable and you can even create your own different types of lifetimes. For example, you can create sequential lifetimes that terminate the current one when you create the next lifetime. This can be useful in situations where you want to cancel previous requests or clean up effects from previous iterations.
All that I've showed you can be handled by something. In our application, Engineer Brains, we call this something Lifetime. What is Lifetime? In a nutshell, it's just a simple object to which we delegate doing all the clean-ups. So, as you can see, it has two steps, is it terminated or not. And you can always add any number of functions which will be called after termination.
It looks very simple and here it is, how we use it. Basically, you need to write a wrapper around some API like event listener, subscription, etc. and bind the clean-up to Lifetime. And yes, you still have to write your clean-up code, but you see, you do it only once. And then you just reuse it everywhere. Just the same for you as writing the React component. Still looks very easy, yes. Then you just use this function, pass Lifetime there, and that's it.
But the major point here, as you can see, you still have control outside in one place. So you decide when to terminate all of this at once, and you don't need to define the clean-up logic in some other places because you have it here. And just like it, all your boilerplate code is now replaced by one line. Just call terminate and all your cleanup functions will be called. So you don't need to think about when something will be dropped, it was automatically done for you. And as I said, you can call your lifetime termination whenever it's needed. So like here you can bind termination or unmount. It's very basic and I'm sure it's very useful for most of you. And because of the simplicity, you can compose it with almost everything. So having all the lifetime logic in one place helps you to make your code logic more scalable. So you can even extend and create your own different types of lifetimes. Now I can just show you a couple of advanced examples of it. So here you can create sequential lifetimes, which terminates the current one. When you create the next lifetime. Like here in this example on the right from me, every time you call next the new lifetime is returned and the previous is destroyed. It could be useful in a situation when you fire the same request multiple times but you want the previous one to be canceled. For example, you can also use it in a user failure because on every effect you might run new effects, but clean up everything from the previous iteration.
3. Nested Lifetimes and Examples
Here, you can create nested lifetimes, which allows you to build lifetime chains and trees. This powerful feature lets you represent your entire application as a lifetime tree, declaratively managing dependencies. When a lifetime is terminated, all its nested lifetimes are destroyed. Check out more examples on our GitHub repo and code library, and don't forget to visit our JetPrints product called Space. If you want some JetPrints stickers, I might still have one.
Here you can create nested lifetimes. For me, it's the most powerful thing because you can create these lifetime chains or even lifetime trees. You can even represent the whole application as such a lifetime tree and put all the dependencies declaratively. You don't need to worry about terminating them all at once. If a lifetime at any level is terminated, all its nested, and then nested, and then nested are destroyed too.
And that's actually it. That's all with the examples. More of them you can find on the GitHub repo as well as the code library and some wrappers. There is a link on the screen. And there is also a link to our JetPrints product called Space where I work. And also if you want to grab some JetPrints stickers, I think I still have one.
And that's it.