در مقاله قبلی اصول SOLID به زبان ساده - اصل اول را توضیح دادیم.حالا ببینیم اصل دوم چی هست.
اصل باز - بسته (Open/Closed Principle)
دومین اصل از اصول SOLID، اصل باز/بسته یا Open/Closed Principle هست که به اختصار OCP گفته میشه. تعریف رسمی این اصل به این صورت هست:
موجودیتهای یک نرمافزار (کلاسها، ماژولها، توابع و ...) باید برای توسعه داده شدن، باز و برای تغییر دادن، بسته باشن
توی این اصل از کلمههای باز و بسته استفاده شده. این کلمات با چیزی که توی ذهنمون داریم یکم متفاوت هست. اول بذارید معنی کلاس باز و بسته رو با هم بررسی کنیم و بعد به توضیح این اصل بپردازیم.
به کلاسی که بشه اون رو توسعه داد، بشه از اون extend کرد، متدها و پراپرتیهای جدید اضافه کرد و ویژگیها و رفتار اون رو تغییر داد، میگن باز.
کلاسی که کامل باشه. یعنی 100% تست شده باشه که بتونه توسط بقیه کلاسها استفاده بشه، پایدار باشه و در آینده تغییر نکنه. توی بعضی از زبانهای برنامهنویسی یکی از راههای بسته نگه داشتن یک کلاس، استفاده از کلمه کلیدی final
هست.
خب حالا بپردازیم به توضیح اصل OCP:
اصل OCP میگه که ما باید کد رو جوری بنویسیم که وقتی میخوایم اون رو توسعه بدیم و ویژگیهای جدید اضافه کنیم، مجبور نشیم اون رو تغییر بدیم و دستکاری کنیم. ویژگیهای جدید باید براحتی و بدون دستکاری کردن قسمتهای دیگه اضافه بشن.
طبق این اصل کلاس باید همزمان هم بسته باشه و هم باز! یعنی همزمان که توسعه داده میشه (باز بودن)، تغییر نکنه و دستکاری نشه (بسته بودن).
خب حالا وقتشه که با مثال درک بهتری از این اصل داشته باشم. کد زیر رو در نظر بگیرید:
class Hello { public say(lang) { if (lang == 'pr') { return 'درود'; } else if (lang == 'en') { return 'Hi'; } } } let obj = new Hello; console.log(obj.say('pr'));
این کلاس، با توجه به زبان ورودی، به ما سلام میکنه. همونطور که میبینیم درحال حاضر ۲ زبان توسط متد say
پشتیبانی میشه. اگه بخوایم زبانهای دیگه رو اضافه کنیم چطور؟ باید متد say
رو ویرایش کنیم:
class Hello { public say(lang) { if (lang == 'pr') { return 'درود'; } else if (lang == 'en') { return 'Hi'; } else if (lang == 'fr') { return 'Bonjour'; } else if (lang == 'de') { return 'Hallo'; } } } let obj = new Hello; console.log(obj.say('de'));
اگه بخوایم تا 150 زبان به این لیست اضافه کنیم چطور؟ ?
همونطور که میبینیم وقتی ویژگیهای جدید اضافه میشه، کلاس ما با توجه به نیازها دستکاری میشه. این اصلا خوب نیست. چون متد say
در برابر تغییرات بسته نیست و همیشه از سمت بیرون در معرض دستکاری هست.
خب یه راه حل بهتر اینه که ما متد say
رو کلی تر و عمومی تر بنویسیم. یعنی جوری که بدون توجه به تغییرات و نیازهای جدید، مستقل و دست نخورده باقی بمونه. به اصلاح Abstract کنیم. یعنی عمومیتر کردن.
خب برای اینکار، مثال رو به شکل زیر تغییر میدیم:
class Persian { public sayHello() { return 'درود'; } } class French { public sayHello() { return 'Bonjour'; } } class Hello { public say(lang) { return lang.sayHello(); } } myHello = new Hello(); myHello.say(new Persian());
همونطور که دیدیم، هر زبان رو به یک کلاس جدید منتقل کردیم. و به این صورت هر وقت که بخوایم زبان جدید اضافه کنیم، کافیه یک کلاس جدید درست کنیم. در نتیجه کلاس Hello
و متد say
دیگه دستکاری نیمشن.
بیشتر بخوانیم: