Bảo trì mã: giữ một mô hình xấu khi mở rộng mã mới để thống nhất, hay không?


45

Tôi phải mở rộng một mô-đun hiện có của một dự án. Tôi không thích cách nó đã được thực hiện (rất nhiều mô hình chống liên quan, như mã sao chép / dán). Tôi không muốn thực hiện một bộ tái cấu trúc hoàn chỉnh vì nhiều lý do.

Tôi có nên:

  • tạo các phương thức mới bằng cách sử dụng quy ước hiện có, ngay cả khi tôi cảm thấy sai, để tránh nhầm lẫn cho người bảo trì tiếp theo và phù hợp với cơ sở mã?

hoặc là

  • Hãy thử sử dụng những gì tôi cảm thấy tốt hơn ngay cả khi nó đang giới thiệu một mẫu khác trong mã?

Chỉnh sửa trước khi trả lời đầu tiên:

Mã hiện tại không phải là một mớ hỗn độn. Nó rất dễ dàng để làm theo và hiểu. NHƯNG nó đang giới thiệu rất nhiều mã soạn sẵn có thể tránh được với thiết kế tốt (kết quả là mã có thể trở nên khó theo dõi hơn). Trong trường hợp hiện tại của tôi, đó là một mô-đun DAO JDBC (mẫu lò xo) cũ, nhưng tôi đã gặp phải tình huống khó xử này và tôi đang tìm kiếm phản hồi khác.

Tôi không muốn tái cấu trúc vì tôi không có thời gian. Và thậm chí với thời gian, thật khó để biện minh rằng toàn bộ mô-đun hoạt động hoàn hảo cần tái cấu trúc. Chi phí tái cấu trúc sẽ nặng hơn lợi ích của nó. Hãy nhớ rằng: mã không lộn xộn hoặc quá phức tạp. Tôi không thể trích xuất một vài phương thức ở đó và giới thiệu một lớp trừu tượng ở đây. Đó là một lỗ hổng trong thiết kế (kết quả của sự cực kỳ 'Giữ cho nó ngu ngốc' tôi nghĩ)

Vì vậy, câu hỏi cũng có thể được hỏi như vậy:
Bạn, với tư cách là nhà phát triển, bạn có muốn duy trì mã nhàm chán ngu ngốc dễ dàng HOẶC để có một số người trợ giúp sẽ thực hiện mã nhàm chán ngu ngốc ở vị trí của bạn không?

Mặt trái của khả năng cuối cùng là bạn sẽ phải học một số thứ và có thể bạn sẽ phải duy trì mã nhàm chán ngu ngốc dễ dàng cho đến khi hoàn tất quá trình tái cấu trúc)


Câu hỏi rất thú vị!
Philippe

1
Duy trì dễ dàng nhàm chán mã ngu ngốc - là theo định nghĩa dễ dàng. Tôi muốn có một cuộc sống dễ dàng và rời đi sớm mỗi ngày.
quick_now

Vâng, nhưng tôi quá lười biếng để làm mã ngu ngốc nhàm chán :) Tôi sẽ thích làm việc chăm chỉ trong 2 hoặc 3 ngày để xây dựng một cái gì đó sẽ làm phần này cho tôi!
Guillaume

1
Khi nào ngu ngốc hay nhàm chán bị nhầm lẫn cho dễ?
Erik Reppen

Xin chào Erik, đôi khi một mã có thể được nhân tố hóa lại đơn giản hơn để đọc: đó là hàng tá thời gian giống nhau và mã đơn giản. Bạn có thể đọc nó liên tiếp mà không cần suy nghĩ về nó và bạn có thể gỡ lỗi theo cách tuyến tính. Không có sự phức tạp tiềm ẩn.
Guillaume

Câu trả lời:


42

Tái cấu trúc được thực hiện tốt nhất trong các bước nhỏ và tốt nhất là chỉ khi bạn có các bài kiểm tra đơn vị để bao gồm mã. (Vì vậy, nếu bạn chưa có bài kiểm tra nào, hãy cố gắng viết chúng trước, và cho đến lúc đó, hãy tuân thủ các phép tái cấu trúc tự động đơn giản nhất, dễ đánh lừa nhất, tốt nhất. Điều này rất hữu ích trong việc này là Làm việc hiệu quả với Bộ luật kế thừa của Michael Feathers.)

Nói chung, nhằm mục đích cải thiện mã một chút bất cứ khi nào bạn chạm vào nó. Thực hiện theo Quy tắc Hướng đạo nam ( do Robert C. Martin đặt ra ) bằng cách để mã sạch hơn bạn tìm thấy. Khi bạn thêm mã mới, hãy cố gắng tách nó khỏi mã xấu hiện có. Ví dụ, đừng chôn nó vào giữa một phương thức dài, thay vào đó hãy thêm một cuộc gọi đến một phương thức riêng biệt và đặt mã mới của bạn vào đó. Bằng cách này, bạn phát triển dần dần các đảo mã sạch (er) lớn hơn trong cơ sở mã hiện có.

Cập nhật

Chi phí tái cấu trúc sẽ nặng hơn lợi ích của nó. [...] Bạn, với tư cách là nhà phát triển, bạn có muốn duy trì mã nhàm chán ngu ngốc dễ dàng HOẶC có một số người trợ giúp sẽ thực hiện mã nhàm chán ngu ngốc ở vị trí của bạn không?

Tôi nhấn mạnh rằng tôi tin là điểm quan trọng ở đây. Luôn luôn đáng để đánh giá chi phí và lợi ích của tái cấu trúc trước khi chúng ta nhảy vào nó. Như trong trường hợp của bạn, hầu hết chúng ta đều có nguồn lực hạn chế để tái cấu trúc nên chúng ta phải sử dụng chúng một cách khôn ngoan. Hãy dành thời gian ít ỏi quý giá đó cho việc tái cấu trúc, nơi nó mang lại nhiều lợi ích nhất với ít nỗ lực nhất.

Là một người có đầu óc sáng tạo, tất nhiên tôi thích sản xuất mã hoàn hảo, đẹp và thanh lịch và viết lại mọi thứ không giống với lý tưởng của tôi :-) Trong thực tế, tôi được trả tiền để sản xuất phần mềm giải quyết các vấn đề thực sự cho người dùng, vì vậy tôi nên nghĩ về việc tạo ra giá trị cao nhất cho tiền của họ trong thời gian dài.

Lợi ích của tái cấu trúc chỉ xuất hiện nếu có đủ tiền tiết kiệm về thời gian và nỗ lực để hiểu, duy trì, sửa chữa và mở rộng mã trong dài hạn . Vì vậy, nếu một đoạn mã - dù xấu đến mức nào - hiếm khi hoặc không bao giờ chạm vào, thì không có lỗi nào được biết đến trong đó và tôi không biết bất kỳ tính năng nào sắp tới trong tương lai có thể yêu cầu tôi chạm vào nó, tôi thích để lại nó trong hòa bình.


7
Thật dễ dàng để rơi vào cái bẫy của 'mã đã bị hút, cũng có thể giữ cho nó tiếp tục ...' Các lập trình viên giỏi thì không. Câu trả lời tốt đẹp.
Sevenseacat

Mặc dù đó rất có thể là cách tiếp cận an toàn nhất (mã được đảm bảo hoạt động nhờ các thử nghiệm) nhưng nó vẫn dẫn đến vấn đề được đề cập trong câu hỏi. Một mô hình khác nhau được đưa vào mã. Nói chung, tôi tin rằng bạn nên cố gắng dành thời gian để cấu trúc lại mọi thứ cùng một lúc (khi thực hiện TDD, tốt nhất với các bước trung gian) để bạn không có trạng thái không nhất quán trung gian đó. Khi kết thúc, cam kết mã của bạn để kiểm soát nguồn.
Steven Jeuris

2
@Steven, sẽ ổn khi tái cấu trúc mọi thứ ngay lập tức nếu bạn có đủ khả năng . Trong hầu hết các dự án thực tế, bạn không thể dừng mọi thứ và dành vài ngày hoặc vài tuần liên tiếp chỉ để tái cấu trúc. Ngay cả khi bạn may mắn có một người quản lý hỗ trợ nó, dự án vẫn cần tiếp tục.
Péter Török

1
@Steven, nó phụ thuộc - xem cập nhật của tôi ở trên.
Péter Török

1
@ Péter Török: Cập nhật tốt đẹp! Mô tả hoàn hảo các yếu tố trong thế giới thực để đưa vào tài khoản.
Steven Jeuris

4

Vì bạn không có thời gian để cấu trúc lại và mã có thể duy trì được, hãy giữ nó nhất quán. Lần sau chắc chắn bao gồm tái cấu trúc trong dự toán.


3

Tính nhất quán chỉ hỗ trợ nhà phát triển tiếp theo khi mã xung quanh ở trạng thái tốt. Hãy suy nghĩ về việc bạn mất bao lâu để hiểu mã trong tay và tìm đúng "điểm mở rộng" để thêm các thay đổi của bạn. Nếu bạn theo xu hướng hiện tại, thì anh chàng tiếp theo phải hiểu mã hiện có cũng như mã mới của bạn khi anh ta phải thay đổi.

Nếu bạn cấu trúc lại mã thành các hàm có ý nghĩa, anh chàng tiếp theo sẽ có thời gian dễ dàng hơn để hiểu những gì đang xảy ra và sẽ cần ít nỗ lực hơn để thêm các thay đổi của anh ta. Nghĩ theo cách này. Giả sử chàng trai tiếp theo là bạn. Bạn muốn thấy gì khi xem lại khối mã này, cùng một mớ hỗn độn mà bạn đang xem bây giờ, hoặc một cái gì đó được xây dựng hợp lý hơn?


3

Tính nhất quán có mức độ ưu tiên cao. Rõ ràng tất cả mọi người trong suy nghĩ đúng đắn của họ sẽ thích một giải pháp DRY thanh lịch ở mọi nơi thay vì nồi hơi được sao chép ở khắp mọi nơi, nhưng bạn có thực sự thích hai cách tiếp cận khác nhau trong cùng một cơ sở mã để áp dụng một cách nhất quán không? Điều gì xảy ra nếu ai đó phát minh ra một giải pháp thậm chí thông minh hơn và cũng áp dụng nó không nhất quán? Sau đó, bạn có ba cách khác nhau để làm điều tương tự.

Tôi đã thấy nhiều mã lộn xộn do các nhà phát triển tìm ra "cách tốt hơn" để làm một cái gì đó, nhưng không áp dụng nó một cách nhất quán trên một cơ sở mã. Nếu nó là một phần của chiến lược được lên kế hoạch và phối hợp để áp dụng một mô hình mới dần dần theo thời gian thì nó có thể hoạt động, nhưng mọi mô hình được thực hiện không nhất quán đều có nguy cơ làm cho toàn bộ hệ thống trở nên tồi tệ hơn.

Có lẽ bạn có thể xem xét tái cấu trúc trong các bước nhỏ hơn, sao cho mỗi bước có thể được áp dụng trên toàn bộ cơ sở mã trong một lần. Ví dụ. trích xuất một phần nhỏ hơn của nồi hơi để hàm trợ giúp trong mỗi lần lặp. Theo thời gian, bạn kết thúc với tất cả các nồi hơi trong một lớp người trợ giúp. Nó có thể trông thực sự xấu xí vì nó không được thiết kế nhưng đã phát triển, nhưng bạn có thể sửa nó ngay bây giờ vì bạn có tất cả mã ở một nơi.


+1 "Sau đó, bạn có ba cách khác nhau để làm điều tương tự." Tôi đã thấy điều này trong mọi dự án doanh nghiệp tôi đã làm việc. Tôi nói thậm chí không thử tái cấu trúc cho đến khi bạn quét mã để chắc chắn rằng đã không có một đoạn mã nào khác đang cố gắng chăm sóc mã xấu mà bạn quyết định muốn cấu trúc lại. Đôi khi, tốt nhất là chỉ cần tuân thủ quy ước soạn sẵn, ít nhất là cho đến khi bạn đã đọc mã kỹ lưỡng.
TK-421

1

Bất kỳ tái cấu trúc nào loại bỏ mã trùng lặp đều là tái cấu trúc tốt và không nên hoãn lại trừ khi sắp hết thời hạn. Thời gian dành cho tái cấu trúc một lần, dễ dàng được bù đắp bằng thời gian giành được trong các lần thực hiện trong tương lai. Nhờ tái cấu trúc, các hoạt động bên trong không thể nhìn thấy được nữa, vì vậy nó sẽ trở nên dễ hiểu hơn, không khó theo dõi hơn.

Theo tôi đó là một quan niệm sai lầm phổ biến rằng mã tái cấu trúc khó theo dõi hơn. Đây thường là một cuộc tranh luận của những người chỉ quen thuộc với những gì đang được tái cấu trúc, và không phải là kết quả được tái cấu trúc. Đối với người mới, kết quả tái cấu trúc sẽ rõ ràng hơn.

Bất kỳ lỗi / tính năng nào cũng có thể được sửa / triển khai ở vị trí trung tâm sau đó và tự động có sẵn ở mọi nơi trong ứng dụng của bạn. Đây là một lợi ích rất lớn thường được đánh giá thấp. Nói chung, tổng cấu trúc lại một thành phần không mất nhiều thời gian. (ngày thay vì tháng) Khi so sánh điều này với thời gian bị mất do lỗi, phải hiểu mã có thể được tái cấu trúc, chi phí tái cấu trúc trở nên tối thiểu.

Cập nhật liên quan đến câu trả lời của Péter Török: Không phải bằng cách hoãn tái cấu trúc "bởi vì nó mất thời gian", thời gian để tái cấu trúc nó sau đó tăng lên? Tái cấu trúc không nên mất nhiều thời gian, khi được thực hiện thường xuyên hơn.

Làm thế nào để giải thích với sếp của bạn rằng bạn sẽ mất vài ngày để viết mã mà không thêm bất cứ điều gì vào sản phẩm, rất khó và là một câu hỏi hoàn toàn khác. :)


1
"Làm thế nào để giải thích với sếp của bạn rằng bạn sẽ dành vài ngày để viết mã mà không thêm bất cứ điều gì vào sản phẩm, rất khó và là một câu hỏi hoàn toàn khác." Rất cố gắng ;-) Thật không may trong cuộc sống thực, chúng ta cũng cần phải giải quyết điều này. Đó là lý do tại sao nó thực tế hơn để đi trong các bước nhỏ. Nửa giờ tái cấu trúc có thể được thực hiện như một phần của nhiệm vụ hai giờ, mà không cần người quản lý của bạn thậm chí không cần biết về nó. OTOH hai ngày đầy đủ dành cho tái cấu trúc hiếm khi không được chú ý.
Péter Török

@ Péter Török: Tôi đã cập nhật bài viết một chút. Tất nhiên bạn vẫn có những tình huống trong thế giới thực mà bạn không được phép dành thời gian để tái cấu trúc. Nhưng tôi tin tưởng mạnh mẽ rằng trên lý thuyết, nó luôn luôn có thời gian. (trừ khi bạn biết mã bạn đang làm việc sẽ không được hỗ trợ nữa trong tương lai gần)
Steven Jeuris

như họ nói, về lý thuyết không có nhiều khác biệt giữa thực tiễn và lý thuyết. Tuy nhiên, trong thực tế ... :-) Trong cuộc sống thực, bạn có thể không phải lúc nào cũng lấy lại được chi phí cho việc tái cấu trúc. Tôi mở rộng câu trả lời của tôi về điều này.
Péter Török

1
Tái cấu trúc loại bỏ mã trùng lặp không phải lúc nào cũng tốt; có thể hai phương pháp có thể giống hệt nhau theo các quy tắc kinh doanh ngày nay, nhưng không phải là ngày mai. Ví dụ, AcmeLockerBankmột getRow(int itemIndex)phương thức có thể có một phương thức trả về index % 5và một phương thức AcmeButtonPanelcó thể có một phương thức giống hệt nhau bởi vì cả khóa và bảng nút đều đánh số thứ theo cùng một cách; nếu không có ngân hàng khóa nào ngày nay có các mục có chỉ số trên 1000 nhưng một số bảng nút thì có và các khóa trong tương lai sử dụng khoảng cách hàng khác nhau cho các chỉ số trong phạm vi 1000-1999 ...
supercat

1
... Thêm hành vi bổ sung vào ngân hàng khóa sẽ dễ dàng nếu ngân hàng khóa và ngân hàng nút có getRowphương pháp riêng biệt , nhưng có thể khó khăn hơn nếu các chức năng đã được hợp nhất thành một phương thức chung.
supercat

0

Bạn không thể tạo Giao diện / Lớp mới hoạt động như một Mặt tiền trên mã cũ, trong khi giới thiệu mã mới theo phong cách của riêng bạn có thể dễ dàng mở rộng?


0

Làm điều đó đúng đi về phía trước. Sử dụng các chức năng thay vì cắt và dán. Điều đó không yêu cầu tái cấu trúc, nhưng nó cho bạn sự khởi đầu của một nền tảng cho tái cấu trúc trong tương lai.


0

Bạn, với tư cách là nhà phát triển, bạn có muốn duy trì mã nhàm chán ngu ngốc dễ dàng HOẶC có một số người trợ giúp sẽ thực hiện mã nhàm chán ngu ngốc ở vị trí của bạn không?

Tôi không hiểu câu hỏi sửa đổi. Tôi nghĩ rằng hầu hết mọi người, như bản thân tôi, không muốn duy trì "mã nhàm chán ngu ngốc". Tôi không biết ý của bạn là gì bởi người trợ giúp, xin lỗi.

Người đăng đã trả lời câu hỏi của riêng họ bằng cách không thực hiện những thay đổi lớn ngay bây giờ. Sự lựa chọn tốt. Tôi có vấn đề với sự kiêu ngạo của một nhà phát triển rằng họ biết điều gì là tốt nhất cho doanh nghiệp. Một sự tái cấu trúc lớn đối với kẻ ranh mãnh ... bởi vì bạn biết rõ hơn ông chủ của mình? Bất kỳ người quản lý có khả năng có thể cân nhắc lợi ích.

Nếu tái cấu trúc không phải là một lựa chọn thì câu hỏi sẽ trở thành một cuộc thảo luận về thời gian, địa điểm chính xác, v.v ... để thực hiện nó. Tính nhất quán là rất quan trọng. Mã sống lâu thường được hưởng lợi từ "đổi mới". Những người khác đã thảo luận về điều này ...

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.