Technical Debt, Solve & Avoid it

@dantech
6 min readMay 29, 2022

Technical Debt

Nợ là 1 khái niệm không quá xa lạ với mỗi người trong xã hội hiện đại. Một bạn sinh viên mới đi học sẽ vay nợ quỹ khuyến học hoặc ngân hàng chính sách để trả học phí, ra trường đi làm chưa có vốn có thể vay các công ty tài chính để mua xe máy, điện thoại, .. Đi làm được vài năm gom góp trả hết các khoản nợ cũ thì bắt đầu cho mục tiêu tài chính lớn hơn như làm đám cưới, vay mua nhà, vay kinh doanh, vay đầu tư bất động sản… Có thể khẳng định 1 câu chắc nịch rằng chẳng có ai làm giàu mà không đi vay nợ.

Lập trình viên (Dev) ngoài việc phải trả các món nợ tài chính như nói trên ra họ còn 1 chủ nợ vô hình luôn theo sau họ mỗi lệnh enter… Vị chủ nợ này không đe dọa hay uy hiếp để đòi nợ ngay mà sẽ từ từ hành hạ đến suy kiệt tinh thần & sức lực Dev nếu họ không có kế hoạch trả nợ đúng đắn và hợp lý. Món nợ đó không gì khác mang tên Nợ Kỹ Thuật (Technical Debt). Và 1 điều chắc chắn rằng 100% Dev đều đã, đang và sẽ luôn mắc Nợ Kỹ Thuật!

Nguồn gốc cái tên Technical Debt

Trong lập trình, phát triển dự án sẽ có những lúc Dev cần chạy deadline để đuổi kịp các release tính năng hỗ trợ sự kiện, KPI của sản phẩm hoặc cần ra prototype sản phẩm nhanh nhất có thể để nhận được đầu tư, mang hợp đồng về cho team … Những yêu cầu gấp rút về thời gian và nhân sự này làm cho quá trình phát triển phần mềm không được trau chuốt kỹ lưỡng, các giải pháp nhanh gọn kiểu copy paste được áp dụng để giải quyết được vấn đề ngay.

Sự phát triển của Technical Debt không phải là ngày 1 ngày 2 hay do 1 2 commits mà thành, nó là cả 1 quá trình chúng ta (Developers) mải miết chạy theo deadline, chạy theo KPI sản phẩm mà để lại. Ban đầu có thể chỉ là những lỗi nhỏ như viết code business logic vào data class , dùng tùy tiện nhiều static variable . Rồi khoản nợ phình ra bằng việc sử dụng chồng chéo các logic giữa các module features mà không có sự thống nhất cụ thể, sự chồng chéo này ban đầu với mục đích rất chính đáng là reuse code (tái sử dụng) nhưng lại sinh ra 1 khoản nợ khổng lồ ở tương lai … đó là không thể dễ dàng thực hiện việc modularize nếu thiếu sự quản lý & thống nhất chặt chẽ của các Dev.

Lâu dần như vậy khoản Technical Debt sẽ tăng lên và tích lũy. Khoản nợ này này đến 1 lúc nào đó Dev phải tự tay trả bằng cách sửa lấy hoặc là phá hủy hết để làm lại 1 codebase mới hoàn toàn, sạch sẽ hơn.

(Và đương nhiên, 1 codebase mới hoàn toàn 1 ngày nào đó vẫn sẽ mắc Technical Debt thôi, hehe)

Hậu quả

Việc tạo ra Technical Debt cho codebase cũng giống như bạn ăn 1 phần Fast Food hay uống 1 ly nước ngọt có Gas vậy. Miếng đầu tiên có vẻ ngon và tiện lợi, bạn có ngay năng lượng để làm việc thật nhiều và nhiều hơn nữa. Vài năm tiếp theo đó, vẫn chế độ ăn với Fast Food và nước ngọt có Gas này khiến cơ thể (codebase) của bạn trở nên không còn đẹp như ngày đầu.

Codebase sẽ bắt đầu lớn lên 1 cách không kiểm soát, coding convention tệ dần và code quality trên Codacy rơi tự do … Việc phát triển feature được add thêm vào không còn nhanh như ngày đầu nữa vì các edge cases cho testing quá nhiều ở mức không kiếm soát, không chắc chắn. Hãy tưởng tượng với 1 tính năng đơn giản như thêm / xóa 1 Button thôi cũng cần resource làm đến 1–2 tuần để chạy hết các edge case … Lúc này Dev cũng như QA sẽ cực kỳ stress với 1 khối lượng công việc có vẻ là nhỏ nhưng lại tiềm tàng những ảnh hưởng lớn.

Nếu coi Nợ Kỹ Thuật như 1 khoản Nợ Tài Chính bình thường. Thì hậu quả của nó là bắt chính bạn phải cày cuốc hàng tháng, hằng năm trời mà thành quả chỉ đủ để trả lãi. Khoản nợ vẫn ở đó và tiềm ẩn nguy cơ vỡ nợ bất kỳ lúc nào nếu lãi suất vô tình tăng cao hơn khả năng chi trả của chúng ta.

Khả năng phát triển của dự án chậm dần → Khả năng phát triển của nhân sự thuộc dự án đó cũng chậm theo. Điều này như 1 vòng lặp lẩn quẩn và không tìm được điểm gỡ cụ thể nào.

Solve & Avoid

Mình chưa có cách nào, và chưa tìm ra Software Architecture nào dùng để khắc phục triệt để vấn đề Technical Debt cả! Tương lai mình nghĩ cũng sẽ chưa có ai tìm ra giải pháp hoàn hảo cho việc này.

Tuy nhiên, nợ thì có nợ tốt & nợ xấu. Mình tin rằng Technical Debt cũng có Good Technical DebtBad Technical Debt. Nếu như Bad Technical Debt mang đến hậu quả tệ cho dự án, thì Good Technical Debt sẽ push tinh thần nhân sự dự án, khiến họ không ngừng phát triển và cống hiến hơn cho sản phẩm.

Hãy làm những điều sau đây để tạo ra Nợ Kỹ Thuật tốt cho dự án của mình. Đến 1 thời điểm nào đó Nợ Kỹ Thuật tốt nhiều hơn sẽ kéo dự án tốt hơn, vượt qua được trở ngại của Technical Debt.

Modularization

Vấn đề cơ bản của Technical Debt là codebase quá lớn để refactor và cải tiến mà không ảnh hưởng đến toàn bộ sản phẩm. Hãy chấp nhận bỏ ra nguồn lực để làm việc này càng sớm càng tốt.

Phân tích, lựa chọn Architecture để dùng chung trong dự án.

Code chung 1 mô hình sẽ dễ đọc, dễ hiểu hơn. Tính mở rộng cũng cao hơn so với việc trộn lẫn nhiều Architecture trong 1 dự án.

Coding Convention, Code Quality Tool trong quá trình phát triển

Điều này nghe như hiển nhiên nhưng mình vẫn sẽ đặt nó ở đây, vì nó quan trọng. Một Coding Convention chuẩn sẽ khiến codebase dễ đọc hơn, kết hợp với Code Quality Tool để đánh giá sự thay đổi của codebase qua mỗi bản release để biết được các Dev đã làm việc tiến bộ và hiệu quả thế nào.

Unit Test Coverage

Unit Test là 1 Good Technical Debt mà mình đánh giá rất cao. Unit Test Coverage càng cao thì việc release sẽ càng dễ dàng hơn. Độ trust của source code cao hơn, hạn chế được 1 phần sức lực manual test mà QC/QA phải bỏ công để verify các edge case.

Viết document, wiki & tech sharing.

Các hoạt động này có thể bị cho là tốn thời gian và không mang lại hiệu quả cao cho cộng việc. Đại loại là sẽ không có kết quả rõ ràng như ngay sau khi làm 1 feature và release đến user. Tuy nhiên nó là hết sức cần thiết để Dev rèn luyện kỹ năng phân tích, phản biện để tìm giải pháp. Một dự án phát triển tốt là dự án có những người Dev được phát triển tốt.

Luôn tỉnh táo trong lối suy nghĩ Result Oriented. Cần có sự cân bằng giữa Result Oriented và Technical Architecture. Có thể coi Result Oriented là kim chỉ nam để dẫn đường phát triển sản phẩm, nhưng Technical Architecture mới là con thuyền dẫn chúng ta đến đó. Một kim chỉ nam có chuẩn đến đâu mà con thuyền xập xệ thì cũng chẳng vượt qua bão biển để mà đến với vùng đất hứa.

Làm việc hướng kết quả (Result Oriented) là 1 khái niệm khá là ngầu mà hầu hết các Lead, các Manager sẽ sử dụng để quản lý kết quả công việc hay thậm chí đánh giá tiến bộ của nhân viên. Cách đánh giá này vẫn có điểm mạnh và hợp lý của nó, tuy nhiên về phương diện Technical mình thấy chưa bao hàm hết, vẫn để dở những thiếu sót.

Một lối mòn Result Oriented không có break-down Result, không có phản biện có thể dẫn đến bias trong vấn đề đánh giá rủi ro sản phẩm cũng như hiệu quả của nhân sự tham gia. Tuy không trực tiếp tạo ra Technical Debt, nhưng sẽ là chất xúc tác cho dự án ngày càng lún sâu vào Bad Technical Debt.

Chốt lại Bad Technical Debt là điều nên tránh, hạn chế. Sẽ không có dự án nào hoàn hảo không có Technical Debt. Thế nhưng việc control Good Technical Debt vs Bad Technical Debt sẽ là giải pháp để kéo dự án đi lên & luôn ở thế cân bằng ổn định.

Happy Coding!

--

--