Menu
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Đang tải...

Bài 34 — Technical Specification Document — Cấu trúc chuẩn

Technical BA Masterclass Bài 34/60

Mở đầu — vì sao bài này quan trọng

Hãy tưởng tượng bạn là Technical BA của một dự án thanh toán. Bạn đã ngồi họp với business cả tháng, hiểu rõ luồng nghiệp vụ, đã vẽ sequence diagram, đã định nghĩa NFR. Nhưng khi developer bắt tay code, họ hỏi: "Anh ơi, cái này gọi API nào? Field transaction_id dài bao nhiêu ký tự? Lỗi timeout thì retry mấy lần?" Bạn trả lời miệng, mỗi người nghe một kiểu. Ba tuần sau, QA test ra một đống bug, ai cũng cãi "tôi làm đúng spec rồi" — nhưng cái "spec" đó nằm trong đầu bạn, không nằm trên giấy.

Đó chính là lý do Technical Specification Document (TSD) tồn tại. Nó là tài liệu kỹ thuật chính thức, biến tất cả những hiểu biết rời rạc — yêu cầu nghiệp vụ, ràng buộc hệ thống, quyết định thiết kế — thành một nguồn sự thật duy nhất (single source of truth) mà developer, QA, DevOps, security và cả vendor đều có thể đọc và làm theo.

Với một Technical BA, biết viết một TSD chuẩn cấu trúc không phải là kỹ năng "nice-to-have" mà là năng lực cốt lõi. Một TSD tốt giúp đội phát triển ước lượng đúng effort, giảm câu hỏi qua lại, giảm hiểu lầm, và quan trọng nhất: khi có tranh chấp, nó là bằng chứng. Bài này sẽ dạy bạn cấu trúc chuẩn 12 phần của một TSD — không phải để bạn học thuộc lòng, mà để bạn hiểu mỗi phần trả lời câu hỏi gì, và biết cách viết sao cho người đọc thật sự dùng được.

Khái niệm cốt lõi

TSD là gì và không là gì

TSD là tài liệu mô tả CÁCH một hệ thống hoặc tính năng sẽ được xây dựng, ở mức đủ chi tiết để developer implement mà không phải đoán. Nó khác với BRD (Business Requirements Document — mô tả "cái gì" và "tại sao" ở góc độ nghiệp vụ) và khác với FSD (Functional Spec — mô tả hành vi chức năng).

Một ranh giới quan trọng cần nhớ: TSD không phải là nơi giải thích lại toàn bộ nghiệp vụ (đó là việc của BRD), cũng không phải là code documentation tự sinh (đó là việc của Swagger/Javadoc). TSD nằm ở giữa: nó nối business với implementation. Nó đủ kỹ thuật để developer dùng, nhưng vẫn đủ ngữ cảnh để người mới đọc hiểu được tại sao thiết kế lại như vậy.

Cấu trúc chuẩn 12 phần

Đây là khung sườn mà tôi khuyên bạn dùng cho hầu hết các TSD. Tùy quy mô dự án bạn có thể lược bớt, nhưng hãy hiểu vai trò từng phần:

1. Title & Metadata — Tên tài liệu, mã dự án, owner (người chịu trách nhiệm chính), reviewers (người duyệt), version, ngày cập nhật, và trạng thái (Draft / In Review / Approved). Đây là phần ai cũng lướt qua nhưng cực kỳ quan trọng cho việc truy vết. Khi có 5 phiên bản spec lẫn lộn trong Confluence, metadata là thứ cứu bạn.

2. Context & Background — Vì sao có spec này? Vấn đề kinh doanh nào đang giải quyết? Hệ thống hiện tại đang vận hành ra sao? Phần này cho người đọc — đặc biệt là người mới hoặc developer thầu ngoài — bối cảnh để hiểu các quyết định phía sau.

3. Scope (In-scope & Out-of-scope) — Liệt kê rõ cái gì nằm trong phạm vi và cái gì không. Phần "out-of-scope" thường bị bỏ qua nhưng lại là phần chống "scope creep" hiệu quả nhất. Ghi rõ "Phiên bản này không xử lý hoàn tiền (refund)" sẽ tránh được vô số tranh cãi sau này.

4. Assumptions & Dependencies — Những giả định bạn đang dựa vào (ví dụ: "giả định hệ thống KYC đã verify khách hàng trước khi gọi API này") và những phụ thuộc bên ngoài (ví dụ: "phụ thuộc vào service notification của team Platform, dự kiến ready vào sprint 12").

5. High-level Architecture / Solution Overview — Sơ đồ tổng thể: các component nào tham gia, dữ liệu chảy qua đâu. Đây là bức tranh toàn cảnh trước khi đi vào chi tiết.

6. Detailed Design — Trái tim của TSD. Bao gồm: data model / schema, API contracts (endpoint, request/response, status code), business logic / xử lý chính, các luồng xử lý (kèm sequence diagram khi cần), và edge cases.

7. Data Specification — Định nghĩa từng trường dữ liệu: tên field, kiểu dữ liệu, độ dài, bắt buộc hay không, giá trị mặc định, ràng buộc validation, ví dụ giá trị. Đây là phần developer và QA tra cứu nhiều nhất.

8. Non-Functional Requirements (tham chiếu) — Performance, security, availability... Ở TSD bạn thường tham chiếu đến tài liệu NFR riêng và chỉ ghi những con số trực tiếp liên quan đến tính năng này (ví dụ: API này phải response < 800ms ở p95).

9. Error Handling & Edge Cases — Hệ thống cư xử thế nào khi có lỗi? Mã lỗi, thông điệp, hành vi retry, fallback. Đừng chỉ mô tả "happy path".

10. Security & Compliance Considerations — Dữ liệu nhạy cảm nào được xử lý? Mã hóa thế nào? Phân quyền ra sao? Có ràng buộc tuân thủ (PCI-DSS, nghị định 13/2023 về bảo vệ dữ liệu cá nhân) không?

11. Open Questions & Risks — Những điểm chưa chốt, rủi ro kỹ thuật, và phương án xử lý. Sự trung thực ở phần này tạo niềm tin với reviewer hơn là che giấu.

12. Appendix & References — Glossary thuật ngữ, link tới BRD/Jira, biên bản họp, tài liệu liên quan.

Nguyên tắc xuyên suốt: viết cho người đọc, không phải cho mình

Mọi phần trên đều phục vụ một mục tiêu: người đọc đúng đối tượng có thể tự lấy được thông tin họ cần mà không phải hỏi bạn. Developer cần data spec và API contract. QA cần edge cases và error handling. DevOps cần dependencies và NFR. Security cần phần 10. Nếu bạn viết TSD mà ai đọc xong cũng phải nhắn tin hỏi thêm, nghĩa là cấu trúc của bạn chưa làm tròn vai.

Tình huống thực tế

Tình huống 1: Ví điện tử và cái bug "mất 200 triệu" vì thiếu data spec

Một ví điện tử tại Việt Nam (gọi là VPay) triển khai tính năng nạp tiền từ tài khoản ngân hàng. BA viết spec mô tả luồng rất chi tiết, có cả sequence diagram đẹp. Nhưng phần Data Specification thì viết qua loa: chỉ ghi "amount: số tiền nạp".

Developer ngân hàng phía đối tác hiểu amount là đơn vị đồng, còn developer phía VPay code theo đơn vị xu (cents) theo thói quen từ dự án quốc tế cũ. Trong môi trường test không ai để ý vì test toàn số tròn nhỏ. Lên production, một giao dịch nạp 2.000.000đ bị nhân/chia sai hệ số, và trong một đợt đối soát cuối ngày, tổng lệch lên tới hơn 200 triệu đồng phải truy ngược thủ công suốt hai ngày.

Diễn giải: Nếu data spec ghi rõ "amount: integer, đơn vị VND, không có phần thập phân, ví dụ 2000000 nghĩa là hai triệu đồng", thì hiểu lầm này không bao giờ xảy ra.

Bài học: Phần Data Specification không bao giờ được viết "qua loa". Đơn vị, kiểu dữ liệu, độ chính xác — đặc biệt với tiền tệ — phải tường minh đến mức không thể hiểu sai.

Tình huống 2: Dự án core banking và sức mạnh của phần "Out-of-scope"

Một ngân hàng cổ phần (giả định tên TPCorp Bank) thuê một công ty phần mềm làm module tính lãi tiết kiệm. BA của ngân hàng viết TSD và dành hẳn một mục Out-of-scope ghi rõ: "Phiên bản 1 chỉ tính lãi cho kỳ hạn cố định (term deposit). KHÔNG bao gồm: tiết kiệm không kỳ hạn, lãi suất bậc thang, tất toán trước hạn."

Đến tháng thứ hai, một giám đốc chi nhánh yêu cầu thêm tính năng tất toán trước hạn và khẳng định "cái này đương nhiên phải có". Vendor lập tức mở TSD đã được ký duyệt, chỉ vào mục Out-of-scope. Kết quả: yêu cầu mới được xử lý như một change request có báo giá và timeline riêng, thay vì bị nhồi vào scope cũ làm vỡ deadline.

Diễn giải: Một dòng "out-of-scope" được viết và ký duyệt từ đầu đã biến một cuộc tranh cãi cảm tính thành một quy trình change request rõ ràng.

Bài học: Phần Scope, đặc biệt là Out-of-scope, là tấm khiên hợp đồng. Với dự án có vendor hoặc nhiều bên, đây là phần tôi khuyên bạn đầu tư công sức nhiều nhất.

Tình huống 3: Tích hợp giao hàng và phần Error Handling bị bỏ quên

Một sàn TMĐT (giả định Shopee-style, gọi là MeShop) tích hợp với một đối tác giao hàng để tạo đơn vận chuyển. TSD mô tả rất kỹ happy path: gọi API tạo đơn, nhận về mã vận đơn, hiển thị cho khách. Nhưng phần Error Handling chỉ ghi vỏn vẹn "nếu lỗi thì báo lỗi".

Thực tế đối tác giao hàng thỉnh thoảng timeout. Vì spec không định nghĩa hành vi, developer tự quyết: cứ lỗi là retry ngay 3 lần liên tiếp. Hậu quả là một số đơn được tạo trùng ở phía đối tác (request đầu thực ra đã thành công, chỉ là response bị mất), khách nhận hai kiện hàng cho một đơn.

Diễn giải: Lỗi không nằm ở developer mà ở spec. TSD lẽ ra phải định nghĩa: timeout thì retry với chiến lược nào, mỗi lần tạo đơn cần một idempotency key để đối tác nhận ra request trùng và không tạo đơn mới.

Bài học: Error handling và edge case phải được đặc tả ngang hàng với happy path. "Nếu lỗi thì báo lỗi" không phải là một spec — đó là một lỗ hổng.

Hướng dẫn từng bước

Đây là quy trình tôi dùng để viết một TSD từ con số 0:

Bước 1 — Xác định người đọc và mục đích. Trước khi gõ chữ nào, hỏi: ai sẽ đọc tài liệu này? Developer nội bộ đã hiểu hệ thống, hay vendor hoàn toàn mới? Điều này quyết định bạn cần viết phần Context dày hay mỏng, cần giải thích thuật ngữ nhiều hay ít.

Bước 2 — Dựng khung 12 phần trước, điền nội dung sau. Tạo file với đủ 12 heading rỗng. Việc này giúp bạn thấy ngay phần nào còn trống, tránh viết lan man phần mình thích rồi quên phần quan trọng.

Bước 3 — Điền Metadata, Context, Scope trước tiên. Ba phần này là nền tảng. Chốt scope rõ ràng ngay từ đầu sẽ định hình toàn bộ phần còn lại. Đưa Scope cho stakeholder xác nhận trước khi viết Detailed Design — tránh việc viết xong 10 trang mới phát hiện hiểu sai phạm vi.

Bước 4 — Viết Detailed Design và Data Specification song song. Mỗi khi mô tả một luồng xử lý, lập tức định nghĩa các field dữ liệu liên quan. Dùng bảng cho data spec (Field | Type | Length | Required | Validation | Ví dụ) — bảng dễ tra cứu hơn văn xuôi rất nhiều.

Bước 5 — Bổ sung Error Handling và Edge Cases. Với mỗi happy path, tự hỏi: "Còn nếu... thì sao?" Nếu input rỗng? Nếu service phụ thuộc chết? Nếu user bấm hai lần? Mỗi câu trả lời là một dòng trong phần này.

Bước 6 — Tham chiếu NFR và Security. Đừng chép lại toàn bộ NFR vào đây, chỉ trích những con số gắn trực tiếp với tính năng, và link tới tài liệu gốc.

Bước 7 — Ghi Open Questions một cách trung thực. Cái gì chưa chốt thì ghi ra, kèm người chịu trách nhiệm và deadline trả lời. Đừng để khoảng trắng đánh lừa người đọc rằng mọi thứ đã rõ.

Bước 8 — Đưa review theo từng nhóm đối tượng. Cho tech lead review phần Design, QA review phần Edge case, security review phần 10. Mỗi nhóm soi đúng phần của họ sẽ hiệu quả hơn bắt tất cả đọc cả tài liệu.

Bước 9 — Version hóa và đánh dấu Approved. Khi đã duyệt, cập nhật version, đổi trạng thái sang Approved, và từ đó mọi thay đổi đều phải qua change log.

Lỗi thường gặp & mẹo

Lỗi 1 — Viết TSD như BRD thứ hai. Nhiều BA chép lại toàn bộ bối cảnh nghiệp vụ vào TSD, làm tài liệu phình to và developer phải lội qua mười trang mới tới phần cần. Mẹo: phần Context chỉ cần đủ để hiểu thiết kế, phần còn lại link tới BRD.

Lỗi 2 — Bỏ trống phần Out-of-scope. Như tình huống 2 đã thấy, đây là phần bảo vệ bạn. Luôn luôn viết, dù chỉ một dòng.

Lỗi 3 — Data spec mơ hồ về đơn vị, độ dài, định dạng. "Ngày" là dd/MM/yyyy hay ISO 8601? "Số điện thoại" có dấu +84 không? Mỗi field cần một ví dụ giá trị cụ thể. Tình huống 1 là cái giá phải trả khi bỏ qua điều này.

Lỗi 4 — Chỉ mô tả happy path. Tự đặt câu hỏi "what if" cho mọi luồng. Một TSD trưởng thành dành 30-40% dung lượng cho error và edge case.

Lỗi 5 — Không version hóa, không có owner. Khi có ba file spec_final, spec_final_v2, spec_final_real trong thư mục, dự án của bạn đang gặp nguy. Metadata và version là kỷ luật tối thiểu.

Mẹo vàng: Sau khi viết xong, đưa TSD cho một developer chưa từng nghe về tính năng và bảo họ đọc rồi mô tả lại cách họ sẽ build. Chỗ nào họ hỏi lại, chỗ đó spec của bạn còn thiếu. Đây là bài "test" rẻ nhất và hiệu quả nhất.

Mẹo về độ dài: Spec không phải càng dài càng tốt. Một TSD 8 trang đầy đủ và rõ ràng tốt hơn 30 trang lan man. Mục tiêu là "đủ để build, không thừa để đọc".

Bài tập thực hành

Bài 1 — Dựng khung. Chọn một tính năng nhỏ bạn quen thuộc (ví dụ: "đặt lại mật khẩu qua email"). Tạo một file TSD với đủ 12 heading. Chỉ cần khung và một dòng mô tả mục đích cho mỗi phần.

Bài 2 — Viết Data Specification. Cho tính năng "đăng ký tài khoản", lập bảng data spec cho 6 field: email, mật khẩu, số điện thoại, họ tên, ngày sinh, mã giới thiệu. Mỗi field ghi đủ: kiểu dữ liệu, độ dài, bắt buộc, ràng buộc validation, ví dụ giá trị. Chú ý định dạng số điện thoại và ngày sinh thật tường minh.

Bài 3 — Săn edge case. Với luồng "nạp tiền vào ví" ở Tình huống 1, viết ra ít nhất 8 edge case / lỗi cần đặc tả (gợi ý: số tiền âm, vượt hạn mức, ngân hàng timeout, request trùng, tài khoản bị khóa giữa chừng...). Với mỗi cái, ghi hành vi mong muốn của hệ thống.

Bài 4 — Viết Out-of-scope. Cho dự án "module tính lãi tiết kiệm" ở Tình huống 2, viết một mục Out-of-scope đầy đủ với ít nhất 5 mục bị loại trừ. Tự hỏi: stakeholder dễ hiểu nhầm cái gì là "đương nhiên có"?

Tóm tắt

Technical Specification Document là cầu nối biến hiểu biết của Technical BA thành một nguồn sự thật duy nhất mà cả đội phát triển dùng được. Cấu trúc chuẩn 12 phần — từ Title & Metadata, Context, Scope, Assumptions, Architecture, Detailed Design, Data Spec, NFR, Error Handling, Security, Open Questions đến Appendix — không phải là form cứng nhắc để học thuộc, mà là một danh sách câu hỏi mà mọi tính năng nghiêm túc đều phải trả lời.

Ba điều quan trọng nhất rút ra từ ba tình huống thực tế: (1) Data Specification phải tường minh đến mức không thể hiểu sai — đơn vị tiền tệ mơ hồ từng làm lệch 200 triệu; (2) Out-of-scope là tấm khiên hợp đồng chống scope creep và tranh cãi; (3) Error handling phải được đặc tả ngang hàng với happy path — "nếu lỗi thì báo lỗi" là một lỗ hổng, không phải một spec.

Cuối cùng, hãy nhớ: bạn viết TSD cho người đọc, không phải cho bản thân. Một tài liệu mà developer, QA, security đều tự lấy được thông tin họ cần mà không phải hỏi bạn — đó mới là một Technical Specification Document đạt chuẩn.