Haruskah kode yang lebih lama diperbarui untuk menggunakan konstruksi bahasa yang lebih baru, atau haruskah konstruksi yang sudah ketinggalan zaman terjebak dengan?

15

Saya ingin membuat beberapa peningkatan dalam beberapa kode masih-fungsional yang telah ditulis sejak lama, sebelum bahasa pemrograman ditulis dalam fitur tumbuh. Secara teori, keseluruhan proyek menggunakan versi bahasa yang terkini; Namun, modul khusus ini (dan pada kenyataannya, banyak modul lain) masih ditulis dalam dialek yang lebih tua.

Haruskah saya:

  • Tidak menyentuh bagian-bagian kode yang tidak harus saya sentuh, tetapi tulis tambalan saya dengan memanfaatkan fitur bahasa baru yang membuatnya lebih mudah untuk menulis tambalan tetapi tidak digunakan dalam situasi analog di tempat lain dalam modul? (Ini solusi yang saya pilih secara intuitif.)
  • Abaikan fakta bahwa bertahun-tahun telah berlalu, dan mencerminkan gaya yang digunakan dalam sisa kode saat menulis tambalan saya, secara efektif berperilaku seolah-olah saya melakukan tugas yang sama bertahun-tahun sebelumnya? (Solusi ini secara intuitif saya anggap konyol, tetapi mengingat banyaknya keributan yang dilakukan setiap orang yang berbicara tentang "kode yang baik" tentang menjaga konsistensi di semua biaya, mungkin inilah yang harus saya lakukan.)
  • Perbarui seluruh modul untuk menggunakan konstruksi dan konvensi bahasa yang lebih baru? (Ini mungkin solusi terbaik, tetapi mungkin membutuhkan banyak waktu & energi yang bisa lebih baik dihabiskan untuk tugas yang berbeda.)
gaazkam
sumber
1
@JerryCoffin Saya tidak akan terus berdebat dalam komentar: Saya memasang meta di mana kita bisa berdiskusi dengan benar.

Jawaban:

10

Tidak mungkin memberikan jawaban yang pasti untuk pertanyaan ini, karena terlalu banyak tergantung pada situasi.

Konsistensi dalam gaya basis kode adalah penting karena membantu dalam membuat kode lebih mudah dipahami, yang merupakan salah satu aspek terpenting dari pemeliharaan.
Anda tidak akan menjadi programmer pertama yang dikutuk ke neraka karena membuat kode sulit dimengerti dengan mencampur gaya yang berbeda. Bahkan mungkin diri Anda yang melakukan kutukan dalam waktu bertahun-tahun.

Di sisi lain, menggunakan konstruksi bahasa baru yang tidak ada ketika kode pertama kali ditulis tidak secara otomatis menyiratkan bahwa Anda mengurangi pemeliharaan atau bahkan Anda melanggar gaya kode. Itu semua tergantung pada fitur bahasa tertentu yang ingin Anda gunakan dan seberapa akrab tim dengan gaya kode yang lama dan fitur yang baru.

Sebagai contoh, umumnya tidak disarankan untuk mulai memperkenalkan konsep pemrograman fungsional seperti peta / reduksi ke basis kode yang sepenuhnya dalam gaya OO, tetapi bisa berfungsi untuk menambahkan fungsi lambda di sana-sini ke program yang tidak menggunakan hal seperti itu sebelumnya.

Bart van Ingen Schenau
sumber
1
Saya sebagian tidak setuju. Kita harus mengikuti prinsip buka tutup. Jadi kita harus mencoba untuk mengisolasi kode baru sebanyak yang kita bisa, dan pada saat yang sama menulis kode baru dengan konstruksi bahasa terbaru.
Anand Vaidya
3
@AnandVaidya: itu adalah harapan yang tidak realistis IMHO, karena mengasumsikan kode lama mengikuti OCP atau dapat dengan mudah diubah untuk mengikuti OCP, yang jarang terjadi atau tidak sepadan dengan usaha.
Doc Brown
1
Ketika saya mengatakan ocp, maksud saya bukan oops ocp, tetapi ocp secara umum. Itu pada dasarnya mencoba untuk tidak mengubah kode yang ada sebanyak mungkin, dan membuat kode Anda sendiri terisolasi. Itu bahkan mungkin dengan kode prosedural lama. Saya mengerti bahwa kode spaghetti tidak dapat dimodifikasi dengan cara itu, tetapi untuk kode yang dirancang dengan baik dalam paradigma apa pun, buka tutup harus mudah diterapkan. Mungkin oops atau prosedural atau fungsional.
Anand Vaidya
2
@AnandVaidya: bila Anda tidak bermaksud OCP, Anda tidak boleh menyebutnya demikian. Saya kira apa yang Anda maksud sebenarnya adalah panggilan Feather menulis kode baru dalam metode sprout , jadi orang dapat membatasi gaya kode baru ke metode baru yang terpisah. Ketika ini mungkin dan masuk akal, Anda benar, itu baik-baik saja. Sayangnya pendekatan ini tidak selalu berlaku, setidaknya tidak jika Anda ingin menjaga kode lama KERING.
Doc Brown
@ DocBrown: Saya tidak berpikir prinsip terbuka / tertutup terbatas pada pemrograman berorientasi objek. Anda dapat memiliki modul tempat Anda menambahkan prosedur baru tetapi tidak memodifikasi yang sudah ada, yaitu Anda mempertahankan semantik kode yang ada dan, jika Anda membutuhkan fungsionalitas baru, Anda menulis kode baru.
Giorgio
5

Sebagian besar, kode dan tampilannya tidak relevan . Apa yang kode lakukan adalah yang penting.

Jika Anda dapat menjamin bahwa mengubah / menulis ulang kode tidak akan mengubah apa yang dilakukan oleh kode tersebut, maka Anda dapat melanjutkan dan memperbaiki kode tersebut menjadi isi hati Anda. "Jaminan" itu adalah serangkaian unit test lengkap yang dapat Anda jalankan sebelum dan sesudah perubahan Anda, tanpa perbedaan yang nyata.

Jika Anda tidak dapat menjamin stabilitas itu (Anda belum mendapatkan tes-tes itu), maka biarkan saja.

Tidak ada yang akan berterima kasih kepada Anda karena telah "melanggar" perangkat lunak bisnis-kritis, bahkan jika Anda mencoba untuk membuatnya "lebih baik". "Bekerja" mengalahkan "lebih baik" setiap saat.

Tentu saja, tidak ada yang menghentikan Anda membuat serangkaian tes dalam kesiapan untuk latihan seperti itu ...

Phill W.
sumber
4

Hampir semua hal dapat dianalisis dalam hal biaya dan manfaat, dan saya pikir ini berlaku di sini.

Manfaat yang jelas dari opsi pertama adalah meminimalkan pekerjaan dalam jangka pendek, dan meminimalkan peluang melanggar sesuatu dengan menulis ulang kode kerja. Biaya yang jelas adalah memperkenalkan inkonsistensi ke dalam basis kode. Ketika Anda melakukan beberapa operasi X, itu dilakukan dengan satu cara di beberapa bagian kode, dan cara yang berbeda di bagian kode yang berbeda.

Untuk pendekatan kedua, Anda sudah mencatat manfaat yang jelas: konsistensi. Biaya yang jelas adalah bahwa Anda harus membengkokkan pikiran Anda untuk bekerja dengan cara yang mungkin telah Anda tinggalkan bertahun-tahun yang lalu, dan kode tetap konsisten tidak terbaca.

Untuk pendekatan ketiga, biaya yang jelas adalah harus melakukan lebih banyak pekerjaan. Biaya yang tidak terlalu jelas adalah Anda dapat merusak barang-barang yang berfungsi. Ini sangat mungkin terjadi jika (seperti yang sering terjadi) kode lama memiliki tes yang tidak memadai untuk memastikan bahwa kode itu terus berfungsi dengan benar. Manfaat yang jelas adalah bahwa (dengan asumsi Anda berhasil melakukannya) Anda memiliki kode baru yang bagus dan berkilau. Seiring dengan menggunakan konstruksi bahasa baru, Anda memiliki kesempatan untuk memperbaiki basis kode, yang hampir selalu akan memberikan perbaikan dalam dirinya sendiri, bahkan jika Anda masih menggunakan bahasa persis seperti yang ada ketika ditulis - tambahkan konstruksi baru yang membuat pekerjaan lebih mudah, dan itu mungkin merupakan kemenangan besar.

Satu poin utama lainnya: saat ini, tampaknya modul ini telah memiliki perawatan minimal untuk waktu yang lama (meskipun proyek secara keseluruhan sedang dipertahankan). Itu cenderung menunjukkan bahwa itu ditulis dengan cukup baik dan relatif bebas bug - jika tidak, itu mungkin akan mengalami lebih banyak pemeliharaan sementara.

Itu mengarah ke pertanyaan lain: apa sumber perubahan yang Anda buat sekarang? Jika Anda memperbaiki bug kecil di modul yang secara keseluruhan masih memenuhi persyaratannya dengan baik, itu akan cenderung menunjukkan bahwa waktu dan upaya refactoring seluruh modul kemungkinan besar akan sia-sia - pada saat seseorang perlu mengacaukan sekali lagi, mereka mungkin berada di posisi yang kira-kira sama dengan Anda sekarang, mempertahankan kode yang tidak memenuhi harapan "modern".

Namun, ada kemungkinan bahwa persyaratan telah berubah, dan Anda sedang mengerjakan kode untuk memenuhi persyaratan baru itu. Dalam hal ini, kemungkinan besar bahwa upaya pertama Anda tidak akan benar-benar memenuhi persyaratan saat ini. Ada juga peluang yang jauh lebih besar bahwa persyaratan akan menjalani beberapa putaran revisi sebelum mereka stabil kembali. Itu berarti Anda jauh lebih mungkin melakukan pekerjaan signifikan dalam modul ini dalam waktu yang relatif dekat, dan jauh lebih mungkin untuk melakukan perubahan di seluruh modul, tidak hanya di satu area yang Anda ketahui tentang benar. sekarang. Dalam hal ini, refactoring seluruh modul jauh lebih mungkin untuk memiliki manfaat nyata, jangka pendek yang membenarkan pekerjaan tambahan.

Jika persyaratan telah berubah, Anda mungkin juga perlu melihat jenis perubahan apa yang terlibat, dan apa yang mendorong perubahan itu. Misalnya, mari kita asumsikan Anda memodifikasi Git untuk mengganti penggunaan SHA-1 dengan SHA-256. Ini adalah perubahan dalam persyaratan, tetapi ruang lingkupnya jelas dan sempit. Setelah Anda membuatnya menyimpan dan menggunakan SHA-256 dengan benar, Anda tidak akan menemukan perubahan lain yang memengaruhi sisa basis kode.

Di arah lain, bahkan ketika itu mulai kecil dan terpisah, perubahan ke antarmuka pengguna memiliki kecenderungan untuk menggelembung, jadi apa yang dimulai sebagai "tambahkan satu kotak centang baru ke layar ini" berakhir lebih seperti: "ubah UI tetap ini untuk mendukung templat yang ditentukan pengguna, bidang khusus, skema warna yang disesuaikan, dll. "

Untuk contoh sebelumnya, mungkin paling masuk akal untuk meminimalkan perubahan dan kesalahan di sisi konsistensi. Untuk yang terakhir, refactoring lengkap jauh lebih mungkin untuk membayar.

Jerry Coffin
sumber
1

Saya akan memilihkan untuk Anda opsi pertama. Ketika saya kode saya mengikuti aturan untuk membiarkannya dalam keadaan yang lebih baik.

Jadi kode baru mengikuti praktik terbaik, tetapi saya tidak akan menyentuh kode yang tidak terkait dengan masalah yang sedang saya kerjakan. Jika Anda melakukan ini dengan baik, kode baru Anda harus lebih mudah dibaca dan dipelihara daripada kode lama. Saya menemukan bahwa perawatan total menjadi lebih baik, karena jika Anda terus begini, kode yang perlu Anda sentuh untuk pekerjaan Anda semakin sering menjadi kode "lebih baik". Yang menyebabkan penyelesaian masalah lebih cepat.

Pieter B
sumber
1

Jawabannya, seperti banyak hal lain, adalah tergantung . Jika ada keuntungan besar untuk memperbarui konstruksi lama, seperti pemeliharaan jangka panjang yang jauh lebih baik (menghindari panggilan balik neraka, misalnya) daripada pergi untuk itu. Jika tidak ada keuntungan besar, konsistensi mungkin adalah teman Anda

Selain itu, Anda juga ingin menghindari menyematkan dua gaya dalam fungsi yang sama lebih dari yang ingin Anda hindari dalam dua fungsi terpisah.

Singkatnya: keputusan akhir Anda harus didasarkan pada analisis 'biaya' / 'manfaat' dari kasus khusus Anda.


sumber