Liệu chiều dài chức năng có ảnh hưởng đến năng suất của một lập trình viên? Nếu vậy, số dòng tối đa tốt để tránh mất năng suất là gì?
Vì đây là một chủ đề rất được quan tâm, vui lòng sao lưu khiếu nại với một số dữ liệu.
Liệu chiều dài chức năng có ảnh hưởng đến năng suất của một lập trình viên? Nếu vậy, số dòng tối đa tốt để tránh mất năng suất là gì?
Vì đây là một chủ đề rất được quan tâm, vui lòng sao lưu khiếu nại với một số dữ liệu.
Câu trả lời:
Kể từ khi tôi bắt tay vào cây vợt điên rồ này vào năm 1970, tôi đã thấy chính xác một mô-đun thực sự cần nhiều hơn một trang in (khoảng 60 dòng). Tôi đã thấy rất nhiều mô-đun dài hơn.
Đối với vấn đề đó, tôi đã viết các mô-đun dài hơn, nhưng chúng thường là các máy trạng thái hữu hạn lớn được viết dưới dạng các câu lệnh chuyển đổi lớn.
Một phần của vấn đề dường như là các lập trình viên ngày nay không được dạy để mô đun hóa mọi thứ.
Các tiêu chuẩn mã hóa tối đa hóa sự lãng phí của không gian dọc dường như cũng là một phần của vấn đề. (Tôi vẫn chưa gặp một người quản lý phần mềm đã đọc " Tâm lý học lập trình máy tính " của Gerald Weinberg . Weinberg chỉ ra rằng nhiều nghiên cứu đã chỉ ra rằng sự hiểu biết của lập trình viên về cơ bản chỉ giới hạn ở những gì lập trình viên có thể thấy ngay lập tức. lập trình viên phải cuộn, hoặc lật một trang, mức độ hiểu của họ giảm đáng kể: họ phải nhớ và trừu tượng.)
Tôi vẫn tin rằng rất nhiều sự tăng năng suất của lập trình viên được chứng minh bằng tài liệu từ FORTH là do hệ thống "khối" FORTH cho mã nguồn: các mô-đun bị giới hạn ở mức tối đa tuyệt đối là 16 dòng 64 ký tự. Bạn có thể yếu tố vô hạn, nhưng trong mọi trường hợp , bạn không thể viết một thói quen 17 dòng.
Phụ thuộc vào ngôn ngữ bạn sử dụng, nhưng nói chung (và theo sở thích cá nhân của tôi):
Nếu nó nhiều hơn, thì đó là thứ tôi cần quay lại sau và làm lại.
Nhưng thực tế , bất kỳ kích thước nào cần có khi bạn cần giao một thứ gì đó và điều đó có ý nghĩa hơn vào lúc này để nhổ chúng ra như thế, đôi khi còn dễ dàng hơn cho ai đó xem xét trước khi vận chuyển. (nhưng vẫn lấy lại được sau).
(Gần đây, nhóm của tôi đã chạy một chương trình trên cơ sở mã của chúng tôi: chúng tôi đã tìm thấy lớp có 197 phương thức và một phương pháp khác chỉ có 3 phương thức nhưng một trong số đó là 600 dòng. Trò chơi dễ thương: điều gì tệ hơn trong 2 tệ nạn?)
Bây giờ để có câu trả lời zen hơn ... Nói chung, nó được coi là một cách thực hành tốt (TM) để trích dẫn một hoặc hai người đàn ông tuyệt vời, vì vậy hãy đi:
Mọi thứ nên được làm đơn giản nhất có thể, nhưng không đơn giản. - A. Einstein
Sự hoàn hảo cuối cùng đạt được không phải khi không còn gì để thêm, mà là khi không còn gì để lấy đi. - A. de Saint Exupéry
Là một phụ lục cho điều này, các chức năng của bạn nên có tên rõ ràng giải thích ý định của chúng. Về ý kiến, tôi thường không bình luận bên trong một chức năng:
Một khối nhận xét ở đầu mỗi chức năng (yêu cầu giải thích) là đủ. Nếu chức năng của bạn nhỏ và tên hàm đủ rõ ràng, thì bạn chỉ cần nói những gì bạn muốn đạt được và tại sao. Tôi chỉ sử dụng nhận xét nội tuyến cho các trường trong một số ngôn ngữ hoặc trên khối bắt đầu cho các chức năng phá vỡ quy tắc dòng 25-35 đó nếu mục đích không rõ ràng. Tôi sử dụng một nhận xét khối bên trong mã khi xảy ra tình huống đặc biệt (ví dụ: khối bắt mà bạn không cần hoặc muốn làm bất cứ điều gì nên có một nhận xét cho biết tại sao, ví dụ).
Để biết thêm, vui lòng đọc câu trả lời của tôi về Phong cách và các đề xuất về mã nhận xét
tt
để tạo ra những thứ này nhưng đôi khi bạn bị mắc kẹt với chức năng ass dài (hoặc chức năng ass dài) không thực sự làm bất cứ điều gì đáng quan tâm vì vậy không phải là vấn đề thực sự.
Map(x => x.Property1); Map(x => x.Property2); Map(x => x.Property3);
rõ ràng thì tất cả đều giống nhau. (Lưu ý đây chỉ là một ví dụ; loại chức năng này thỉnh thoảng bật lên)
Theo tôi, mọi chức năng nên càng nhỏ càng tốt. Mỗi chức năng chỉ nên làm một việc và làm tốt. Điều đó không thực sự trả lời câu hỏi về độ dài tối đa, nhưng cảm nhận của tôi nhiều hơn về độ dài của các chức năng.
Để sử dụng câu nói của chú Bob, "Trích xuất cho đến khi bạn không thể giải nén được nữa. Trích xuất cho đến khi bạn thả."
Chiều cao tối đa của một tòa nhà là bao nhiêu? Phụ thuộc vào vị trí của bản dựng hoặc chiều cao bạn muốn.
Bạn có thể nhận được câu trả lời khác nhau từ những người khác nhau đến từ thành phố khác nhau.
Một số hàm script và trình xử lý ngắt kernel rất dài.
Một phương pháp phù hợp với tôi là: Tôi có thể có một phần của hàm dài hơn để đặt tên có ý nghĩa không. Tôi nghĩ độ dài của một phương thức không quan trọng bằng việc đặt tên tốt. Phương pháp nên làm những gì tên nói, không hơn không kém. Và bạn sẽ có thể đặt một cái tên hay. Nếu bạn không thể đặt tên cho phương thức của mình là tốt, thì mã có thể không được đặt cùng nhau.
Miễn là nó cần phải làm những gì nó cần làm, nhưng không còn nữa.
Tôi nghĩ rằng có một sự đánh đổi. Nếu bạn có nhiều phương thức ngắn, việc gỡ lỗi chúng thường khó hơn một phương thức dài. Nếu bạn phải nhảy xung quanh trình soạn thảo 20 hoặc 30 lần khác nhau để theo dõi một cuộc gọi phương thức, sẽ rất khó để giữ tất cả trong đầu. Trong khi đó, nếu có một phương pháp rõ ràng bằng văn bản, ngay cả khi nó là 100 dòng, việc giữ trong đầu bạn thường dễ dàng hơn.
Câu hỏi thực sự là tại sao các mục nên ở các phương thức khác nhau và câu trả lời như đã nêu ở trên là sử dụng lại mã. Nếu bạn không sử dụng lại mã (hoặc không biết) thì có thể nên để lại mã theo một phương pháp dễ thực hiện và sau đó khi bạn cần sử dụng lại, hãy chia các phần cần tái sử dụng sử dụng thành các phương pháp nhỏ hơn.
Trong thực tế, một phần của thiết kế phương pháp tốt là tạo ra các phương thức gắn kết chức năng (về cơ bản chúng làm một việc). Độ dài của các phương pháp không quan trọng. Nếu một hàm thực hiện một điều được xác định rõ và là 1.000 dòng thì đó là một phương thức tốt. Nếu một hàm thực hiện 3 hoặc 4 điều và chỉ có 15 dòng, thì đó là một phương pháp tồi ...
Tôi thấy dễ dàng hơn để theo dõi những gì tôi đang làm nếu tôi có thể thấy toàn bộ chức năng cùng một lúc. Vì vậy, đây là cách tôi thích viết hàm:
Tôi hiếm khi viết các chức năng lâu hơn thế. Hầu hết trong số đó là các câu lệnh chuyển đổi C / C ++ khổng lồ.
Câu hỏi nên là một chức năng nên làm bao nhiêu. Và thông thường, thật hiếm khi bạn cần 100 dòng để thực hiện "một". Một lần nữa, điều đó phụ thuộc vào mức độ bạn đang xem mã: Việc băm mật khẩu có phải là một điều không? Hoặc là băm và lưu mật khẩu một điều?
Tôi muốn nói, hãy bắt đầu với việc lưu mật khẩu như một chức năng. Khi bạn cảm thấy băm là khác nhau, và bạn cấu trúc lại mã. Tôi không phải là chuyên gia lập trình bằng bất kỳ phương tiện nào, nhưng IMHO, toàn bộ ý tưởng về các hàm bắt đầu nhỏ là các hàm của bạn càng nguyên tử, cơ hội sử dụng lại mã càng cao, không bao giờ phải thay đổi giống nhau ở nhiều nơi v.v.
Tôi đã thấy các thủ tục lưu trữ SQL chạy hơn 1000 dòng. Có phải số lượng dòng thủ tục lưu trữ cũng ít hơn 50? Tôi không biết, nhưng nó làm cho việc đọc mã, chết tiệt. Bạn không chỉ phải tiếp tục cuộn lên xuống, bạn cần đặt một vài dòng mã như "this does verify1", "bản cập nhật này trong cơ sở dữ liệu", v.v. - một công việc mà lập trình viên nên làm.
Từ độ phức tạp Cyclomatic (Wikipedia):
Độ phức tạp chu kỳ của một phần của mã nguồn là số lượng các đường dẫn độc lập tuyến tính thông qua mã nguồn.
Tôi khuyên bạn nên giữ số đó dưới 10 trong một phương pháp duy nhất. Nếu nó lên 10, thì đã đến lúc phải tính lại.
Có những công cụ có thể đánh giá mã của bạn và cung cấp cho bạn số phức tạp theo chu kỳ.
Bạn nên cố gắng tích hợp các công cụ này vào đường ống xây dựng của bạn.
Đừng theo đuổi một kích thước phương thức theo nghĩa đen, nhưng hãy thử xem xét độ phức tạp và trách nhiệm của nó. Nếu nó có nhiều hơn một trách nhiệm, thì có lẽ nên tái lập yếu tố. Nếu độ phức tạp chu kỳ của nó tăng lên, thì có lẽ đã đến lúc phải tính lại.
Tôi khá chắc chắn có những công cụ khác cung cấp cho bạn thông tin phản hồi tương tự, nhưng tôi chưa có cơ hội để xem xét vấn đề này.
Thông thường, tôi cố gắng giữ các phương thức / chức năng của mình phù hợp với màn hình của màn hình 1680x1050. Nếu nó không phù hợp, sau đó sử dụng các phương thức / hàm trợ giúp để phân chia nhiệm vụ.
Nó giúp dễ đọc trên cả màn hình và giấy.
Tôi không đặt giới hạn cứng cho bất cứ điều gì vì một số hàm thực hiện các thuật toán vốn đã phức tạp và bất kỳ nỗ lực nào để làm cho chúng ngắn hơn sẽ làm cho các tương tác giữa các hàm mới, ngắn hơn trở nên phức tạp đến mức không thể giảm được sự đơn giản. Tôi cũng không tin rằng một chức năng chỉ nên làm "một việc" là một hướng dẫn tốt, vì "một điều" ở mức độ trừu tượng cao có thể là "nhiều việc" ở cấp độ thấp hơn.
Đối với tôi, một hàm chắc chắn là quá dài nếu độ dài của nó gây ra vi phạm tinh vi DRY ngay bây giờ và trích xuất một phần của hàm vào một hàm hoặc lớp mới có thể giải quyết điều này. Một hàm có thể quá dài nếu không phải như vậy, nhưng một hàm hoặc lớp có thể dễ dàng được trích xuất để làm cho mã trở nên mô đun hơn theo cách có thể hữu ích khi đối mặt với sự thay đổi có thể thấy trước.
Đủ ngắn để được tối ưu hóa chính xác
Các phương pháp nên ngắn gọn để làm chính xác một điều. Lý do cho điều này là đơn giản: vì vậy mã của bạn có thể được tối ưu hóa đúng.
Trong ngôn ngữ JIT-ted như Java hoặc C #, điều quan trọng là các phương thức của bạn phải đơn giản để trình biên dịch JIT có thể tạo mã nhanh chóng. Các phương pháp dài hơn, phức tạp hơn tự nhiên đòi hỏi nhiều thời gian JIT hơn. Ngoài ra, trình biên dịch JIT chỉ cung cấp một số tối ưu hóa và chỉ các phương thức đơn giản nhất được hưởng lợi từ việc này. Thực tế này thậm chí đã được nêu ra trong C # hiệu quả của Bill Wagner .
Trong một ngôn ngữ cấp thấp hơn, như C hoặc C ++, việc có các phương thức ngắn (có thể là hàng tá dòng) cũng rất quan trọng vì cách đó giúp bạn giảm thiểu nhu cầu lưu trữ các biến cục bộ trong RAM thay vì trong một thanh ghi. (Aka 'Đăng ký đổ'.) Tuy nhiên, lưu ý rằng trong trường hợp không được quản lý này, chi phí tương đối của mỗi lệnh gọi hàm có thể khá cao.
Và ngay cả trong một ngôn ngữ động, như Ruby hay Python, việc có các phương thức ngắn cũng giúp tối ưu hóa trình biên dịch. Trong một ngôn ngữ động, một tính năng càng 'động', càng khó tối ưu hóa. Ví dụ: một phương thức dài lấy X và có thể trả về Int, Float hoặc String có thể sẽ hoạt động chậm hơn nhiều so với ba phương thức riêng biệt mà mỗi phương thức chỉ trả về một loại duy nhất. Điều này là do, nếu trình biên dịch biết chính xác loại hàm nào sẽ trả về, nó cũng có thể tối ưu hóa trang gọi hàm. (Ví dụ: không kiểm tra chuyển đổi loại.)
Nó phụ thuộc rất nhiều vào những gì trong mã.
Tôi đã thấy một thói quen hàng ngàn dòng mà tôi không có vấn đề với. Đó là một tuyên bố chuyển đổi lớn, không có tùy chọn nào vượt quá một chục dòng và cấu trúc điều khiển duy nhất trong bất kỳ tùy chọn nào là một vòng lặp. Ngày nay, nó đã được viết với các đối tượng nhưng đó không phải là một lựa chọn trước đó.
Tôi cũng đang nhìn vào 120 dòng trong một công tắc trước mặt tôi. Không có trường hợp nào vượt quá 3 dòng - một người bảo vệ, một nhiệm vụ và phá vỡ. Đó là phân tích tệp văn bản, các đối tượng không có khả năng. Bất kỳ thay thế sẽ khó đọc hơn.
Hầu hết các trình biên dịch không quan tâm đến độ dài của hàm. Một chức năng nên có chức năng, nhưng phải dễ hiểu, thay đổi và tái sử dụng cho con người. Chọn độ dài phù hợp với bạn nhất.
Nguyên tắc chung của tôi là một chức năng phải phù hợp trên màn hình. Chỉ có ba trường hợp tôi thấy có xu hướng vi phạm điều này:
1) Chức năng điều phối. Ngày xưa, những thứ này là phổ biến nhưng hầu hết chúng được thay thế bằng sự kế thừa đối tượng ngày nay. Tuy nhiên, các đối tượng chỉ hoạt động trong chương trình của bạn và do đó bạn sẽ vẫn thấy các chức năng điều phối thỉnh thoảng khi xử lý dữ liệu đến từ nơi khác.
2) Các chức năng thực hiện một loạt các bước để hoàn thành mục tiêu và trong đó các bước thiếu một phân ngành tốt. Bạn kết thúc với một hàm chỉ đơn giản gọi một danh sách dài các hàm khác theo thứ tự.
3) Giống như # 2 nhưng trong đó các bước riêng lẻ quá nhỏ đến mức chúng chỉ được nội tuyến đơn giản thay vì được gọi riêng.
Có lẽ chiều dài chức năng không phải là một số liệu tốt. Chúng tôi cũng cố gắng sử dụng độ phức tạp chu kỳ , trên các phương thức và một trong những quy tắc kiểm tra kiểm soát nguồn trong tương lai rằng độ phức tạp chu kỳ trên các lớp và phương thức phải thấp hơn X.
Đối với các phương thức, X được đặt thành 30 và khá chặt chẽ.