Khi nào một chức năng quá dài? [đóng cửa]


130

35 dòng, 55 dòng, 100 dòng, 300 dòng? Khi nào bạn nên bắt đầu phá vỡ nó? Tôi đang hỏi bởi vì tôi có một chức năng với 60 dòng (bao gồm cả các bình luận) và đã suy nghĩ về việc tách nó ra.

long_function(){ ... }

vào:

small_function_1(){...}
small_function_2(){...}
small_function_3(){...}

Các hàm sẽ không được sử dụng bên ngoài hàm dài, làm cho các hàm nhỏ hơn có nghĩa là nhiều lệnh gọi hàm hơn, v.v.

Khi nào bạn sẽ tách một chức năng thành các chức năng nhỏ hơn? Tại sao?

  1. Các phương thức chỉ nên làm một điều hợp lý (nghĩ về chức năng)
  2. Bạn sẽ có thể giải thích phương pháp trong một câu duy nhất
  3. Nó phải phù hợp với chiều cao của màn hình của bạn
  4. Tránh chi phí không cần thiết (ý kiến ​​chỉ ra điều hiển nhiên ...)
  5. Kiểm thử đơn vị dễ dàng hơn cho các hàm logic nhỏ
  6. Kiểm tra xem một phần của hàm có thể được sử dụng lại bởi các lớp hoặc phương thức khác không
  7. Tránh khớp nối giữa các lớp quá mức
  8. Tránh các cấu trúc điều khiển lồng nhau sâu

Cảm ơn mọi người vì câu trả lời , chỉnh sửa danh sách và bỏ phiếu cho câu trả lời đúng Tôi sẽ chọn câu trả lời đó;)

Bây giờ tôi đang tái cấu trúc với những ý tưởng đó trong đầu :)


Có một lỗi đánh máy trong câu hỏi của bạn, tôi nghĩ bạn có nghĩa là "Khi nào một chức năng quá dài?".
Tom

1
Bạn đang đánh lạc hướng câu hỏi bằng cách đặt câu hỏi về các dòng mã. Các yếu tố quyết định không được đo bằng các dòng mã.
dkretz

Câu hỏi này có thể trở nên phức tạp tùy thuộc vào mã và ngôn ngữ. có lẽ bạn có thể gửi nó
Ray Tayek

Nếu nó được tuân thủ theo nguyên tắc trách nhiệm duy nhất - chỉ cần làm điều đó. Tôi thường cảm thấy cần phải tạo một tiêu đề hoặc cứ sau 20 dòng mã, điều này sẽ đánh dấu tôi để trừu tượng hóa nó và đặt tên cho đoạn này là một hàm có tên có ý nghĩa thay vì tạo tiêu đề chương.
Yevgeniy Afanasyev

Câu trả lời:


75

Không có quy tắc thực sự khó khăn và nhanh chóng cho nó. Nói chung tôi thích phương pháp của tôi chỉ "làm một việc". Vì vậy, nếu nó lấy dữ liệu, sau đó thực hiện một cái gì đó với dữ liệu đó, sau đó ghi nó vào đĩa thì tôi sẽ tách ra lấy và viết thành các phương thức riêng biệt để phương thức "chính" của tôi chỉ chứa "làm gì đó".

Mặc dù "làm một cái gì đó" vẫn có thể là một vài dòng, vì vậy tôi không chắc chắn một số dòng là số liệu phù hợp để sử dụng :)

Chỉnh sửa: Đây là một dòng mã tôi đã gửi xung quanh công việc vào tuần trước (để chứng minh một điểm .. đó không phải là điều tôi tạo thói quen :)) - Tôi chắc chắn sẽ không muốn 50-60 chàng trai xấu này theo phương pháp của mình : D

return level4 != null ? GetResources().Where(r => (r.Level2 == (int)level2) && (r.Level3 == (int)level3) && (r.Level4 == (int)level4)).ToList() : level3 != null ? GetResources().Where(r => (r.Level2 == (int)level2) && (r.Level3 == (int)level3)).ToList() : level2 != null ? GetResources().Where(r => (r.Level2 == (int)level2)).ToList() : GetAllResourceList();

1
LOL Vâng tôi có thể loại bỏ tất cả các khoảng trắng trong phương thức của mình và nó sẽ chỉ là một dòng rất dài và không phải là một hàm dài. Làm một điều, đó có lẽ là câu trả lời hơn, cảm ơn

@Movaxes Đoạn mã mà tôi đã đăng chỉ là một câu lệnh, không chỉ có nhiều dòng trên một dòng .. không có dấu chấm phẩy nào trong đó :) Tôi có thể mở rộng GetResource () mỗi lần để làm cho nó thậm chí còn tệ hơn: P
Steven Robbins

Vâng, điều đó có ý nghĩa. Tại sao không chỉ lấy toàn bộ tệp nguồn của bạn và đặt nó trong một dòng. Ý tôi là sau đó bạn thực sự trở thành một "ninja" Web 2.0 :)
BobbyShaftoe

Tôi nhớ trên các tạp chí cũ (tôi đang nói BBC Micro cũ) họ từng có "chương trình 10 dòng" chỉ có một số tuyên bố trên mỗi dòng, cho đến độ dài tối đa mà BBC có thể xử lý .. họ luôn là một nỗi đau đúng để nhập: D
Steven Robbins

6
Tôi thích khái niệm về chức năng chỉ làm một việc, .... nhưng. Nếu bạn có một chức năng thực hiện 10 việc và bạn chuyển 9 trong số đó thành các chức năng riêng biệt, chức năng còn lại vẫn được gọi là chức năng còn lại vẫn thực chất là thực hiện 10 việc! Tôi nghĩ rằng việc phá vỡ chức năng như thế này sẽ giúp kiểm tra dễ dàng hơn nhiều.
mtnpaul

214

Dưới đây là danh sách các cờ đỏ (không theo thứ tự cụ thể) có thể chỉ ra rằng một hàm quá dài:

  1. Các cấu trúc điều khiển lồng nhau sâu : ví dụ: vòng lặp for sâu 3 cấp hoặc thậm chí chỉ sâu 2 cấp với câu lệnh if lồng nhau có điều kiện phức tạp.

  2. Quá nhiều tham số xác định trạng thái : Theo tham số xác định trạng thái , tôi có nghĩa là một tham số chức năng đảm bảo một đường dẫn thực hiện cụ thể thông qua chức năng. Nhận quá nhiều loại tham số này và bạn có sự bùng nổ kết hợp của các đường dẫn thực thi (điều này thường xảy ra song song với # 1).

  3. Logic được nhân đôi trong các phương pháp khác : sử dụng lại mã kém là một đóng góp rất lớn cho mã thủ tục nguyên khối. Rất nhiều sự trùng lặp logic như vậy có thể rất tinh tế, nhưng một khi được tái hiện, kết quả cuối cùng có thể là một thiết kế thanh lịch hơn nhiều.

  4. Khớp nối giữa các lớp quá mức : việc thiếu đóng gói thích hợp này dẫn đến các hàm liên quan đến các đặc điểm gần gũi của các lớp khác, do đó kéo dài chúng.

  5. Chi phí không cần thiết : Các nhận xét chỉ ra các lớp rõ ràng, được lồng sâu, các biểu đồ và setters không cần thiết cho các biến lớp lồng nhau riêng tư và các tên hàm / biến dài bất thường đều có thể tạo ra tiếng ồn cú pháp trong các hàm liên quan cuối cùng sẽ làm tăng độ dài của chúng.

  6. Màn hình cấp nhà phát triển khổng lồ của bạn không đủ lớn để hiển thị : Trên thực tế, màn hình ngày nay đủ lớn để một chức năng ở bất kỳ đâu gần với chiều cao của nó có thể quá dài. Nhưng, nếu nó lớn hơn , đây là một khẩu súng hút thuốc có gì đó không ổn.

  7. Bạn có thể không ngay lập tức xác định mục đích của chức năng : Hơn nữa, một khi bạn thực sự làm xác định mục đích của nó, nếu bạn không có thể tóm tắt mục đích này trong một câu duy nhất hay xảy ra để có một cơn đau đầu khủng khiếp, điều này sẽ là một đầu mối.

Tóm lại, các chức năng nguyên khối có thể có hậu quả sâu rộng và thường là một triệu chứng của sự thiếu hụt thiết kế chính. Bất cứ khi nào tôi gặp mã đó là một niềm vui tuyệt đối để đọc, sự thanh lịch của nó là rõ ràng ngay lập tức. Và đoán xem: các hàm thường độ dài rất ngắn.


1
Bài đăng hay! Rất quyết đoán
Chuck Conway

2
@PedroMorteRolo Chính xác. API tiêu chuẩn không phải lúc nào cũng là một mô hình của sự thanh lịch. Hơn nữa, phần lớn API Java đã được phát triển với kiến ​​thức sâu sắc về Trình biên dịch Java và JVM, do đó bạn có các cân nhắc về hiệu năng có thể giải thích nó. Tôi thừa nhận rằng các phần quan trọng của mã không thể lãng phí một mili giây có thể phải phá vỡ một số quy tắc này, nhưng điều đó luôn phải được coi là trường hợp đặc biệt. Dành thêm thời gian phát triển trước mắt là một khoản đầu tư ban đầu có thể tránh được nợ công nghệ trong tương lai (có khả năng làm tê liệt).
Ryan Delucchi

2
Nhân tiện .. tôi cho ý kiến ​​rằng các phương thức dài là xấu-heuristic cũng áp dụng cho các lớp. IMHO, các lớp dài là xấu, bởi vì chúng có xu hướng vi phạm nguyên tắc khả năng đáp ứng duy nhất. Sẽ rất vui khi có các trình biên dịch phát ra các cảnh báo cho cả các lớp dài và phương thức ....
Pedro Rolo

3
@PedroMorteRolo Tôi chắc chắn đồng ý về điều này. Hơn nữa, các lớp lớn có thể có trạng thái đột biến hơn: dẫn đến mã rất khó duy trì.
Ryan Delucchi

1
Câu trả lời tốt nhất. Một manh mối tốt khác là: các ý kiến ​​trong mã trông như thế nào? Số lần tôi tình cờ tìm thấy mã của ai đó với một dòng như : // fetch Foo's credentials where Bar is "uncomplete". Đó gần như chắc chắn là một tên hàm ngay tại đó và nên được tách ra. Có lẽ muốn được tái cấu trúc thành một cái gì đó như: Foo.fetchCredentialWhereBarUncomplete()
Jay Edwards

28

Tôi nghĩ rằng có một sự cảnh báo lớn đến câu thần chú "chỉ làm một việc" trên trang này. Đôi khi làm một điều tung hứng rất nhiều biến. Đừng chia một hàm dài thành một nhóm các hàm nhỏ hơn nếu các hàm nhỏ hơn kết thúc có danh sách tham số dài. Làm điều đó chỉ biến một hàm duy nhất thành một tập hợp các hàm được ghép cao mà không có giá trị riêng thực sự.


18

Một chức năng chỉ nên làm một điều. Nếu bạn đang làm nhiều việc nhỏ trong một chức năng, hãy biến mỗi việc nhỏ thành một chức năng và gọi các chức năng đó từ chức năng dài.

Những gì bạn thực sự không muốn làm là sao chép và dán cứ sau 10 dòng hàm dài của bạn vào các hàm ngắn (như ví dụ của bạn gợi ý).


Vâng, tạo ra rất nhiều chức năng nhỏ với mẫu sao chép và dán không phải là một ý tưởng tuyệt vời, tôi đồng ý rằng một chức năng nên luôn luôn cố gắng chỉ làm một việc

"làm một việc" có thể đúng hoặc không, tùy thuộc vào độ chi tiết. Nếu một hàm nhân một ma trận, điều đó tốt. Nếu một chức năng xây dựng một chiếc xe ảo - đó là "một điều" nhưng đó cũng là một điều rất lớn. Nhiều chức năng có thể được sử dụng để xây dựng một chiếc xe, từng thành phần.
void.pulum

16

Tôi đồng ý một chức năng chỉ nên làm một việc, nhưng ở cấp độ đó là một điều.

Nếu 60 dòng của bạn đang hoàn thành một điều (từ quan điểm chương trình của bạn) và các phần tạo nên 60 dòng đó sẽ không được sử dụng bởi bất cứ điều gì khác thì 60 dòng là tốt.

Không có lợi ích thực sự để phá vỡ nó, trừ khi bạn có thể phá vỡ nó thành những mảnh bê tông tự đứng. Số liệu để sử dụng là chức năng và không phải là dòng mã.

Tôi đã làm việc trên nhiều chương trình trong đó các tác giả đã đưa một điều duy nhất đến một mức độ cực đoan và tất cả những gì nó đã làm là làm cho nó trông giống như ai đó đã lấy một quả lựu đạn cho một chức năng / phương pháp và thổi nó thành hàng chục mảnh không liên kết được khó theo dõi.

Khi rút ra các phần của chức năng đó, bạn cũng cần xem xét liệu bạn có thêm bất kỳ chi phí không cần thiết nào không và tránh truyền một lượng lớn dữ liệu.

Tôi tin rằng điểm quan trọng là tìm kiếm khả năng tái sử dụng trong chức năng dài đó và kéo những phần đó ra. Những gì bạn còn lại là chức năng, cho dù nó dài 10, 20 hoặc 60 dòng.


2
+1 "Số liệu cần sử dụng là chức năng chứ không phải dòng mã"
Cody Piersall

Một số liệu quan trọng khác là số lượng các cấp lồng nhau. Giữ ở mức tối thiểu. Phá vỡ một chức năng thành các phần nhỏ hơn thường giúp. Những thứ khác cũng có thể giúp, chẳng hạn như nhiều lợi nhuận.
dùng2367418

10

60 dòng là lớn nhưng không quá dài cho một chức năng. Nếu nó vừa trên một màn hình trong trình chỉnh sửa, bạn có thể thấy tất cả cùng một lúc. Nó thực sự phụ thuộc vào những gì các chức năng đang làm.

Tại sao tôi có thể chia tay một chức năng:

  • Nó dài quá
  • Nó làm cho mã dễ bảo trì hơn bằng cách phá vỡ nó và sử dụng các tên có ý nghĩa cho hàm mới
  • Chức năng không gắn kết
  • Các bộ phận của chức năng là hữu ích trong chính họ.
  • Khi rất khó để đưa ra một tên có ý nghĩa cho hàm (Có lẽ nó đang làm quá nhiều)

3
Điểm tốt, tôi đồng ý, nếu bạn phải đặt tên cho hàm Do ThisAnd ThisAndAlso Điều này có lẽ nó làm quá nhiều. cảm ơn :)

2
Bạn chỉ là cách để ra khỏi trật tự với người bạn đời này. 60 dòng sẽ luôn là quá nhiều. Tôi muốn nói rằng nếu bạn đóng trên 10 dòng thì có lẽ bạn đã gần đến giới hạn.
willcodejavaforfood

Nhưng một chức năng khác vẫn đang gọi các chức năng này và về cơ bản là cùng một DoThisAndThisAndAlsoThischức năng nhưng với rất nhiều sự trừu tượng mà bạn vẫn phải đặt tên bằng cách nào đó
Timo Huovinen

6

Kinh nghiệm cá nhân của tôi là nó quá dài nếu tôi không thể nhìn thấy toàn bộ mọi thứ mà không cuộn.


4
... Trong khi đã đặt kích thước phông chữ thành 5?
EricSchaefer

5

Kích thước xấp xỉ kích thước màn hình của bạn (vì vậy hãy lấy một màn hình rộng trục lớn và xoay nó) ... :-)

Đùa sang một bên, một điều hợp lý cho mỗi chức năng.

Và điều tích cực là kiểm thử đơn vị thực sự dễ thực hiện hơn nhiều với các hàm logic nhỏ làm 1 việc. Các chức năng lớn làm nhiều việc khó xác minh hơn!

/ Johan


Điểm hay về kiểm tra đơn vị :)

5

Quy tắc ngón tay cái: Nếu một hàm chứa các khối mã làm một cái gì đó, phần nào tách ra khỏi phần còn lại của mã, hãy đặt nó vào một hàm riêng biệt. Thí dụ:

function build_address_list_for_zip($zip) {

    $query = "SELECT * FROM ADDRESS WHERE zip = $zip";
    $results = perform_query($query);
    $addresses = array();
    while ($address = fetch_query_result($results)) {
        $addresses[] = $address;
    }

    // now create a nice looking list of
    // addresses for the user
    return $html_content;
}

đẹp hơn nhiều:

function fetch_addresses_for_zip($zip) {
    $query = "SELECT * FROM ADDRESS WHERE zip = $zip";
    $results = perform_query($query);
    $addresses = array();
    while ($address = fetch_query_result($results)) {
        $addresses[] = $address;
    }
    return $addresses;
}

function build_address_list_for_zip($zip) {

    $addresses = fetch_addresses_for_zip($zip);

    // now create a nice looking list of
    // addresses for the user
    return $html_content;
}

Cách tiếp cận này có hai ưu điểm:

  1. Bất cứ khi nào bạn cần tìm nạp địa chỉ cho một mã zip nhất định, bạn có thể sử dụng chức năng có sẵn.

  2. Khi bạn cần đọc lại hàm, build_address_list_for_zip()bạn sẽ biết khối mã đầu tiên sẽ làm gì (nó tìm địa chỉ cho một mã zip nhất định, ít nhất đó là những gì bạn có thể rút ra từ tên hàm). Nếu bạn đã để lại mã truy vấn nội tuyến, trước tiên bạn cần phân tích mã đó.

[Mặt khác (tôi sẽ phủ nhận tôi đã nói với bạn điều này, ngay cả khi bị tra tấn): Nếu bạn đọc nhiều về tối ưu hóa PHP, bạn có thể lấy ý tưởng để giữ số lượng hàm nhỏ nhất có thể, bởi vì lệnh gọi hàm rất, rất tốn kém trong PHP. Tôi không biết về điều đó vì tôi chưa bao giờ thực hiện bất kỳ tiêu chuẩn nào. Nếu đó là trường hợp bạn có lẽ sẽ tốt hơn nếu không theo bất kỳ câu trả lời nào cho câu hỏi của bạn nếu ứng dụng của bạn rất "nhạy cảm về hiệu suất" ;-)]


cảm ơn ví dụ hay :) Tôi sẽ google cho điểm chuẩn chức năng trong php

5

Hãy xem qua chu kỳ của McCabe, trong đó anh ta chia mã của mình thành một biểu đồ trong đó, "Mỗi nút trong biểu đồ tương ứng với một khối mã trong chương trình trong đó luồng là tuần tự và các cung tương ứng với các nhánh được lấy trong chương trình. "

Bây giờ hãy tưởng tượng mã của bạn không có chức năng / phương thức; nó chỉ là một đoạn mã khổng lồ dưới dạng biểu đồ.

Bạn muốn phá vỡ sự ngổn ngang này thành các phương pháp. Hãy xem xét rằng, khi bạn làm, sẽ có một số khối nhất định trong mỗi phương thức. Chỉ một khối của mỗi phương thức sẽ hiển thị cho tất cả các phương thức khác: khối đầu tiên (chúng tôi cho rằng bạn sẽ có thể nhảy vào một phương thức tại một điểm duy nhất: khối đầu tiên). Tất cả các khối khác trong mỗi phương thức sẽ là thông tin ẩn trong phương thức đó, nhưng mỗi khối trong một phương thức có thể có khả năng nhảy sang bất kỳ khối nào khác trong phương thức đó.

Để xác định kích thước của các phương thức của bạn theo số lượng khối cho mỗi phương thức, một câu hỏi bạn có thể tự hỏi là: tôi phải có bao nhiêu phương pháp để giảm thiểu số lượng phụ thuộc tiềm năng tối đa (MPE) giữa tất cả các khối?

Câu trả lời được đưa ra bởi một phương trình. Nếu r là số phương thức giảm thiểu MPE của hệ thống và n là số khối trong hệ thống, thì phương trình là: r = sqrt (n)

Và có thể chỉ ra rằng điều này cho số khối cho mỗi phương thức là, sqrt (n).


4

Hãy nhớ rằng bạn có thể kết thúc việc bao thanh toán lại chỉ vì mục đích bao thanh toán lại, có khả năng làm cho mã không thể đọc được hơn ở nơi đầu tiên.

Một đồng nghiệp cũ của tôi có một quy tắc kỳ lạ rằng một hàm / phương thức chỉ phải chứa 4 dòng mã! Anh ta cố gắng bám vào điều này một cách cứng nhắc đến nỗi tên phương thức của anh ta thường trở nên lặp đi lặp lại & vô nghĩa cộng với các cuộc gọi trở nên lồng nhau sâu sắc và khó hiểu.

Vì vậy, câu thần chú của riêng tôi đã trở thành: nếu bạn không thể nghĩ ra một tên hàm / phương thức hợp lý cho đoạn mã bạn đang thực hiện lại, đừng bận tâm.


2

Lý do chính mà tôi thường phá vỡ một chức năng là vì các bit và các phần của nó cũng là các thành phần trong một chức năng khác gần đó tôi đang viết, vì vậy các phần phổ biến được đưa ra. Ngoài ra, nếu nó sử dụng nhiều trường hoặc thuộc tính từ một số lớp khác, rất có thể phần này có thể được gỡ bỏ bán buôn và nếu có thể được chuyển sang lớp khác.

Nếu bạn có một khối mã với một nhận xét ở trên cùng, hãy xem xét kéo nó ra thành một hàm, với các tên hàm và đối số minh họa cho mục đích của nó và bảo lưu nhận xét cho lý do của mã.

Bạn có chắc chắn không có mảnh nào trong đó sẽ hữu ích ở nơi khác không? Đó là loại chức năng gì?


Hàm tạo một tệp bộ đệm từ một mẫu, dựa trên url, như post_2009_01_01.html từ url / post /

2

Theo tôi câu trả lời là: khi nó làm quá nhiều thứ. Hàm của bạn chỉ thực hiện các hành động bạn mong đợi từ tên của chính hàm đó. Một điều khác cần xem xét là nếu bạn muốn sử dụng lại một số phần chức năng của mình trong các phần khác; trong trường hợp này có thể hữu ích để phân chia nó.


2

Tôi thường phá vỡ các chức năng bằng cách đặt các bình luận mô tả khối mã tiếp theo. Những gì trước đây đã đi vào các ý kiến ​​bây giờ đi vào tên chức năng mới. Đây không phải là quy tắc cứng, nhưng (đối với tôi) một quy tắc tốt đẹp. Tôi thích mã nói cho chính nó tốt hơn một mã cần bình luận (vì tôi đã học được rằng các bình luận thường nói dối)


Tôi thích bình luận mã của tôi, chủ yếu không phải cho tôi mà cho những người khác, loại bỏ rất nhiều câu hỏi về nơi biến $ được định nghĩa, nhưng tôi cũng thích mã để tự giải thích. Có ý kiến ​​nói dối?

vâng, bởi vì nhiều hơn không phải chúng không được duy trì. Tại thời điểm viết chúng có thể đúng, nhưng một khi lỗi hoặc tính năng mới được đưa ra, không ai buộc phải thay đổi nhận xét theo tình huống mới. Tên phương thức có xu hướng nói dối ít thường xuyên hơn bình luận IMHO
Olaf Kock

Tôi chỉ bắt gặp câu trả lời này: stackoverflow.com/questions / 406760 / Nói rằng "Hầu hết các bình luận trong mã trên thực tế là một hình thức sao chép mã nguy hiểm". Ngoài ra - Dài dòng ý kiến ​​đó.
Olaf Kock

1

Đây là một phần của vấn đề sở thích, nhưng làm thế nào tôi xác định được điều này là tôi cố gắng giữ các chức năng của mình chỉ chừng nào sẽ phù hợp với màn hình của tôi tại một thời điểm (tối đa). Lý do là dễ hiểu hơn những gì đang xảy ra nếu bạn có thể nhìn thấy toàn bộ sự việc cùng một lúc.

Khi tôi viết mã, đó là sự pha trộn của việc viết các hàm dài, sau đó tái cấu trúc để lấy ra các bit có thể được sử dụng lại bởi các hàm khác - và viết các hàm nhỏ thực hiện các tác vụ rời rạc khi tôi đi.

Tôi không biết rằng có bất kỳ câu trả lời đúng hay sai cho vấn đề này (ví dụ: bạn có thể giải quyết trên 67 dòng là tối đa của mình, nhưng có thể đôi khi có ý nghĩa để thêm một vài câu nữa).


Vâng, tôi cũng muốn thấy chức năng hoàn chỉnh của mình trong màn hình :) đôi khi điều đó có nghĩa là phông chữ Monospace 9 và độ phân giải lớn trong nền đen, tôi đồng ý là dễ hiểu hơn theo cách đó.

1

Đã có một số nghiên cứu kỹ lưỡng được thực hiện về chính chủ đề này, nếu bạn muốn có ít lỗi nhất, mã của bạn không nên quá dài. Nhưng nó cũng không nên quá ngắn.

Tôi không đồng ý rằng một phương thức sẽ phù hợp với màn hình của bạn trong một, nhưng nếu bạn đang cuộn xuống nhiều hơn một trang thì phương thức đó quá dài.

Xem Kích thước lớp tối ưu cho phần mềm hướng đối tượng để thảo luận thêm.


cảm ơn vì đã liên kết, đọc :)

1

Tôi đã viết 500 hàm dòng trước đây, tuy nhiên đây chỉ là các câu lệnh chuyển đổi lớn để giải mã và trả lời tin nhắn. Khi mã cho một tin nhắn trở nên phức tạp hơn một if-then-other, tôi đã trích xuất nó ra.

Về bản chất, mặc dù chức năng là 500 dòng, các vùng được duy trì độc lập trung bình 5 dòng.


1

Tôi thường sử dụng một cách tiếp cận hướng kiểm tra để viết mã. Trong phương pháp này, kích thước chức năng thường liên quan đến độ chi tiết của các bài kiểm tra của bạn.

Nếu bài kiểm tra của bạn đủ tập trung thì nó sẽ dẫn bạn viết một hàm tập trung nhỏ để thực hiện bài kiểm tra.

Điều này cũng hoạt động theo hướng khác. Các chức năng cần phải đủ nhỏ để kiểm tra hiệu quả. Vì vậy, khi làm việc với mã kế thừa, tôi thường thấy rằng tôi chia nhỏ các hàm lớn hơn để kiểm tra các phần khác nhau của chúng.

Tôi thường tự hỏi mình "trách nhiệm của chức năng này là gì" và nếu tôi không thể nêu trách nhiệm trong một câu ngắn gọn rõ ràng, và sau đó dịch nó thành một bài kiểm tra tập trung nhỏ, tôi tự hỏi liệu chức năng này có quá lớn không.


1

Nếu nó có nhiều hơn ba nhánh, nói chung, điều này có nghĩa là một hàm hoặc phương thức nên được tách rời, để đóng gói logic phân nhánh trong các phương thức khác nhau.

Mỗi vòng lặp for, if statement, v.v. sau đó không được xem như là một nhánh trong phương thức gọi.

Cobertura cho mã Java (và tôi chắc chắn có các công cụ khác cho các ngôn ngữ khác) tính toán số if, v.v. trong một hàm cho mỗi hàm và tính tổng của nó cho "độ phức tạp chu kỳ trung bình".

Nếu một hàm / phương thức chỉ có ba nhánh, nó sẽ nhận được ba trên số liệu đó, điều này rất tốt.

Đôi khi rất khó để làm theo hướng dẫn này, cụ thể là để xác nhận đầu vào của người dùng. Tuy nhiên, việc đưa các nhánh vào các phương thức khác nhau không chỉ hỗ trợ phát triển và bảo trì mà còn kiểm tra, vì các đầu vào cho các phương thức thực hiện phân nhánh có thể được phân tích dễ dàng để xem những gì đầu vào cần được thêm vào các trường hợp thử nghiệm để bao quát các nhánh đó đã không được bảo hiểm.

Nếu tất cả các nhánh nằm trong một phương thức, các đầu vào sẽ phải được theo dõi kể từ khi bắt đầu phương thức, điều này cản trở khả năng kiểm tra.


0

Tôi nghi ngờ bạn sẽ tìm thấy rất nhiều câu trả lời về điều này.

Tôi có thể sẽ phá vỡ nó dựa trên các nhiệm vụ logic đang được thực hiện trong hàm. Nếu bạn thấy rằng truyện ngắn của bạn đang chuyển thành tiểu thuyết, tôi sẽ đề nghị tìm và trích xuất các bước khác biệt.

Ví dụ: nếu bạn có một hàm xử lý một số loại đầu vào chuỗi và trả về kết quả chuỗi, bạn có thể phá vỡ hàm dựa trên logic để tách chuỗi của bạn thành các phần, logic để thêm các ký tự phụ và logic để đặt nó tất cả trở lại với nhau như một kết quả được định dạng.

Nói tóm lại, bất cứ điều gì làm cho mã của bạn sạch sẽ và dễ đọc (cho dù đó chỉ bằng cách đảm bảo chức năng của bạn có nhận xét tốt hoặc phá vỡ nó) là cách tiếp cận tốt nhất.


0

giả sử rằng bạn đang làm một việc, độ dài sẽ phụ thuộc vào:

  • những gì bạn đang làm
  • bạn đang sử dụng ngôn ngữ nào
  • bạn cần bao nhiêu mức độ trừu tượng

60 dòng có thể quá dài hoặc nó có thể vừa phải. Tôi nghi ngờ rằng nó có thể quá dài mặc dù.


Tôi đang thực hiện một số bộ nhớ đệm trong PHP, vâng, có lẽ 60 dòng là quá nhiều, tái cấu trúc ...

0

Một điều (và điều đó nên rõ ràng từ tên hàm), nhưng không nhiều hơn một đoạn mã, bất kể. Và cảm thấy tự do để tăng kích thước phông chữ của bạn. Và nếu nghi ngờ, hãy cấu trúc lại nó thành hai hoặc nhiều chức năng.


0

Mở rộng tinh thần của một tweet từ chú Bob một thời gian trước, bạn biết một chức năng đang trở nên quá dài khi bạn cảm thấy cần phải đặt một dòng trống giữa hai dòng mã. Ý tưởng là nếu bạn cần một dòng trống để phân tách mã, thì trách nhiệm và phạm vi của nó sẽ tách ra tại thời điểm đó.


0

Ý tưởng của tôi là nếu tôi phải tự hỏi mình nếu nó quá dài thì có lẽ nó quá dài. Nó giúp tạo ra các chức năng nhỏ hơn, trong lĩnh vực này, bởi vì nó có thể giúp sau này trong vòng đời của ứng dụ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.