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)