Welcome to MikeDaDev's Blog – notes on Java, backend & system design.

Explore
MikeDaDev's Blog

Critical Thinking

Tung Bui Thanh (TungDaDev)18 mins read

Critical thinking problem solving.webp

Phần lớn thời gian và tiền bạc trong công ty bị phí không phải vì người ta tìm sai câu trả lời, mà vì họ đã trả lời rất xuất sắc một câu hỏi sai. Tư duy phản biện không bắt đầu bằng việc lao vào tìm giải pháp, mà bắt đầu bằng việc gọi đúng tên vấn đề.

# sao vấn đề cứ nối đuôi nhau xuất hiện?

Ở công ty nào cũng vậy, cảm giác "vừa dập xong vụ này thì vụ khác ập tới" quá quen thuộc. Nhiều anh em kỹ sư kiệt sức chỉ vì ngày nào cũng chữa cháy (firefighting).

Gốc rễ thường nằm ở hai chuyện:

  1. Entropy trong hệ thống phức tạp: tổ chức hay hệ thống phần mềm càng lớn thì số tương tác chồng chéo giữa người, quy trình và công nghệ tăng nhanh hơn nhiều so với quy mô. Riêng số cặp người cần phối hợp đã là n(n-1)/2: team 5 người có 10 cặp, team 50 người có 1.225 cặp. Mọi thứ tự nhiên sẽ ngày càng lộn xộn, trừ khi có ai đó bỏ công sức ra giữ trật tự.
  2. Nhầm triệu chứng (symptom) với nguyên nhân gốc (root cause): hệ thống trục trặc thì thứ mình thấy đầu tiên thường chỉ là phần nổi của tảng băng. Vội dập triệu chứng thì được yên vài hôm, còn nguyên nhân gốc vẫn âm thầm tích tụ chờ lần bùng phát sau.

# xác định loại bối cảnh bằng khung Cynefin

Trước khi phân tích bài toán nào, việc đầu tiên là xem nó thuộc loại bối cảnh nào, dùng khung Cynefin (Cynefin Framework, Dave Snowden). Snowden cho rằng rất nhiều thất bại đến từ việc dùng cách xử lý của bối cảnh này cho một bối cảnh khác, kiểu đem checklist đi giải bài toán thị trường:

Loại bối cảnhĐặc điểmNên xử lý thế nàoLỗi hay mắc
Rõ ràng (Clear)Nguyên nhân và kết quả rõ rành rành, ai nhìn cũng thấy.Nhận biết → Phân loại → Phản hồi (Sense - Categorize - Respond). Cứ theo quy trình có sẵn (Standard Operating Procedures - SOP).Quan liêu, cố làm phức tạp một chuyện đơn giản.
Phức tạp (Complicated)Có quan hệ nhân quả rõ ràng nhưng phải có người chuyên môn sâu mới phân tích được.Nhận biết → Phân tích → Phản hồi (Sense - Analyze - Respond). Dựa vào dữ liệu và kinh nghiệm chuyên gia (Good Practice).Tự tin quá đà, bỏ qua ý kiến của người rành nghiệp vụ.
Phức hợp (Complex)Hệ thống phi tuyến (con người, thị trường, AI), nguyên nhân chỉ hiểu được khi nhìn lại (in retrospect).Thử nhỏ → Đo → Điều chỉnh (Probe - Sense - Respond). Giải pháp hình thành dần qua thử nghiệm (Emergent Practice).Rất nguy hiểm: bê nguyên "Best Practice" từ chỗ khác áp cứng vào một hệ thống phức hợp đang thay đổi.
Hỗn loạn (Chaotic)Khủng hoảng cấp tính, hệ thống sập, không có thời gian ngồi phân tích.Hành động ngay → Đo → Phản hồi (Act - Sense - Respond). Cầm máu trước đã (Novel Practice).Ngồi họp tìm nguyên nhân trong khi lẽ ra phải dập lửa ngay.

Cynefin còn một vùng thứ năm ở giữa là Confusion (bản cũ gọi là Disorder): lúc mình chưa biết vấn đề thuộc loại nào. Trạng thái này nguy hiểm vì người ta hay mặc định chọn loại bối cảnh hợp với sở trường của mình (dân kỹ thuật thấy cái gì cũng là Complicated). Lối ra là chia vấn đề thành từng phần nhỏ rồi xếp từng phần vào đúng vùng. Một incident production là ví dụ dễ thấy: lúc hệ thống đang sập là Chaotic (rollback, chặn traffic trước), ổn định rồi thì việc tìm root cause chuyển sang Complicated, còn câu chuyện "vì sao team hay để lọt loại lỗi này" thường lại là Complex.


# mấy cái bẫy nhận thức khi giải quyết vấn đề

Não người tiến hoá để tiết kiệm năng lượng bằng các lối tắt (heuristics). Nhưng trong công việc phức tạp, chính mấy lối tắt này lại hay gây hại:

# bẫy muốn làm gì đó ngay (Action Bias)

Bị dí deadline hay gặp khủng hoảng thì ai cũng muốn "làm cái gì đó ngay" hơn là dừng lại suy nghĩ. Viết vội một bản hotfix hay triệu tập họp khẩn cho ta cảm giác đang hành động, nhưng nhiều khi chỉ làm hệ thống rối thêm.

# bẫy chỉ tìm cái mình muốn tin (Confirmation Bias)

Khi đã có sẵn một giả thuyết "ruột" (ví dụ: "Hệ thống chậm chắc chắn là do database"), người ta vô thức chỉ gom số liệu ủng hộ nó và bỏ qua mọi dấu hiệu cho thấy lỗi thật ra nằm ở network hay bộ nhớ của app.

# bẫy nhìn công cụ theo lối mòn (Functional Fixedness)

Là thói quen chỉ thấy một công cụ hay quy trình theo đúng công dụng quen thuộc của nó. Bối cảnh nghiệp vụ đã đổi mà vẫn bám công cụ cũ, team sẽ không nhìn ra những cách làm gọn hơn nhiều.

# bẫy suy luận theo người khác (Reasoning by Analogy)

Là bắt chước nguyên xi đối thủ hoặc mấy công ty công nghệ lớn (kiểu "Google với Netflix làm Microservices thì mình cũng phải chẻ hệ thống ra 50 services"). Cách nghĩ này bỏ qua khác biệt về nguồn lực, đội vận hành và bài toán kinh doanh của chính mình.


# tư duy nguyên lý đầu tiên (First Principles Thinking)

Ý tưởng này có từ thời Aristotle, và được nhiều nhà khoa học, founder công nghệ (như Elon Musk) dùng rất nhiều. First Principles Thinking là bóc một vấn đề phức tạp ra tới những sự thật cơ bản nhất không thể chối cãi, rồi từ đó lập luận lại một giải pháp mới từ đầu:

Ví dụ trong ngành mình:

  • Suy luận theo người khác: "Công ty khác thuê cloud hết $50,000/tháng cho cụm Elasticsearch, vậy mình cũng phải dự trù chừng đó."
  • Nguyên lý đầu tiên: "Hệ thống mình thật ra ghi bao nhiêu byte mỗi giây? Disk I/O thực tế cần bao nhiêu? Một con bare-metal server ngoài thị trường giá bao nhiêu? Sao mình phải trả tiền cho cả trăm GB index mà người dùng không bao giờ query tới?". Trả lời xong mấy câu đó, rất có thể team sẽ thấy chỉ cần giữ data nóng vài tuần gần nhất trên node mạnh, phần còn lại đẩy xuống lưu trữ phân tầng (Tiered Storage) rẻ hơn nhiều, và hoá đơn có thể giảm cả chục lần so với con số "người ta cũng tiêu chừng đó".

# chia nhỏ vấn đề: MECE và cây vấn đề (Issue Tree)

Để không bỏ sót nguyên nhân nào mà cũng không phân tích trùng lặp, dân tư vấn chiến lược ở McKinsey dùng nguyên tắc MECE (Mutually Exclusive, Collectively Exhaustive):

  • Mutually Exclusive (không trùng nhau): mỗi nhánh nguyên nhân độc lập, không chồng lên nhau.
  • Collectively Exhaustive (không sót): gộp tất cả các nhánh lại phải phủ được toàn bộ bài toán.

Chia bài toán thành cây vấn đề (Issue Tree) đúng kiểu MECE rồi thì giao cho từng nhóm nhỏ đi kiểm chứng dữ liệu rất dễ, không lo giẫm chân nhau.

Nói cho công bằng thì cây ở trên vẫn chưa thật sự "không sót": khách có thể rời đi vì lý do chẳng liên quan gì tới mình, như bị sáp nhập, cắt ngân sách hay đổi chiến lược. Cách thực tế là chia theo một tiêu chí rõ ràng (ví dụ "lý do nằm trong tầm kiểm soát của mình / ngoài tầm kiểm soát") rồi mới chia nhỏ tiếp, và chấp nhận có một nhánh "khác" để gom phần còn lại. Ngược lại, hai nhánh hay bị trùng nhau nhất là "lỗi hệ thống" và "hỗ trợ chậm": một outage kéo theo cả hai, nên khi đếm số liệu cần quy ước rõ một ca sẽ tính vào nhánh nào.


# 5 Whys làm cho có kỷ luật và Problem Statement Canvas

# 5 Whys có kỷ luật

5 Whys (hỏi "tại sao" năm lần, xuất phát từ hệ thống sản xuất của Toyota) chỉ hiệu quả khi giữ đúng một nguyên tắc: mỗi câu hỏi phải dẫn tới một sự thật khách quan về hệ thống hoặc quy trình, không dừng lại ở chuyện đổ lỗi cho người.

  • Nếu câu trả lời dừng ở "Do dev sơ suất" thì coi như phân tích hỏng.
  • Phải đào tiếp: "Tại sao CI/CD hay code review lại để một câu query không có index lọt thẳng lên production?".

# mẫu định nghĩa vấn đề (Problem Statement Canvas)

Trước khi bắt tay tìm giải pháp, bắt cả mình lẫn team điền đủ 5 mục sau:

MụcCâu hỏi kiểm traVí dụ
Hiện trạng (Status Quo)Thật sự đang xảy ra chuyện gì, theo số liệu đo được?Tỷ lệ giao dịch thanh toán lỗi giờ cao điểm tăng từ 0.1% lên 4.2%.
Khoảng cách (The Gap)Mức mong muốn là bao nhiêu, đang lệch bao nhiêu?SLA cam kết lỗi < 0.05%; đang lệch 4.15%.
Phạm vi (Scope)Sự cố xảy ra ở đâu, lúc nào, với ai?Chỉ dính giao dịch qua cổng thanh toán quốc tế, khung giờ 20h - 22h.
Tác động (Impact)Công ty hoặc khách hàng đang thiệt hại cụ thể gì?Mất ước tính $12,000 doanh thu mỗi ngày, ticket hỗ trợ tăng 15%.
Ngoài phạm vi (Non-goals)Những gì không nằm trong việc cần xử lý lần này?Chưa tính chuyện đổi nhà cung cấp cổng thanh toán ở giai đoạn này.

# nhìn lại vai trò của chính mình (Role Examination)

Một bước quan trọng mà nhiều người bỏ qua: nhận ra phần của mình trong việc gây ra hoặc duy trì vấn đề.

Nhìn theo tư duy hệ thống (Systems Thinking), mình hiếm khi chỉ là nạn nhân của hoàn cảnh. Cách mình hành xử thường là một mắt xích trong một vòng phản hồi (feedback loop):

Thử tự hỏi mình mấy câu (Self-Reflective Questions):

  • "Mình đang làm gì mà vô tình khiến chuyện này cứ tiếp diễn?"
  • "Mình đang ôm những giả định nào mà chưa từng kiểm chứng?"
  • "Nếu mình rút ra khỏi quy trình này, cái cổ chai có tự biến mất không?"

# đặt lại câu hỏi: Goal-Oriented Reframing

Reframing là đổi góc nhìn để biến một câu hỏi đang bế tắc thành một câu hỏi mở, hướng về mục tiêu.

Câu chuyện "thang máy chậm" mà Thomas Wedell-Wedellsborg dùng trong bài Are You Solving the Right Problems? (Harvard Business Review, 2017) cho thấy rõ cách này hiệu quả thế nào. Nó là một giai thoại để minh hoạ, đừng coi là case study có số liệu:

  • Câu hỏi ban đầu: "Làm sao cho thang máy chạy nhanh hơn?" \rightarrow Giải pháp: thay động cơ, nâng cấp cả hệ thống thang, vừa đắt vừa lâu.
  • Nhìn lại theo người dùng: "Cái người ta khó chịu không phải thang máy chậm, mà là đứng chờ thì chán và sốt ruột".
  • Câu hỏi mới: "Làm sao cho lúc chờ dễ chịu hơn?" \rightarrow Giải pháp: gắn gương cạnh cửa thang máy (có thể thêm nhạc nhẹ, bảng thông tin). Người ta mải ngắm mình nên quên mất thời gian chờ, phàn nàn giảm hẳn mà chi phí chẳng đáng là bao.

# công thức "How Might We" (HMW)

Để biến vấn đề thành câu hỏi có thể bắt tay làm ngay:

[Vấn đề đang bế tắc] → Làm thế nào để chúng ta (HMW) + [Mục tiêu mong muốn] + [Cho ai] + [Trong giới hạn X]?

  • Câu hỏi đóng: "Làm sao ép nhân viên viết tài liệu kỹ thuật đúng quy trình?"
  • Đổi thành HMW: "Làm thế nào để việc cập nhật tài liệu kỹ thuật diễn ra tự nhiên ngay trong lúc code hằng ngày, mà không làm đứt mạch suy nghĩ của kỹ sư?".

# nghĩ tới hậu quả bậc hai (Second-Order Thinking) và hiệu ứng rắn hổ mang

Người mới giải quyết vấn đề thường dừng ở tư duy bậc một (First-Order Thinking): "X xảy ra, làm Y để xử lý X". Người có kinh nghiệm thì nghĩ thêm một bước (Second-Order Thinking): "Làm Y xong thì 3 tháng tới chuyện gì xảy ra? Hệ thống và con người sẽ phản ứng với giải pháp này ra sao?".

Tên gọi "hiệu ứng rắn hổ mang" (cobra effect) do nhà kinh tế học Horst Siebert đặt ra năm 2001, dựa trên một giai thoại thời Anh cai trị Ấn Độ. Các nhà sử học tìm thấy dấu vết của chương trình treo thưởng, nhưng đoạn "nuôi rắn rồi thả ra" thì gần như không có tư liệu gốc. Cứ coi nó là truyện ngụ ngôn về động cơ khuyến khích, bài học vẫn đúng.

Chuyện tương tự trong làm phần mềm:
Đặt KPI: "Đo năng suất dev bằng số dòng code viết ra mỗi ngày".

  • Hậu quả bậc hai: dev cố viết dài dòng, copy-paste thay vì gom lại thành hàm, nợ kỹ thuật và chi phí bảo trì tăng vọt.

# giải quyết vấn đề cùng nhau theo 4 bước

Để cùng đồng nghiệp và các bên liên quan xử lý vấn đề (collaborative problem solving) mà không sa vào cãi nhau theo cảm tính, có thể dùng mô hình Double Diamond (kim cương đôi, do Design Council của Anh đưa ra năm 2005). Mỗi "viên kim cương" gồm một pha mở rộng (diverge) rồi một pha thu hẹp (converge):

  1. Khám phá (Diverge - Explore): gom dữ liệu khách quan từ nhiều nguồn: log hệ thống, nói chuyện với người dùng, hỏi các bộ phận liên quan. Ở bước này chưa vội phán đúng sai.
  2. Định nghĩa (Converge - Define): gom nhóm những gì tìm được, dùng 5 Whys và Problem Statement Canvas để rút lại thành đúng một câu hỏi chính.
  3. Nghĩ giải pháp (Diverge - Ideate): đưa ra ít nhất 3 phương án khác nhau (từ cách không tốn đồng nào tới cách dùng công nghệ cao). Đừng bám lấy ý tưởng đầu tiên nảy ra.
  4. Thử và đo (Converge - Deliver): triển khai thử ở quy mô nhỏ (PoC / A/B Testing), đặt sẵn chỉ số đo rõ ràng để đánh giá trước khi nhân rộng ra cả công ty.

# checklist trước khi chốt giải pháp

Trước khi duyệt ngân sách, sửa kiến trúc hay áp một quy trình mới, tự rà qua mấy câu này:

  • Dữ liệu có thật không: nhận định này dựa trên số liệu đo được, hay chỉ là cảm giác của vài người có tiếng nói lớn?
  • Có chạm tới nguyên nhân gốc không: giải pháp này xử lý được gốc rễ, hay chỉ đang dập triệu chứng bên ngoài?
  • Hậu quả bậc hai (Second-Order Consequences): nếu làm thành công, 3 tháng tới nó gây ra tác dụng phụ gì cho các bộ phận khác?
  • Chi phí cơ hội (Opportunity Cost): thời gian, tiền, người bỏ vào đây, nếu dồn cho vấn đề khác thì có đáng hơn không?
  • Có quay lại được không (Reversibility): đây là quyết định một chiều (Type 1, khó quay đầu) hay hai chiều (Type 2, hỏng thì quay về trạng thái cũ dễ dàng)? Cách chia này lấy từ thư gửi cổ đông năm 2015 của Jeff Bezos: quyết định hai chiều thì nên chốt nhanh, quyết định một chiều mới đáng bỏ công phân tích kỹ.

Nếu chỉ chọn một thứ để bắt đầu, mình nghĩ nên thử Problem Statement Canvas ở lần họp xử lý sự cố tới: chỉ cần điền đủ năm ô trước khi bàn giải pháp là cuộc họp đã khác hẳn.


Chỉ là những ghi chép cá nhân với hy vọng mang lại chút giá trị. Nếu thấy hữu ích, đừng ngại chia sẻ cho bạn bè & đồng nghiệp nhé!

Happy coding 😎 👍🏻 🚀 🔥.