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

Service per Team

คุณมีชุด service ที่ดี วาดเส้นตาม capability และ subdomain มาแล้ว และออกแบบให้รันแยกกันได้ เป้าหมายของงานทั้งหมดนั้นคือความเร็ว คือให้ทีมส่งงานขนานกันไปโดยไม่ต้องรอกัน แต่ความเป็นเจ้าของกลับถูกปล่อยให้คลุมเครือ หลายทีมเข้าไปแตะ Order service ทีม platform เป็นทีมเดียวที่มีสิทธิ์ deploy Billing และการแก้ Shipping ต้องขออนุมัติจากกลุ่มที่ไม่ได้ลงมือทำจริง สถาปัตยกรรมถูก decompose แล้วก็จริง แต่องค์กรรอบ ๆ ไม่ได้ถูก decompose ตาม ความเป็นอิสระที่สัญญาไว้จึงไม่เคยมาถึง

Conway’s law ชี้ว่าโครงสร้างของระบบมักสะท้อนโครงสร้างการสื่อสารขององค์กรที่สร้างระบบนั้น นี่ไม่ใช่คำคม แต่เป็นข้อจำกัดจริง ถ้าสามทีมช่วยกันสร้าง service ตัวเดียว service นั้นจะงอกรอยต่อขึ้นมาสามชุดตามจำนวนทีม และทุกการเปลี่ยนแปลงต้องเจรจากันสามฝ่าย ในทางกลับกัน ถ้าทีมเดียวต้องแตะสี่ service เพื่อส่ง feature หนึ่ง service ทั้งสี่ก็จะ couple เข้ากับตาราง release ของทีมนั้นแบบเงียบ ๆ ความเป็นเจ้าของร่วมเปลี่ยนทุกการ deploy ให้กลายเป็นปัญหาการประสานงาน ทั้งใครมีสิทธิ์ merge ใครต้อง review เทสของใครต้องผ่าน และใคร on call เวลาพัง สุดท้ายต้นทุนของการเปลี่ยนแปลงถูกกำหนดด้วยจำนวนคนที่ต้องเห็นพ้องกัน ไม่ใช่ด้วย code

ดังนั้นแรงต่าง ๆ คือ คุณต้องการให้แต่ละ service ถูกเปลี่ยนแปลงและ deploy ได้อย่างรวดเร็วและมั่นใจ แต่ความเป็นเจ้าของที่กระจายไปทั่วหลายทีม (หรือหลายทีมที่อัดแน่นอยู่บน service เดียว) นำการประสานงานข้ามทีมที่การ decompose ตั้งใจจะกำจัดกลับมาเสียพอดี

Service per Team ทำให้ความเป็นเจ้าของชัดเจนและผูกขาด คือ แต่ละ service ถูกเป็นเจ้าของโดยทีมเดียวเท่านั้น และทีมหนึ่งเป็นเจ้าของชุด service ที่เกี่ยวข้องกันขนาดเล็กแบบ end to end — ออกแบบ, เขียน code, ทดสอบ, deploy, และทำงาน ไม่มีทีมอื่น deploy service ของคุณ ไม่มี service ใดมีสองนาย ที่สำคัญคือ คุณไม่ปล่อยให้ผังองค์กรหลุดออกมาโดยบังเอิญ — คุณปฏิบัติต่อ Conway’s law เป็นเครื่องมือออกแบบ (inverse Conway manoeuvre) และปั้นทีมอย่างจงใจให้เข้ากับเส้นแบ่งของ service ที่คุณต้องการ

ขนาดของทีมต้องพอดีกับการดูแล service ที่ถืออยู่ คือเล็กพอจะคุยกันเองรู้เรื่อง แต่ใหญ่พอจะแบกทั้งภาระ on-call และการส่งมอบ ทีมทำงานร่วมกันแบบเดียวกับที่ service ทำ คือผ่าน API และ contract ที่นิ่งและเผยแพร่ไว้แล้ว ไม่ใช่ผ่าน code ร่วมหรือ deployment pipeline ร่วม เวลาทีม A ต้องการอะไรจาก service ของทีม B ก็ขอผ่าน interface ที่มีเวอร์ชันกำกับ ไม่ใช่เข้าไปแก้ code ของ B เอง

ผลลัพธ์คือองค์กรและสถาปัตยกรรมเสริมแรงซึ่งกันและกัน เส้นแบ่งที่สอดคล้องกันหมายความว่าการเปลี่ยนแปลงส่วนใหญ่อยู่ภายใน service ของทีมเดียว ดังนั้นทีมนั้นจึงสามารถตัดสินใจ, สร้าง, ทดสอบ, และ release ตามจังหวะของตัวเองได้ — ที่เป็นความเป็นอิสระที่ความพยายามทั้งหมดนี้มีไว้เพื่อสิ่งนั้น

flowchart TB
  subgraph TeamA[Team Checkout]
    direction TB
    SA1[Order Service]
    SA2[Cart Service]
  end
  subgraph TeamB[Team Billing]
    direction TB
    SB1[Billing Service]
    SB2[Invoice Service]
  end
  subgraph TeamC[Team Fulfilment]
    direction TB
    SC1[Shipping Service]
    SC2[Inventory Service]
  end
  TeamA -. published API .-> TeamB
  TeamA -. published API .-> TeamC
  TeamB -. published API .-> TeamC
  Note[One team owns each service end to end;<br/>teams collaborate only through stable contracts]
แต่ละทีมเป็นเจ้าของชุด service ขนาดเล็กแบบ end to end และทำงานร่วมกับทีมอื่นผ่าน published API เท่านั้น

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

  • ความเป็นอิสระและความเร็วที่แท้จริง ทีมที่เป็นเจ้าของ service ของตนแบบ end to end สามารถออกแบบ, สร้าง, ทดสอบ, และ deploy ได้โดยไม่ต้องรอใคร ดังนั้นการเปลี่ยนแปลงส่วนใหญ่จึงส่งมอบได้ตามจังหวะของทีมเอง
  • ความรับผิดชอบชัดเจน แต่ละ service มีทีมเดียวเป็นเจ้าของ คำถามว่า “ใครรับผิดชอบ” จึงหมดไป ทั้งเรื่อง review code เรื่อง deploy pipeline และเรื่องใครรับสายเวลาระบบพัง
  • สถาปัตยกรรมเข้ากับองค์กร พอปั้นทีมให้ตรงกับเส้นแบ่ง service ที่ต้องการ คุณก็เลิกฝืน Conway’s law แล้วหันมาใช้ประโยชน์จากกฎนี้แทน รอยต่อในระบบจะไปลงตรงกับรอยต่อระหว่างทีมพอดี

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

  • การประสานงานถูกผลักไปอยู่ที่เส้นแบ่ง ความเป็นอิสระภายในทีมแลกมาด้วยวินัยเรื่อง contract ระหว่างทีม การเปลี่ยนแปลงที่ข้ามเส้นแบ่ง service ก็ยังต้องตกลงกันข้ามทีมอยู่ดี ถ้าเส้นแบ่งวางไม่ดี ก็แค่ย้ายความเจ็บปวดไปอีกที่ ไม่ได้กำจัดออกไปจริง ๆ
  • การปรับองค์กรเป็นเรื่องยากและการเมือง การจัดทีมให้เข้ากับ service อาจหมายถึงการเปลี่ยนสายการรายงานและจำนวนคน — การเปลี่ยนแปลงเชิงองค์กรที่ช้ากว่าและละเอียดอ่อนกว่าการเปลี่ยน code ใด ๆ
  • ความเสี่ยงของ coupling และความซ้ำซ้อน หากไม่ระวัง ทีมก็จะ couple ผ่าน library และ database ร่วม (สร้าง distributed monolith ขึ้นมาใหม่) หรือทำงานซ้ำซ้อนเพราะไม่มีใครเป็นเจ้าของพื้นที่ส่วนกลาง ทั้งสองอย่างต้องการการกำกับดูแลอย่างจริงจังเพื่อหลีกเลี่ยง
  • Decompose by Business Capability — capability แมปลงทีมได้อย่างหมดจด ทำให้การกำหนดความเป็นเจ้าของง่าย
  • Decompose by Subdomain — bounded context ให้แต่ละทีมมีส่วนที่ self-contained ไว้เป็นเจ้าของ
  • Self-Contained Service — ความเป็นอิสระตอน runtime และความเป็นอิสระของทีมเสริมแรงซึ่งกันและกัน ทีมที่ไม่ขึ้นกับใครตอน deploy ก็ต้องการ service ที่ไม่ขึ้นกับใครตอน runtime เช่นกัน
ข้อดีข้อแลกเปลี่ยน
ทีมเป็นเจ้าของ service ชัดเจน — ไม่มีสองทีมแย่งแก้ service เดียวต้องออกแบบ team topology ก่อน service boundary
team autonomy สูง — deploy ได้โดยไม่ต้องรอทีมอื่นservice ใหญ่เกินถ้าทีมใหญ่เกิน
accountability ชัด — ถ้า service พัง รู้ว่าใครดูแลConway’s Law ทำงานสองทาง — org เปลี่ยนต้องปรับ service
ลด governance overheadทีมใหม่อาจได้รับ legacy service ที่ยาก

Service ที่ไม่มีเจ้าของ — service ที่ “เป็นของทุกคน” แปลว่าไม่มีใครรับผิดชอบ อาการ:

  • bug ใน service ไม่มีทีมไหนรับไป fix
  • ไม่มีทีมไหน on-call สำหรับ service นั้น
  • technical debt สะสมเพราะไม่มีใครรู้สึกเป็นเจ้าของ

Team Silos — ทีมแยกกันทำงานแต่ service ยังพึ่งพากันสูง อาการ:

  • deploy service A ต้องรอทีม B approve
  • interface ระหว่าง service ไม่มี contract — break บ่อย

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

Spotify:

  • “Squad” model — แต่ละ squad เป็นเจ้าของ service ของตัวเอง
  • squad มี full-stack capability — frontend, backend, data, ops
  • deploy อิสระ ไม่ต้องรอ squad อื่น

Amazon:

  • “You build it, you run it” — ทีมที่ build service คือทีมที่ on-call
  • ownership ชัดเจนทำให้ทีมใส่ใจ reliability มากขึ้น
Conway's law บอกอะไร
กฎหลักของ pattern Service per Team คืออะไร
ข้อใดคือข้อเสียจริงของการจัด service ให้ตรงกับทีม