Technical Debt và Legacy System

1810

Bài viết được sự cho phép của tác giả Edward Thiên Hoàng

Technical debt – tạm dịch là “Khoản nợ kỹ thuật” được dùng nhiều trong Software Engineering. Theo Henrik Kniberg, những khoản nợ kỹ thuật là bất cứ thứ gì trong việc viết mã khiến bạn chậm lại về lâu dài. Ví dụ như là mã khó đọc, thiếu (hoặc không có) kiểm thử tự động, mã trùng lặp, hoặc sự liên kết lằng nhằng giữa lớp, mô-đun… (Think of technical debt as anything about your code that slows you down over the long term. Hard-to-read code, lack of test automation, duplication, tangled dependencies, etc. Henrik Kniberg).

  10 bí kíp để startup và FinTech startup thành công đột phá
  Cách trở thành một MarTech Developer trong năm 2024

Technical Debt và Legacy System

Cũng giống như những khoản nợ về tài chính: có vay mới có nợ, có nợ ắt sẽ sinh lãi. Technical debt sinh ra vì nhiều lý do: áp lực kinh doanh, thiếu kỹ năng trong phân tích thiết kế cũng như kỹ năng lập trình, không có các bộ mã kiểm thử dẫn đến việc trì hoãn (hoặc không thể) tái cấu trúc lại mã nguồn… Nếu không được trả, theo thời gian, nợ sẽ đẻ lãi, dẫn đến việc chậm tiến độ, những đoạn mã mới được thêm vào sẽ mất nhiều thời gian và chi phí hơn, mà đa phần trong số đó là chi phí cho việc gỡ rối (debugging) và kiểm thử hồi quy (regression testing).

Technical Debt và Legacy System

Nếu bạn đang làm việc với 1 legacy system (có rất nhiều định nghĩa về legacy code, nhưng mình thích nhất định nghĩa của Robert C. Martin: legacy code = code without test) nghĩa là bạn đang mang trên mình món nợ về kỹ thuật. Một đoạn mã được viết cách đây 10 năm cũng gọi là legacy code, một đoạn mã được viết ngày hôm qua cũng gọi là legacy code nếu chúng đều không được “chống lưng” bằng mã kiểm thử. Và nếu bạn vẫn tiếp tục tạo ra những đoạn mã “without test”, cũng tức là bạn đang tự đẻ thêm nợ cho chính system của mình. Điều đó cũng giống như việc bạn thêm vào những đoạn mã khó đọc, mã trùng lặp, hoặc sự kiên kết lằng nhằng giữa lớp, mô-đun… (Có phải mình cũng vừa lặp lại những gì đã nói ở trên?).

Vậy bạn sẽ trả nợ bằng cách nào? Hay thõa hiệp trước món nợ + lãi đang ngày một tăng khi mã mới được thêm vào?
Có hàng tá lý do để biện minh cho việc thõa hiệp, có thể kể ra như: đừng phá vỡ những đoạn mã đã chạy ổn định, hệ thống chúng ta quá phức tạp, do đó cần thêm thời gian để (tìm hiểu) thêm mới hoặc sữa chữa một đoạn mã nào đó (và đảm bảo không phá vỡ những đoạn mã hiện tại). Có một câu ví von khá hay về vấn đề này. “The code may not be pretty, but damnit, it works!” dùng để nói về Duct Tap Programmer – người viết mã chỉ để “chạy được”.
Nếu chọn cách trả nợ, những việc bạn sẽ làm là đừng (hoặc hạn chế) để lại nợ nần cho những thế hệ (mã) phía sau. Và điều đầu tiên đó là Hãy ngừng việc tạo ra những đoạn mã xấu (Stop writing crappy code).

Technical Debt và Legacy System

TDD đã khó, TDD cho legacy system còn khó gấp bội. Bài viết dưới đây của Mark Levison bàn về việc những vấn đề gặp phải khi áp dụng TDD trong Legacy System, qua đó trích dẫn 1 số phương pháp của Keith Ray – XP Coach để làm việc với legacy code nhằm giảm (paying down) những khoản technical debt, dựa trên nền tảng cốt lõi là viết mã sạch, tái cấu trúc mã nguồn và bỏ túi SOLID principles.

Xin trích dẫn nguyên văn bài viết bởi Mark Levison từ http://www.infoq.com/news/2009/11/legacy-code

Allan Baljeu was trying to TDD with a legacy C++ code base, he was running into trouble because:

He wondered if Big Design Up Front would help solve the problem. George DinwiddieAgile Coach, suggested that Alan’s design was trying to tell him something. You have to pay attention to the fundamentals of clean code. You can look at basic coupling and cohesion (i.e. SOLID).

Mike “Geepaw” HillAgile Coach, says that in his years of coaching agile teams, one of the following has been at the root of these problems:

  • team is not yet up to speed on refactoring, so your classes aren’t really
    minimal
  • team is not yet skilled at simplicity, so ditto
  • team is not yet doing aggressive & rapid microtesting (aka unit testing), so changes break tests too often
  • team doesn’t know how to handle cross-team or company-to-public dependencies, e.g. shipping api’s
  • team neither pairing nor open workspacing, dramatically slowing team-wide understanding.
  • team likely has no jiggle-less build
  • team could be using tools from the ’40s

Keith RayXP Coach, suggests that with legacy code (i.e. systems with high technical debt) the cost of repaying technical debt dominates the cost of implementing a story. He goes on to offer an approach:

Keith also wrote “Refactoring: Small Steps Guaranteed to Help You Clean Up Your Code” an article on refactoring C++ code in Better Software Magazine.

Previously on InfoQ: Dealing with Legacy CodeUncle Bob On The Applicability Of TDD andMaking TDD Stick: Problems and Solutions for Adopters

Bài viết gốc được đăng tải tại edwardthienhoang.wordpress.com
Có thể bạn quan tâm:
Xem thêm Việc làm System Engineer hấp dẫn trên TopDev