Tại sao lập trình viên không thể estimate thời gian hiệu quả?
Tại sao lập trình viên không thể estimate thời gian hiệu quả?
Gambaru - 2020/11/02 11:13
COPY
Hãy cùng Gambaru xem xét một cách tiếp cận thống kê để giải thích tại sao nhiều dự án công nghệ lại trễ hạn.
Cho dù bạn là lập trình viên junior, senior, quản lý dự án hay quản lý cấp cao với 20 năm kinh nghiệm, việc ước lượng thời gian trong các dự án phần mềm không bao giờ là dễ dàng.
Tổng quan
Trước tiên, hãy nhìn tổng thể vào vấn đề, hậu quả và nguyên nhân gốc rễ tiềm ẩn.
Vấn đề
Các dự án phần mềm hiếm khi đáp ứng đúng thời hạn.
Hậu quả
Các nỗ lực tiếp thị bị lãng phí, khách hàng không hài lòng, lập trình viên gặp áp lực có thể viết code chất lượng kém để chạy kịp deadline, khiến độ tin cậy của sản phẩm bị ảnh hưởng, và cuối cùng, các dự án hoàn toàn có thể bị hủy.
Các nguyên nhân đã được biết
Estimate thời gian sai(trọng tâm của bài viết này).
Yêu cầu không rõ ràng khi bắt đầu dự án và các yêu cầu thay đổi ở những giai đoạn sau.
Hội chứng “dát vàng” (gold plating): quá chú ý đến những chi tiết ngoài phạm vi công việc.
Không dành đủ hoặc mất quá nhiều thời gian cho giai đoạn nghiên cứu và thiết kế kiến trúc.
Bỏ qua các vấn đề tiềm ẩn liên quan đến sự tích hợp của bên thứ ba.
Mong muốn “làm đúng ngay lần đầu tiên”.
Thực hiện quá nhiều dự án cùng một lúc hoặc bị phân tâm (thường xuyên phá vỡ quy trình).
Quy mô chất lượng-số lượng không cân bằng.
Lạc quan quá mức, Hiệu ứng Dunning-Kruger, Yếu tố bất định hay Tất cả chỉ là toán?
Thật dễ để loại bỏ giả thuyết về việc lạc quan quá mức chỉ vì một lẽ thường thấy rằng không có lập trình viên nào từng vật vã với deadline lại lạc quan khi đặt ra thời hạn làm task. Còn tình huống khi việc quản lý dự án đến từ người không có nền tảng kỹ thuật và họ đặt ra thời hạn mà không biết mình đang làm gì lại là một vấn đề hoàn toàn khác nằm ngoài phạm vi của bài viết này.
Một số cũng cho rằng việc ước lượng thời gian kém là do hiệu ứng Dunning-Kruger (đánh giá năng lực của bản thân cao hơn thực tế). Tuy nhiên, nếu việc thiếu kinh nghiệm hoặc đánh giá quá cao khả năng của một người là nguyên nhân dẫn đến đánh giá thấp thời gian, vậy có phải nhiều kinh nghiệm hơn sẽ giảm bớt vấn đề không? Thực tế, các công ty lớn với nhiều nguồn lực vẫn có tỷ lệ trễ deadline cao choáng váng, do đó giả thuyết này bị loại bỏ.
Hầu hết các lập trình viên, đặc biệt là lập trình viên có kinh nghiệm, nhanh chóng kết luận cho yếu tố bất định. Theo họ, việc ước lượng thời gian sẽ luôn sai, “cuộc sống mà”, và điều duy nhất ta có thể làm là cố gắng đáp ứng yêu cầu khách hàng và bảo team lập trình “thôi ráng thêm xíu nữa” khi có sự cố. Tất cả chúng ta đều quen thuộc với những căng thẳng, code lỗi và sự hỗn loạn ở kịch bản này.
Đây có thực sự là cách tốt nhất mà ta có thể hoàn thành công việc không? Chà, tôi không nghĩ vậy và đó là khi tôi bắt đầu cố tìm ra một lời giải thích có tính toán học hợp lý về lý do tại sao những người thông minh như kỹ sư phần mềm không thể ước lượng thời gian hiệu quả được.
Nó chỉ là toán thôi!
Ngày nọ, tôi thực hiện một task lẽ ra chỉ mất 10 phút nhưng rốt cuộc nó tốn mất 2 giờ. Tôi bắt đầu suy ngẫm về lý do tại sao.
Tôi nghĩ sẽ mất 10 phút vì thực tế trong đầu đã biết 100% đoạn code mình cần viết.
Sau đó, nó ngốn mất của tôi đến 2 giờ vì có bug trong framework mà tôi hoàn toàn không biết.
Trong quản lý dự án, điều này được gọi là force majeure (sự kiện bất khả kháng): các nguyên nhân bên ngoài không thể kiểm soát được gây nên chậm trễ.
Đến đây bạn có thể nghĩ rằng tôi đang chứng minh cho giả thuyết các yếu tố bất định với kịch bản này. Đúng và Sai. Hãy nhìn rộng hơn một chút.
Sự bất định là nguyên nhân gốc rễ cho sự chậm trễ của task này bởi vì tôi sẽ không bao giờ đoán trước được có bug đó. Nhưng có nên cho đó là lý do dẫn đến sự chậm trễ của toàn bộ dự án?
Đến đây, ta cần phân biệt được rằng một task đơn lẻ không phải đại diện cho toàn bộ dự án và ngược lại.
Cách chúng ta “thường” ước lượng thời gian
Mean (giá trị trung bình)
Median (giá trị trung vị): giá trị tách giữa nửa lớn hơn và nửa bé hơn của một mẫu.
Mode (giá trị yếu vị): giá trị thường xuyên xuất hiện nhiều nhất.
Phân phối chuẩn
Phân phối chuẩn(normal distribution) rất phổ biến và bộ não người đã khá quen với chúng.
Về bản chất, chúng ta là những chuyên gia ước lượng mọi thứ tuân theo nguyên tắc phân phối chuẩn; đó là cơ sở để tích lũy kinh nghiệm trong quá trình làm việc.
Nếu bạn đã đi làm 7-11 lần trên 20 lần trong tháng này và mỗi lần đều mất 5 phút, ngoại trừ hôm thang máy đang bảo trì và bạn phải đợi 10 phút và có hôm bạn đợi vài phút cho đến khi trời tạnh mưa mới đi làm.
Vậy bạn ước tính thời gian đến chỗ làm hôm nay là bao nhiêu? 5 phút?
Nếu nói 15 phút thì không hợp lý vì thang máy hư là sự cố hy hữu hoặc 7 phút nếu hôm nay trời mưa.
Nếu 7-11 lần trên 20 lần, bạn mất 5 phút thì chắc chắn có khả năng lớn là hôm nay cũng chỉ mất 5 phút (median – giá trị trung vị), xác suất khoảng 90%.
Phân phối lệch
Ngay cả khi thực sự giỏi ước lượng thời gian cho một task, điều đó không có nghĩa là bạn sẽ giỏi ước lượng thời gian cho toàn dự án! Trái với những gì mọi người thường nghĩ, bạn sẽ ngày càng mắc nhiều sai lầm.
Meme ở phần 3 chính là nói về phân phối lệch (skewed distribution)! Hãy thử làm rõ cùng tôi.
Phỏng đoán “tự nhiên” của chúng ta dựa trên số trung vị (median) giúp tối đa hóa xác suất đoán đúng; tuy nhiên, con số thực khi “sự kiện” đó xảy ra đủ số lần sẽ luôn gần với giá trị trung bình (mean).
Nói cách khác: Bạn càng làm nhiều task tương tự nhau, lỗi đó càng tích lại nhiều hơn!
Các task lập trình trong một dự án thường khá giống nhau hoặc ít nhất được nhóm thành vài cụm tương tự! Phương trình này cũng gợi ý rằng vấn đề có thể mở rộng! Ai cũng muốn mọi thứ trong dự án phần mềm có thể mở rộng, trừ các vấn đề!
Vậy làm thế nào để áp dụng kiến thức này?
Thành thật mà nói, khi viết bài, tôi không hề có ý định đưa ra “hướng dẫn” dựa trên giả thuyết này.
Bài viết là một phân tích mang tính khám phá, việc kết luận với một giả thuyết và hiểu nó là tùy thuộc vào độc giả.
Tuy nhiên, tôi biết rằng nhiều người sẽ thất vọng với kết luận mở trên, vì vậy đây là những gì cá nhân tôi đúc kết.
Sẽ dễ dàng hơn để biết liệu task X sẽ mất nhiều / ít / cùng thời gian so với task Y hơn là nói chính xác chúng sẽ mất bao lâu. Điều này là do việc so sánh các giá trị median hoạt động giống như việc so sánh giá trị mean nếu độ lệch của các đường cong gần như nhau (điều này đúng với các task tương tự nhau).
Tôi không nhớ hoặc ghi lại mọi task tương tự để tính toán và lấy giá trị trung bình. Vì vậy, tôi thường ước tính sai số không thể tránh khỏi (mean – median) theo phần trăm thời gian làm task đó tăng / giảm tùy thuộc vào mức độ thoải mái của tôi với môi trường development (tôi có thích ngôn ngữ / framework này không? (40%) Tôi có công cụ debug tốt không? (30%) Hỗ trợ IDE có tốt không? (25%) v.v.).
Tôi chia sprint thành các task tương đương nhau, nhằm tạo sự đồng nhất trong quá trình ước lượng thời gian. Điều này cho phép tôi hưởng lợi từ điểm 1 ở trên, do sẽ dễ dàng biết được liệu hai task có thời gian gần bằng nhau hay không. Điều này cũng làm cho các task có thể có độ tương đương nhiều hơn, để có thể áp dụng hiệu quả giả thuyết trên và mọi thứ trở nên dễ đoán hơn.
Áp dụng các nguyên tắc này, bạn có thể thực hiện “thử nghiệm” nếu có đủ tài nguyên.
Ví dụ: nếu trong X1 ngày với Y1 lập trình viên, Z1 task tương đương đã được hoàn thành, thì ta có thể dễ dàng giải quyết X2 (ngày) nếu biết có sẵn Y2 lập trình viên và Z2 số task còn lại.