SOLID Principle (Part 1)
ဒီတခေါက် ကတော့ OO Design မှာအခြေခံအကျဆုံး principle လို.ဆိုရမဲ့ SOLID ပါ။ SOLID ကိုလူသိများလာအောင် လုပ်ခဲ့တဲ့သူတော့ Uncle Bob လို.လူသိများတဲ့ Robert C Martin ပါ။ သူရေးခဲ့တဲ့ စာအုပ်တွေထဲက ထင်ရှားတဲ့တအုပ်ကတော့ Clean Code ပါ။ SOLID က principle တခုတည်းမဟုတ်ပဲ ၄ ခုကိုစုပေါင်းထားတာပါ။ အဲ့ဒါတွေက
SRP (Single Responsibility)
OCP (Open Close Principle)
LSP(Liskov Substitution Principle)
ISP(Interface Segregation Principle)
DI(Dependency Inversion)
တို.ပဲဖြစ်ပါတယ်။
SRP (Single Responsiblity)
ပထမဆုံး principle က အရိုးရှင်းဆုံးနဲ. သုံးရတာ လက်အဝင်ဆုံး principle ပါ။ သူ.ရဲ. definition ကတော့ The Single Responsibility Principle (SRP) states that each software module should have one and only one reason to change. Class တစ်ခု သို.မဟုတ် module တခုဟာ အကြောင်းရင်းတခုကြောင့်ပဲ code ကို changes လုပ်ရမယ်။ ဒီနေရာမှာ class or module ရဲ. responsibility ဆိုတာ သူလုပ်ရမဲ့ behaviour(set of method) ကိုဆိုချင်တာပါ။ ဆိုချင်တာက class, module တွေဟာ တူညီတဲ့ behaviour တွေကို စုထားတာပဲဖြစ်ရမယ် လို.ဆိုချင်တာပါ။ တူညီတဲ့ responsibility တွေကိုပဲစုထားရမယ် ဒါမှမဟုတ် responsibility တခုတည်းကိုပဲ အာရုံစိုက်ရမယ် လုပ်ရမယ်လို.ဆိုချင်တာပါ။ Robert C Matrin ရဲ.ဥပမာ အတိုင်းပဲ ပြပါမယ်။ အောက်က class ကိုကြည့်ပါ။
public class Employee {
public Money calculatePay();
public void save();
public String reportHours();
}
ပြထားတဲ့ class မှာ responsiblitiy 3 ခုပါနေပါတယ်။ ဒီအတိုင်းကြည့်ရင် တခုတည်းထင်ရပေမဲ့ calculatePay ဆိုတာ accounting နဲ.ဆိုင်တာပါ။ save ကတော့ database operation နဲ.ဆိုင်တာပါ။ reportHours() ကတော့ HR နဲ.ဆိုင်တာပါ။ ပြင်ပ realworld က အဲ့ဒီ responsibility တွေနဲ. တိုက်ရိုက်သက်ဆိုင်တဲ့ entity (ဒီနေရာမှာ calculatePay သည် HR accounting, save သည် database, reportHours သည် HR, management) တွေသည် မတူပါဘူး။ ဒါကြောင့် Employee class သည် single responsiblity ကိုချိုးဖောက်နေပါတယ်။ မြင်သာအောင်ပြောရမယ်ဆိုရင်။ Database ကိုပြောင်းမယ်ဆိုလဲ (ဥပမာ Employee Table structure ပြောင်းသွားလို.ဆိုပါတော့ ) Employee class ကိုပြင်ရမယ်။ Payment တွေပြောင်းသွားတယ်ဆိုရင်လဲ Employee class ကိုပြင်ရမယ် ဒါဆိုရင် reason of change သည် တခုထက်ပိုနေပါပြီ ဒါဆိုရင် single responsibility နဲ.မကိုက်တော့ပါဘူး။ Single Responsiblity နဲ.မကိုက်တော့ ဘာဖြစ်လဲဆိုတော့ Cohesion နည်းပါတယ်။ Cohesion နည်းတော့ သူ.ကို resuse လုပ်ဖို.အဆင်မပြေပါဘူး။ ဥပမာ တခြား module တခုကနေ Employee data ကိုပဲသုံးချင်တယ် pay တွက်တာ မလိုချင်ဘူးဆိုရင် Employee ကို reuse လုပ်ဖို.အဆင်မပြေပါဘူး။ နောက်တခုက responsibility တွေရောနေတဲ့အတွက် maintenance လုပ်ရတာခက်ပါတယ်။ အဆင်မပြေပါဘူး။ ဒါကြောင့် နောက်ပိုင်း JavaEE Framework တွေဖြစ်တဲ့ spring framework လိုကောင်မျိုးတွေမှာ layer ခွဲပြီးတော့ domain model ကိုသက်သက် (ဒီနေရာမှာ Employee နဲ.ဆိုင်တဲ့ အချက်အလက်ကိုပဲသိမ်းမယ်)။ နောက် service layer (ဒီနေရာမှာ pay calculation နဲ. reportHour ကိုလုပ်မယ်) နောက် DAO layer(ဒီနေရာမှာ Employee object ကို database မှာ save တာကိုလုပ်မယ် )ဒါမျိုးတွေခွဲလုပ်ကြပါတယ်။ အဲ့လိုခွဲလုပ်တော့ တခုခုကို ပြင်ချင်ရင် နောက်တခုကိုသွားမထိပါဘူး။ ဥပမာ view layer ကိုပြင်တာနဲ. database layer ကိုသွားထိစရာမလိုပါဘူး။ အဲ့ဒါမျိုးကိုကျတော့ seperation of concern လို.သုံးပါတယ်။ Concern ဆိုတာကတော့ system တစ်ခုကို feature တွေ အပေါ်မူတည်ပြီး ခွဲတာပါ။ Feature ဆိုတာကတော့ (domain, service, controller, view,database) အဲ့လို feature တွေ ပေါ်မူတည်ပြီး ခွဲပစ်တာပါ။
နောက်မြင်နိုင်တဲ့ Example တခုကတော့ begineer PHP example တွေမှာတွေ.ရတဲ့ code တွေပါပဲ။ Business logic နဲ. view (html markup, CSS etc) စတာတွေကို ရောရေးတာပါပဲ။ နောက်ပိုင်း framework တွေမှာတော့ တခုချင်းကို MVC သုံးပြီး seperation of concern နဲ.ခွဲထုတ်လိုက်ပါတယ်။ အကျိုးဆက်ကတော့ better maintenance ဖြစ်ပါတယ်။
နောက် VB program တွေမှာရေးလေ့ရှိပါတယ်။ Button တခုရဲ. OnClick event မှာ တခါတည်း database ကိုတန်းချိတ်တာရော business logic ပေါင်းရေးတာမျိုးရောပါ။ အဲ့လိုဆိုရင် single responsibility ကိုချိုးဖောက်ရာကျပါတယ်။ ဒါဆို maintenance လုပ်ရတာအဆင်မပြေပါဘူး။
Single Responsiblity နဲ.ပြောင်းပြန် anti pattern ကတော့ God Object ပါ ။ God Object ဆိုတာ object, class တစ်ခုမှာ ရှိသမျှ responsiblity တွေ method တွေ function တွေစုရေးထားတာကိုပြောတာပါ။ ဒါမျိုးက maintenance လုပ်ရတာ အလွန်ခက်တဲ့အတွက် မသုံးသင့်ပါဘူး။ SRP ဟာ class module တွေမှာပဲအသုံးဝင်တာမဟုတ်ပါဘူး method level, code block level မှာသုံးလဲရပါတယ်။ ဥပမာ method တခုဟာ responsibility တခုထက်ပိုနေပြီဆိုရင် ထပ်ခွဲထုတ် (refactoring နည်းနဲ. method အသစ်ပြန်ထပ်ထဲ့တာမျိုး )လုပ်ရမှာပါ။
OCP (Open Close Principle)
OCP ကတော့ open of extension ,close for modification ကို ရည်ညွှန်းတာပါ။ Class, module code တွေဟာ လွယ်လွယ်ကူကူ functionality တွေထပ်ထဲ့နိုင်ရမယ် (open for extension) ဒါပေမဲ့ သူတို.ကို code modification လုပ်စရာမလိုပဲနဲ. (close for modification) ဖြစ်ရမယ်လို.ဆိုချင်တာပါ။ ဥပမာနဲ.ပြပါမယ်။ ကျွန်တော်တို.က Shape တွေရဲ. sum area ကိုတွက်ပါမယ်။ Shape ကလောလောဆယ်မှာ Circle,Rectangle ဆိုပါစို.ဒါဆို pseudo code အနေနဲ.ဆိုဒီလိုရပါမယ်။
public long sumArea(List<Shape> shapes)
{
long totalArea = 0;
for(Shape s : shapes)
{
if(s instanceof Circle)
{
Circle c = (Circle)s;
totalArea += c.area();
}
else if(s instanceof Rectangle)
{
Rectangle r = (Rectangle) s;
totalArea += r.area();
}
}
return totalArea;
}
အပေါ်ကပေးထားတဲ့ method မှာ shape တွေကို loop ပတ်ပြီး တခုချင်းစီကို စစ်ပါတယ် ။ Circle ဆို Circle, Rectangle ဆို Rectangle အနေနဲ. typecast လုပ်ပြီး area တွေကိုပေါင်းပါတယ်။ အဲ့မှာ ဘာပြဿ နာရှိလဲဆိုတော့ close for extension ဖြစ်နေတာပါ။ ဆိုချင်တာက ကျွန်တော်က နောက်ထပ် Shape အသစ် area ကိုတွက်ချင်တယ် Cube ဆိုပါတော့ဒါဆိုရင် ခုနက method sumArea ရဲ. for loop ထဲမှာ if တကြောင်းထဲ့ပြီး type cast လုပ် area ကိုခေါ် အဲ့လိုလုပ်ရမှာပါ။ ဘာလို.လဲဆိုတော့ OCP ကိုဖောက်ဖျက်လို.ပါ။ OCP အတိုင်း ရေးမယ်ဆိုရင် ဒီလိုရမှာပါ။
class Shape//base class
{
long area();
}
class Circle extends Shape
{
long area(){};
}
class Rectangle extends Shape
{
long area(){};
}
class Cube extends Shape
{
long area(){};
}
class AreaSummer
{
public long sum(List<Shape> allShape)
{
long totalArea = 0;
for(Shape s : allShape)
{
totalArea += s.area(); //Here is the point of OCP using, polymorphism
}
}
}
အပေါ်က AreaSummer class ဟာ OCP ကိုလိုက်နာပါတယ် သူ. loop ထဲမှာ polymorphism ကိုသုံးပြီး s.area ဆိုပြီးခေါ်ပါတယ်။ ဒါဆိုရင် ကျွန်တော်တို.က နောက်ထပ် shape တခုကိုထပ်ထဲ့မယ် သူ. area ကိုပေါင်းမယ်ဆို ရင် AreaSummer ရဲ. sum method ကိုပြင်စရာမလိုတော့ပါဘူး။ ဥပမာ Square class ကိုတွက်ချင်ရင် Sqaure class ကို base class Shape ကနေ extend လုပ်ပြီး area method ကို override လုပ်ပေးလိုက်ယုံပါပဲ။ ဒါဆိုရင် ရှိပြီးသားမူရင်း code ကိုလဲမထိပဲနဲ. ကိုလိုချင်တဲ့ functionality (extension ) ကိုလဲ ထပ်ထဲ့နိုင်တဲ့အတွက် OCP နဲ.ကိုက်ညီပါပြီ။ OCP နဲ.ကိုက်အောင်ရေးမထားဘူးဆိုရင် code တွေဟာ တခုခု ထပ်ထဲ့မယ်ဆိုရင် လိုက် change နေရပါလိမ့်မယ်။
Original link =>(https://m.facebook.com/story.php?story_fbid=pfbid0iMw8cp4MzbNrWs8xDhKxoWcUkEYXPeVfqQLsf723iyRHfK5bXW99eB8GigRU9wzil&id=1819241055&mibextid=Nif5oz)