December 11th, 2023 × #Observer pattern#Design patterns#Game development
The Observer Pattern
Discussion on the observer pattern, its use in game dev and JavaScript frameworks, differences from observables, and its relation to promises and streams.
- Overview of observer pattern
- Used in game development
- Achievements as observer example
- Decoupled event communication
- Observer and subject components
- Intersection observer example
- Potential downsides of observers
- Observers in JavaScript
- Other DOM observers
- Event listeners as observers
- Differences from observables
- Signals and observer pattern
Transcript
Scott Tolinski
Welcome to Syntax on this Monday, hasty treat. We're gonna be talking about a design pattern in computer programming, one that is becoming more and more relevant the more in which we see these things in our JavaScript.
Scott Tolinski
And I'm talking about the observer pattern. What the heck the observer pattern is, where it comes from, and how it relates to the things that we do in JavaScript.
Wes Bos
the boss. Yeah. We've we've had this to talk about observer pattern. And, in a future episode, we're going to talk about the observable, Both like RxJS. I know Angular has a lot of observers in it. And now there is a proposal to add The observables to JavaScript as a native thing, which is pretty nifty. So this is kind of going to be like a first run sort of explaining what the observer pattern is for you, as well as some of the things in JavaScript that are already using that. Then we'll do another episode on the the proposed addition to the language.
Scott Tolinski
Yeah. So this will be definitely a bit higher level.
Scott Tolinski
But when you're learning anything new like this, it's important that you use error and exception handling tracking.
Scott Tolinski
That way, in case you goof it up, you have The ability to track if you mess something up. So, this show is presented by Sentry, the perfect place to track all of your errors and Not only that, but your performance and your, web vitals and all sorts of awesome stuff. So head on over to Century dot I o. Use the coupon code at tasty treat, and you'll get 2 months for free.
Scott Tolinski
So, Again, this episode is gonna be mostly about the concept, and we will relate it to how this concept is applied in JavaScript.
Scott Tolinski
But to get a a bit of a overview, so to say, this design pattern, the observer pattern, is basically a pattern that is used in a ton of different contexts in programming and has been for a long time.
Used in game development
Scott Tolinski
And in fact, one of the places that it's very frequently used is in game development.
Scott Tolinski
And, Wes, I you you remember we were talking to Mark Texan a few a few supper clubs ago about Angular. Right? You remember? Yep. And he he had mentioned wanting to learn Godot or Godot.
Scott Tolinski
I believe it's called Godot, actually, and that's a game development framework. He wanted to learn that with his son. Well, I spent some time learning Godot over a little Thanksgiving break because I I wanted to to do that. And guess what? The observer pattern was all Over the place in Godot, and that is a game development platform. So this is something that, you know, a lot of different programming context use this, and we're seeing it more and more In development front end framework framework world, not that we have been, but we're hearing about it more now that, A lot of frameworks using things like signals and yada yada yada. Can you can you give an example in, like, a in a game what you might want to observe just to sort of frame this for everyone listening. Like, what's part of a game that you might wanna observe something? Yeah. Well, think about, like, anybody who's played games in a little while, have has probably seen the idea of, like, an achievement. Right? Mhmm. You do something, and an achievement might get fired off. You know, you chop down a tree in Minecraft for the 1st time. It'll give you a little achievement. Hey. I chopped down my 1st tree.
Achievements as observer example
Scott Tolinski
And that's a good example because, the The observer pattern is basically where you're tying events to situations, and the event the event or the observer is fired, essentially. We'll we'll talk about the The observer in the subject is just a little bit to dive into more of the conceptual type of things. But you can imagine that in Minecraft, There isn't going to be a function that's like you're you're chopping down every time you chop down a tree. You can imagine there isn't an if statement In that tree chopping down that says, hey. If this is my 1st time doing this, then fire off the achievement. Yeah. It's more or less listening for that and seeing if that achievement has happened then firing it off. So, again, it it's you're you're doing what is an event based, nontightly coupled, Yep. Situation event firing. So the the main thing here is that you allow different parts of a system to communicate and react to events
Wes Bos
without being tightly coupled. That's that's I I love that. You how you said, Like, there's no if statement. Every time you chop down a tree, there's not an if statement that checks it.
Decoupled event communication
Wes Bos
And then also to add that. There's probably not a function running on a 500 millisecond interval saying, did they chop down their 1st tree? Did they chop down their 1st tree? Did they chop down? Right? Like that's both of those ways of just sort of waiting for something to happen are they're they're not scalable. They're too tightly coupled. They can use too much memory.
Scott Tolinski
So the observer pattern is super handy here. Yeah. And so this was created in the 19 seventies.
Scott Tolinski
Jump. It's widely used as part of MVC. So anybody who's you done any sort of MVC programming, maybe Java, c sharp, they have core language features around observables Or the observer pattern itself.
Scott Tolinski
These things, if you're a classic programmer, it has been ingrained in you in terms of These are these are things that, have existed in most systems. Web developers, and believe it or not, these are things that you've used a whole bunch with maybe out different part of the app needs to respond. We understand A different part of the app needs to respond.
Scott Tolinski
We understand that in, like, a React application, a tightly coupled event system might be your Prop drilling the an event down into a component, and that function is fired. That's tightly coupled. Right? As opposed to an event is fired, and then something else is listening for that somewhere else in the application, non tightly coupled.
Observer and subject components
Scott Tolinski
So there's 2 Key components to the observer pattern, which is the observer itself and the subject.
Scott Tolinski
The observer is the thing that wishes to be notified when something happens.
Scott Tolinski
The code that is called when an event has happened. Right? The observer.
Scott Tolinski
The subject is the thing that triggers the event. It maintains a list of observers Just that the observers exist and that it needs to notify them when something has happened. Okay. So,
Wes Bos
If I think about Intersection Observer, that's a one in the browser that we have already.
Intersection observer example
Wes Bos
You create an Intersection Observer.
Wes Bos
That would probably be the section or sorry, the subject. Right.
Wes Bos
And then what you do is you add elements to that observer. And you're basically saying, I want to be notified when these things are on or off the screen.
Wes Bos
And then The other part of it, which is the code that's triggered, and that's the observer itself. What do you want to do? All right, I'll let you know when those things are on the screen. But stuff. What do you wanna do when we do that? And that's the the callback function that's triggered when it runs. Totally. So before we get into the JavaScript parts of this,
Scott Tolinski
given that you just mentioned intersection observer, which is something that many of us have used, can you see what the downsides to observer pattern might be in regards to even keeping in that context of, like, What would happen if you had too many different intersection observers or mutation observers or any of that sort of stuff? Yeah, I well, I can tell you what the downside to
Potential downsides of observers
Wes Bos
it when we had a polyfill for IntersectionObserver, because The polyfill would just simply run an interval checking every single element's x, y, width and height and check and then how big the the actual browser was and saying, okay, this element is on the screen or off the screen or partially on or partially off.
Wes Bos
And checking, like, doing that polling over and over again is heavy on memory. Right.
Wes Bos
So you can Seize things up pretty quickly when you're doing that. And that's why it's nice because that Intersection Observer was part of the browser
Scott Tolinski
Without that polyfill, the downside of this type of pattern is memory usage because the subject Maintains a list of observers and notifies them when something happens.
Scott Tolinski
And you're keeping all that stuff in memory. Right? Z. Depends on how much you have in your memory, what the potential downsides could be beyond just, like, a polling situation.
Scott Tolinski
If you're storing a lot of stuff to use later, you know, there's potential issues there. That said, I think this might have been a concern more when Memory usage was a bit more constrained.
Scott Tolinski
My computer has a gazillion gigabytes of RAM, and I'm on a Mac. You know? So just imagine what PC users have. They have a gazillion gigabytes more.
Observers in JavaScript
Scott Tolinski
So let's talk about now the, like, the JavaScript connection here.
Scott Tolinski
Things that maybe have already existed or exist in library land or things that, You know, you may have used I think a a good first one is intersection observer. The word is In the thing right there, it's an observer.
Scott Tolinski
And like you mentioned, you're waiting for something to happen, And that thing is happening. You have also mutation and performance observer. Do you wanna talk about those, Wes? Yeah. So we talked about intersex observer when it comes on or off the screen. That's really handy
Other DOM observers
Wes Bos
if you want to, like, for example, in my slide deck, when something when a video is on visible on the screen, I play it. And then when it goes off the screen, I pause it. Right? That was a really handy way to see if something needs to currently be on.
Wes Bos
But then there's also Mutation Observer, which will allow you to Watch when an element has there's several parts to it. But basically when an element changes right, it doesn't get children.
Wes Bos
The attributes on this element change is the text content of a node been updated.
Wes Bos
And if you want to closely watch an element on the page. This is more of a lower level thing, but you certainly can do that.
Wes Bos
And then there's Performance Observer, which I've not Done, ever used. I've used both Intersection and MutationObserver quite a bit, but not Performance Observer. But It's a feature used to observe performance measurement events. So if you're using the Performance API to measure how long certain things take.
Wes Bos
You can it's kind of nice. You can decouple other things from that and sort of like wait for those events to fire.
Wes Bos
Yeah, and I didn't have to check it out. It's relatively new, maybe 33 years old, 4 years old.
Scott Tolinski
But, again, it's it's probably more of a performance tool. Yeah. I also have not used that. And, likewise, resize observer, one that we used a whole bunch before container queries, and now resize observer is still useful without them. But being able to observe whether or not a a DOM element has been resized, the dimensions have changed, And it's firing off. Notice how all of these things are exactly what we've been talking about. Right? Yeah. You're looking at something, a subject, And then you're going to fire off an event when that, an event has happened.
Event listeners as observers
Scott Tolinski
And, likewise, I think that is Classically related to something we've just about all done in JavaScript. Even if you haven't used any of these observers, What can you think of that waits for an event and then fires off a function when that event has happened? Yeah. I I was curious about this because,
Wes Bos
Like, at event listener and, like, the whole event system in JavaScript is is kind of like this. Right? You you take your your element.
Wes Bos
You attach an event listener to it. You tell it what you wanna listen for, whether it's a click or a mouse over, mouse move.
Wes Bos
And then when that happens, it run some code. And I'm curious if, like, some people think, like, no, that's callback based coding.
Wes Bos
And I think that like the observer, especially when you get into RX JS, I think that that is a little bit more Flexible in that you can map filter over your observables.
Wes Bos
You can do a little bit more with it rather than just like listening for an event and running some code when that happens, because often your event listener callbacks have a bunch of if statements inside of it.
Wes Bos
But Like, is it? What do you think? Is it unobservable? The docs for MDN say add event listener observes an element
Scott Tolinski
Or when that event happens. Yeah. So whether or not it it is an observable, I think I need to understand more the term observable implies there because at event listener is An example of the observer pattern where you're have a subject, the subject in this case being the DOM element, And the observer being the event listener and callback. Right? You're you're firing off that event, And you're sending it a function whether or not that function's a a callback or not. It doesn't necessarily matter. I don't necessarily understand what the distinction between the word observable versus the observer pattern is there, and that might include Some of the reasons why they're not that not why you wouldn't say it is an observable, but it's a part of the Or it is an example of the observer callback. Yeah. I think also like the observable pattern
Differences from observables
Wes Bos
allows you to Add multiple elements to it just like MutationObserver, IntersectionObserver, and Resize Observer is you can Throw multiple elements into that subject, and when any of them change, you can with an event listener.
Wes Bos
That's not really the case, right? You attach it to 1 single Dom element, and then if you want to remove it, Jeff. There's no nice API. There's remove. You have to reference the function and whatnot, but the observable pattern has like a little bit nicer
Scott Tolinski
the API for for working with and removing elements from it. Yeah. I think the distinction here is that one of these things is a pattern.
Scott Tolinski
It's a high level concept, and the other is a feature which contains features. You know? It's a a thing that does a thing and has features. One of them is like, oh, you you have a a wide ranging concept that just includes a subject and observer, and the other is, you know, a little bit more in-depth. And likewise, signals is becoming a big thing because signals are very event driven.
Scott Tolinski
And, again, a signals It is kind of like a a a state system or an event system in your application that is, again, event driven and, definitely also part of the observer pattern itself. So something that, again, we're going to be talking about and seeing and using in all sorts of different ways. But at the end of the day, This thing is really just a pattern where you have something that fires off an event when that event has happened, And, we keep track of those events and what needs to be fired off, the observer and the subject.
Scott Tolinski
That's really it. You have anything else to add here? Because we're going to be taking a whole another show to talk about observables
Signals and observer pattern
Wes Bos
themself. I I think, like, The only thing I'll add here and I'll wait till the next episode to talk about it is I have been wanting like a mix between Observable And Promise API and maybe even like a stream API, meaning that, like, sometimes I wish that I could have an API that like, let's say, for example, I'm streaming in a result from AI and I'm getting pieces of data in.
Wes Bos
And as those pieces of data come in, it would be nice to, like, react to them and and tack them on. But then also, I want to await that entire thing And have it resolve when the entire thing is finished. Right. So I think that between those 3 APIs, observables, promises, and streams.
Wes Bos
There's I think you can put streams and promises into an observable, And I think it would be pretty nifty. I'm going to dive into the proposed API quite a bit more before the next episode, but that is something that I have often found myself wanting where I want the data as it comes in, but I also want the promise to be resolved when it's finished.
Scott Tolinski
The Responding to events. So, hey, I'm I'm down for all that. I'm excited to learn more about this stuff. I personally didn't have a background In computer science classically, so really diving into some of these patterns or just general concepts Has been interesting for me in a contextual view to say, like, not only do I understand these concepts, but I've been using these concepts in actual code without just giving them a name. You know what I mean?
Wes Bos
Word. Awesome. That's it for today. Thanks tuning in, and we'll catch you on Wednesday. Peace.
Wes Bos
Peace.
Scott Tolinski
Head on over to syntax dotfm for a full archive of all of our shows.
Scott Tolinski
And don't forget to subscribe in your podcast player or drop a review if you like this show.