Menu
ESC

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

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

Đang tải...

Bài 14 — Tư duy bút toán kép → state machine

Từ Finance/Kế Toán sang BA: Lộ Trình Chuyển Đổi Bài 14/60

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

Nếu bạn đã từng làm kế toán hoặc tài chính, có một thứ đã ăn sâu vào tư duy của bạn đến mức gần như bản năng: mỗi giao dịch đều có hai vế, và mọi thứ phải cân. Bạn không cần ai nhắc cũng tự động kiểm tra "tổng Nợ có bằng tổng Có không?". Khi một con số lệch, bạn cảm thấy khó chịu trong người cho đến khi tìm ra nguyên nhân.

Cái cảm giác "khó chịu khi không cân" đó chính là một trong những tài sản quý giá nhất bạn mang theo khi chuyển sang nghề Business Analyst (BA). Bởi vì ở phần lõi nhất của công việc BA — đặc biệt khi bạn làm việc với hệ thống phần mềm xử lý nghiệp vụ — có một khái niệm gần như song sinh với bút toán kép: state machine (máy trạng thái).

Trong những bài trước của module này, chúng ta đã nói về việc tận dụng Excel sang SQL, mapping skill Finance sang competencies BA. Bài 14 này đi sâu vào MỘT cây cầu tư duy cụ thể và rất đẹp: từ bút toán kép (double-entry bookkeeping) sang state machine. Đây không phải là phép so sánh cho vui. Khi bạn hiểu rằng bộ não kế toán của bạn đã được "lập trình" sẵn để suy nghĩ theo kiểu state machine, bạn sẽ học cách mô tả vòng đời của một đối tượng nghiệp vụ (đơn hàng, hồ sơ vay, yêu cầu hoàn tiền...) nhanh hơn người học BA thông thường rất nhiều.

Mục tiêu của bài: giúp bạn nhìn ra cấu trúc chung giữa "ghi sổ kép" và "chuyển trạng thái", để bạn tự tin viết được mô tả trạng thái — một sản phẩm đầu ra mà dev cực kỳ cần và đánh giá cao.

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

Bút toán kép — nhắc lại để làm bệ phóng

Bút toán kép là nguyên tắc nền tảng của kế toán hiện đại: mỗi giao dịch kinh tế tác động lên ít nhất hai tài khoản, một bên ghi Nợ (Debit), một bên ghi Có (Credit), và tổng Nợ luôn bằng tổng Có. Nhờ đó phương trình kế toán Tài sản = Nợ phải trả + Vốn chủ sở hữu luôn được giữ cân bằng sau mỗi nghiệp vụ.

Ví dụ kinh điển: công ty bán hàng thu tiền mặt 10 triệu. Bạn ghi Nợ "Tiền mặt" 10 triệu (tài sản tăng), ghi Có "Doanh thu" 10 triệu. Không có giao dịch nào "lơ lửng" chỉ ảnh hưởng một vế. Mọi thay đổi đều có nguồn gốc và đích đến rõ ràng, và đều để lại dấu vết.

Ba đặc tính của bút toán kép mà ta sẽ dùng làm cầu nối:

  • Tính nguyên tử (atomic): một bút toán hoặc được ghi trọn vẹn cả hai vế, hoặc không ghi gì cả. Không có chuyện ghi nửa vời.
  • Tính chuyển dịch có quy tắc: không phải tài khoản nào cũng được phép kết hợp tùy tiện; có những bút toán hợp lệ và bút toán vô lý.
  • Tính kiểm toán (auditable): mỗi thay đổi để lại một bản ghi, có thể truy ngược lại được ai làm, khi nào, vì sao.

State machine — ngôn ngữ mô tả vòng đời

State machine (máy trạng thái) là một cách mô tả: một đối tượng tại mỗi thời điểm chỉ ở MỘT trạng thái (state), và nó chuyển từ trạng thái này sang trạng thái khác thông qua các chuyển tiếp (transition) được kích hoạt bởi sự kiện (event).

Lấy ví dụ một đơn hàng trên Tiki: nó có thể ở các trạng thái như Chờ xác nhận → Đã xác nhận → Đang đóng gói → Đang giao → Đã giao → Hoàn tất. Hoặc rẽ nhánh sang Đã hủy, Đang hoàn trả. Mỗi mũi tên giữa hai trạng thái là một transition, và nó chỉ xảy ra khi có một sự kiện cụ thể (khách bấm "Hủy đơn", nhân viên kho bấm "Xác nhận giao thành công"...).

Bốn thành phần của một state machine:

  • States: tập hợp các trạng thái hợp lệ (đối tượng luôn ở trong một và chỉ một).
  • Transitions: các đường chuyển hợp lệ giữa các trạng thái.
  • Events/Triggers: cái gì kích hoạt một transition.
  • Guards/Conditions: điều kiện phải thỏa thì transition mới được phép xảy ra.

Cây cầu: vì sao kế toán đã "nghĩ" theo kiểu state machine

Đây là phần đắt giá. Hãy đặt hai khái niệm cạnh nhau:

Bút toán képState machine
Mỗi giao dịch làm tài khoản đổi số dưMỗi sự kiện làm đối tượng đổi trạng thái
Nợ và Có phải cân — không vế nào lơ lửngFrom-state và To-state phải khớp — không transition nào "treo"
Chỉ một số bút toán là hợp lệChỉ một số transition là hợp lệ
Bút toán là atomic (ghi cả hai vế hoặc không)Transition là atomic (chuyển hẳn sang state mới hoặc giữ nguyên)
Sổ cái lưu vết mọi thay đổiAudit log/history lưu vết mọi transition
Số dư hiện tại = kết quả của mọi bút toán trước đóTrạng thái hiện tại = kết quả của mọi transition trước đó
Bạn thấy không? Khi bạn ghi sổ, bạn vốn đã làm một việc giống hệt việc mô tả transition: "Từ tình huống A, khi sự kiện X xảy ra, hệ thống chuyển sang tình huống B, và phải ghi nhận điều đó một cách cân bằng, có vết." Sự khác biệt duy nhất là kế toán đo bằng tiền và tài khoản, còn BA đo bằng trạng thái và đối tượng nghiệp vụ.

Đặc biệt, cái "tổng Nợ = tổng Có" của bạn chính là phiên bản tài chính của nguyên tắc không có transition bất hợp lệ và không có state mồ côi (orphan state) trong state machine. Bản năng kiểm tra cân bằng của bạn sẽ tự động giúp bạn phát hiện những lỗ hổng mà dev hay bỏ sót: "Nếu đơn hàng đang ở trạng thái Đã giao, có sự kiện nào đưa nó về Chờ xác nhận không? Nếu không, ai sẽ chặn?".

Tình huống thực tế

Tình huống 1 — Hồ sơ vay tiêu dùng tại một công ty tài chính (FE Credit / Home Credit kiểu)

Lan từng là kế toán công nợ 4 năm tại một doanh nghiệp bán lẻ, mới chuyển sang làm BA tại một công ty tài chính tiêu dùng ở TP.HCM. Dự án đầu tiên của cô là số hóa quy trình duyệt hồ sơ vay trả góp.

Ban đầu, team dev mô tả vòng đời hồ sơ rất sơ sài: "nộp hồ sơ → duyệt → giải ngân". Lan nhìn vào và thấy ngay sự "không cân". Cô đặt câu hỏi đúng kiểu một kế toán soi sổ: *"Nếu hồ sơ bị từ chối thì nó đi đâu? Nếu khách bổ sung giấy tờ thì nó quay lại trạng thái nào? Một hồ sơ đã giải ngân rồi có thể bị hủy không, và nếu hủy thì bút toán... à nhầm, transition đó dẫn về đâu?"

Cô vẽ lại state machine đầy đủ:

  • Nháp → Đã nộp → Đang thẩm định → (Yêu cầu bổ sung → Đang thẩm định) — vòng lặp
  • Đang thẩm định → Từ chối (state cuối)
  • Đang thẩm định → Đã duyệt → Đã giải ngân → Đang trả góp → Tất toán (state cuối)
  • Đã giải ngân → Hủy giải ngân → Đóng hồ sơ (nhánh ngoại lệ)
Diễn giải: Lan dùng đúng tư duy "không vế nào lơ lửng". Cô liệt kê mọi state, rồi với từng state hỏi "có đường vào nào, có đường ra nào?". Trạng thái nào không có đường ra hợp lý chính là một "bút toán lệch" — một lỗ hổng nghiệp vụ. Nhờ vậy cô phát hiện ra dev đã quên hoàn toàn nhánh "Yêu cầu bổ sung", một tình huống xảy ra với hơn 30% hồ sơ thực tế.

Bài học: bản năng "soi cho cân" của kế toán giúp bạn tìm ra các transition thiếu mà người khác bỏ qua. Một state machine "cân" là một state machine không có state mồ côi (không có đường vào) và không có dead-end ngoài ý muốn (không có đường ra).

Tình huống 2 — Quy trình hoàn tiền của một ví điện tử

Một ví điện tử (kiểu MoMo/ZaloPay) cần xây tính năng hoàn tiền (refund) cho giao dịch lỗi. Hùng — cựu chuyên viên phân tích tài chính — được giao viết requirement cho luồng này.

Hùng nhận ra ngay điểm tương đồng với bút toán: một giao dịch hoàn tiền không bao giờ chỉ đơn thuần là "đổi trạng thái". Nó luôn đi kèm một tác động tiền tệ (giống vế Có/Nợ). Vì vậy anh mô tả state machine của một "Yêu cầu hoàn tiền" gắn chặt với điều kiện guard:

  • Khởi tạo → Đang xác minh giao dịch gốc
  • Đang xác minh → Đã duyệt hoàn (guard: giao dịch gốc đã thành công VÀ chưa hoàn lần nào VÀ trong thời hạn 7 ngày)
  • Đã duyệt hoàn → Đang xử lý hoàn → Hoàn thành công (đồng thời tạo bút toán đối ứng ghi Có ví khách / ghi Nợ tài khoản nhà cung cấp)
  • Đang xử lý hoàn → Hoàn thất bại → Chờ xử lý thủ công
Diễn giải: Điểm tinh tế Hùng đưa vào là các guard condition — tương đương với "các bút toán hợp lệ". Trong kế toán, bạn không thể ghi Có một tài khoản không có số dư hợp lệ; trong state machine, bạn không thể chuyển sang "Đã duyệt hoàn" nếu giao dịch gốc chưa thành công. Anh cũng nhấn mạnh tính idempotent (không hoàn hai lần) — chính là phiên bản số hóa của nguyên tắc "không ghi trùng bút toán".

Bài học: với người Finance, hãy luôn hỏi "transition này có cần điều kiện gì để hợp lệ không?" và "transition này có sinh ra tác động tiền/dữ liệu cần ghi đối ứng ở đâu khác không?". Đây là thế mạnh tự nhiên của bạn mà BA thuần công nghệ thường yếu.

Tình huống 3 — Đối soát trạng thái với nhà cung cấp (reconciliation)

Tại một startup logistics ở Hà Nội, BA cần mô tả trạng thái kiện hàng đồng bộ giữa hệ thống nội bộ và API của đối tác vận chuyển (GHN, GHTK). Vấn đề: hai hệ thống đôi khi "lệch trạng thái" — bên mình ghi "Đang giao", bên đối tác đã "Giao thành công".

Minh, cựu kế toán, lập tức gọi đây là bài toán đối soát (reconciliation) — thứ anh làm hàng tháng với sao kê ngân hàng. Anh thiết kế một state machine có thêm trạng thái trung gian "Chờ đối soát" và quy tắc: khi trạng thái nội bộ và trạng thái đối tác lệch nhau, kiện hàng tự động vào Chờ đối soát, sinh cảnh báo, và chỉ chuyển tiếp khi có nguồn-sự-thật (source of truth) được xác lập.

Diễn giải: tư duy đối soát của kế toán — "hai sổ phải khớp, lệch thì phải tìm ra và xử lý" — chính là một dạng đồng bộ state machine giữa các hệ thống. Anh áp nguyên tắc "nguồn sự thật duy nhất" để tránh tình trạng hai bên cứ ghi đè lẫn nhau.

Bài học: nhiều bài toán hệ thống thực chất là bài toán giữ cho nhiều state machine "cân" với nhau — và đó đúng là nghề cũ của bạn.

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

Đây là quy trình để bạn dựng một state machine cho bất kỳ đối tượng nghiệp vụ nào, dùng chính tư duy kế toán:

Bước 1 — Xác định đối tượng và "sổ" của nó. Hỏi: đối tượng nào có vòng đời? (đơn hàng, hồ sơ, vé hỗ trợ, yêu cầu hoàn tiền...). Cũng như mỗi tài khoản có một sổ, mỗi đối tượng sẽ có một "lịch sử trạng thái".

Bước 2 — Liệt kê toàn bộ states hợp lệ. Viết ra mọi trạng thái mà đối tượng có thể ở. Đánh dấu rõ state đầu (initial) và các state cuối (final/terminal). Giống như xác định số dư đầu kỳ và số dư cuối kỳ.

Bước 3 — Vẽ các transition và gắn sự kiện. Với mỗi cặp state, hỏi "có chuyển được từ A sang B không, và sự kiện gì kích hoạt?". Đây là lúc bạn áp bản năng "không vế nào lơ lửng": mỗi state (trừ state cuối) phải có ít nhất một đường ra; mỗi state (trừ state đầu) phải có ít nhất một đường vào.

Bước 4 — Thêm guard condition. Với mỗi transition, hỏi "điều kiện gì phải đúng thì mới được phép chuyển?". Đây là phiên bản "bút toán hợp lệ" của bạn.

Bước 5 — Định nghĩa tác động đối ứng (side effect). Mỗi transition có thể sinh ra hành động khác: gửi email, tạo bút toán, gọi API, cập nhật tồn kho. Hãy ghi rõ — đây là "vế Có" tương ứng với "vế Nợ" của transition.

Bước 6 — Kiểm tra tính cân. Rà lại: có state mồ côi không? Có dead-end ngoài ý muốn không? Có transition nào cho phép quay về quá khứ một cách vô lý không (ví dụ từ "Đã giao" về "Chờ xác nhận")? Đây chính là bước "cân sổ".

Bước 7 — Trình bày cho dev. Dùng bảng transition (state hiện tại | sự kiện | điều kiện | state mới | side effect) hoặc sơ đồ. Bảng này gần như một bảng cân đối — dev rất thích vì nó không mơ hồ.

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

Lỗi 1 — Nhầm "hành động" với "trạng thái". "Đang xác nhận" là trạng thái; "Xác nhận đơn hàng" là sự kiện. Người mới hay đặt tên transition và state lẫn lộn. Mẹo: state thường là tính từ/danh từ chỉ tình trạng (Đã duyệt, Đang giao); event thường là động từ (Duyệt, Giao).

Lỗi 2 — Quên các nhánh ngoại lệ. Ai cũng vẽ được luồng thuận (happy path). Nhưng giá trị của bạn nằm ở việc hỏi "còn khi hủy thì sao, khi lỗi thì sao, khi timeout thì sao?". Dùng đúng tư duy soi sổ: với mỗi state, ép mình liệt kê tất cả đường ra.

Lỗi 3 — Bỏ qua guard condition. Cho phép mọi transition xảy ra vô điều kiện sẽ tạo ra hệ thống không an toàn (ví dụ hoàn tiền hai lần). Luôn hỏi "transition này cần điều kiện gì?".

Lỗi 4 — Cho phép transition lùi vô lý. Trong nhiều nghiệp vụ, một số state là không thể đảo ngược (giống bút toán đã khóa sổ). Hãy đánh dấu rõ state nào là terminal và không transition nào được thoát ra.

Mẹo vàng: khi bí, hãy tự hỏi "nếu đây là một cuốn sổ, bút toán này có cân không?". Bản năng kế toán của bạn thường phát hiện lỗ hổng trước cả khi bạn diễn đạt được nó bằng ngôn ngữ kỹ thuật. Hãy tin vào cảm giác "khó chịu khi không cân" đó.

Mẹo công cụ: bạn có thể vẽ state machine bằng Mermaid (cú pháp stateDiagram-v2) ngay trong Confluence hoặc Markdown, hoặc dùng draw.io. Không cần phần mềm đắt tiền.

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

Bài tập 1 (cơ bản). Lấy đối tượng "Đơn xin nghỉ phép" trong một hệ thống HR. Hãy liệt kê tất cả states, vẽ các transition kèm sự kiện, đánh dấu state đầu và state cuối. Yêu cầu tối thiểu phải có nhánh: được duyệt, bị từ chối, nhân viên tự rút đơn.

Bài tập 2 (vận dụng tư duy bút toán). Cho luồng "Yêu cầu hoàn tiền" của một sàn TMĐT. Hãy lập bảng transition với 5 cột: State hiện tại | Sự kiện | Guard condition | State mới | Side effect (đặc biệt ghi rõ tác động tiền tệ cần đối ứng). Cố ý tìm và bịt ít nhất hai "lỗ hổng cân bằng" (state mồ côi hoặc dead-end).

Bài tập 3 (nâng cao). Lấy một nghiệp vụ bạn từng làm thời kế toán/tài chính (ví dụ: quy trình duyệt thanh toán nhà cung cấp, quy trình khóa sổ cuối kỳ). Mô hình hóa nó thành một state machine hoàn chỉnh và viết một đoạn 150 từ giải thích cho dev tại sao một transition cụ thể cần guard condition. Đây chính là dạng output bạn sẽ nộp trong công việc BA thật.

Sau khi làm xong, hãy tự chấm bằng câu hỏi: "Có state nào không có đường vào hoặc đường ra không? Có transition nào thiếu điều kiện không?". Nếu cân — chúc mừng, bạn vừa dùng kỹ năng 4 năm kế toán để làm việc của một BA.

Tóm tắt

Bút toán kép và state machine là hai mặt của cùng một tư duy: mọi thay đổi đều có cấu trúc, có điều kiện, có dấu vết, và tổng thể phải cân. Là người từ Finance, bạn không học state machine từ con số không — bạn chỉ đang đổi ngôn ngữ cho một bản năng đã có sẵn.

Ba điều cần nhớ:

  • State = số dư, Transition = bút toán, Event = giao dịch. Trạng thái hiện tại là kết quả tích lũy của mọi transition trước đó, hệt như số dư là kết quả của mọi bút toán.
  • Bản năng "soi cho cân" là siêu năng lực BA của bạn. Nó giúp bạn phát hiện state mồ côi, dead-end, và transition thiếu điều kiện — những lỗ hổng dev hay bỏ sót.
  • Luôn hỏi ba câu: trạng thái này có đường vào/ra không (cân bằng)? Transition này cần điều kiện gì (guard)? Transition này sinh ra tác động đối ứng nào (side effect)?
Ở bài tiếp theo, chúng ta sẽ nâng cấp kỹ năng mô hình hóa quy trình này lên một chuẩn công nghiệp — BPMN 2.0 — để bạn có thể vẽ không chỉ vòng đời một đối tượng mà cả luồng nghiệp vụ end-to-end với nhiều người tham gia.