Vòng đời phát triển phần mềm và vì sao lỗi muộn thì đắt

Xem thử

Tối thứ Sáu, ứng dụng đặt đồ uống của Cà Phê Chú Tư có thêm tính năng mã giảm giá. Hai mã được tung ra: CHUTU20 giảm 20% và GIAM15K giảm 15.000 đồng. Tài liệu yêu cầu chỉ có đúng một câu: "Khách nhập mã giảm giá để được giảm tiền." Mọi người về nhà trong tâm trạng nhẹ nhõm.

Sáng thứ Bảy, Chú Tư nhìn sổ bán hàng và thấy lạ. Có 212 đơn trả về đúng 0 đồng. Một khách gọi hai ly trà đào, tổng 70.000 đồng, bấm nút Áp dụng với mã GIAM15K năm lần liền. Ứng dụng trừ 15.000 đồng mỗi lần bấm, tổng tiền xuống 0 đồng, và ly trà vẫn được pha. Nếu mỗi đơn như vậy làm quán thiệt khoảng 28.000 đồng tiền nguyên liệu, thì một đêm quán mất cỡ 6 triệu đồng. Con số này là số liệu minh họa của bài, không phải số đo thật.

Lỗi nằm ở đâu? Không phải ở một dòng code tệ, mà ở chỗ không ai từng quyết định một đơn được dùng tối đa bao nhiêu mã. Trước khi đọc tiếp, hãy tự trả lời: câu "mỗi đơn dùng tối đa một mã" có thể được chặn ở những bước nào của việc làm ứng dụng, và theo bạn bước nào rẻ nhất? Hãy ghi ra giấy một thứ tự trước khi đọc phần sau.

Sau bài này, bạn có thể

  • Kể tên sáu pha của vòng đời phát triển phần mềm và nói mỗi pha tạo ra thứ gì cho pha kế tiếp.
  • Giải thích vì sao một lỗi bị phát hiện càng muộn thì thường càng tốn công sửa, và nói rõ đây là xu hướng chứ không phải công thức.
  • Chỉ ra việc tester làm ở từng pha, kể cả những pha mà ứng dụng chưa có dòng code nào.

Cần biết trước: không cần bài nào trước đó; chỉ cần bạn từng dùng một ứng dụng đặt đồ uống hoặc đặt xe trên điện thoại.

Bằng chứng: cùng một lỗi, năm thời điểm phát hiện

Quay lại lỗi "bấm Áp dụng nhiều lần". Hãy tưởng tượng đội của Chú Tư gồm Lan (người làm việc với chủ quán để hiểu nhu cầu), Bình (lập trình) và An (tester). Nếu lỗi này bị bắt ở từng thời điểm khác nhau, việc phải làm sẽ rất khác nhau:

Phát hiện ở phaViệc phải làmCông quy đổi (minh họa)
Yêu cầuThêm một câu "mỗi đơn dùng tối đa một mã" vào tài liệu15 phút
Thiết kếSửa luồng màn hình, họp lại để chốt, cập nhật tài liệu thiết kế2 giờ
Lập trìnhBình sửa vài dòng, tự chạy lại, nhờ người đọc lại mã4 giờ
Kiểm thửAn báo lỗi, Bình sửa, An kiểm lại, chạy lại các ca đã đạt trước đó8 giờ
Sau phát hànhSửa khẩn, bù lỗ cho quán, xin lỗi khách, họp rút kinh nghiệm48 giờ, kèm 6 triệu đồng thiệt hại

Cột bên phải là số liệu minh họa để bạn thấy hình dạng của vấn đề. Chúng không đến từ một thống kê thật, và mỗi dự án sẽ ra con số khác. Điều đáng nhìn là hướng đi: đi từ trên xuống dưới, mỗi bậc đều đắt hơn bậc trước.

Hãy tự tính trước khi xem tiếp: trong bảng này, sửa sau phát hiện bằng bao nhiêu lần so với sửa ở pha yêu cầu? Lấy 48 giờ chia 0,25 giờ ta được khoảng 190 lần. Một câu văn mất 15 phút để thêm, còn cùng nội dung đó sau phát hành mất gần hai ngày của cả đội, chưa tính uy tín.

Mô hình tư duy 1: phần mềm ra đời qua một chuỗi pha, đầu ra của pha này là đầu vào của pha kia

Vòng đời phát triển phần mềm (software development life cycle, viết tắt SDLC) là cách ta chia việc làm ra một phần mềm thành các pha, để mỗi pha có việc rõ ràng và có thứ bàn giao rõ ràng. Một cách chia phổ biến có sáu pha:

PhaCâu hỏi trả lờiThứ tạo ra (đầu ra)Ví dụ ở quán Chú Tư
Yêu cầuPhần mềm cần làm gì cho ai?Tài liệu yêu cầuKhách nhập mã để giảm tiền
Thiết kếNó sẽ trông và vận hành thế nào?Bản vẽ màn hình, luồng, cấu trúc dữ liệuÔ nhập mã, nút Áp dụng, bảng lưu mã
Lập trìnhViết nó ra bằng mã thế nào?Mã nguồn chạy đượcHàm tính tiền sau giảm
Kiểm thửNó có làm đúng điều đã hứa không?Kết quả kiểm thử, danh sách lỗiDanh sách lỗi và báo cáo
Triển khaiĐưa nó đến tay người dùng bằng cách nào?Bản chạy thật cho kháchCập nhật ứng dụng lên điện thoại
Bảo trìSau khi dùng, cần sửa và cải thiện gì?Bản vá, bản nâng cấpSửa lỗi mã giảm giá, thêm mã mới

Điều quan trọng không nằm ở tên sáu pha mà ở quan hệ phụ thuộc. Đội lập trình viết mã dựa trên bản thiết kế, bản thiết kế dựa trên tài liệu yêu cầu. Nếu tài liệu yêu cầu thiếu câu "tối đa một mã", thì bản thiết kế sẽ cho phép bấm nhiều lần, và mã sẽ trừ tiền nhiều lần, một cách hoàn toàn logic. Mỗi pha làm đúng việc của mình dựa trên thứ nhận được, vậy mà kết quả cuối vẫn sai. Lỗi đi theo chuỗi như nước chảy xuôi dòng.

Đây là lý do cần có quy trình. Không có quy trình, quyết định "một đơn dùng mấy mã" vẫn xảy ra, nhưng xảy ra ngầm, trong đầu Bình lúc gõ code vào lúc 11 giờ đêm. Có quy trình, ta ép quyết định đó lộ ra ở một pha nhất định, có người đọc, có người hỏi lại.

Đang tải sơ đồ…

Cách đọc hình: đi từ trên xuống. Bốn pha đầu nối với nhau bằng đường thẳng, đó là đường mà đầu ra pha trước thành đầu vào pha sau. Ở ô quyết định, nếu kiểm thử còn lỗi nghiêm trọng thì quay lại pha lập trình rồi kiểm thử lại; nếu không thì mới triển khai. Sau khi phát hành, bảo trì không phải điểm kết thúc: một yêu cầu mới hoặc một lỗi do khách báo đưa ta về lại pha yêu cầu, và vòng đời bắt đầu một vòng nữa.

Mô hình tư duy 2: lỗi sống càng lâu, cái giá để gỡ càng lớn

Vì sao bảng ở trên đi từ 15 phút lên 48 giờ? Có ba lý do thực tế, và bạn sẽ gặp lại cả ba trong cả khóa học này.

  1. Lỗi bị chôn dưới việc khác. Khi lỗi nằm trong tài liệu yêu cầu, sửa chỉ là sửa một câu. Khi lỗi đã thành mã, các hàm khác đã gọi đến nó. Sửa một chỗ có thể làm hỏng chỗ khác.
  2. Càng muộn càng nhiều người phải biết. Một lỗi lọt ra khách hàng kéo theo Chú Tư, nhân viên quán, người chăm sóc khách hàng, cả đội phát triển, cả buổi họp sau sự cố.
  3. Thiệt hại ngoài phần mềm. Ở pha yêu cầu chỉ tốn giờ đọc và viết. Sau phát hành, tiền thật rời khỏi quán, như 6 triệu đồng nguyên liệu trong ví dụ.

Điều này khớp với một nguyên tắc kiểm thử mà chương trình đào tạo của ISTQB (tổ chức cấp chứng chỉ kiểm thử phần mềm quốc tế) đưa ra: kiểm thử sớm giúp tiết kiệm thời gian và chi phí. Tuy vậy, hãy nhớ đây là xu hướng, không phải định luật. Có lỗi nhỏ phát hiện muộn vẫn rẻ, có lỗi trong yêu cầu phát hiện sớm vẫn tốn nếu cả đội đã tranh cãi suốt hai tuần. Con số 190 lần trong bài là của ví dụ minh họa, không dùng để dự báo cho dự án của bạn.

Phần mô phỏng dưới đây cho bạn đi cùng lỗi mã giảm giá qua từng pha. Hãy ghi giả thuyết của bạn về chi phí ở pha lập trình trước khi bấm bước tiếp, rồi thử nút biến thể để xem điều gì xảy ra nếu có người hỏi đúng câu ngay từ pha đầu.

Đang tải Animation…

Điều mô phỏng cho thấy mà bảng không cho thấy là chuyển động của lỗi: nó không cần ai cố ý đưa vào, nó chỉ cần không ai nhìn thấy. Ở biến thể có người hỏi sớm, chi phí không phải "bớt đi" mà là chưa từng phát sinh.

Mô hình tư duy 3: kiểm thử là hoạt động chạy dọc mọi pha, không chỉ một pha

Nhiều người mới nghe "pha kiểm thử" là nghĩ tester chỉ xuất hiện sau khi có code. Cách nghĩ này khiến tester đến đúng lúc rẻ nhất để lỗi đã trôi qua. Thực tế, kiểm thử là một nhóm hoạt động rải khắp vòng đời, còn pha "kiểm thử" chỉ là nơi hoạt động đó đậm đặc nhất.

PhaViệc của testerVí dụ ở quán Chú Tư
Yêu cầuĐọc yêu cầu, hỏi chỗ mơ hồ, viết tiêu chí để biết "xong là thế nào"An hỏi: một đơn dùng được mấy mã? Hai mã có cộng dồn không?
Thiết kếXem bản thiết kế có chỗ hở không, bắt đầu lập kế hoạch kiểm thửAn thấy nút Áp dụng bấm được nhiều lần, ghi lại để hỏi
Lập trìnhViết test case, chuẩn bị dữ liệu thử, thử sớm những phần đã xongChuẩn bị đơn 70.000 đồng, mã còn hạn, mã hết hạn
Kiểm thửChạy test case, ghi nhận và báo lỗi, kiểm lại sau khi sửaThử bấm Áp dụng năm lần, báo lỗi nếu tổng tiền giảm quá mức
Triển khaiKiểm tra nhanh bản vừa phát hành có chạy được các việc chính khôngĐặt thử một đơn thật, trả tiền, thấy đơn hiện trên quầy
Bảo trìKiểm tra lỗi đã sửa xong chưa, và việc sửa không làm hỏng chỗ khácChạy lại các ca về thanh toán sau khi sửa mã giảm giá

Hãy chú ý hai pha đầu: tester chưa chạy phần mềm nào cả, vì chưa có phần mềm. Công việc lúc này là kiểm thử tài liệu và ý tưởng, và nó rẻ nhất. Một câu hỏi đúng của An ở pha yêu cầu có giá trị hơn hàng chục test case ở pha sau.

Hiểu lầm thường gặp

  • "Tester chỉ làm việc sau khi lập trình xong." Sai ở chỗ coi kiểm thử là một pha duy nhất. Tester giỏi tham gia từ lúc đọc yêu cầu, vì lỗi trong tài liệu rẻ nhất để sửa.
  • "Có quy trình nghĩa là không còn lỗi." Quy trình không loại bỏ lỗi, nó chỉ làm cho lỗi lộ ra sớm hơn và rẻ hơn. Một đội theo đúng quy trình vẫn có lỗi.
  • "Lỗi nào cũng đắt gấp hàng trăm lần nếu phát hiện muộn." Con số trong bài là minh họa. Mức tăng thật thay đổi theo loại lỗi, loại dự án, độ nhạy cảm của nơi dùng phần mềm. Cái đúng là xu hướng: muộn hơn thường đắt hơn.
  • "Các pha phải tách bạch, xong pha này mới sang pha kia." Một số mô hình làm vậy (bài sau sẽ gặp thác nước), số khác làm nhiều pha chồng lên nhau theo vòng ngắn (Agile). Sáu pha là các loại việc, không bắt buộc là sáu giai đoạn nối tiếp nhau trên lịch.

Điều kiện và giới hạn

Cách chia sáu pha là mô hình đơn giản để học, không phải bản mô tả mọi dự án. Có tài liệu chia ra bảy hoặc tám pha, có tài liệu gộp thiết kế và lập trình. Tên gọi cũng khác nhau, ví dụ "phân tích" thay vì "yêu cầu". Quan trọng là bạn nhận ra loại việc nào đang diễn ra và ai chịu trách nhiệm kiểm tra nó. Ngoài ra, phần mềm rất nhỏ (một trang cá nhân, một đoạn mã dùng một lần) có thể không cần đủ sáu pha; quy trình càng nặng khi phần mềm càng nhiều người dùng và càng nhiều tiền chảy qua.

Tự kiểm tra (có đáp án)

Câu 1. Vì sao câu "mỗi đơn dùng tối đa một mã" thêm ở pha yêu cầu rẻ hơn nhiều so với sửa sau phát hành? Đáp án: ở pha yêu cầu nó chỉ là một câu trong tài liệu, chưa có thiết kế hay mã nào dựa vào. Sau phát hành, lỗi đã thành mã, đã đến tay khách, đã làm quán mất tiền, và cả đội phải ngừng việc để sửa khẩn.

Câu 2. Một tester được mời vào dự án khi mã đã viết xong. Hai thứ cụ thể nào đã mất đi so với việc được tham gia từ đầu? Đáp án: mất cơ hội hỏi lại các chỗ mơ hồ trong yêu cầu và thiết kế khi sửa còn rẻ, và mất thời gian chuẩn bị test case song song với việc lập trình, nên phần kiểm thử bị dồn vào cuối.

Câu 3. Bạn nghe một người nói "lỗi phát hiện muộn luôn đắt gấp 100 lần". Bạn trả lời thế nào? Đáp án: xu hướng muộn thì đắt là có cơ sở, nhưng con số cụ thể phụ thuộc loại lỗi và dự án nên không thể khẳng định cố định. Con số trong bài là minh họa, không phải thống kê.

Điều cần nhớ

  • Phần mềm ra đời qua sáu pha: yêu cầu, thiết kế, lập trình, kiểm thử, triển khai, bảo trì; đầu ra pha trước là đầu vào pha sau, nên lỗi cũng đi theo chuỗi.
  • Lỗi sống càng lâu thường càng đắt; con số trong bài là minh họa của quán Chú Tư, không phải định luật.
  • Tester làm việc ở mọi pha; hai pha đầu là lúc rẻ nhất để chặn lỗi, vì ta chỉ kiểm tra chữ và ý tưởng.
  • Bài sau xem cách xếp các pha này lên lịch theo kiểu tuần tự: mô hình thác nước.

Nguồn tham khảo