Technical debt (nợ kĩ thuật) là gì? Làm gì để giải quyết "món nợ" này?

  1. Công nghệ thông tin

download


Nợ kĩ thuật được hiểu nôm na là khối lượng công việc còn lại (cần được giải quyết) trong một dự án công nghệ.


Mình tạm dịch technical debt là nợ kĩ thuật vì mình chưa tìm được cụm từ tương đương trong Tiếng Việt. :thinking:


Nếu là nợ thì ta có thể cân đo/đong đếm nó không?

Khi nói về "nợ", bạn sẽ nghĩ ngay rằng đấy là một thứ có thể được "định lượng", ví dụ: nợ đồng nghiệp 500k, nợ người yêu 1 con gấu bông, nợ bạn thân 1 ly cafe. Tuy nhiên, đối với nợ kĩ thuật, đôi khi bạn khó có thể định lượng được rằng món nợ là "bao nhiêu" vì việc này còn phụ thuộc rất nhiều vào định nghĩa của "nợ kĩ thuật" trong suy nghĩ của từng lập trình viên thuộc dự án.

debt


Vậy nợ kĩ thuật được hình thành như thế nào? Nó tồn tại như thế nào trong một dự án công nghệ?

Xuyên suốt quá trình phát triển dự án, mọi quyết định kĩ thuật đều đi kèm "một món nợ kĩ thuật" nhất định.

Với các dự án dù là công nghệ hay bất kì lĩnh vực nào thì cũng cần phải có hạn chót (deadline) cho mọi công việc. Deadline sẽ giúp đảm bảo dự án phát triển ổn định, đúng thời hạn và còn đảm bảo sự phối hợp tốt nhất giữa những thành viên trong dự án. Tuy nhiên, đôi khi những deadline được đặt ra không hoàn toàn phù hợp với khối lượng thời gian cần bỏ ra để hoàn thành một công việc cụ thể. Do đó, những lập trình viên sẽ phải có những thỏa hiệp nhất định, với bản thân và cả với đội công nghệ. Họ sẽ phải chấp nhận dùng những "giải pháp tạm thời" để cho ra sản phẩm "chạy được và ổn định" trong thời gian ngắn nhất và sau đó sẽ dành thời gian để cải tiến, nâng cấp thành những giải pháp hiệu quả, có thể tồn tại lâu dài hơn. Đây là cách mà nợ kĩ thuật "hình thành và tích lũy".

youtuber-2838945_640

Nguồn: pixabay.com

Thông thường, cụm từ "kế hoạch trả nợ kĩ thuật" sẽ không xuất hiện trong bất kì một bản kế hoạch nào của dự án và những lập trình viên sẽ phải song song "trả nợ cũ" trong quá trình phát triển tính năng mới. Nếu bạn may mắn được tham gia trong một đội kĩ thuật (technical team) có người quản lí (technical leader) hiểu rõ và có thể cảm thông với bạn về "vấn đề nợ kĩ thuật", bạn sẽ có thời gian để "trả nợ" dưới sự bảo hộ của người quản lí ấy.

Vì sao mình lại dùm cụm từ "dưới sự bảo hộ" và vì sao lại cần "sự bảo hộ" ấy? Những thành viên trong dự án chịu trách nhiệm về mảng kinh doanh và vận hành nói chung (business và operation) thông thường sẽ không thích các lập trình viên dành thời gian "trả nợ kĩ thuật" vì, đối với họ, suy cho cùng việc làm ấy sẽ không tạo nên một tính năng mới hay thay đổi bất kì yếu tố giao diện nào. Họ sẽ đặt ra một câu hỏi: "Tại sao phải làm việc đấy khi mà nó không dẫn đến bất kì tính năng nào mới cho sản phẩm?". Nhưng thật ra những người làm business và operation cũng có lí do riêng của họ. :sigh:

Đối với trường hợp xấu nhất, nợ kĩ thuật sẽ tích lũy và lớn dần đến khi bạn "mất khả năng chi trả". Một ví dụ điển hình cho nợ kĩ thuật là khả năng mở rộng của sản phẩm (scalability of applications). Những quyết định ban đầu bạn lựa chọn để có thể cho ra một sản phẩm "chạy được" trong thời gian ngắn nhất chỉ phù hợp cho 1,000 người dùng (users) truy cập cùng 1 lúc. Tuy nhiên, để đáp ứng được 1,000,000 người dùng là một câu chuyện hoàn toàn khác. Những lập trình viên hiểu rõ rằng để đạt được điều đó, rất nhiều thời gian và công sức cần được bỏ ra, ví dụ như làm sao để giảm truy cập database, tạo những logic caching ra sao, ... Nhưng thời gian không cho phép họ thực hiện tất cả những công việc ấy và thế là họ mang trên vai một món nợ kĩ thuật khá lớn khi sản phẩm lớn dần.

you-cant-pay-your-debt-back-if-youre-dead

*Đùa thôi*

Nói thêm một chút cụ thể về lập trình (mình sẽ cố gắng viết dễ hiểu để những bạn không làm công nghệ cũng có thể đọc và nắm được ý chính :P). Bản thân mình là một lập trình viên front-end và công nghệ mà mình sử dụng là React cho lập trình web.

React đi theo một khái niệm gọi là component-based
(tạm hiểu đây là một nguyên tắc chỉ ra rằng việc tạo nên thành phần lớn sẽ đi từ việc xây dựng các thành phần nhỏ). Tuân theo nguyên tắc này, việc xác định kiến trúc hệ thống gồm những components là điều khá quan trọng. Việc bạn xác định kiến trúc ban đầu của những components, từ component bé đến component lớn, sẽ ảnh hưởng tới khả năng tái sự dụng (reusability), khả năng bảo trì (maintainability) và khả năng thay đổi linh động theo design (flexibility). Tuy nhiên, nếu deadline quá dồn dập và ngắn hạn thì những lập trình viên React phải "luôn bước trên ranh giới đúng/sai của việc thiết kế hệ thống" và từ đó dẫn đến những thiết kế sai, sau này phải tốn thời gian và công sức thiết kế lại (và vô tình bạn đã tạo nên một "món nợ kĩ thuật"!). Tuy nhiên, nói đi cũng phải nói lại, một lập trinh viên React dày dặn kinh nghiệm thì hoàn toàn có khả năng tạo ra thiết kế đúng trong thời gian ngắn. Ở đây mình chỉ muốn làm rõ những khái niệm về nợ kĩ thuật thôi :hearteyes:


Câu "bước trên ranh giới đúng/sai của việc thiết kế hệ thống" trên là mình tạm dịch từ câu "constantly walk on the thin line of architectural correctness" lấy từ bài blog
7 architectural attributes of a reliable React component
- một bài blog rất hay viết về cách thiết kế một React component (bạn nào làm về React thì nên đọc nhé).


work-life-balance

Nguồn: https://dmitripavlutin.com


Giải quyết "món nợ" này như thế nào? Làm sao để hạn chế tạo ra nợ?

Đối với bất kì món nợ nào, giải quyết khi nợ chưa trở nên quá lớn (và dẫn đến việc mất khả năng chi trả) luôn luôn là cách tốt nhất. Mình sẽ tạm gọi quá trình "trả nợ" là "dọn code". Trong quá trình làm việc, bạn sẽ phải luôn để ý "dọn code" bất cứ khi nào "có thể" (có thể ở đây có nghĩa là bạn có đủ thời gian và kiến thức).

Dọn code thông thường sẽ bao gồm những hoạt động sau:

  • Cải tiến code (refractor code): việc để "code xấu" tồn tại trong mã nguồn ứng dụng là không hề tốt. "Code xấu" có thể bị nhân bản bất kì lúc nào (duplicate). Lập trình viên mới xem xét code có sẵn để làm nền móng phát triển một tính năng mới sẽ tìm thấy code xấu và tái sử dụng nó, và thế là nợ kĩ thuật cho phần "code xấu" ấy nhân đôi!
  • Viết lại code (rewrite code): nếu cải tiến code mà không giúp cải thiện được tình hình thì đó là lúc bạn phải xóa toàn bộ code cũ và thay bằng code mới. Tuy nhiên, viết lại code không phải luôn mang lại lợi ích nên bạn và mọi người trong team phải luôn cân nhắc/bàn bạc kĩ lưỡng trước khi đưa ra quyết định. Một trong những thời điểm để viết lại code phổ biến là viết lại khi bạn xây dựng một tính năng mới vì khi ấy bạn sẽ có đủ thời gian để đưa ra những quyết định chính xác hơn.
  • Sử dụng giải phát mới tốt hơn, lâu bền hơn và tuân theo những quy tắc lập trình tốt hơn: code tốt thì sẽ có vòng đời lâu, có thể là vài năm nhưng "code xấu" thì phải được dành thời gian ra để nâng cấp. Lập trình viên luôn có thể ước lượng được "vòng đời" của một đoạn code mà họ viết ra. Họ là những người hiểu rõ nhất "đoạn code" ấy có thể tồn tại bao lâu và đến khi nào thì phải viết code mới. Tuy nhiên, những đoạn code tốt và tối ưu hơn thì chắc chắn cần nhiều thời gian để tạo ra. Do đó, nếu team thường xuyên phải chạy đua deadline thì bạn và đồng nghiệp nên định kỳ dành ra những khoảng thời gian để nâng cấp hệ thống hiện tại.
  • Xóa những đoạn code không dùng tới


Bạn có thể dễ dàng nhận ra rằng nợ kĩ thuật hầu như là điều không thể tránh khỏi trong mọi dự án công nghệ. Tuy nhiên, nếu những thành viên trong dự án có tư duy nhất định về việc giải quyết và hạn chế nợ kĩ thuật thì việc "mất khả năng chi trả" là hoàn toàn có thể tránh khỏi. Đội kĩ thuật cần có những quy tắc được đề ra sẵn (coding conventions) để hạn chế tối đa những món nợ không mong muốn. Bên cạnh đó, bạn và đồng nghiệp có thể thực hiện những kế hoạch sau:

  • Dành thời gian nghiên cứu những phương pháp và quy tắc lập trình tốt (best coding practices and conventions) để viết nên những tính năng chỉ để hỗ trợ cho việc phát triển sản phẩm (engineering-driven features), không phải là tính năng cho người dùng (end-user features).
  • Duyệt code (code reviews) để góp ý và học tập lẫn nhau


---------------------------


Và đấy là tất cả những gì mình cảm nhận và đồng thời tham khảo từ một số nguồn khác nhau về nợ kĩ thuật - technical debt. Hãy bình luận bên dưới cho mình biết bạn đồng tình/không đồng tình với những ý nào trong bài viết trên và, nếu có thể, hãy chia sẻ với mình cách bạn và đồng nghiệp sử dụng để giải quyết và hạn chế nợ kĩ thuật nhé :)


Nguồn tham khảo thêm:

  • Introduction to the Technical Debt Concept
  • There are 3 main types of technical debt. Here’s how to manage them.
  • Understanding technical debt
  • Refactoring techniques
Từ khóa: 

engineering

,

technical practices

,

vtcc_intern_6

,

công nghệ thông tin

Bài viết giúp mình nhận ra rất nhiều "sạn" trong phong thái "code" của bản thân.

Cảm ơn bạn vì bài viết hữu ích.

Trả lời

Bài viết giúp mình nhận ra rất nhiều "sạn" trong phong thái "code" của bản thân.

Cảm ơn bạn vì bài viết hữu ích.