Có bao giờ có ý nghĩa cho một refactor kết thúc với LỘC cao hơn không? [đóng cửa]


25

Có trường hợp nào nhiều mã dài hơn (như trong các câu lệnh logic hơn) sạch hơn mã ngắn gọn hơn không?



18
Tất nhiên nó. Ngay cả khi loại bỏ trùng lặp, mã để xác định hàm trích xuất mới chiếm không gian của chính nó. Viết một hàm mới có thể mất bốn dòng và chỉ lưu hai, và vẫn là một việc đáng làm.
Kilian Foth

5
"Mã ngắn gọn hơn"? Tôi thực sự ghét niềm tin sai lầm rằng số dòng nhỏ hơn có nghĩa là mã "tốt hơn". Nó không. Trong thực tế, nó thường ngược lại. Có một điểm - và nó đạt đến rất nhanh - nơi nhồi nhét ngày càng nhiều ý nghĩa vào không gian ngày càng ít làm cho mã khó hiểu hơn. Trên thực tế, có cả một cuộc thi - Cuộc thi mã C bị xáo trộn quốc tế - nơi nhiều người chiến thắng dựa vào những giới hạn hiểu biết của con người để viết mã không thể xuyên thủng.
Andrew Henle

1
Tiêu đề của câu hỏi của bạn và chính câu hỏi của bạn đang hỏi những câu hỏi khác nhau. Ví dụ, một câu lệnh if có thể được thay đổi thành biểu thức ternary giống như logic nhưng chỉ có 1 dòng.
Thuyền trưởng Man

1
-1 *** mã dài hơn (như trong các câu lệnh logic hơn) *** tính dài dòng và số lượng câu lệnh logic là hai điều không liên quan. Đó là hình thức xấu để thay đổi định nghĩa.
Pieter B

Câu trả lời:


71

Để trả lời điều đó, hãy lấy một ví dụ thực tế xảy ra với tôi. Trong C # một thư viện mà tôi duy trì, tôi có đoạn mã sau:

TResult IConsFuncMatcher<T, TResult>.Result() =>
    TryCons(_enumerator) is var simpleMatchData && !simpleMatchData.head.HasValue
        ? _emptyValue.supplied
            ? _emptyValue.value
            : throw new NoMatchException("No empty clause supplied");
        : _recursiveConsTests.Any() 
            ? CalculateRecursiveResult() 
            : CalculateSimpleResult(simpleMatchData);

Thảo luận về vấn đề này với các đồng nghiệp, phán quyết nhất trí là các biểu thức ternary lồng nhau, kết hợp với việc sử dụng "thông minh" is vardẫn đến kết quả ngắn gọn, nhưng khó đọc mã.

Vì vậy, tôi đã tái cấu trúc nó thành:

TResult IConsFuncMatcher<T, TResult>.Result()
{
    var simpleMatchData = TryCons(_enumerator);

    if (!simpleMatchData.head.HasValue)
    {
        return _emptyValue.supplied
            ? _emptyValue.value
            : throw new NoMatchException("No empty clause supplied");
    }

    return _recursiveConsTests.Any() 
        ? CalculateRecursiveResult() 
        : CalculateSimpleResult(simpleMatchData);
}

Phiên bản gốc chỉ chứa một biểu thức ghép với ẩn return. Phiên bản mới hiện chứa một khai báo biến rõ ràng, một iftuyên bố và hai rõ ràng returns. Nó chứa nhiều câu lệnh và nhiều dòng mã hơn. Tuy nhiên, mọi người tôi đã tham khảo đều cho rằng nó dễ đọc hơn và lý do, đó là các khía cạnh chính của "mã sạch".

Vì vậy, câu trả lời cho câu hỏi của bạn là "có" rõ ràng, dài dòng hơn có thể sạch hơn mã ngắn gọn và do đó là một cấu trúc lại hợp lệ.


34
Trong thời đại ngày nay, bộ não của nhà phát triển là nguồn tài nguyên khan hiếm hơn so với đĩa, CPU, RAM hoặc băng thông mạng. Những thứ khác rất quan trọng và trong một số ứng dụng nhất định, chúng có thể là yếu tố hạn chế của bạn, nhưng trong hầu hết các trường hợp, bạn muốn tối ưu hóa cho khả năng hiểu mã của nhà phát triển trước , sau đó là những thứ khác.
anaximander

2
@anaximander, Hoàn toàn đồng ý. Viết mã cho người khác đọc trước và trình biên dịch thứ hai. Đó là lý do tại sao tôi thấy hữu ích khi nhờ người khác xem xét mã của mình, ngay cả khi tôi là người duy nhất phát triển mã.
David Arno

4
Nếu tôi đang xem xét điều đó, tôi sẽ đề nghị đảo ngược thứ tự của các báo cáo trả lại và loại bỏ !khỏi điều kiện. Tôi cũng sẽ đề nghị đưa sự trở lại thứ hai trong một else. Nhưng ngay cả khi nó đứng, nó là một cải tiến lớn.
Martin Bonner hỗ trợ Monica

2
@DavidArno Tôi thấy logic đó, và nếu if (!foo.HasValue)là một thành ngữ trong mã của bạn, thậm chí còn mạnh mẽ hơn như vậy. Tuy nhiên, ifđây không thực sự là một lối thoát sớm - đó là "làm điều này hoặc điều đó tùy thuộc."
Martin Bonner hỗ trợ Monica

2
@foven So sánh các giá trị boolean là nguy hiểm. Tôi tránh nó nhiều nhất có thể.
Martin Bonner hỗ trợ Monica

30

1. Thiếu mối tương quan giữa LỘC và chất lượng mã.

Mục tiêu của tái cấu trúc là cải thiện chất lượng của một đoạn mã.

LỘC là một số liệu rất cơ bản, đôi khi, tương quan với chất lượng của một đoạn mã: ví dụ, một phương thức có vài nghìn LỘC có thể có vấn đề về chất lượng. Tuy nhiên, cần lưu ý rằng LỘC không phải là số liệu duy nhất và trong nhiều trường hợp thiếu mối tương quan với chất lượng. Chẳng hạn, phương thức 4 LỘC không nhất thiết phải dễ đọc hơn hoặc dễ bảo trì hơn phương pháp 6 LỘC.

2. Một số kỹ thuật tái cấu trúc bao gồm thêm các LỘC.

Nếu bạn có một danh sách các kỹ thuật tái cấu trúc , bạn có thể dễ dàng phát hiện ra các kỹ thuật bao gồm việc cố ý thêm các LỘC. Ví dụ:

Cả hai đều là các kỹ thuật tái cấu trúc rất hữu ích và tác dụng của chúng đối với LỘC là hoàn toàn không liên quan khi xem xét có nên sử dụng chúng hay không.

Tránh sử dụng LỘC.

LỘC là một số liệu nguy hiểm. Nó rất dễ đo lường, và rất khó để giải thích chính xác.

Cho đến khi bạn trở nên quen thuộc với các kỹ thuật đo lường chất lượng mã, hãy cân nhắc tránh việc đo LỘC ở nơi đầu tiên. Hầu hết thời gian, bạn sẽ không nhận được bất cứ điều gì liên quan và sẽ có trường hợp nó sẽ đánh lừa bạn làm giảm chất lượng mã của bạn.


Bạn đã tái cấu trúc câu trả lời của mình và cải thiện chất lượng bằng cách thêm nhiều LÔ (dòng văn bản): p
grinch

12

Nếu bạn muốn xem kết quả cuối cùng của việc chỉ giảm thiểu số byte hoặc số LoC của mã nguồn của bạn, hãy xem các bài nộp cho trang web Stack Exchange Code Golf .

Nếu mã nguồn của bạn bị giảm theo kiểu như vậy, bạn sẽ sớm có một mớ hỗn độn không thể nhầm lẫn. Ngay cả khi bạn là người đã viết mã như vậy và hiểu nó đầy đủ vào thời điểm đó, bạn sẽ hiệu quả như thế nào khi bạn quay lại mã đó sau sáu tháng? Không có bằng chứng cho thấy mã tối thiểu như vậy thực sự thực thi bất kỳ nhanh hơn.

Mã phải được viết theo cách mà bất kỳ thành viên nào trong nhóm của bạn có thể nhìn vào nó và hiểu ngay lập tức nó đang làm gì.


Có thể dư thừa, nhưng chỉ để đánh vần nó ra; nếu bạn cấu trúc lại mã golf để dễ đọc, bạn luôn kết thúc với nhiều LoC hơn
JollyJoker

1

Có tái cấu trúc chắc chắn có thể dẫn đến nhiều dòng mã hơn.

Trường hợp phổ biến nhất IMO là khi bạn lấy mã không chung chung và bạn làm cho nó chung chung / linh hoạt hơn . Nói chung mã dễ dàng làm cho các dòng mã tăng đáng kể (đôi khi theo hệ số hai hoặc nhiều hơn).

Nếu bạn mong đợi mã chung chung mới được người khác sử dụng (thay vì chỉ là một thành phần phần mềm nội bộ) làm thư viện thì bạn thường kết thúc việc thêm mã không đánh dấu và đánh dấu tài liệu trong mã sẽ làm tăng dòng mã một lần nữa.

Ví dụ: đây là một tình huống rất phổ biến xảy ra với mọi nhà phát triển phần mềm:

  • sản phẩm của bạn cần một tính năng mới ưu tiên cao hoặc sửa lỗi hoặc nâng cao lỗi trong hai tuần (hoặc bất kỳ khung thời gian nào được coi là khẩn cấp đối với quy mô dự án / quy mô công ty / v.v.) của bạn
  • bạn làm việc chăm chỉ và cung cấp XYZ đúng giờ và nó hoạt động. Xin chúc mừng! Lam tôt lăm!
  • Trong khi bạn đang phát triển XYZ, thiết kế / triển khai mã hiện tại của bạn không thực sự hỗ trợ XYZ nhưng bạn có thể chuyển XYZ vào cơ sở mã
  • vấn đề là shim xấu xí và có mùi mã khủng khiếp vì bạn đã làm một số việc khó khăn / thông minh / xấu xí / thực hành xấu nhưng làm việc tử tế
  • khi bạn tìm thấy thời gian sau đó, bạn cấu trúc lại mã có thể thay đổi nhiều lớp hoặc thêm một lớp mới và giải pháp mới của bạn là "được thực hiện đúng" và không còn mùi mã xấu nữa ... tuy nhiên, làm điều đó "Đúng cách" bây giờ chiếm nhiều dòng mã hơn.

Một số ví dụ cụ thể xuất hiện trong đầu tôi:

  • đối với giao diện dòng lệnh, bạn có thể có 5000 dòng mã if / other-if hoặc bạn có thể sử dụng các cuộc gọi lại ... mỗi cuộc gọi lại sẽ nhỏ hơn nhiều và dễ đọc / kiểm tra / xác minh / gỡ lỗi / vv nhưng nếu bạn đếm các dòng mã 5000 dòng xấu xí của if / other-if code có thể nhỏ hơn
  • đối với một đoạn mã xử lý hỗ trợ N phương thức xử lý , bạn có thể sử dụng lại các câu lệnh if / other trông xấu nhất ...
    • hoặc bạn có thể chuyển sang các cuộc gọi lại sẽ đẹp hơn / tốt hơn nhưng các cuộc gọi lại mất nhiều dòng mã hơn (mặc dù vẫn có thời gian biên dịch)
    • hoặc bạn có thể trừu tượng hơn nữa và làm các plugin có thể thay đổi khi chạy. plugin rất hay vì bạn không phải biên dịch lại sản phẩm chính cho mỗi plugin mới hoặc sửa đổi thành plugin hiện có. và bạn có thể xuất bản API để người khác có thể mở rộng sản phẩm. NHƯNG một lần nữa cách tiếp cận plugin sử dụng nhiều dòng mã hơn.
  • Đối với GUI bạn tạo một tiện ích mới tuyệt vời
    • bạn hoặc đồng nghiệp lưu ý rằng tiện ích mới sẽ rất tốt cho XYZ và ABC nhưng ngay bây giờ tiện ích này được tích hợp chặt chẽ chỉ để hoạt động cho XYZ
    • bạn cấu trúc lại widget để làm việc cho cả hai nhưng bây giờ tổng số dòng mã tăng
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.