Khác với Agile, các chương trình phần mềm truyền thống được thực hiện theo cách phát triển dựa trên giai đoạn (phrase-based): phát triển tính năng, alpha, beta và golden master (GM).
Mỗi bản phát hành bắt đầu với giai đoạn xây dựng các tính năng và (lý tưởng là) giải quyết các vấn đề tồn đọng từ bản phát hành trước đó (tuy nhiên phải thừa nhận rằng điều này hiếm khi xảy ra). Chu kỳ phát triển tiến tới alpha khi các tính năng được triển khai và sẵn sàng cho việc kiểm thử, sau đó là giai đoạn beta khi các lỗi đã được sửa và phần mềm sẵn sàng nhận phản hồi của khách hàng. Thế nhưng thật không may, khi nhóm đang cố gắng sửa lỗi để tiến tới bản beta thì các lỗi mới lại xuất hiện, giống như trò chơi đập chuột: cứ sửa một lỗi thì lại có hai lỗi phát sinh. Cuối cùng, bản phát hành tiến tới mốc GM khi đạt được trạng thái zero open bugs – tức là khắc phục một số sự cố đã biết và trì hoãn phần còn lại (phần lớn?) qua bản phát hành tiếp theo.
Việc thường xuyên trì hoãn các lỗi cần sửa là một cách phát triển phần mềm nguy hiểm. Khi số lượng lỗi tăng lên, việc giải quyết chúng sẽ càng khó khăn hơn, cuối cùng sẽ dẫn đến một vòng luẩn quẩn nợ kỹ thuật. Vấn đề thậm chí có thể trở nên tệ hơn khi lịch trình bị xáo trộn vì các lỗi làm chậm quá trình phát triển. Các lỗi chưa được khắc phục cũng gây ra trải nghiệm người dùng tệ hại, và chắc chắn một số khách hàng sẽ rời đi vì điều đó.
Phải có một cách tốt hơn!
Giảm nợ kỹ thuật với quy trình Agile
Agile đưa chất lượng vào phương pháp phát triển lặp lại, để nhóm có thể duy trì chất lượng nhất quán sau mỗi bản phát hành. Nếu một tính năng chưa đủ chất lượng, nó sẽ không được xuất xưởng. Thật khó tin phải không? Hãy định nghĩa hoặc tái định nghĩa Definition of Done.
Đối với các nhóm phát triển truyền thống, done có nghĩa là đủ tốt để QA bắt đầu làm việc. Vấn đề của định nghĩa này là, lỗi xuất hiện sớm trong chu kỳ phát hành và sẽ tiếp tục xâm nhập vào, do đó vào thời điểm đến tay QA, sản phẩm sẽ được đắp thêm nhiều lớp mỗi khi QA tìm ra lỗi. Trái lại, các nhóm Agile xác định done là sẫn sàng để phát hành, có nghĩa là các nhà phát triển không chuyển sang làm việc trên tính năng hoặc câu chuyện tiếp theo khi sản phẩm hiện tại của họ chưa thực sự đến tay khách hàng. Để đẩy nhanh tiến độ, họ áp dụng các kỹ thuật như quy trình làm việc phân nhánh tính năng, kiểm tra tự động và tích hợp liên tục trong suốt quy trình phát triển.
Việc ngăn chặn nợ kỹ thuật giúp quá trình phát triển trở nên nhanh nhẹn trong thời gian dài.
Nhánh chính của cơ sở mã nguồn phải luôn sẵn sàng để chuyển giao. Đó là ưu tiên số một! Do đó, các tính năng mới bắt đầu hoạt động trên một nhánh tác vụ (task) chứa mã nguồn cho chính tính năng đó, cùng với các kiểm tra tự động. Sau khi tính năng được hoàn thành và vượt qua các kiểm tra tự động, nhánh tác vụ có thể được hợp nhất vào nhánh chính. Bởi vì thanh chất lượng luôn luôn được cố định (và ở mức cao), nợ kỹ thuật vẫn sẽ nằm trong tầm kiểm soát.
Đây sẽ là một thay đổi lớn về văn hoá đối với nhiều tổ chức. Agile hỗ trợ nhóm tập trung vào việc phát triển một phần mềm có chất lượng cao và có thể demo, thay vì lịch trình. Product Owner có trách nhiệm giúp nhóm tập trung vào công việc có giá trị nhất trước tiên, có thể giảm phạm vi phát hành thay vì hạ thấp chất lượng.
Hãy luôn nhớ rằng: lỗi tồn tại càng lâu thì càng khó sửa và gây ra càng nhiều vấn đề.
Xử lý nợ kỹ thuật
Nếu bạn đang làm việc với mã nguồn kế thừa, rất có thể bạn cũng kế thừa cả một số nợ kỹ thuật. Các ý tưởng sau đây sẽ giúp khắc phục hoàn toàn nợ kỹ thuật hiện có và hỗ trợ nhóm của bạn tập trung vào những điều thú vị như phát triển tính năng mới.
Xác định nợ
Đôi khi, các nhà phát triển và nhà quản lý sản phẩm không đồng ý về những lý do tạo ra nợ kỹ thuật. Do đó, trước tiên hãy làm rõ về nợ kỹ thuật:
Nợ kỹ thuật là sự khác biệt giữa những gì đã hứa và những gì đã thực sự được giao.
Điều này bao gồm bất kỳ lối tắt kỹ thuật (technical shortcut) nào được thực hiện để đáp ứng thời hạn chuyển giao!
Các nhà phát triển có xu hướng cho rằng công việc kiến trúc là nợ kỹ thuật. Điều này có thể đúng hoặc sai, tuỳ vào bản chất của sự thay đổi (ví dụ, thay thế một lối tắt bằng giải pháp “thật” >< tách một cơ sở mã nguồn nguyên khối thành các monoservice). Mặt khác, các nhà quản lý sản phẩm thường cảm thấy việc xây dựng tính năng mới là cấp bách hơn so với việc sửa lỗi hoặc khắc phục vấn đề hiệu suất chậm. Để tránh một trong hai bên trở nên bối rối về quan điểm của bên còn lại, tất cả mọi người cần hiểu rõ sự khác biệt giữa nợ kỹ thuật, các thay đổi kiến trúc mong muốn trong cơ sở mã nguồn và các tính năng mới. Quá trình giao tiếp rõ ràng giữa các nhà phát triển và nhà quản lý sản phẩm đóng vai trò vô cùng quan trọng trong việc xác định thứ tự ưu tiên cho các công việc tồn đọng và phát triển cơ sở mã nguồn.
Mẹo
Hãy ưu tiên việc trả nợ kỹ thuật trong khi lập kế hoạch cho sprint giống như các công việc tính năng thông thường. Đừng giấu chúng trong backlog hoặc một trình theo dõi issue riêng biệt.
Cẩn thận với việc kiểm thử sprint và task
Hãy chống lại việc thoả hiệp definition of done bằng cách thêm một task kiểm thử riêng biệt vào câu chuyện người dùng ban đầu. Việc này chắc chắn sẽ dẫn đến nợ kỹ thuật. Nếu quá trình kiểm thử không được thực hiện như một phần của câu chuyện gốc hoặc task sửa lỗi, thì câu chuyện gốc hay lỗi không thể được xem là done. Hãy duy trì một định nghĩa done chặt chẽ và đảm bảo nó bao gồm kiểm thử tự động. Thứ dễ làm mất sự nhanh nhẹn của nhóm nhất chính là kiểm thử thủ công và một cơ sở mã đầy lỗi!
Tự động hoá lỗi
Khi ai đó phát hiện ra một lỗi trong phần mềm, hãy dành thời gian thêm một kiểm thử tự động để chứng minh lỗi đó. Sau khi lỗi được sửa, hãy chạy lại kiểm thử để đảm bảo mã nguồn đã vượt qua. Đây là cốt lỗi của test-driven development – một phương pháp luận nhằm duy trì chất lượng trong phát triển Agile được đánh giá cao qua thời gian.
Bắt đầu từ đâu?
Hãy thay đổi triết lý của nhóm (và cả các bên liên quan) về cách quản lý nợ kỹ thuật. Đây là một việc không hề dễ dàng, vì các nhu cầu kinh doanh đôi khi đòi hỏi rút ngắn thời gian phát triển để có thể tiếp cận thị trường sớm hơn. Dưới đây là một số cách nhóm có thể áp dụng để khắc phục nợ kỹ thuật:
- – Hướng dẫn Product Owner về chi phí thật sự của nợ kỹ thuật. Hãy đảm bảo xác định chính xác điểm câu chuyện cho các câu chuyện trong tương lai yêu cầu giải quyết nợ kỹ thuật hiện có.
- – Mô-đun hoá kiến trúc và giữ lập trường vững chắc về nợ kỹ thuật trong các thành phần hoặc thư viện mới của ứng dụng. Khi nhóm và doanh nghiệp nhận thấy sự linh hoạt trong các thành phần mới này, một cách tự nhiên họ sẽ muốn mở rộng và áp dụng thực hành đó cho những phần khác của mã.
- – Viết các kiểm thử tự động! Không gì ngăn chặn lỗi tốt hơn kiểm thử tự động và tích hợp liên tục. Khi phát hiện một lỗi mới, hãy tạo một kiểm thử mới để tái tạo nó và sau đó mới khắc phục sự cố. Nếu lỗi đó xuất hiện trở lại, kiểm thử tự động sẽ bắt được nó trước khi khách hàng làm điều đó.
Hãy nhớ rằng nợ kỹ thuật là một thực tế trong tất cả các nhóm phần mềm. Không ai hoàn toàn tránh được nợ kỹ thuật, do đó điều quan trọng chính là giữ cho nó nằm trong tầm kiểm soát.
Theo Atlassian
Xem thêm bài viết kỳ trước: Chiến lược phân nhánh mã nguồn: Con đường dẫn đến sự vĩ đại