ข้ามไปยังเนื้อหา

Decompose by Business Capability

คุณกำลังจะแกะระบบออกเป็น service และอยากได้หลักการสักข้อมาชี้นำการตัดแบ่ง คุณต้องการเส้นแบ่งที่ยังฟังขึ้นในอีกสามปีข้างหน้า และมีทีมเจ้าของที่ส่งงานได้โดยไม่ต้องเจรจาข้ามทีมตลอดเวลา วิศวกรหลายคนมีสัญชาตญาณจะหั่นตามเทคโนโลยี — service หนึ่งสำหรับ API หนึ่งสำหรับ workflow engine หนึ่งสำหรับ reporting job — เพราะภาพ codebase ในหัวเขาเรียงมาแบบนั้นอยู่แล้ว

เทคโนโลยีเปลี่ยนเร็วกว่าสิ่งที่ธุรกิจทำจริงมาก framework มาแล้วก็ไป data store โดนสับเปลี่ยน API ย้ายจาก REST ไป gRPC แต่ร้านค้าปลีกก็ยังรับ order เก็บเงินลูกค้า และจัดส่งสินค้าเหมือนเดิม ถ้าคุณวาดเส้นแบ่ง service ตามเทคโนโลยีของวันนี้ ทุกครั้งที่เทคโนโลยีเปลี่ยนคุณก็ต้อง decompose ใหม่ ที่แย่กว่านั้นคือการหั่นตามชั้นทำให้การเปลี่ยนแปลงทางธุรกิจที่ง่ายที่สุด อย่างการเพิ่มกฎส่วนลด ต้องไปแตะ web service, logic service และ data service พร้อมกัน เส้นที่คุณวาดไม่ตรงกับเส้นที่ระบบเปลี่ยนแปลงจริง

แรงที่ขัดกันจึงเป็นแบบนี้ คุณต้องการเส้นแบ่งที่ มั่นคง ให้ cohesion สูง คือทุกอย่างที่เปลี่ยนพร้อมกันอยู่ด้วยกัน และ coupling ต่ำ คือ service แทบไม่ต้องเปลี่ยนพร้อมกัน แถมต้อง map ลงโครงสร้างองค์กรได้พอดี

business capability คือสิ่งที่องค์กรทำเพื่อสร้างคุณค่า เป็นคำตอบของคำถามว่า “ธุรกิจนี้ ทำ อะไร” โดยจงใจไม่สนใจว่าตอนนี้ ทำอย่างไร capability มั่นคงเพราะนิยามด้วยวัตถุประสงค์ ไม่ใช่ implementation สำหรับบริษัท e-commerce capability อาจได้แก่ Order Management, Product Catalog, Inventory, Billing, Shipping และ Customer Accounts

pattern นี้คือ หนึ่ง service ต่อหนึ่ง business capability หรือต่อหนึ่งกลุ่ม capability ที่เกี่ยวข้องกันแน่น วิธีหา capability คือศึกษาองค์กร ทั้งวัตถุประสงค์ โครงสร้าง และ value stream ที่องค์กรทำงานอยู่ capability มักซ้อนกันเป็นลำดับชั้น เช่น Order Management อาจประกอบด้วย Order Capture, Order Fulfilment และ Returns ลำดับชั้นนี้แหละคือคันโยกตามธรรมชาติที่ให้คุณเลือกว่าจะทำ service หยาบหรือละเอียดแค่ไหน

เพราะ capability สะท้อนว่าธุรกิจ ทำอะไร ไม่ใช่ ทำอย่างไร เส้นแบ่งที่ได้จึงทนทาน คุณเขียนภายใน service ใหม่ สับ database หรือเปลี่ยน API ได้ แต่เส้นแบ่งยังอยู่ที่เดิม เพราะ capability ที่ service นั้นเป็นตัวแทนไม่ได้เปลี่ยนไปไหน

flowchart LR
  subgraph Org[Business capabilities]
    direction TB
    OM[Order Management]
    PC[Product Catalog]
    INV[Inventory]
    BIL[Billing]
    SHP[Shipping]
    ACC[Customer Accounts]
  end
  OM --> SOM[Order Service]
  PC --> SPC[Catalog Service]
  INV --> SINV[Inventory Service]
  BIL --> SBIL[Billing Service]
  SHP --> SSHP[Shipping Service]
  ACC --> SACC[Account Service]
แต่ละ business capability กลายเป็น service หนึ่งตัว เส้นแบ่งอิงตามสิ่งที่ธุรกิจทำ ไม่ใช่วิธีสร้างระบบ

capability เป็นเรื่องเชิงแนวคิด แต่ออกมาเป็นรูปธรรมในรูปของ module ที่คุณใช้จัดระเบียบ code และความเป็นเจ้าของ snippet ด้านล่างไม่ใช่ algorithm แต่เป็นการบันทึก capability map ไว้เป็น manifest เล็ก ๆ เป็นเอกสารแบบที่ทีมเก็บไว้เพื่อให้เส้นแบ่งชัดและตรวจทานกันได้

type Capability = {
name: string;
service: string;
// Sub-capabilities help decide how coarse the service should be.
subCapabilities: string[];
};
const capabilityMap: Capability[] = [
{ name: 'Order Management', service: 'order-service',
subCapabilities: ['Order Capture', 'Order Fulfilment', 'Returns'] },
{ name: 'Billing', service: 'billing-service',
subCapabilities: ['Invoicing', 'Payments', 'Refunds'] },
{ name: 'Shipping', service: 'shipping-service',
subCapabilities: ['Carrier Selection', 'Tracking'] },
];

สิ่งที่คุณได้:

  • เส้นแบ่งมั่นคง capability เปลี่ยนช้ากว่าเทคโนโลยีมาก service ที่วาดตาม capability จึงแทบไม่ต้องตัดใหม่ การเขียนใหม่จบอยู่ใน service เดียว
  • cohesion สูง coupling ต่ำ ทุกอย่างที่ต้องใช้ทำ capability หนึ่งอยู่ในที่เดียวกัน การเปลี่ยนแปลงทางธุรกิจส่วนใหญ่จึงลงที่ service เดียว ไม่กระเพื่อมข้ามหลายตัว
  • map ลงองค์กรได้พอดี capability มักเรียงตรงกับวิธีที่ธุรกิจมองตัวเองอยู่แล้ว การกำหนดความเป็นเจ้าของและความรับผิดชอบจึงง่าย

สิ่งที่คุณต้องจ่าย:

  • คุณต้องเข้าใจธุรกิจจริง ๆ นี่คือส่วนที่ยาก การระบุ capability ให้ดีต้องอาศัยความรู้ domain และต้องคุยกับคนนอกฝ่ายวิศวกรรม map ตื้น ๆ ก็ได้เส้นแบ่งตื้น ๆ
  • ความหยาบละเอียดต้องใช้วิจารณญาณ capability ซ้อนกันได้ การตัดสินว่า Order Capture กับ Returns ควรเป็นหนึ่งหรือสอง service ไม่มีสูตรตายตัว หยาบไปก็ได้ mini-monolith กลับมา ละเอียดไปก็จมอยู่กับการคุยข้าม service
  • ไม่ได้แก้เรื่องโมเดลร่วมให้ สอง service อาจใช้คำว่า “order” ในความหมายที่ต่างกันนิดหน่อย การแบ่งด้วย capability หยุดก่อนจะแก้เรื่องนี้ และนี่คือจุดที่การแบ่งด้วย subdomain เข้ามารับช่วงต่อพอดี
  • Decompose by Subdomain — วิธีเสริมที่ขับเคลื่อนด้วยโมเดล ใช้หาและเกลาเส้นแบ่งชุดเดียวกันให้คมขึ้น
  • Service per Team — เพราะ capability map ลงทีมได้ ความเป็นเจ้าของจึงลงตัวโดยธรรมชาติ
  • ภาพรวมการ decompose — กลยุทธ์นี้เข้ากับกลยุทธ์อื่นอย่างไร
ข้อดีข้อแลกเปลี่ยน
service boundary สอดคล้องกับ org structure — ลด cross-team coordinationต้องเข้าใจ business capability ก่อน — ถ้าผิดต้องแก้ทีหลัง
แต่ละ service เปลี่ยนได้ตาม business ไม่กระทบ service อื่นbusiness capability อาจ overlap — เส้นแบ่งไม่ชัดเสมอไป
Conway’s Law เป็นประโยชน์ — team = servicecapability coarse-grained เกินไป → service ใหญ่ไป, fine-grained เกินไป → service เล็กเกิน
ง่ายต่อการอธิบายให้ stakeholder เข้าใจต้องการ business analysis ก่อน — ไม่ใช่แค่ technical design

Copy-paste Org Chart — แปลง org chart ตรง ๆ เป็น service โดยไม่วิเคราะห์ capability อาการ:

  • service ตาม department แต่ business process ข้าม department ต้องเรียกหลาย service
  • reorganize ทีมต้องปรับ service architecture ด้วย

Capability เปลี่ยนบ่อย — ใช้ capability ที่ไม่ stable เป็น boundary อาการ:

  • service boundary เปลี่ยนทุก quarter ตาม business priority
  • refactor service บ่อยมากจนไม่มีเวลา build feature

💡 ตัวอย่างจากของจริง

Amazon:

  • แบ่ง service ตาม business capability: catalog, ordering, payment, fulfillment, recommendation
  • แต่ละ capability มีทีมเป็นเจ้าของ — “two-pizza team” rule
  • capability-based decomposition ช่วยให้ scale team และ service พร้อมกัน

Uber:

  • capability หลัก: rider matching, pricing, payment, driver management, notification
  • แต่ละ capability deploy และ scale อิสระ
business capability คืออะไร
ทำไมเส้นแบ่งที่วาดตาม business capability จึงถือว่ามั่นคง
ข้อใดคือข้อเสียจริงของการแบ่งด้วย business capability