Null Object Pattern - Design Patterns
HTML-код
- Опубликовано: 7 фев 2025
- Design patterns are one of the easiest and quickest ways to create clean manageable code whether you are starting from scratch or refactoring existing code. One of the easiest to implement design patterns is the Null Object Pattern. This pattern is all about handling the null keyword in a way that removes all of those nasty if (object == null) checks from your code. It also makes handling default values for null objects a breeze.
If you want to learn more about the Null Object Pattern make sure to checkout the repository linked below.
Design Pattern Playlist:
bit.ly/2QrGnDq
Design Pattern Repository:
github.com/Web...
Twitter:
/ devsimplified
GitHub:
github.com/Web...
CodePen:
codepen.io/Web...
#DesignPatterns #CleanCode #Programming
Don't forget to checkout the GitHub repository for extra examples and explanations of all the code in this video. github.com/WebDevSimplified/Design-Patterns
Me: Okk... but I’m not gonna
Thanks, I'm really glad that you did a follow up video to the original! Looking forward to more design pattern videos. 👍
I'm glad you liked it. I love design patterns so I will be making lots more videos as long as you all still enjoy them.
I don't understand why you have just 500 likes, you explain so well! Keep it up!
one of my fav channel ... you have knack of explaining a complex topic really well
thanks kyle. There is a special place in heaven for people kinda you !
Sometimes, if the returned object doesn't implement an interface, adding if guard clauses inside the "class" might be more convenient than making another "class". For instance, in C++ I have wrappers for the SDL2 library. When a property is null, the methods that would access it return immediately without null checks outside the "class".
7:58 Coding peeve: redundant "if ... else" clauses. The "return" ends the function execution.
Some might it makes the flow explicit, but I think it makes the code less readable and, like in a UML Use Case diagrams, I like to think the most important part of the code is the main success scenario. You look at the end of the code, before the "if ... return" to understand the main goal. You look at the "if ... return" to understand the exceptions and alternate flows. With that "if ... else" you're not making a distinction between the code with the main goal and other code.
The "if ... else ..." makes it look like the code inside the "if" scope is the most common branch (it's the first thing we read before the "else", "else" sounds like an afterthought and compilers and machines assume the code inside an "if" is more commonly executed). Or, at least, visually, they're at the same level.
That's a much cleaner way of implementing it. Currently, when I make a class, I check for the null or empty possibilities and assign them a default as soon as possible.
I know this is a old video. But here is an easier way
user.find(user => user.id === id) ?? new User(-1, 'Guest')
Now the function still returns the same type.
Wow that's a nice idea!!
I'm a self taught dev.
Helping me code better!
To improve this even further, e.g. for a really large project the getUser function should be inside of some repository type class where all users are stored and the User and NullUser could be a Administrator and Guest class that both inherit from a superclass User (abstract class is probably best for this useCase). that way all functionality that both types must provide can be defined in the user class and anything specific to administrator or Guest can be done inside the respective classes :-) another way (if u hate inheritance) is to use interfaces and dependancy injection
I think GuestUser as being a NullUser would be a good idea. The Guest user is a user that doesn't have a username, an account, a session, etc. It's empty.
But making it the Administrator doesn't make sense, and it's very risky. The administrator user is not like a NullUser. It has data about a user. It's not empty. And it has access to functions that other users shouldn't access. And many times when you make an abstract class instead of an interface, you might be calling for trouble.
(added)
Instead of making classes for different user roles and inheriting code, think about how, for instance, UNIX and several CMS do it: use roles or groups to determine what a user can do. For instance: administrators, editors, publishers, readers, etc. For each role, you have a list of available function. Relate users and roles, like a relational database. By the way, that makes it possible to configure the roles and the user roles in a DB.
Great video! You have a really nice and clear way of explaining things :)
Thanks!
It's almost as if he is simplifying web dev....😲
Please, keep this series going!
Thanks. It has been on a bit of a break recently, but I do want to try and revive it sometime. I need to just dive into it and get started again.
Very very good explanation thank you!
Instead of the NullObject, you can initialize the properties with default values.
separation of concerns. you should not initialize anything inside the user class. you can, but it is not a good/clean practice.
Thank you, your teaching skill is amazing
Really amazing explanation, thank you very much 🙏
When we use the find function and the id is not present in the array we will get the undefined instead of null.
const user = users.find(user => user.id === id)
for example, in the above case if we try to find the is which is not present in the array we will get the value undefined.
Hi Kyle, really nice video. I am a student who is learning web design now, I learned a lot from your tutorials. Btw I think I heard League of Legend background sound 8:39 from this video XD, do you play it too Lol
Great videos. I learned another way to reduce checking null. many thanks. Quang from Viet Nam
Great pattern and great explanation! My other favourite is the adapter pattern :)
I use the adapter pattern all the time. Anytime I want to consume an external library or API being able to wrap it makes your code so much safer in the case of future changes with the library or API. It also makes it much easier to swap libraries later which is usually a huge pain.
@@WebDevSimplified Hey Kyle , great stuff . Please do make a video on Adapter Pattern too with the example you mention.It will be really helpful :)
@@WebDevSimplified Please do make video on adapter pattern also bro. It will really help. Thanks for such content.
Nice explanation
Awesome explanation, thanks 🙏
Wouldn't be easier to have default arguments in the User constructor and if user not found just return new User()? Or to have an object linked to the User class and use as User.Null?
Hi,
can you please create more video about design patterns please ?
These are very well explained with great examples.
I plan to make more. I have been busy with other ideas but plan to keep this series going.
I like the idea but don't you have to maintain 2 copies of basically the same class now? if you make a change to User you have to do it to NullUser also
Yeah there should be a way to do this with extends somehow in getUser
Bro this is awesome!!
great explanation
Hey love your channel, keep it up!
Nice explaination. I guess you forgot to save your edited code before running it. :D
So well explained !! Thanks
Is there a specific reason that you so not user the triple equal operator? Double equals perform type conversion... You'd actually would have to check against "undefined", not "null".
I believe “value == null” is a way of checking if “value” is null or undefined. It’s using type coercion to make the code shorter. Some people prefer that brevity, others prefer to be explicit and say “value === null || value === undefined”. The result is the same either way.
Correct me if I am wrong, but seems like it did not solve the null check required for name? (shown in 3:51) If we have a user with null name this will still cause an error. If it is impossible to have such a user, then this condition check was not required in the first place and the Null Object Pattern did not actually help on this.
Great vid otherwise though!
It's possible to add a setter that makes sure the "name" is never null.
Anyway, the database table might have constraints, like a NOT NULL for the name.
In principle, the name should not be changed when outside a form submission. You'd only need to check if the name is null in the validation, before creating a user or updating it.
And the name of the NullUser is "Guest": 7:29
I have question here, is there code repeatability rule violated here because of null check class again repeated with other values
It would probably be better to have a getNullUser function that returns a normal object with null values than to have to maintain yet another class when modifying the normal class (maybe as a part of the class itself).
May be the getNullUser can be a static function inside the User class itself.
we should use singleton to return the same object reference
@@unique_god why not just use a simple object literal 😑 with a name, id and hasAccess() function.
If you can create a default constructor that uses "Guest" if no user was passed, why not do that? CS student asking a legit question. I could be missing a bunch because I am still very new. So why would we not use a default constructor in place of a Null design pattern?
thanx 4 the video. but what if im using C#.. what would be the return type of function getUser?
in here getuser function return two different objects (user and NullUser). insted of creating seperate class what is we can use different constructor to set default values
on line 40, why do you need to check if the user has the method hasAccess itself?
good explaination
Thanks for the video! To add my five cents, I would derive class NullUser from class User. So the same pattern could be used in a more type-safe language, like typescript, for instance. But I wonder if this would violate the Lyskov substitution principle…
is there a video on Factory Design Pattern ?
Thank you !!!
thanks for the great video😄 ... it is amazing👌
You are welcome.
can't we have default params inside the User constructor instead of managing another class ?
Why did we use the double equal check instead of the triple equal check?
Also the (typeof user) is returning undefined and not null
== checks if the truth values are equal.
null has the same truth value as undefined i.e. (null == undefined).
=== checks if the truth values are equal and if the data types are equal.
null is a distinct data type from undefined i.e. (null !=== undefined).
(obj == undefined) is the same as (obj == null) but the latter is more common.
These are both identical to (obj === undefined || obj === null), but this looks messy.
In this scenario, (user === undefined) would work just as well as (user == null) but not (user === undefined), since it returns an undefined as you said.
However, this is bad practice, because a function like this could return null, and therefore (user === undefined) would return false when user is null.
We don't care about the distinction of undefined and null in this case, so we can easily check if it is either by using (user == null).
Since, you have two maintain 2 different classes for the smae Object. Is there any better way to handle this situation?
I'm thinking about you saying don't use else and here you're using it
I know, by the way
You caught me :P
thank you!
Doesnt null have to be set in order for a variable to equal null
Would it be adivisible to make NullUser a subclass of User to having to write less code, just calling super with my default values and being able to use it things like an array of users or will this bring more trouble than it is worth?
Why not just assign a default value to each property of the object in the constructor instead of creating a new null class? I'm just curious.
find returns undefined if it does not finds a match, then why are you checking for null
note it is not common to prefix null objects by null, this is because in other languages this wouldn’t work, a function that returns a null obj is more common
For printUser(3), getUser() function isn't returning null. In my case, it's returning undefined. Did anyone else found this issue ?
is this the same pattern as "Naked objects pattern"?
Thanks!
Thank you very much, kind sir!
I don't understand why you couldn't just create a separate user with id -1 and name guest and use it in getUser function whenever user isn't found in users array
Could make video on custom react component based custom library like material ui
good stuff!
Thanks!
Very good video, I was wondering why not try to return new user(-1,´Guest´) directly avoiding to add an extra class !
The purpose of this class is to have a predictable user object that is always the same. If you use your method you need to ensure everytime you want a null user you return that exact constructor which is hard to ensure. It also allows you to check if the user is a null user by having the class
@@WebDevSimplified thank you very much for the feedback !
thanks a lot
I'm blown away by quality and clarity of your tutorials! Sir, I bet you IQ is 195 or higher!
and yours might be 0 or lower
@@sppanday_ I complimented him in my comment. But you asshole thought I mocked him, because you live in a place that everyone treat you like shit and no one gives you any attention so you think everybody is like those who live with you in that shithole that you call home. I hate your guts, and I hope I never hear from you asshole.
@@sppanday_ no surprise india is a stinking shithole!
@@Admiral_Ducky And, no surprise that you are a fucking idiot.
THANKS BRO
After implementing null object pattern, can't you just check if (!user) return new NullUser() ? Since find() return undefined if it doesn't find
Correct. You can do that.
thanks
cool thanks
Awesome
We could also just put default values for your variables and have your User class be responsible to return a user with default values , not seeing how this simplifies things
I Wish i know design pattern before
USA 🇺🇸
Downvotes? Who and why...
When these users signed in they received a "you are not allowed" message
man idk if theres any money in web development :/ kyle is an expert but he still cant afford doorknobs for his closet doors
just use TS XD
notNull comment
This pattern is really unnecessary.
Why so ?
///