Menciptakan fungsi bersarang untuk alasan estetika murni?

16

Saya selalu bertanya-tanya apa pendapat programmer lain tentang ide menciptakan fungsi estetika murni.

Katakanlah saya memiliki fungsi yang memproses sepotong data: Function ProcessBigData. Katakanlah saya perlu beberapa langkah proses, hanya berlaku untuk data yang: Step1, Step2, Step3.

Aproach normal yang saya lihat paling dalam kode sumber adalah menulis komentar seperti:

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

    #Does Step2
    Step2..
    Step2..

Apa yang biasanya saya lakukan, tetapi selalu merasa salah karena kurangnya gaya pengkodean seperti itu oleh sesama rekan adalah:

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

    Function Step2:
        Step2..
        Step2..

    Step1() -> Step2()

Saya terutama khawatir jika ada kelemahan untuk gaya seperti itu di Javascript dan Python

Apakah ada alternatif yang tidak saya lihat?

Slytael
sumber
3
Saya tidak bisa mengatakan apa-apa tentang Python, tetapi untuk Javascript, ada biaya kinerja untuk fungsi bersarang: sebagian besar mesin JavaScript menggunakan struktur seperti daftar-tertaut untuk mewakili ruang lingkup variabel. Menambahkan lapisan fungsi tambahan dengan demikian memaksa engine untuk mencari struktur data yang lebih panjang / lebih besar saat menyelesaikan variabel. Di sisi lain, akar dari semua kejahatan, tentu saja, optimasi prematur. :)
Marco

Jawaban:

4

Ini tidak seaneh yang Anda kira. Misalnya, dalam ML Standar itu biasa untuk membatasi ruang lingkup fungsi pembantu. Memang, SML memiliki sintaks untuk memfasilitasinya:

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

Saya akan mempertimbangkan gaya yang baik ini, mengingat bahwa 1) fungsi kecil memfasilitasi penalaran tentang program, dan 2) memberi sinyal kepada pembaca bahwa fungsi-fungsi ini tidak digunakan di luar ruang lingkup itu.

Saya kira itu mungkin ada beberapa overhead dalam menciptakan fungsi dalam setiap kali fungsi luar dipanggil (Saya tidak tahu apakah JS atau Python mengoptimalkan itu jauh) tetapi Anda tahu apa yang mereka katakan tentang optimasi prematur.

Doval
sumber
11

Biasanya merupakan hal yang baik untuk melakukan hal ini sedapat mungkin, tetapi saya suka menganggap pekerjaan semacam ini bukan sebagai "langkah", tetapi sebagai subtugas .

Subtugas adalah unit kerja tertentu yang dapat dilakukan: ia memiliki tanggung jawab spesifik, dan input dan output yang ditentukan (pikirkan "S" dalam SOLID ). Subtitle tidak perlu digunakan kembali: beberapa orang cenderung berpikir "Saya tidak akan pernah harus memanggil ini dari yang lain jadi mengapa menulisnya sebagai fungsi?" tapi itu salah.

Saya akan mencoba juga menguraikan manfaat dan juga bagaimana itu berlaku untuk fungsi bersarang (penutupan) vs hanya fungsi lain di kelas. Secara umum, saya akan merekomendasikan untuk tidak menggunakan penutupan kecuali Anda secara khusus membutuhkannya (ada banyak kegunaan, tetapi memisahkan kode menjadi potongan logis bukan salah satunya).

Keterbacaan.

200+ baris kode prosedural (badan fungsi) sulit dibaca. Fungsi 2-20 baris mudah dibaca. Kode untuk manusia.

Bersarang atau tidak, Anda sebagian besar mendapatkan manfaat keterbacaan, kecuali Anda menggunakan banyak variabel dari lingkup induknya, dalam hal ini bisa jadi sama sulitnya untuk dibaca.

Batasi ruang lingkup variabel

Memiliki fungsi lain memaksa Anda untuk membatasi ruang lingkup variabel, dan secara khusus melewati apa yang Anda butuhkan.

Ini sering juga membuat Anda menyusun kode lebih baik, karena jika Anda memerlukan semacam variabel status dari "langkah" sebelumnya, Anda mungkin benar-benar menemukan sebenarnya ada subtugas lain yang harus ditulis dan dijalankan terlebih dahulu untuk mendapatkan nilai itu. Atau dengan kata lain, membuatnya lebih sulit untuk menulis potongan kode yang sangat berpasangan.

Memiliki fungsi bersarang memungkinkan Anda untuk mengakses variabel dalam lingkup induk dari dalam fungsi bersarang (penutupan). Ini bisa sangat berguna, tetapi juga dapat menyebabkan bug yang sulit ditemukan karena eksekusi fungsi mungkin tidak terjadi dengan cara yang tertulis. Ini bahkan menjadi masalah jika Anda memodifikasi variabel dalam lingkup induknya (umumnya ide yang sangat buruk).

Tes unit

Setiap subtugas, menerapkan fungsi (atau bahkan kelas) adalah bagian kode yang berdiri sendiri, dapat diuji. Manfaat pengujian unit dan TDD didokumentasikan dengan baik di tempat lain.

Menggunakan fungsi / penutupan bersarang tidak memungkinkan pengujian unit. Bagi saya, ini adalah pemecah kesepakatan dan alasan mengapa Anda harus menjalankan fungsi lainnya, kecuali ada kebutuhan khusus untuk penutupan.

Bekerja pada desain tim / Top-down

Subtugas dapat ditulis oleh orang yang berbeda, secara mandiri, jika perlu.

Bahkan oleh Anda sendiri, dapat berguna ketika menulis kode untuk hanya memanggil beberapa subtugas yang belum ada, sambil membangun fungsionalitas utama, dan khawatir tentang benar-benar menerapkan subtugas hanya setelah Anda tahu itu akan mendapatkan hasil yang Anda butuhkan dalam sebuah cara yang berarti. Ini juga disebut desain / pemrograman Top-down.

Kode digunakan kembali

Oke, jadi terlepas dari apa yang saya katakan sebelumnya, kadang-kadang ada akhirnya menjadi alasan nanti untuk menggunakan kembali subtugas untuk hal lain. Saya sama sekali tidak mendukung "arsitektur astronot" -ism tetapi hanya dengan menulis kode yang digabungkan secara longgar, Anda mungkin mendapatkan manfaat nanti dari penggunaan kembali.

Seringkali yang menggunakan kembali berarti beberapa refactoring, yang sangat diharapkan, tetapi refactoring parameter input ke fungsi mandiri kecil JAUH lebih mudah daripada mengekstraksinya dari fungsi garis 200+ bulan setelah ditulis, yang benar-benar poin saya di sini.

Jika Anda menggunakan fungsi bersarang, menggunakannya kembali biasanya adalah masalah refactoring ke fungsi terpisah, yang lagi-lagi, itulah sebabnya saya berpendapat bahwa bersarang bukanlah cara yang harus dilakukan.

gregmac
sumber
2
Ini adalah beberapa poin yang benar-benar valid untuk menggunakan fungsi secara umum, tetapi saya tidak mendapatkan jawaban Anda jika Anda berpikir fungsi NESTED adalah ide yang bagus. Atau apakah Anda mendapatkan fungsi di lingkup hulu?
Slytael
Maaf poin bagus, saya terjebak dalam manfaat lain yang saya lupa untuk membahas bagian itu. :) Diedit.
gregmac