เรื่องของตัว O (Open-Closed) ในหลักการ SOLID สำหรับคนเขียน OOP

Screen Shot 2560-08-23 at 12.08.07 AM.png

หลังจากที่พูดถึง S (หรือ Single Responsibility) ไปแล้วหลักการต่อมาก็คือ O ซึ่งย่อมาจาก  Open-Closed Principle ซึ่งเป็นหลักการที่ 2 ของ SOLID ที่มีใจความสำคัญแบบ Abstractๆ ว่า

เราควรออกแบบระบบให้ง่ายต่อการเพิ่มเติมอะไรใหม่ๆ โดยที่ไม่ต้องแก้ไขระบบเก่า (ถ้าไม่จำเป็น)

Open-Closed Principle (OCP) จะกล่าวถึงการออกแบบ Class หรือทั้งระบบให้ยืดหยุ่นมากขึ้น โดยที่เราใช้ความสามารถของ OOP มาช่วย โดยยกตัวอย่างเช่น ถ้าเราต้องเพิ่ม Feature ใหม่ให้ Class เรา จุดที่ควรจะแก้ไข Code นั้นควรจะเป็นจุดที่เหมาะสมและไม่ควรกระทบกับสิ่งที่ไม่ควรจะแก้ไข

อธิบายเพิ่มก็ยัง งง อีก…งั้นเรามาดูตัวอย่างกันดีกว่าครับ

เช่นเดิม ผมมี Class SmartPhone ซึ่งมี Constructor ที่มีการ Set ค่าต่างๆให้กับ Object ที่กำลังถูกสร้างตามชื่อ Model เช่น S10 หรือ 8s

*Code ตัวอย่างเป็น TypeScript

    
class SmartPhone {
    private phoneModel : string;
    private phoneFullName : string;
    private screenWidth : number;
    private screenHeigth : number;
    constructor(model : string){
       if(model ==='S10'){
          this.phoneModel ='S10';
          this.screenWidth =5;
          this.screenHeigth =10;
          this.phoneFullName ='Samsung Galaxy S10';
        }
        else if(model ==='8s'){
          this.phoneModel ='8s';
          this.screenWidth =4;
          this.screenHeigth =3;
          this.phoneFullName ='Apple iPhone 8s';
        }
    }
}

จาก Code นี้ถ้าผมทำการเพิ่ม Model ใหม่สิ่งที่ผมต้องทำคือผมต้องผมแก้ Contructor ของ Class SmartPhone โดยการเพิ่ม else if  แล้วทำการเพิ่ม Code ของ Model Nexus 9 เข้าไป

constructor(model : string){
       if(model ==='S10'){
          this.phoneModel ='S10';
          this.screenWidth =5;
          this.screenHeigth =10;
          this.phoneFullName ='Samsung Galaxy S10';
        }
        else if(model ==='8s'){
          this.phoneModel ='8s';
          this.screenWidth =4;
          this.screenHeigth =3;
          this.phoneFullName ='Apple iPhone 8s';
        }
        else if(model ==='Nexus 9'){
          this.phoneModel ='Nx9';
          this.screenWidth =5;
          this.screenHeigth =5;
          this.phoneFullName ='Google Nexus 9';
        }
}
       
การทำแบบนี้ไม่ผิดครับ แต่เนื่องจากเราเขียนภาษา OO และต้องการทำให้ Design ของเราเป็นไปตามหลักการ OCP ดังนั้นเราต้องทำการ Refactor Code กันครับ
ลองคิดดูก่อนนะครับว่าจะ Refactor กันยังไงดี…
.
.
.
เอาล่ะมาเริ่มกัน
เทคนิคที่เราจะใช้ในการเพิ่ม Code Quality ครั้งนี้คือการใช้ Inherithance หรือการสืบทอดนั่นเอง ดังนั้นเรามาสร้างเป็น 3 Classes โดยที่ SmartPhone จะเป็น Base Class
   class SmartPhone { // Base Class
        protected phoneModel : string;
        protected phoneFullName : string;
        protected screenWidth : number;
        protected screenHeigth : number;
        constructor(){
            this.init();
        }
        protected init(){};
    }

    class S10Phone extends SmartPhone{// Inherited จาก Base Class
        protected init(){
            this.phoneModel = 'S10';
            this.screenWidth = 5;
            this.screenHeigth = 10;
            this.phoneFullName = 'Samsung Galasy S10';
        } 
    }

    class i8sPhone extends SmartPhone{// Inherited จาก Base Class
        protected init(){
            this.phoneModel = '8s';
            this.screenWidth = 4;
            this.screenHeigth = 3;
            this.phoneFullName = 'Apple iPhone 8s';
        } 
    }

    class Nx9Phone extends SmartPhone{ // Inherited จาก Base Class
        protected init(){
              this.phoneModel ='Nx9';
              this.screenWidth =5;
              this.screenHeigth =5;
              this.phoneFullName ='Google Nexus 9';
        }
    }

ซึ่งการทำแบบนี้จะเห็นว่าถ้าเราต้องการเพิ่ม model ใหม่ๆเข้าไปเราจะไม่ต้องมาแก้ไข้ base class เลยครับแค่ทำการ Inheritance กับสร้าง Class ใหม่แทน ซึ่งนี่ก็คือหลักการของ OCP ครับ 🙂

SOLID The Series:

3 thoughts on “เรื่องของตัว O (Open-Closed) ในหลักการ SOLID สำหรับคนเขียน OOP”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s