Open Closed Principle ( OCP )

AndriawanAndriawan
3 min read

Prinsip yang pertama kali dikenalkan oleh Bertrand Meyer pada buku Object Oriented Software Construction pada tahun 1988. Idea dasar dari Prinsip ini adalah Software Entity baik itu class, module, function terbuka untuk penambahan feature baru tanpa merubah code yang ada. Sebagai contoh adalah seperti berikut ini.

Tulisan ini adalah bagian dari SOLID Principles Series, sehingga untuk bisa membaca secara menyeluruh dan berkesinambungan, alangkah lebih baik bisa membaca secara urut dari link series berikut.

Asumsi kita sudah membuat class untuk Notification dengan nama file NotifyEvent.ts dengan content seperti berikut:

class NotifyEvent {

    private email: string
    private phone: string
    private id: string
    private content: string

    static new(data: Record<string, any>) : NotifyEvent {
        const instance = new NotifyEvent
        instance.setEntity(data)
        return instance
    }

    setEntity(data: Record<string,any>) {
        this.id = data.id
        this.email = data.email
        this.phone = data.phone
        this.content = data.content
    }

    sendEmail() {
        // code untuk mengirim email
    }

    sendSMS() {
        // code untuk mengirim sms
    }

}

Class tersebut hanya memiliki tugas yang yaitu Notification. Tapi class ini bermasalah atau orang biasanya menyebutnya tidak fleksible. Kenapa? karena, seandainya kita ingin menambah fitur notifikasi baru untuk mengirim infomasi ke Telegram Messanger misalnya, maka kita harus merubah class tersebut untuk menambah method baru semisal bernama sendTelegram . Jika kita mengimplementasikan Prinsip OpenClose, Code class di atas akan menjadi seperti ini:

Pertama kita perlu melakukan abstraction agar semua method yang required, diharuskan diimplementasi. Kita bisa menggunakan abtract class atau kita bisa menggunakan Interface. Tapi pada tulisan ini saya akan menggunakan Class Abstraction. Tapi apa bedanya? Saya akan buat tulisan khusus untuk membahas itu. Berikut contoh abstract cclass yang kita gunakan.

abstract class NotifyEvent {
    abstract setProp(data: Record<string,any>): void
    abstract log(): Promise<void>
    abstract send(): Promise<boolean>
}

Buat class event yang extends dari class NotifyEvent tersebut. Sebagai contoh di sini akan membuat event notifier untuk SMS.

class NotifySMSEvent extends NotifyEvent {
    private phone: string

    static new(data: Record<string,any>): NotifyEvent {
        const instance = new NotifySMSEvent
        instance.setProp(data)
        return instance
    }

    setProp(data: Record<string, any>) {
        // set property
    }

    async log() {
      // Log to database
    }

    async send() {
        // Send Code di sini
    }
}

Lalu kita buat dispatcher class atau executor untuk notifier SMS diatas.

class NotifyDispatcher {
    private events: NotifyEvent[] = []; 

    async execute() {
      const events: any[] = []
      for(let e of this.events) {
         events.push(e,send(), e.log())
      }
      return Promise.all(events)
    }    

    pushEvent(event: NotifyEvent) {
        this.events.push(event)
    }
}

Class dipatcher inilah yang seharusnya ada pada bagian core dengan tujuan agar tidak ada perubahan pada core atau module utama ketika business menginginkan penambahan feature untuk notification.

Selanjutnya pada function utama, kita perlu untuk meng-initialisasi class-class diatas. Seperti berikut.

function main() {
        const data = {} 
        const event: NotifyEvent = NotifySMSEvent.new(data)

        const dispatcher= new NotifyDispatcher
        dispatcher.pushEvent(event)

        await dispatcher.execute()
}

Kesimpulan

Dengan mengimplementasikan OCP, maka program akan lebih flexible dalam melakukan pergantian usecase module yang akan digunakan.

references:

0
Subscribe to my newsletter

Read articles from Andriawan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Andriawan
Andriawan