Microfrontend, microservice, monolith, monorepo, DDD တွေဆိုတာဘာတွေလဲ?
ကျနော့် အတွေ့အကြုံအရ သိထားတဲ့ Software Architecture တွေ၊ ခေတ်စားနေတဲ့ ချဉ်းကပ်ပုံ (Approach) တွေကို တတ်သလောက် မှတ်သလောက် Introduction သဘောမျိုး မျှဝေပေးပါရစေ။ (By Ronald)
1. Microfrontend
Microfrontend ဆိုတာ Component တွေ ခွဲရေးတဲ့ သဘောတရားကို Application Level အထိကြီးအောင်လုပ်လိုက်တာမျိုး ဖြစ်ပါတယ်။ ကျနော်တို့ React ဒါမှမဟုတ် Vue တို့မှာ အစိတ်အပိုင်းတစ်ခုစီကို Component တွေအဖြစ် ခွဲထုတ်ပစ်လိုက်သလိုမျိုးပါပဲ။ ဒါပေမဲ့ ကွာခြားချက်ကတော့ သာမန် Component ခွဲထုတ်တာက Repository (Repo) တစ်ခုတည်းမှာပဲ လုပ်ဆောင်တာ ဖြစ်ပါတယ်။
Microfrontend မှာတော့ လုပ်ဆောင်ချက် အစိတ်အပိုင်းတစ်ခုစီအတွက် Repo သီးသန့်စီ ခွဲထုတ်လိုက်တာမျိုး ဖြစ်နိုင်သလို၊ Service တစ်ခုစီအနေနဲ့ သီးခြား Domain သို့မဟုတ် Port တစ်ခုစီမှာ Run ထားတာမျိုးလည်း ဖြစ်နိုင်ပါတယ်။ အဓိက ရည်ရွယ်ချက်ကတော့ Code ချင်း Conflict မဖြစ်စေဘဲ Team အလိုက် သီးသန့်ခွဲပြီး စိတ်ကြိုက် ရေးသားနိုင်ဖို့ ဖြစ်ပါတယ်။
ဥပမာ
Facebook App ကို Microfrontend ပုံစံနဲ့ မြင်ကြည့်မယ်ဆိုရင် - "Like Feature" ကို Team A က ရေးပြီး၊ "Comment Feature" ကိုတော့ Team B က သီးသန့် ရေးသားတာမျိုး ဖြစ်ပါတယ်။ ပြီးမှ Facebook App တစ်ခုလုံး အဆင်ပြေပြေ Run နိုင်အောင် Host App တစ်ခုကနေ အဲဒီ Repo တွေ၊ Service တွေကို ရှေ့တန်း (Frontend) မှာ ပြန်လည် ပေါင်းစည်း (Orchestrate) ပေးထားတဲ့ သဘောဖြစ်ပါတယ်။
2. Microservice
Microservice ကလည်း Microfrontend ရဲ့ သဘောတရားနဲ့ ဆင်တူပေမဲ့ သူကတော့ Backend Layer နဲ့ Database Layer ကို အဓိက တာဝန်ယူတာ ဖြစ်ပါတယ်။
Backend Logic တစ်ခုလုံးကို စုပြုံပြီး တစ်နေရာတည်းမှာ Run ထားတာမျိုး မလုပ်တော့ဘဲ၊ သေးငယ်ပြီး သီးခြားလွတ်လပ်တဲ့ Service လေးတွေအဖြစ် ခွဲထုတ်ပစ်လိုက်တဲ့ သဘောတရား ဖြစ်ပါတယ်။
Microservice တွေကို သာမန် REST API သို့မဟုတ် gRPC တွေနဲ့ပဲ တိုက်ရိုက်ချိတ်ဆက်တာမျိုး ရှိသလို၊ စနစ်ကြီးလာရင် စွမ်းဆောင်ရည် ပိုကောင်းအောင် Messages နဲ့ Events (Event-Driven Architecture) တွေကို အသုံးပြုပြီး အလုပ်လုပ်လေ့ ရှိပါတယ်။
ဥပမာ
E-commerce App တစ်ခုမှာ Checkout, Orders နဲ့ Products ဆိုပြီး လုပ်ငန်းစဉ်တွေ ရှိတယ်ဆိုပါစို့။
- Monolithic Database မဟုတ်ခြင်း: အဲဒီ Checkout, Orders, Products တွေကို Database တစ်ခုတည်းမှာ စုပြုံထည့်ထားတာမျိုး မလုပ်တော့ဘဲ သီးသန့် Service တစ်ခုစီ၊ Database တစ်ခုစီ (Database-per-service pattern) ခွဲရေးလိုက်တာမျိုး ဖြစ်ပါတယ်။
- ဆက်သွယ်ပုံ: Service တစ်ခုနဲ့တစ်ခုကြားမှာတော့ Event Broker (ဥပမာ- RabbitMQ, Kafka) တွေကနေတစ်ဆင့် Events တွေ အပြန်အလှန် ပေးပို့ပြီး ဆက်သွယ်ဆောင်ရွက်ကြပါတယ်။
ဒီလိုမျိုး ခွဲထုတ်ထားတဲ့အတွက်ကြောင့် တကယ်လို့ လူသုံးများပြီး Checkout Service လေး ခေတ္တ Down သွားခဲ့ရင်တောင်မှ အခြား Orders နဲ့ Products Service တွေကို ထိခိုက်မှုမရှိစေဘဲ User က Product တွေကို ဆက်ကြည့်နေလို့ရတဲ့ အားသာချက် ရှိပါတယ်။
3. Monolith
Monolith ကတော့ Microservice နဲ့ လုံးဝ ဆန့်ကျင်ဘက် ချဉ်းကပ်ပုံ ဖြစ်ပါတယ်။
ဒါကို အရင်က သုံးခဲ့ကြတဲ့ Traditional Approach (နည်းလမ်းဟောင်း) လို့ ပြောရင်လည်း မမှားပါဘူး။ သို့သော် Project အစောပိုင်း (MVP Stage) မှာတော့ အမြန်ဆုံး ထွက်နိုင်ဖို့အတွက် အကောင်းဆုံး နည်းလမ်းတစ်ခု ဖြစ်နေဆဲပါ။ Application Logic တွေ၊ Database တွေ အားလုံးကို နေရာတစ်ခုတည်းမှာပဲ စုပြုံပြီး တည်ဆောက်ထားတဲ့ သဘောဖြစ်ပါတယ်။
-
အားသာချက်: Repo တွေ၊ Service တွေ အများကြီး ခွဲထုတ်နေစရာမလိုဘဲ တစ်နေရာတည်းမှာတင် အလွယ်တကူ Manage လုပ်နိုင်ပါတယ်။ Developer အားလုံး တစ်စုတစ်စည်းတည်း ပေါင်းရေးကြတဲ့အတွက် Deployment တစ်ခါလုပ်ရင် အကုန်ပါသွားပြီး Management ပိုင်းမှာ ပိုမို ရိုးရှင်းပါတယ်။
-
အားနည်းချက်: Horizontal Scaling (Server အလုံးရေ တိုးချဲ့ခြင်း) လုပ်ဖို့ ခက်ခဲပြီး Vertical Scaling (Server Resource မြှင့်တင်ခြင်း) မျိုးပဲ အားကိုးရပါတော့တယ်။ အဓိပ္ပာယ်ကတော့ Application ကြီးလာလေလေ Repo ကြီးက ပိုမို ဖောင်းပွလာလေလေ ဖြစ်ပြီး၊ Team Member တစ်ယောက်ယောက်က Code တစ်ခုခု ပြင်ဆင်မယ်ဆိုရင် သေသေချာချာ စိစစ်ရပါတယ်။ မဟုတ်ရင် Code တစ်ချက် အမှားကြောင့် Production တစ်ခုလုံး Down သွားတာမျိုး ဖြစ်နိုင်ပါတယ်။ ဒါ့အပြင် Local Setup လုပ်တဲ့အခါမှာ ဖြစ်ဖြစ်၊ Testing လုပ်တဲ့အခါမှာ ဖြစ်ဖြစ် Size အရမ်းကြီးမားလွန်းတဲ့အတွက် Developer စက်တွေမှာ Memory (RAM) အရမ်းစားတာမျိုး ကြုံတွေ့ရနိုင်ပါတယ်။
4. Monorepo
Monorepo ကတော့ အခုနောက်ပိုင်း ခေတ်စားလာတဲ့ ချဉ်းကပ်ပုံတစ်ခု ဖြစ်ပြီး၊ များသောအားဖြင့် Frontend Library တွေနဲ့ Framework တွေ (ဥပမာ- Turborepo, Nx သုံးပြီး Next.js/TypeScript stack တွေ) မှာ အရမ်းခေတ်စားပါတယ်။
သတိပြုရန်မှာ Monorepo ဆိုတာ Monolith မဟုတ်ပါဘူး။ သူက ကုဒ်တွေကို သိမ်းဆည်းတဲ့ Repository ပုံစံသာ ဖြစ်ပြီး၊ ၎င်းထဲမှာ Microservices တွေ သို့မဟုတ် Microfrontends တွေ အများကြီး ခွဲရေးထားလို့ ရပါတယ်။
သူက ဘယ်လို ပြဿနာမျိုးကို ဖြေရှင်းပေးတာလဲ?
Frontend App တွေမှာ Dependencies (Libraries) တွေ အရမ်းများလာတဲ့အခါ ထိန်းသိမ်းရတာ (Maintenance) တော်တော်လေး ခက်ခဲလာတတ်ပါတယ်။
- ရက်ပိုင်းလောက်ပဲ ရှိသေးတယ်၊ ကိုယ်ရေးထားတဲ့ Code က Deprecated ဖြစ်သွားတာမျိုး။
- Developer အသစ်တစ်ယောက် ဝင်လာပြီး နောက်ထပ် Library တစ်ခု ထပ်ထည့်လိုက်တဲ့အခါ Library ချင်း ထပ်နေတာမျိုး။
- Versioning အဆင်မပြေဘဲ ဟို Code နဲ့မကိုက်၊ ဒီ Code နဲ့မကိုက်ဘဲ Conflict တွေ ဖြစ်လာတာမျိုး။
ဘယ်လို ဖြေရှင်းပေးလဲဆိုရင် -
ပုံမှန်အားဖြင့် ကိုယ်တိုင် Custom ရေးထားတဲ့ Library သို့မဟုတ် UI Component တွေကို Project အသီးသန့်မှာ ထပ်ခါထပ်ခါ ပြန်သုံးချင်ရင် Node Package (npm) တစ်ခုအနေနဲ့ npm registry ပေါ်ကို Publish လုပ်ရလေ့ရှိပါတယ်။ Monorepo မှာတော့ Publish လုပ်စရာမလိုဘဲ packages/ ဆိုတဲ့ Folder တစ်ခုထဲမှာ စုထည့်ထားပြီး အခြား App တွေ (ဥပမာ- Landing Page ရော၊ Dashboard App ရော) ကနေ တိုက်ရိုက် Share ပြီး ဆွဲသုံးနိုင်အောင် လုပ်ဆောင်ပေးပါတယ်။
လက်ရှိ သုံးနေတဲ့ External Library တစ်ခုက Deprecated ဖြစ်သွားရင်တောင်မှ ကိုယ့် Project ရဲ့ Packages Folder ထဲမှာ အဲဒီ Library ရဲ့ Stable Version ကိုပဲ သီးသန့် ထိန်းသိမ်းထားလို့ ရပါတယ်။ ကုဒ်တစ်ခု ပြင်လိုက်ရင်လည်း ၎င်းနဲ့ ချိတ်ဆက်နေတဲ့ App တွေအားလုံးမှာ တစ်ပြိုင်နက် Update ဖြစ်သွားတာကြောင့် Version လိုက်ညှိရတဲ့ ဒုက္ခကနေ ကင်းဝေးစေပါတယ်။
5. Domain-Driven Design (DDD)
DDD ကတော့ Server တွေ ခွဲထုတ်တာထက် Code ရေးသားတဲ့အပိုင်းနဲ့ Project Folder Structure ဆောက်တဲ့ အပိုင်းတွေမှာ ပိုမို အသုံးများပါတယ်။ အဓိက ရည်ရွယ်ချက်ကတော့ စနစ်ကြီးလာရင်တောင် တခြားသူတွေ ဝင်ကြည့်ရင် နားလည်လွယ်စေဖို့နဲ့ စီးပွားရေးလုပ်ငန်းစဉ် (Business Logic) အတိုင်း ကုဒ်ကို ပုံဖော်ဖို့ ဖြစ်ပါတယ်။
ပုံမှန်အားဖြင့် Application တွေ သို့မဟုတ် Framework တွေဟာ သူတို့ သတ်မှတ်ထားတဲ့ စည်းမျဉ်းအတိုင်း Folder Structure (ဥပမာ- controllers/, models/, views/) တွေကို ချပေးထားလေ့ရှိပြီး ကျနော်တို့က အဲဒါကို လိုက်နာကြရပါတယ်။
ဒါဟာ တစ်ခါတလေ Technical အမြင် (Performance ပိုင်း၊ Speed ပိုင်း) အတွက် အဆင်ပြေစေနိုင်ပေမဲ့၊ တကယ့် လက်တွေ့ Business Logic (လုပ်ငန်းစဉ် သဘောတရား) တွေနဲ့ ကိုက်ညီမှုမရှိဘဲ ရှုပ်ထွေးသွားတတ်ပါတယ်။ အဲဒီအခါမှာ ရေရှည် Maintain လုပ်ရတဲ့အပိုင်းမှာ ခေါင်းခဲရပါတော့တယ်။
ဥပမာ
Products, Orders, Payments ဆိုင်ရာ Code တွေကို Framework standard အတိုင်း ရေးထားတယ်ဆိုပါစို့။ Technical အရ Code တွေက သန့်ရှင်းနေပေမဲ့ Business Logic တွေ တစ်ခုနဲ့တစ်ခု ရောထွေးငြိစွန်းနေတာမျိုး ကြုံဖူးကြမှာပါ။ Product Folder ထဲမှာ Payment အပိုင်းတွေ ရောက်နေတာမျိုး၊ သို့မဟုတ် Order ထဲမှာ Payment Logic တွေ ဝင်ရှုပ်နေတာမျိုး ဖြစ်တတ်ပါတယ်။
DDD က ဘာလုပ်ပေးလဲဆိုတော့: Framework ရဲ့ စည်းမျဉ်းထက် လုပ်ငန်းစဉ် (Domain) ကို အဓိက ဦးစားပေးပါတယ်။ Product Domain, Order Domain, Payment Domain ဆိုပြီး သီးသန့် ခွဲထုတ်ပစ်လိုက်ပြီး အဲဒီ Domain Folder တစ်ခုစီအောက်မှာတင် သူ့ဆိုင်ရာ Logic, Controller, Model အကုန်လုံးကို စုစည်းထားလိုက်တာ ဖြစ်ပါတယ်။ ဒါဟာ တခြား Repo တွေ၊ Service တွေနဲ့ ချိတ်ဆက်တာထက် လက်ရှိ Project တစ်ခုတည်းမှာပဲ Business Logic အပေါ် အခြေခံပြီး စနစ်တကျ Architecture ပုံဖော်တာမျိုး ဖြစ်ပါတယ်။
နိဂုံးချုပ်အမြင်
အကျဉ်းချုပ်ရရင် Architecture တစ်ခုစီမှာ သူ့အားသာချက်၊ အားနည်းချက်နဲ့ သုံးရမယ့် နေရာ (Use Case) သီးသန့်စီ ရှိကြပါတယ်။
- Monolith က အစပြုဖို့ အကောင်းဆုံးဖြစ်ပြီး၊
- စနစ်ကြီးလာရင် Backend အတွက် Microservices နဲ့ Frontend အတွက် Microfrontends ကို စဉ်းစားနိုင်ပါတယ်။
- ကုဒ်တွေကို စနစ်တကျနဲ့ Dependencies တွေ မျှဝေသုံးချင်ရင် Monorepo က အသုံးတည့်ပြီး၊
- လုပ်ငန်းစဉ်ကြီးမားပြီး ရှုပ်ထွေးတဲ့ Business Logic တွေကို ကိုင်တွယ်တဲ့အခါ DDD က အကောင်းဆုံး လမ်းပြပေးနိုင်မှာ ဖြစ်ပါတယ်။
ဒီမျှဝေပေးခဲ့တဲ့ Architectures အချက်အလက်လေးတွေက သူငယ်ချင်းတို့အတွက် တစ်ထောင့်တစ်နေရာမှာ အကျိုးရှိမယ်လို့ မျှော်လင့်ပါတယ်။ ✌🏻Ronald