Saya mendengar banyak tentang menjaga metode tetap pendek dan saya telah mendengar banyak programmer mengatakan bahwa menggunakan tag #region dalam suatu metode adalah tanda yang pasti bahwa metode ini terlalu panjang dan harus di refactored menjadi beberapa metode. Namun, menurut saya ada banyak kasus di mana memisahkan kode dengan tag #region dalam suatu metode adalah solusi terbaik untuk refactoring ke dalam beberapa metode.
Misalkan kita memiliki metode yang komputasinya dapat dipisahkan menjadi tiga fase yang agak berbeda. Lebih jauh, masing-masing tahapan ini hanya relevan dengan perhitungan untuk metode ini , dan dengan mengekstraksinya ke dalam metode baru, tidak ada gunanya bagi kita untuk menggunakan kembali kode. Lalu, apa manfaat dari mengekstraksi setiap fase ke dalam metodenya sendiri? Sejauh yang saya tahu, yang kita dapatkan hanyalah keterbacaan dan ruang lingkup variabel yang terpisah untuk setiap fase (yang akan membantu mencegah modifikasi dari fase tertentu dari secara tidak sengaja melanggar fase lain).
Namun, kedua hal ini dapat dicapai tanpa mengekstraksi setiap fase ke dalam metodenya sendiri. Tag wilayah memungkinkan kami untuk menciutkan kode ke dalam bentuk yang sama terbaca (dengan manfaat tambahan bahwa kita tidak lagi harus meninggalkan tempat kita di file ini jika kita memutuskan untuk memperluas dan memeriksa kode), dan cukup membungkus setiap fase dalam {}
menciptakan ruang lingkup sendiri untuk bekerja dengannya.
Manfaat melakukannya dengan cara ini adalah bahwa kita tidak mencemari ruang lingkup tingkat kelas dengan tiga metode yang sebenarnya hanya relevan dengan cara kerja dalam metode keempat. Segera refactoring metode panjang menjadi serangkaian metode pendek bagi saya tampaknya menjadi kode-reuse yang setara dengan optimasi prematur; Anda memperkenalkan kompleksitas ekstra untuk mengatasi masalah yang dalam banyak kasus tidak pernah muncul. Anda selalu dapat mengekstrak salah satu fase ke dalam metode sendiri nanti jika ada peluang untuk menggunakan kembali kode.
Pikiran?
sumber
#region
tag, saya mematikan kode lipat di Visual Studio sama sekali. Saya tidak suka kode yang mencoba bersembunyi dari saya.Jawaban:
Yang harus Anda pedulikan hanyalah agar kode Anda dapat digunakan, bukan dapat digunakan kembali. Monyet dapat mengubah kode yang dapat digunakan menjadi kode yang dapat digunakan kembali, jika ada transformasi yang harus dilakukan sama sekali.
Argumen "Aku butuh ini hanya di sini" adalah miskin, untuk membuatnya sopan. Teknik yang Anda gambarkan sering disebut sebagai teknik tajuk utama dan umumnya tidak disukai.
Juga relevan: Pikiran Jeff Atwoods pada kode lipat
sumber
Ini bukan daerah dalam metode yang merupakan masalah, tetapi kasus ketika ada kebutuhan (atau bahkan penggunaan) untuk menempatkan daerah dalam metode.
Setelah harus men-debug banyak metode garis 200-300, saya dapat memberitahu Anda bahwa saya tidak akan berharap itu pada siapa pun. Jika Anda menulis dan menjaga kode Anda sendiri tidak apa-apa - lakukan apa pun yang Anda inginkan. Tetapi begitu orang lain melihatnya, harus segera jelas apa metode yang dilakukan.
Tidak, itu tidak cukup baik. Pecah menjadi beberapa wilayah yang Anda inginkan, tetapi saya masih menggelengkan kepala hanya memikirkannya.
Jika Anda masuk ke metode Anda mendapatkan banyak manfaat:
///
) dan masukkan deskripsi, parameter, kembali jenis, dan jugaexception
,example
,remarks
node terhadap detail skenario tersebut. Di situlah ia pergi, itu untuk apa!{}
, tetapi apakah saya harus memeriksa setiap metode untuk memastikan Anda tidak 'menipu'? Apakah ini yangdodgyObject
saya gunakan di sini hanya karena digunakan di wilayah ini, atau apakah itu berasal dari tempat lain? Jika saya menggunakan metode saya sendiri, saya akan dapat dengan mudah melihat apakah itu diteruskan kepada saya atau apakah saya membuatnya sendiri (atau lebih tepatnya, apakah Anda yang membuatnya).TurnThingsUpsideDown
metodenya gagal - mungkin gagal saat membalikkan hal yang buruk" jauh lebih baik daripada "Oh,DoEverything
metodenya gagal - bisa saja 50 hal berbeda dan aku harus menggali sekitar satu jam untuk menemukannya" .Ini semua sebelum masalah reusability atau improvability. Metode yang dipisahkan dengan benar jelas memfasilitasi penggunaan kembali, dan juga memungkinkan Anda dengan mudah mengganti metode yang tidak berkinerja (terlalu lambat, terlalu buggy, perubahan ketergantungan dll). Pernahkah Anda mencoba refactoring salah satu metode besar ini? Tidak ada cara untuk mengetahui bahwa apa yang Anda ubah tidak akan memengaruhi hal lain.
Harap enkapsulasi logika Anda dengan benar ke dalam metode berukuran wajar. Saya tahu bahwa mudah bagi mereka untuk keluar dari kendali, dan berpendapat bahwa tidak pantas mendesain ulang satu kali pada saat itu adalah masalah lain. Tetapi Anda harus menerima kenyataan bahwa tidak ada salahnya dan setidaknya potensi manfaat memiliki metode yang dienkapsulasi dengan benar, ditulis dengan rapi dan dirancang sederhana.
sumber
Jika metode Anda cukup kompleks sehingga dapat dipisahkan menjadi tiga fase yang berbeda, maka tidak hanya itu harus menjadi tiga metode yang terpisah ... tetapi metode Anda sebenarnya harus menjadi kelas yang terpisah, yang didedikasikan untuk perhitungan itu.
"Tapi kalau begitu kelasku hanya akan memiliki satu metode publik!"
Anda benar, dan tidak ada yang salah dengan itu. Gagasan prinsip tanggung jawab tunggal adalah bahwa kelas Anda melakukan satu hal .
Kelas Anda dapat memanggil masing-masing dari tiga metode secara bergantian, dan mengembalikan hasilnya. Satu hal.
Sebagai bonus, sekarang metode Anda dapat diuji karena ini bukan metode pribadi lagi.
Tapi jangan pedulikan satu kelas; pada kenyataannya Anda harus memiliki empat : Satu untuk masing-masing bagian dari metode Anda, ditambah satu yang menggunakan masing-masing ketiganya sebagai ketergantungan dan memanggil mereka dalam urutan yang tepat, mengembalikan hasilnya.
Ini membuat kelas Anda bahkan lebih dapat diuji. Ini juga memudahkan Anda untuk mengubah salah satu dari tiga potong itu. Cukup tulis kelas baru yang diwarisi dari yang lama, dan ganti perilaku yang berubah. Atau buat antarmuka untuk perilaku masing-masing dari tiga bagian Anda; dan kemudian untuk menggantinya, cukup tulis kelas baru yang mengimplementasikan antarmuka itu dan gantikan dengan yang lama dalam konfigurasi wadah injeksi ketergantungan Anda.
Apa? Anda tidak menggunakan injeksi ketergantungan? Yah, Anda mungkin belum melihat kebutuhan itu, karena Anda tidak mengikuti prinsip tanggung jawab tunggal. Setelah Anda mulai, Anda akan menemukan bahwa cara termudah untuk memberikan setiap kelas ketergantungannya adalah dengan menggunakan wadah DI.
EDIT :
Oke, mari kita kesampingkan pertanyaan refactoring. Tujuannya
#region
adalah untuk menyembunyikan kode , yang terutama berarti kode yang tidak perlu diedit dalam keadaan normal. Kode yang dihasilkan adalah contoh terbaik. Itu harus disembunyikan di daerah karena biasanya Anda tidak perlu mengeditnya. Jika Anda perlu melakukannya, maka tindakan memperluas wilayah memberi Anda sedikit -gaya peringatan "Here be dragons" untuk memastikan Anda tahu apa yang Anda lakukan.Oleh karena itu saya akan mengatakan
#region
seharusnya tidak digunakan di tengah-tengah sebuah metode. Jika saya membuka metode, saya ingin melihat kode. Menggunakan #region memberi saya tingkat persembunyian yang tidak saya butuhkan, dan itu menjadi gangguan: Saya membuka metode ini ... dan masih tidak dapat melihat kode apa pun.Jika Anda khawatir orang-orang melihat struktur metode (dan Anda menolak untuk menolaknya), maka tambahkan komentar spanduk seperti ini:
Ini akan membantu seseorang yang menelusuri kode melihat setiap bagian dari metode Anda tanpa harus berurusan dengan memperluas dan menciutkan
#region
tag.sumber
ctrl+n
Saya pikir contoh yang Anda berikan dalam argumen Anda kurang tentang YAGNI (Anda tidak akan membutuhkannya) dan lebih banyak tentang menulis kode kualitas yang tepat yang mudah dipelihara.
Dalam kursus pemrograman paling awal kita belajar bahwa jika suatu metode panjangnya 700 LOC, itu mungkin terlalu besar dan tentu saja akan sangat menyebalkan untuk dicoba dan didebug.
Kedua jika saya menulis metode A, B dan C yang hanya digunakan dalam metode D, maka saya dapat lebih mudah menguji unit AB dan C secara independen dari D, memungkinkan untuk tes unit yang lebih kuat di keempat metode.
sumber
Itulah dua manfaatnya. Tetapi yang penting, bagi saya, adalah debuggability . Jika Anda harus menelusuri kode itu, jauh lebih mudah untuk dapat Melangkah ke Dua dari tiga bagian dan hanya melacak ke bagian yang Anda pedulikan. Refactoring menjadi metode yang lebih kecil memungkinkan ini; tag wilayah tidak.
sumber
ctrl-f10
- lari ke kursorAturan pribadi saya adalah bahwa jika suatu metode lebih panjang dari satu layar, katakanlah 40 baris, itu terlalu panjang. Jika suatu kelas lebih panjang dari 500 baris, itu terlalu besar. Saya melanggar aturan-aturan ini kadang-kadang, kadang-kadang bahkan oleh kelipatan besar, tetapi saya biasanya menyesal dalam tahun ini.
Bahkan metode yang terdiri dari 20 hingga 30 baris agak lama dalam banyak kasus. Jadi saya akan mengatakan menggunakan daerah dalam suatu metode biasanya merupakan ide yang buruk, hanya karena hampir tidak pernah masuk akal untuk meruntuhkan wilayah 20 hingga 30 baris menjadi beberapa sub-wilayah.
Memecah fungsi yang panjang dengan definisi ini memiliki setidaknya dua manfaat:
Anda bisa memberi nama pada apa yang sub-fungsi lakukan, yang mengklarifikasi pemikiran Anda saat ini dan menyederhanakan tugas pengelola berikutnya.
Penguraian menjadi fungsi-fungsi yang lebih kecil memaksa Anda untuk hanya melewati parameter yang dibutuhkan fungsi-fungsi yang lebih kecil, sehingga ruang lingkup data yang mereka butuhkan dan modifikasi sangat jelas. Ini mengasumsikan Anda tidak mengakses dan mengubah status objek dalam seratus fungsi daun yang berbeda, yang juga akan saya tolak.
Dalam pengalaman saya, aturan-aturan ini menghasilkan kode yang lebih mudah untuk ditulis tanpa membuat kesalahan umum dan dapat dipahami dan dimodifikasi kemudian tanpa melanggar perilaku halus. Tidak masalah jika orang yang harus memahami / memodifikasi kode adalah orang lain, atau saya sendiri setelah saya tidur dan melupakan semuanya.
Jadi saya akan menganggap daerah dalam metode sebagai "bau kode" yang menunjukkan bahwa praktik yang tidak berkelanjutan sedang diterapkan. Seperti biasa, mungkin ada pengecualian, tetapi jarang terjadi sehingga hampir tidak layak untuk dibahas.
sumber
Kita mulai lagi ... Ada banyak topik lain di sini tentang programmer yang berakhir dengan diskusi yang sama.
Anda menunjukkan beberapa argumen yang sangat menarik terkait dengan fungsi pendek. Ini bukan pernyataan populer, tapi saya bersama Anda dalam hal ini . Setelah membahasnya berkali-kali sebelumnya, menurut saya diskusi biasanya bermuara pada apakah Anda terutama berfokus pada enkapsulasi yang tepat, atau mengikuti perkembangan yang didorong oleh tes. Ini adalah dua pesaing utama dalam apa yang tampaknya akan berubah menjadi perang suci lainnya, dan saya khawatir kita berada di pihak yang berada di bawah kekuasaan.
Namun ...
Solusi menurut saya jelas tidak membungkus 'fase' di daerah. Lipat kode digunakan untuk menyapu kode di bawah karpet. Biarkan kode di sana apa adanya, mungkin mengingatkan Anda bahwa Anda mungkin ingin memperbaiki itu nanti! Untuk mengaitkannya dengan argumen dalam pertanyaan Anda: bagaimana Anda dapat melihat peluang untuk menggunakan kembali kode jika Anda tidak melihat kode apa pun? Segmen kode yang panjang harus persis seperti itu, duri di mata yang membuat Anda ingin mengubahnya.
Sebagai pengganti yang sesuai untuk daerah, saya sarankan menggunakan paragraf kode sebagai nama Alex Papadimoulis mereka dalam komentar . Anda mungkin sebenarnya sudah menggunakan pendekatan serupa. Ini hanya blok kode dengan tajuk komentar, yang menjelaskan apa yang dilakukan seluruh blok. Anda memiliki keterbacaan fungsi, tetapi dapat menggunakan kalimat bahasa Inggris dengan spasi normal, dan Anda tidak kehilangan enkapsulasi.
sumber
Meskipun saya setuju bahwa biasanya lebih baik untuk memperbaiki kode daripada menggunakan
#region
, itu tidak selalu mungkin.Untuk mendukung pernyataan itu, izinkan saya memberi contoh.
Sangat mudah untuk menyesuaikan kembali wilayah untuk mengubah urutan, atau untuk memperluas ketika bidang tambahan ditambahkan ke kelas. Bagaimanapun, diperlukan komentar untuk segera melihat bagaimana pemesanan seharusnya berfungsi. Dan yang paling penting: Saya tidak melihat bagaimana refactoring akan membantu keterbacaan dalam kasus ini.
Namun, pengecualian itu jarang terjadi. Biasanya dimungkinkan untuk refactor, seperti banyak jawaban lain katakan.
sumber
Saya tidak berpikir ada satu jawaban untuk mengapa orang atau tim tertentu memutuskan untuk tidak menggunakan
#region
tetapi jika saya harus membuat daftar beberapa ini akan menjadi alasan utama yang saya lihat.sumber