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π
Top comments (0)