Conway's Law & Team Topologies — Tổ chức team theo dòng chảy (BMS)

Phong

Mở đầu

Mười mấy chương trước, cuốn sách toàn nói chuyện kỹ thuật: communication, deployment, testing, scaling. Chương 15 bất ngờ chuyển hẳn sang chuyện con người và tổ chức — và đây mới là chương "đau" nhất. Vì microservices nghe là quyết định kiến trúc, nhưng người thực thi nó là các team, mà cấu trúc team thì quyết định luôn hình dạng hệ thống. Sam Newman dành trọn một chương cho organizational structures vì ông biết chắc một điều: bao nhiêu pattern kỹ thuật cũng vô nghĩa nếu team không được tổ chức đúng.

Bài về User Interfaces ở chương 14 đã chạm tới cùng một nỗi đau: tách service mà team vẫn phối hợp quanh một khối duy nhất thì chỗ nghẽn chỉ dời chỗ, không biến mất. Chương này đi sâu hơn — tổ chức team thế nào để kiến trúc tách rời được theo đúng ranh giới nghiệp vụ, thay vì theo đúng... sự tình cờ.

Ảnh: MART PRODUCTION — Pexels

Conway's Law — kiến trúc là tấm gương phản chiếu tổ chức

Năm 1968, Mel Conway viết một câu mà đến giờ vẫn ám ảnh ngành phần mềm: organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations. Nôm na: hệ thống bạn xây ra sẽ mô phỏng đúng cách tổ chức của bạn giao tiếp với nhau. Team chia theo chức năng — dev một nơi, QA một nơi, ops một nơi — thì hệ thống sẽ đầy những đường nối dài ngoằng giữa các module, bởi mỗi lần bàn giao qua team khác là một lần phối hợp, mà phối hợp nhiều thì sinh ra interface.

Điều này giải thích một hiện tượng ai làm backend lâu năm đều gặp: hai service "về lý thuyết" hoàn toàn độc lập nhưng cứ dính vào nhau, deploy phải đi cùng nhau, đổi schema phải hỏi nhau trước. Không phải ai đó cố tình thiết kế vậy — chính là vì hai team sở hữu chúng ngồi sát nhau, chat với nhau mỗi ngày, nên ranh giới kỹ thuật cứ mờ dần theo đúng mức độ giao tiếp của con người. Đó là Conway's Law vận hành âm thầm, không cần ai ra lệnh.

Inverse Conway Maneuver — đổi tổ chức trước, kiến trúc theo sau

Từ nhận xét của Conway, người ta đảo ngược nó thành một mẹo chủ động, được ThoughtWorks phổ biến với cái tên inverse Conway maneuver: nếu muốn kiến trúc mục tiêu, hãy sắp xếp lại tổ chức sao cho cấu trúc giao tiếp của nó khớp với kiến trúc đó. Muốn tách monolith thành các service theo bounded context? Đừng chỉ ngồi vẽ sơ đồ kiến trúc — hãy dựng team theo đúng bounded context đó trước, rồi để kiến trúc tự bám theo.

Nghe hơi duy tâm, nhưng đây là thứ tự đúng đắn. Nếu team vẫn chia theo chức năng mà code đã tách service, cuộc chơi "ai sửa service nào" sẽ lộn xộn — mỗi thay đổi xuyên service lại cần họp ba bốn team, ai cũng phải đồng ý thì mới merge nổi. Còn nếu team đã đứng theo dòng nghiệp vụ, việc tách service chỉ là formalize cái ranh giới con người đã có sẵn, tự nhiên hơn hẳn. Đổi team trước, kiến trúc đi theo sau — và ngược lại thì không bao giờ hiệu quả.

Ảnh: cottonbro studio — Pexels

Stream-aligned teams — team gắn với một dòng công việc

Nói về cách tổ chức cụ thể, mô hình team topologies của Matthew Skelton và Manuel Pais (cuốn Team Topologies) đưa ra bốn kiểu team, trong đó stream-aligned team là trung tâm. Một stream-aligned team gắn với một stream of work duy nhất — một sản phẩm, một dịch vụ, một nhóm người dùng — và tự chịu trách nhiệm từ đầu đến cuối: thiết kế, code, test, deploy, vận hành. Team đủ mọi kỹ năng cần thiết, không phải xin ai giúp giữa chừng, không phải chờ ai duyệt deploy.

Đây chính là thứ microservices cần: mỗi service thuộc về một team duy nhất, team đó muốn đổi gì thì đổi, muốn release lúc nào thì release. Ba kiểu team còn lại đóng vai trò hỗ trợ xung quanh. Platform team xây nền tảng dùng chung — CI/CD, observability, infrastructure-as-code — để stream-aligned team không phải tự dựng lại từ đầu mỗi lần. Enabling team chuyên đi "cầm tay chỉ việc", giúp team khác học kỹ năng mới rồi rút lui. Còn complicated-subsystem team sở hữu những mô-đun cần chuyên môn cực sâu, như engine encode video hay hệ thống recommendation, thứ mà team sản phẩm bình thường không đủ sức duy trì.

Cognitive load và quy mô team

Một giới hạn ít ai nghĩ tới nhưng lại quyết định ranh giới service: cognitive load của team. Ý tưởng đến từ Domain-Driven Design — mỗi team chỉ nên gánh một lượng hiểu biết vừa phải về hệ thống. Khi một team phải nắm quá nhiều domain, chất lượng quyết định bắt đầu trượt: sửa chỗ này lại vỡ chỗ kia, vì không ai giữ nổi toàn bộ bức tranh trong đầu. Lúc đó chỉ có hai lối thoát: tách service để giảm tải, hoặc đẩy phần hạ tầng lặp lại vào platform team để team tập trung vào nghiệp vụ.

Quy mô team cũng có ngưỡng. Khái niệm two-pizza team của Amazon — đội đủ nhỏ để hai cái pizza là đủ ăn — và con số của Dunbar đều chỉ về một hướng: team càng đông, chi phí phối hợp càng tăng theo cấp số nhân, ai cũng bận họp mà không ai code. Với microservices, team từ 4-8 người là vùng an toàn: đủ kỹ năng để tự vận hành, đủ nhỏ để giữ tốc độ. Sở hữu quá nhiều service cũng là một kiểu quá tải — team ôm năm bảy service khác nhau thì khác gì ôm một monolith, chỉ khác là nó rải rác.

Ảnh: Reza Tavakoli — Pexels

Sở hữu code và team API

Cuối cùng là chuyện quyền sở hữu. Mô hình phổ biến nhất là source code ownership: mỗi service do một team duy nhất sở hữu, mọi thay đổi phải đi qua team đó. Đổi lại, team cần đối xử với nhau như khách hàng — expose API rõ ràng, document tử tế, thay đổi breaking phải báo trước. Hãy hình dung mỗi team là một black box: người ngoài chỉ cần biết interface, không cần biết bên trong vận hành ra sao. Ruth Malan gọi đây là team API — ranh giới giữa các team cũng là một loại interface, và nó cần được thiết kế cẩn thận không kém interface của service.

Mô hình shared ownership — nhiều team cùng sửa một codebase, kiểu Linux kernel — nghe linh hoạt, nhưng với microservices thường sinh ra hỗn loạn: không rõ ai chịu trách nhiệm khi service sập lúc 2 giờ sáng. Muốn dung hoà, nhiều tổ chức chọn internal open source: ai cũng đọc được code, ai cũng đóng góp được qua pull request, nhưng team sở hữu vẫn giữ quyền quyết định cuối cùng. Vừa giữ được tốc độ, vừa tránh được cảnh mười team cùng đụng vào một file.

Key Takeaways

  • Conway's Law: cấu trúc giao tiếp của tổ chức định hình kiến trúc hệ thống — muốn kiến trúc khác đi, phải đổi tổ chức trước (inverse Conway maneuver).
  • Stream-aligned team là đơn vị trung tâm: một team gắn với một dòng công việc, tự lo từ thiết kế đến vận hành; platform, enabling và complicated-subsystem team hỗ trợ xung quanh.
  • Cognitive load là một ranh giới thiết kế hợp lệ: team quá tải thì tách service, hoặc đẩy hạ tầng chung vào platform team.
  • Team nhỏ (4-8 người) giữ chi phí phối hợp ở mức chấp nhận được; team quá đông làm chậm mọi thứ, kể cả khi ai cũng giỏi.
  • Mỗi service nên có một team sở hữu duy nhất; giao tiếp giữa các team là "team API" — thiết kế nó cẩn thận như thiết kế interface.

📋 Phụ lục thuật ngữ

Conway's LawHệ thống được thiết kế ra sẽ phản chiếu cấu trúc giao tiếp của tổ chức tạo ra nó.
Inverse Conway ManeuverChủ động sắp xếp lại tổ chức để cấu trúc giao tiếp khớp với kiến trúc mục tiêu.
Stream-aligned teamTeam gắn với một dòng công việc (sản phẩm/dịch vụ), tự chịu trách nhiệm từ đầu đến cuối.
Platform teamTeam xây nền tảng dùng chung (CI/CD, observability, infrastructure) cho các team khác.
Enabling teamTeam hỗ trợ giúp team khác học và áp dụng kỹ năng mới rồi rút lui.
Complicated-subsystem teamTeam sở hữu mô-đun cần chuyên môn sâu đặc biệt (ví dụ engine encode video).
Cognitive loadLượng nhận thức cần thiết để hiểu và duy trì một phần hệ thống.
Two-pizza teamQuy mô team đủ nhỏ để hai cái pizza đủ cho cả team ăn (Amazon).
Team APIRanh giới giao tiếp giữa các team, được thiết kế như một interface.
Internal open sourceCode nội bộ mở cho mọi người đóng góp qua PR, team sở hữu giữ quyền quyết định cuối cùng.

Kết

Microservices không chỉ là chuyện kỹ thuật — nó là chuyện tổ chức được ngụy trang thành chuyện kỹ thuật. Chương 15 nhắc lại một sự thật mà nhiều team đau đớn mới học được: cứ giữ nguyên cấu trúc team cũ rồi hì hục tách service, kiến trúc "đẹp trên giấy" sẽ nhanh chóng biến dạng theo đúng đường giao tiếp của con người. Đổi team trước, kiến trúc tự tìm đường theo sau. Chương cuối của cuốn sách — A Generalized Microservice Architecture — sẽ gom tất cả các chủ đề từ đầu sách lại thành một kiến trúc mẫu hoàn chỉnh, để xem mọi mảnh ghép khớp với nhau thế nào ở quy mô thực tế.