SOLID : Open closed principle, explain simply
Kaziu
Posted on September 11, 2022
Open closed principle defines like that
Software elements (classes, modules, function...) should be open for extension, but closed for modification
😦? ← if you react like this now, keep reading this article👍
👎 Bad code
This is super small application that you can find how to say "Good morning" in each country
class Country {
name: string
constructor(name: string) {
this.name = name
}
}
const greetingList = (countries: Country[]) => {
countries.forEach(country => {
switch (country.name) {
case 'poland':
console.log('dzien dobry')
break
case 'japan':
console.log('ohayo')
break
case 'usa':
console.log('good morning')
break
default:
console.log('* no data *')
break
}
})
}
const countries: Country[] = [
new Country('poland'),
new Country('japan'),
new Country('usa')
]
greetingList(countries)
// dzien dobry
// ohayo
// good morning
😅 How could be bad code ??
well, if you want to add "spain" now, you would modify code like this
const greetingList = (countries: Country[]) => {
countries.forEach(country => {
switch (country.name) {
case 'poland':
console.log('dzien dobry')
break
case 'japan':
console.log('ohayo')
break
case 'usa':
console.log('good morning')
break
// 👇 add this code "spain", this is key code!
case 'spain':
console.log('buenos dias')
break
default:
console.log('* no data *')
break
}
})
}
const countries: Country[] = [
new Country('poland'),
new Country('japan'),
new Country('usa')
// 👇 add this code "spain"
new Country('spain')
]
This is exactly anti open-closed principle because greetingList()
should be closed, we don't want it to be open.
In other words, we shouldn't modify greetingList()
when we add/extension
Someone even makes some mistake while modifying code.
👍 Good code
So how we write code ??
// create interface
interface ICountry{
greeting(): string
}
// create each country class
class Poland implements ICountry {
greeting = () => 'dzien dobry'
}
class Japan implements ICountry {
greeting = () => 'ohayo'
}
class Usa implements ICountry {
greeting = () => 'good morning'
}
const greetingList = (countries: ICountry[]) => {
for (let i = 0; i < countries.length; i++) {
console.log(countries[i].greeting())
}
}
const countries: ICountry[] = [
new Poland(),
new Japan(),
new Usa()
]
greetingList(countries)
Important part of good code is creating each country class which depends on ICountry interface.
Then when you add "spain", just like that ↓
// create interface
interface ICountry{
greeting(): string
}
// create each country class
class Poland implements ICountry {
greeting = () => 'dzien dobry'
}
class Japan implements ICountry {
greeting = () => 'ohayo'
}
class Usa implements ICountry {
greeting = () => 'good morning'
}
// 👇 add just "Spain class"
class Spain implements ICountry {
greeting = () => 'Buenos dias'
}
// ⭐ Don't need to modify this function!
// ⭐ It means greetingList is closed, but for extension, it is opened
const greetingList = (countries: ICountry[]) => {
for (let i = 0; i < countries.length; i++) {
console.log(countries[i].greeting())
}
}
const countries: ICountry[] = [
new Poland(),
new Japan(),
new Usa(),
new Spain()
]
greetingList(countries)
Now as you see, just add Spain class. You don't need to modify greetingList()
, so you might not make some mistake when you add country 👍
(Add) 💎 React.js
I even tweeted
He wrote it as clean code, but it also resolve opened principle problem 😎
Some people says open-closed principle is a bit exaggerated, because it makes code more complicate than bad code.
Actually I think so too, and it depends on situation.
But I'm sure it's important that you know this knowledge aside from whether you will use it or not.
And I highly recommend you to implement some code by yourself
sayonara👋
Posted on September 11, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.