Tạo các hàm lồng nhau vì lý do thẩm mỹ hoàn toàn?


16

Tôi đã luôn tự hỏi những lập trình viên khác nghĩ gì về ý tưởng tạo ra các chức năng thẩm mỹ thuần túy.

Nói rằng tôi có một chức năng xử lý một khối dữ liệu : Function ProcessBigData. Nói rằng tôi cần một số bước xử lý, chỉ có giá trị cho dữ liệu mà: Step1, Step2,Step3 .

Aproach bình thường tôi thấy nhiều nhất trong mã nguồn là viết bình luận như vậy:

Function ProcessBigData:
    # Does Step1
    Step1..
    Step1..

    #Does Step2
    Step2..
    Step2..

Những gì tôi thường làm, nhưng luôn cảm thấy sai lầm do sự thiếu phong cách mã hóa như vậy của các đồng nghiệp là:

Function ProcessBigData:
    Function Step1:
        Step1..
        Step1..

    Function Step2:
        Step2..
        Step2..

    Step1() -> Step2()

Tôi chủ yếu quan tâm nếu có bất kỳ nhược điểm nào cho phong cách như vậy trong JavascriptPython

Có sự thay thế nào mà tôi không thấy?


3
Tôi không thể nói bất cứ điều gì về Python, nhưng đối với Javascript, có một chi phí hiệu năng cho các hàm lồng nhau: hầu hết các công cụ JavaScript sử dụng cấu trúc giống như danh sách liên kết để phản ánh phạm vi biến. Do đó, việc thêm một lớp chức năng bổ sung sẽ buộc động cơ có thể tìm kiếm cấu trúc dữ liệu dài hơn / lớn hơn khi giải quyết các biến. Mặt khác, gốc rễ của mọi tội lỗi dĩ nhiên là tối ưu hóa sớm. :)
Marco

Câu trả lời:


4

Nó không lạ như bạn nghĩ. Ví dụ, trong ML tiêu chuẩn, thông thường sẽ giới hạn phạm vi của các hàm trợ giúp. Cấp, SML có cú pháp để tạo điều kiện cho nó:

local
    fun recursion_helper (iteration_variable, accumulator) =
        ... (* implementation goes here *)
in
    fun recursive_function (arg) = recursion_helper(arg, 0);
end

Tôi sẽ xem xét phong cách tốt này, vì 1) các chức năng nhỏ tạo điều kiện cho lý luận về chương trình và 2) nó báo hiệu cho người đọc rằng các chức năng này không được sử dụng ngoài phạm vi đó.

Tôi cho rằng có thể có một số chi phí trong việc tạo các hàm bên trong bất cứ khi nào hàm ngoài được gọi (Tôi không biết nếu JS hoặc Python tối ưu hóa điều đó) nhưng bạn biết họ nói gì về tối ưu hóa sớm.


11

Nó thường là một điều tốt để làm điều này bất cứ khi nào có thể, nhưng tôi thích nghĩ về loại công việc này không phải là "các bước", mà là nhiệm vụ .

Một nhiệm vụ con là một đơn vị công việc cụ thể có thể được thực hiện: nó có trách nhiệm cụ thể, và (các) đầu vào và đầu ra được xác định (nghĩ về "S" trong RẮN ). Một nhiệm vụ con không cần phải sử dụng lại: một số người có xu hướng nghĩ rằng "Tôi sẽ không bao giờ phải gọi điều này từ bất cứ điều gì khác, vậy tại sao lại viết nó như một chức năng?" nhưng đó là một ngụy biện.

Tôi cũng sẽ cố gắng phác thảo các lợi ích và cả cách nó áp dụng cho các hàm lồng nhau (bao đóng) so với chỉ một hàm khác trong lớp. Nói chung, tôi khuyên bạn không nên sử dụng các bao đóng trừ khi bạn đặc biệt cần một cách sử dụng (có nhiều cách sử dụng, nhưng tách mã thành các đoạn logic không phải là một trong số chúng).

Dễ đọc.

Hơn 200 dòng mã thủ tục (phần thân của hàm) khó đọc. Chức năng 2-20 dòng dễ đọc. Mã dành cho con người.

Lồng nhau hay không, bạn chủ yếu nhận được lợi ích của khả năng đọc, trừ khi bạn đang sử dụng rất nhiều biến từ phạm vi cha, trong trường hợp đó có thể khó đọc như vậy.

Giới hạn phạm vi biến

Có một chức năng khác buộc bạn phải giới hạn phạm vi biến, và đặc biệt vượt qua những gì bạn cần.

Điều này cũng thường làm cho bạn cấu trúc mã tốt hơn, bởi vì nếu bạn cần một loại biến trạng thái nào đó từ "bước" trước đó, bạn thực sự có thể tìm thấy thực sự có một ẩn phụ khác nên được viết và thực thi trước để có giá trị đó. Hay nói cách khác, nó khó hơn để viết các đoạn mã được ghép nối cao.

Có các hàm lồng nhau cho phép bạn truy cập các biến trong phạm vi cha từ bên trong hàm lồng nhau (bao đóng). Điều này có thể rất hữu ích, nhưng nó cũng có thể dẫn đến các lỗi tinh vi, khó tìm vì việc thực thi chức năng có thể không xảy ra theo cách nó được viết. Điều này thậm chí còn đúng hơn nếu bạn sửa đổi các biến trong phạm vi cha (nói chung là một ý tưởng rất tệ).

Bài kiểm tra đơn vị

Mỗi tập con, được triển khai một hàm (hoặc thậm chí là một lớp) là một đoạn mã độc lập, có thể kiểm tra được. Lợi ích của kiểm tra đơn vịTDD được ghi nhận tốt ở nơi khác.

Sử dụng các chức năng / đóng cửa lồng nhau không cho phép thử nghiệm đơn vị. Đối với tôi, đây là một công cụ thỏa thuận và lý do bạn chỉ nên thực hiện một chức năng khác, trừ khi có nhu cầu cụ thể cho việc đóng cửa.

Làm việc theo nhóm / Thiết kế từ trên xuống

Nhiệm vụ phụ có thể được viết bởi những người khác nhau, độc lập, nếu cần.

Ngay cả với chính bạn, nó có thể hữu ích khi viết mã để chỉ cần gọi một số nhiệm vụ con chưa tồn tại, trong khi xây dựng chức năng chính và lo lắng về việc thực sự thực hiện chỉ mục phụ sau khi bạn biết rằng nó sẽ nhận được kết quả bạn cần trong một cách ý nghĩa. Điều này cũng được gọi là thiết kế / lập trình từ trên xuống.

Mã sử ​​dụng lại

Được rồi, vì vậy bất chấp những gì tôi đã nói trước đó, đôi khi thực sự cuối cùng lại có một lý do để sử dụng lại một bảng con cho một thứ khác. Tôi hoàn toàn không ủng hộ chủ nghĩa "phi hành gia kiến ​​trúc" mà chỉ bằng cách viết mã ghép lỏng lẻo, bạn có thể sẽ được hưởng lợi sau khi sử dụng lại.

Thông thường việc sử dụng lại có nghĩa là một số tái cấu trúc, điều này hoàn toàn được mong đợi, nhưng việc tái cấu trúc các tham số đầu vào thành một hàm độc lập nhỏ dễ dàng hơn nhiều so với trích xuất nó từ hơn 200 chức năng dòng sau khi nó được viết, đây thực sự là điểm của tôi ở đây.

Nếu bạn sử dụng một hàm lồng nhau, thì việc sử dụng lại nó thường là vấn đề tái cấu trúc thành một hàm riêng biệt, một lần nữa, đó là lý do tại sao tôi cho rằng lồng nhau không phải là hướng đi.


2
Đây là một số điểm thực sự hợp lệ để sử dụng các hàm nói chung, nhưng tôi không nhận được từ câu trả lời của bạn nếu bạn nghĩ rằng các hàm NESTED là một ý tưởng tốt. Hay bạn có được các chức năng trong phạm vi ngược dòng?
Slytael

Xin lỗi điểm tốt, tôi đã bị cuốn vào những lợi ích khác mà tôi quên giải quyết phần đó. :) Đã chỉnh sửa.
gregmac
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.