Tái cấu trúc mã nguồn: Khi nào (và khi nào thì không) nên làm.

code-refactoring

Code refactoring – Tái cấu trúc mã nguồn là một quá trình được sử dụng trong phương pháp phát triển phần mềm DevOps bao gồm việc chỉnh sửa và làm sạch mã nguồn đã viết trước đó mà không thay đổi chức năng của mã.

Mục đích cơ bản của việc tái cấu trúc mã nguồn là làm cho mã nguồn hiệu quả hơn và có thể bảo trì được. Đây là chìa khóa trong việc giảm chi phí kỹ thuật vì việc xóa mã ngay bây giờ tốt hơn nhiều so với việc fix các lỗi tốn kém sau này. Tái cấu trúc mã, cải thiện khả năng đọc, làm cho quá trình QA và fix bug diễn ra suôn sẻ hơn nhiều. Và mặc dù nó không loại bỏ được bug, nhưng nó chắc chắn có thể giúp ngăn chặn chúng trong tương lai.

Và đó là lý do tại sao cần phải cấu trúc lại mã thường xuyên.

Tái cấu trúc mã rất quan trọng nếu bạn muốn tránh bị mã “thối” đáng sợ. Lỗi mã là kết quả từ mã trùng lặp, vô số bản vá lỗi, phân loại sai và các sai lệch lập trình khác. Việc có một cánh cửa quay vòng của các nhà phát triển khác nhau viết theo phong cách riêng của họ cũng có thể góp phần làm “thối” mã, vì không có sự gắn kết với tập lệnh mã hóa tổng thể.

Khi nào bạn nên xem xét việc tái cấu trúc phần mềm?

Thời điểm tốt nhất để xem xét tái cấu trúc là trước khi thêm bất kỳ bản cập nhật hoặc tính năng mới nào vào mã hiện có. Quay lại và làm sạch mã hiện tại trước khi thêm vào chương trình mới sẽ không chỉ cải thiện chất lượng của sản phẩm mà còn giúp các nhà phát triển trong tương lai dễ dàng xây dựng trên mã gốc hơn.

Một thời điểm khác để nghĩ đến việc tái cấu trúc là ngay sau khi bạn đưa một sản phẩm ra thị trường. Vâng, điều đó nghe có vẻ vô lý?. Cuối cùng, bạn đã tung ra một sản phẩm mà bạn đã làm việc trong nhiều tháng, thậm chí có thể là nhiều năm và bây giờ bạn phải quay lại từ đầu? Đây thực sự là thời điểm hoàn hảo để thực hiện một chút công việc dọn dẹp các mã xấu, vì rất có thể các nhà phát triển có nhiều khả năng hơn để làm việc tái cấu trúc trước khi chuyển sang công việc tiếp theo.

Các kỹ thuật thực hiện tái cấu trúc mã nguồn

Như đã đề cập trước đây, cách tốt nhất để cấu trúc lại là thực hiện theo từng bước nhỏ. Điều quan trọng là phải thực hiện trước khi thêm bất kỳ chức năng hoặc tính năng mới nào. Việc tái cấu trúc mã sẽ không thay đổi bất kỳ điều gì về cách sản phẩm hoạt động.

Tuy nhiên, có nhiều cách tiếp cận và kỹ thuật khác nhau để tái cấu trúc mã. Dưới đây là các cách phổ biến nhất:

Red-Green-Refactor

Một trong những kỹ thuật được sử dụng rộng rãi nhất để tái cấu trúc mã là quy trình Red-Green-Refactor được sử dụng trong phát triển theo phướng pháp Agile. Áp dụng phương pháp Red-Green-Refactor, các nhà phát triển chia nhỏ việc tái cấu trúc thành ba bước riêng biệt:

  1. Hãy dừng lại và xem xét những gì cần được phát triển. [RED]
  2. Nhận sự phát triển để vượt qua thử nghiệm cơ bản. [GREEN]
  3. Thực hiện các cải tiến. [RÈACTOR]

red-green-refactor

Tái cấu trúc bằng Abstraction

Tái cấu trúc theo  hướng trừu tượng hoá là một phương pháp được sử dụng chủ yếu khi có một lượng lớn cấu trúc lại được thực hiện. Tính trừu tượng liên quan đến kế thừa lớp, hệ thống phân cấp và trích xuất. Mục tiêu của sự trừu tượng hóa là giảm bớt sự trùng lặp không cần thiết trong mã nguồn.

Một ví dụ về sự trừu tượng là phương pháp Pull-Up/Push-Down. Đây là hai hình thức tái cấu trúc đối lập liên quan đến các lớp. Phương thức Pull-Up kéo các phần mã vào một lớp cha để loại bỏ sự trùng lặp mã. Push-Down lấy nó từ một lớp cha và chuyển nó xuống các lớp con.

Composing Method

Việc soạn thảo liên quan đến việc hợp lý hóa mã để giảm sự trùng lặp. Điều này được thực hiện thông qua các quy trình khác nhau, bao gồm cả phương pháp chiết xuất và nội tuyến.

Khai thác liên quan đến việc chia nhỏ mã thành các phần nhỏ hơn để tìm và “trích xuất” sự phân mảnh. Sau đó, mã bị phân mảnh được chuyển sang một phương thức riêng biệt và được thay thế bằng một lệnh gọi đến phương thức mới này. Ngoài phương thức, trích xuất có thể liên quan đến các biến lớp, giao diện và cục bộ

Tái cấu trúc nội tuyến là một cách để giảm số lượng các phương thức không cần thiết trong khi đơn giản hóa mã. Bằng cách tìm tất cả các lệnh gọi đến phương thức và thay thế chúng bằng nội dung của phương thức, phương thức sau đó có thể bị xóa.

Simplifying Methods

Mã càng cũ thì càng bị cắt xén và phức tạp hơn. Do đó, nó có ý nghĩa khi đi vào và đơn giản hóa rất nhiều logic. Điều này có thể được thực hiện theo nhiều cách khác nhau, bao gồm hợp nhất các đoạn và biểu thức có điều kiện và thay thế có điều kiện bằng tính đa hình.

Việc đơn giản hóa các cuộc gọi phương thức liên quan đến việc điều chỉnh sự tương tác giữa các lớp. Thêm, xóa và giới thiệu các tham số mới cùng với việc thay thế các tham số bằng các phương thức rõ ràng và các cuộc gọi phương thức là tất cả các khía cạnh của sự đơn giản hóa.

Tính năng di chuyển giữa các đối tượng

Phương pháp này liên quan đến việc tạo các lớp mới và di chuyển chức năng giữa các lớp cũ và mới. Khi một lớp có quá nhiều thứ đang diễn ra, đã đến lúc chuyển một số mã đó sang lớp khác. Hoặc, mặt khác, nếu một lớp không thực sự hoạt động nhiều, bạn có thể di chuyển các tính năng của lớp đó sang một lớp khác và xóa hoàn toàn.

Preparatory Refactoring

Trong cuốn sách Refactoring: Improving the Design of Existing Code, tác giả Martin Fowler nói về quá trình chuẩn bị cấu trúc lại. Điều này được thực hiện khi một nhà phát triển nhận thấy cần phải cấu trúc lại trong khi thêm một tính năng mới, vì vậy, đó thực sự là một phần của bản cập nhật phần mềm chứ không phải một quy trình tái cấu trúc riêng biệt. Bằng cách nhận thấy rằng mã cần được cập nhật tại thời điểm đó, nhà phát triển đang thực hiện phần việc của mình để giảm nợ kỹ thuật trong tương lai.

Nhà phát triển phần mềm Jessica Kerr cung cấp một lời giải thích minh họa tuyệt vời cho việc tái cấu trúc chuẩn bị:

“Nó giống như tôi muốn đi 100 dặm về phía đông nhưng thay vì chỉ traipsing qua rừng, tôi sẽ lái xe 20 dặm về phía bắc đến đường cao tốc và sau đó tôi sẽ đi 100 dặm về phía đông ở ba lần so với tốc độ tôi có thể có nếu tôi chỉ đi thẳng đến đó. Khi mọi người thúc đẩy bạn chỉ cần đi thẳng đến đó, đôi khi bạn cần phải nói, “Chờ đã, tôi cần kiểm tra bản đồ và tìm tuyến đường nhanh nhất.” Việc tái cấu trúc chuẩn bị thực hiện điều đó cho tôi. ”

Bạn có thể tìm thấy hàng tá phương pháp khác để tái cấu trúc mã tại trang web của Martin Fowler và tại Refactoring.com. Giải pháp phù hợp nhất với bạn sẽ phụ thuộc vào quy mô và phạm vi giải pháp của bạn, khung thời gian bạn phải thực hiện tái cấu trúc và số lượng người có sẵn để hỗ trợ trong quá trình tổng thể.

Khi nào bạn không cần cấu trúc lại

Trước đó, chúng tôi đã nhấn mạnh rằng việc tái cấu trúc sẽ không bao giờ ảnh hưởng đến hiệu suất của một ứng dụng và nó chỉ được coi là một nỗ lực dọn dẹp các mã bẩn. Tuy nhiên, có những lúc, một ứng dụng cần được cải tiến hoàn toàn ngay từ đầu. Trong những trường hợp này, việc tái cấu trúc là không cần thiết, vì sẽ hiệu quả hơn nhiều nếu chỉ bắt đầu từ đầu.

Một tình huống khác mà sẽ là khôn ngoan nếu bạn bỏ qua việc tái cấu trúc là nếu bạn đang cố gắng đưa một sản phẩm ra thị trường trong một khung thời gian đã định. Tái cấu trúc có thể giống như đi xuống lỗ thỏ:

Một khi bạn bắt đầu, nó có thể trở nên khá tốn thời gian. Việc thêm bất kỳ mã hoặc thử nghiệm bổ sung nào vào một khung thời gian vốn đã chật hẹp sẽ dẫn đến sự thất vọng và chi phí bổ sung cho khách hàng của bạn.

Các phương pháp hay nhất để tái cấu trúc mã

Có một số phương pháp hay nhất và khuyến nghị liên quan đến việc tái cấu trúc mã. Một trong những cách tiếp cận thông minh nhất là áp dụng phương pháp Agile và thực hiện từng bước một, sau đó là kiểm thử. Đây là lý do tại sao rất nhiều nhà phát triển sử dụng phương pháp Agile là những người ủng hộ lớn cho việc tái cấu trúc mã.

Chia nhỏ quy trình tái cấu trúc thành các phần có thể quản lý và thực hiện kiểm thử kịp thời trước khi chuyển sang các bản cập nhật khác luôn dẫn đến ứng dụng chất lượng cao hơn và trải nghiệm phát triển tổng thể tốt hơn.

Dưới đây là một số phương pháp hay khác:

  1. Refactor đầu tiên trước khi thêm bất kỳ tính năng mới nào

Bạn nên thực hiện tái cấu trúc bất cứ khi nào bạn được yêu cầu thêm các tính năng hoặc bản cập nhật mới vào giải pháp hiện có. Có, nó sẽ mất lâu hơn để hoàn thành dự án, nhưng nó cũng sẽ giảm số nợ kỹ thuật mà bạn hoặc chủ sở hữu sản phẩm sẽ phải giải quyết trong tương lai.

  1. Lập kế hoạch dự án tái cấu trúc và tiến trình của bạn một cách cẩn thận

Một trong những phần khó nhất của quá trình tái cấu trúc mã là tìm thời gian để thực hiện đúng cách.

Suy nghĩ về mục tiêu tổng thể của bạn. Bạn chỉ muốn thay đổi tên biến để cải thiện khả năng đọc? Hay bạn muốn dọn dẹp toàn bộ? Cách tốt nhất để bạn tối ưu hóa mã trong một khung thời gian hợp lý là gì?

Kết quả quan trọng nhất của việc tái cấu trúc không chỉ là mã sạch hơn mà còn là nó thực sự hoạt động. Và hãy nhớ rằng sẽ mất nhiều thời gian hơn bạn nghĩ, vì vậy hãy lập kế hoạch phù hợp và dành cho mình một chút thời gian.

  1. Kiểm thử thường xuyên

Điều cuối cùng bạn muốn làm khi tái cấu trúc là làm rối tung thứ gì đó trong quy trình và tạo ra lỗi hoặc sự cố ảnh hưởng đến chức năng của sản phẩm. Đây là lý do tại sao việc kiểm thử trong suốt quá trình tái cấu trúc là bắt buộc. Đảm bảo rằng bạn có các bài kiểm tra thích hợp trước khi bắt đầu bất kỳ dự án tái cấu trúc nào.

  1. Mời nhóm QA của bạn tham gia

Luôn luôn là một ý kiến ​​hay để nhờ nhóm QA và thử nghiệm của bạn tham gia vào quá trình tái cấu trúc. Bất cứ khi nào bạn thực hiện các thay đổi đối với mã hiện có, ngay cả khi là một dự án dọn dẹp, nó có thể ảnh hưởng đến kết quả thử nghiệm.

Những thay đổi trong phân loại được thực hiện trong quá trình tái cấu trúc có thể khiến các bài kiểm tra cũ không thành công. Ngoài ra, các thử nghiệm mới có thể phải được tạo cho các hệ thống phần mềm cũ đã lỗi thời. Cả kiểm tra chuyên sâu và kiểm tra hồi quy phải được thực hiện như một phần của nỗ lực tái cấu trúc. Điều này sẽ đảm bảo rằng chức năng của giải pháp không bị ảnh hưởng theo bất kỳ cách nào.

Các nhóm phát triển sử dụng phương pháp Agile cho cả lập trình và thử nghiệm rất có thể đã ở trên cùng một trang liên quan đến tái cấu trúc.

  1. Tập trung vào sự tiến bộ, không phải sự hoàn hảo

Tất cả mã cuối cùng trở thành mã kế thừa đáng sợ. Chấp nhận sự thật rằng bạn sẽ không bao giờ hài lòng 100%. Mã bạn hiện đang cấu trúc lại sẽ trở nên cũ và lỗi thời trong tương lai gần và sẽ yêu cầu cấu trúc lại toàn bộ.

Bạn phải bắt đầu nghĩ đến việc tái cấu trúc như một dự án bảo trì đang diễn ra. Giống như việc bạn phải dọn dẹp và sắp xếp nhà cửa trong suốt cả tuần, bạn sẽ cần phải dọn dẹp và sắp xếp mã của mình vào nhiều dịp khác nhau.

  1. Thử tự động hóa tái cấu trúc mã nguồn lại

Như với hầu hết các quy trình, càng có thể tự động hóa thì việc tái cấu trúc càng trở nên dễ dàng và nhanh chóng.

Tự động hóa một số hoặc tất cả các quy trình tái cấu trúc đang ngày càng trở nên phổ biến hơn với các nhà phát triển. Có nhiều phím tắt và công cụ giúp việc tái cấu trúc bớt đau đớn hơn. Bạn có thể học được rất nhiều thứ bằng cách đọc sách của Martin Fowler.

Bài viết này chia sẻ một số nguyên tắc và lời khuyên dành cho bạn. Hãy tái cấu trúc mã càng sớm càng tốt.

Nguồn: https://www.altexsoft.com/blog/engineering/code-refactoring-best-practices-when-and-when-not-to-do-it/