Saya baru saja menulis fungsi yang membentang sekitar 100 baris. Mendengar itu, Anda mungkin tergoda untuk memberi tahu saya tentang tanggung jawab tunggal dan mendesak saya untuk menolak. Ini naluri saya juga, tapi ini masalahnya: Fungsi melakukan satu hal. Ini melakukan manipulasi string yang kompleks, dan fungsi tubuh sebagian besar terdiri dari satu regex verbose, dipecah menjadi banyak baris yang didokumentasikan. Jika saya memecah regex menjadi beberapa fungsi, saya merasa seperti saya akan benar-benar kehilangan keterbacaan, karena saya secara efektif beralih bahasa, dan tidak akan dapat mengambil keuntungan dari beberapa fitur yang ditawarkan regex. Ini pertanyaan saya sekarang:
Ketika menyangkut manipulasi string dengan ekspresi reguler, apakah fungsi besar masih anti-pola? Sepertinya kelompok yang diberi nama melayani tujuan yang sangat mirip dengan fungsi. Omong-omong, saya memiliki tes untuk setiap aliran melalui regex.
sumber
Jawaban:
Apa yang Anda temui adalah disonansi kognitif yang berasal dari mendengarkan orang-orang yang mendukung kepatuhan terhadap pedoman dengan kedok "praktik terbaik" atas pengambilan keputusan yang beralasan.
Anda jelas telah melakukan pekerjaan rumah Anda:
Jika salah satu dari poin itu tidak benar, saya akan menjadi yang pertama mengatakan bahwa fungsi Anda perlu bekerja. Jadi ada satu suara untuk meninggalkan kode apa adanya.
Suara kedua berasal dari melihat opsi Anda dan apa yang Anda dapatkan (dan kehilangan) dari masing-masing:
Keputusan ini jatuh di mana Anda lebih menghargai: keterbacaan atau panjang. Saya jatuh ke dalam kemah yang percaya bahwa panjang itu bagus tapi mudah dibaca itu penting dan akan mengambil yang terakhir dari yang pertama setiap minggu.
Intinya: jika tidak rusak, jangan memperbaikinya.
sumber
Jujur, fungsi Anda mungkin "melakukan satu hal", tetapi seperti yang Anda nyatakan sendiri
yang berarti kode reg Anda melakukan banyak hal. Dan saya kira itu bisa dipecah menjadi lebih kecil, unit yang dapat diuji secara individual. Namun, jika ini adalah ide yang baik tidak mudah dijawab, (terutama tanpa melihat kode yang sebenarnya). Dan jawaban yang benar mungkin bukan "ya" atau "tidak", tapi "belum, tapi lain kali Anda harus mengubah sesuatu di reg exp itu".
Dan ini adalah intinya - Anda memiliki kode yang ditulis dalam bahasa reg ex . Bahasa ini tidak menyediakan sarana abstraksi yang baik (dan saya tidak menganggap "kelompok penangkap" sebagai pengganti fungsi). Jadi refactoring "dalam bahasa reg ex" tidak benar-benar mungkin, dan menjalin exp yang lebih kecil dengan bahasa host mungkin tidak benar-benar meningkatkan keterbacaan (setidaknya, Anda merasa begitu, tetapi Anda memiliki keraguan, jika tidak, Anda tidak akan memposting pertanyaan) . Jadi inilah saran saya
tunjukkan kode Anda ke pengembang lanjutan lain (mungkin di /codereview// ) untuk memastikan orang lain berpikir tentang keterbacaan seperti yang Anda lakukan. Bersikaplah terbuka terhadap gagasan bahwa orang lain mungkin tidak menemukan reg line 100 exp yang dapat dibaca seperti Anda. Kadang-kadang gagasan "tidak mudah pecah menjadi potongan-potongan kecil" dapat diatasi hanya dengan sepasang mata yang kedua.
mengamati evolvabilitas aktual - apakah reg Anda yang mengkilap masih terlihat begitu baik ketika persyaratan baru tiba dan Anda harus menerapkan dan mengujinya? Selama reg exp Anda berfungsi, saya tidak akan menyentuhnya, tetapi setiap kali sesuatu harus diubah, saya akan mempertimbangkan kembali jika itu benar-benar ide yang baik untuk menempatkan setiap orang ke dalam satu blok besar ini - dan (serius!) Memikirkan kembali jika membelah menjadi potongan yang lebih kecil tidak akan menjadi pilihan yang lebih baik.
amati rawatan - dapatkah Anda secara efektif men-debug reg exp dalam bentuk saat ini dengan sangat baik? Terutama setelah Anda harus mengubah sesuatu, dan sekarang tes Anda memberi tahu Anda ada sesuatu yang salah, apakah Anda memiliki debugger reg exp yang membantu Anda menemukan akar masalahnya? Jika debugging menjadi sulit, itu juga akan menjadi kesempatan untuk mempertimbangkan kembali desain Anda.
sumber
Terkadang fungsi yang lebih panjang yang melakukan satu hal adalah cara yang paling tepat untuk menangani suatu unit kerja. Anda dapat dengan mudah masuk ke fungsi yang sangat panjang ketika Anda mulai berurusan dengan query database (menggunakan bahasa query favorit Anda). Untuk membuat suatu fungsi (atau metode) lebih mudah dibaca sementara membatasinya untuk tujuan yang dinyatakannya adalah apa yang saya anggap sebagai hasil yang paling diinginkan dari suatu fungsi.
Panjang adalah "standar" sewenang-wenang dalam hal ukuran kode. Di mana fungsi 100 baris dalam C # dapat dianggap gondrong, itu akan menjadi kecil di beberapa versi perakitan. Saya telah melihat beberapa query SQL yang masuk ke dalam 200 baris rentang kode yang mengembalikan satu set data yang sangat rumit untuk sebuah laporan.
Kode sepenuhnya bekerja , yang adalah yang sederhana seperti Anda dapat cukup membuatnya adalah tujuan.
Jangan mengubahnya hanya karena itu panjang.
sumber
Anda selalu dapat memecah regex menjadi sub-regex, dan secara bertahap menyusun ekspresi akhir. Ini bisa membantu pemahaman untuk pola yang sangat besar, terutama jika sub-pola yang sama diulang berkali-kali. Misalnya dalam Perl;
sumber
Saya akan mengatakan istirahat jika itu bisa pecah. dari sudut pandang rawatan dan mungkin daya masuk akal untuk melanggarnya, tetapi tentu saja Anda harus mempertimbangkan secara alami fungsi Anda dan bagaimana Anda mendapatkan input dan apa yang akan dikembalikan.
Saya ingat saya sedang mengerjakan parsing streaming chunked data menjadi objek, jadi apa yang saya lakukan pada dasarnya adalah saya membaginya menjadi dua bagian utama, satu sedang membangun unit String lengkap dari teks yang disandikan dan pada bagian kedua mengurai unit-unit tersebut ke dalam kamus data dan mengatur mereka (bisa berupa properti acak untuk objek yang berbeda) dan daripada memperbarui atau membuat objek.
Saya juga dapat memecah setiap bagian utama menjadi beberapa fungsi yang lebih kecil dan lebih spesifik sehingga pada akhirnya saya memiliki 5 fungsi berbeda untuk melakukan semuanya dan saya dapat menggunakan kembali beberapa fungsi di tempat yang berbeda.
sumber
Satu hal yang Anda mungkin atau mungkin tidak mempertimbangkan adalah untuk menulis parser kecil dalam bahasa yang Anda gunakan alih-alih menggunakan regex dalam bahasa itu. Ini mungkin lebih mudah dibaca, diuji, dan dirawat.
sumber
Regex raksasa adalah pilihan yang buruk dalam banyak kasus. Dalam pengalaman saya, mereka sering digunakan karena pengembang tidak terbiasa dengan parsing (lihat jawaban Thomas Eding ).
Bagaimanapun, mari kita asumsikan Anda ingin tetap berpegang pada solusi berbasis regex.
Karena saya tidak tahu kode sebenarnya, saya akan memeriksa dua skenario yang mungkin:
Regex sederhana (banyak pencocokan literal dan beberapa alternatif)
Dalam hal ini fitur-fitur canggih yang ditawarkan oleh satu regex tidak diperlukan. Ini berarti Anda kemungkinan akan mendapat manfaat dari membaginya.
Regex itu kompleks (banyak alternatif)
Dalam hal ini Anda tidak dapat secara realistis memiliki cakupan pengujian penuh, karena Anda mungkin memiliki jutaan kemungkinan aliran. Jadi, untuk mengujinya, Anda harus membaginya.
Saya mungkin kurang imajinasi, tetapi saya tidak bisa memikirkan situasi dunia nyata di mana regex 100-line adalah solusi yang baik.
sumber