Apakah berguna untuk kode mini-refactor dengan harapan meningkatkan kualitas, atau hanya "memindahkan kode" tanpa banyak manfaat?

12

Contoh

Saya menemukan kode monolitik yang melakukan "segalanya" di satu tempat - memuat data dari basis data, menunjukkan markup HTML, bertindak sebagai router / controller / action. Saya mulai menerapkan kode database bergerak SRP ke file sendiri, memberikan penamaan yang lebih baik untuk hal-hal, dan semuanya terlihat bagus, tapi kemudian saya mulai ragu mengapa saya melakukan ini.

Mengapa refactor? Apa tujuannya? Apakah itu tidak berguna? Apa manfaatnya? Perhatikan bahwa saya kebanyakan meninggalkan file monolitik seperti apa adanya, tetapi hanya me-refacted bagian yang lebih kecil yang relevan dengan area di mana saya perlu melakukan beberapa pekerjaan.

Kode asli:

Untuk memberikan contoh nyata, saya menemukan potongan kode ini - ia memuat spesifikasi produk baik oleh id produk yang dikenal, atau oleh id versi yang dipilih pengguna:

if ($verid)
    $sql1 = "SELECT * FROM product_spec WHERE id = " . clean_input($verid);
else
    $sql1 = "SELECT * FROM product_spec WHERE product_id = " . clean_input($productid) ;
$result1 = query($sql1);
$row1 = fetch_array($result1);
/* html markup follows */

Refactoring:

Karena saya sedang melakukan pekerjaan yang mengharuskan saya untuk mengubah hal-hal di bagian kode ini, saya mengubahnya untuk menggunakan pola repositori dan memutakhirkannya untuk menggunakan fasilitas MySQL berorientasi objek:

//some implementation details omitted 
$this->repository = new SpecRepository($mysql);
if ($verid)
    $row1 = $this->repository->getSpecByVersion($verid);
else 
    $row1 = $this->repository->getSpecByProductId($productid);
/* html markup follows to be refactored or left alone till another time*/

//added new class:
class SpecRepository extends MySqlRepository
{

    function getSpecByVersion(int $verid)
    {
        return $this->getMySql()->paramQuery("
            SELECT * FROM product_spec WHERE id = ?
        ", $verid)->getSingleArray();
    }

    function getSpecByProductId(int $productid)
    {
        return $this->getMySql()->paramQuery("
            SELECT * FROM product_spec WHERE product_id = ?
        ", $productid)->getSingleArray();
    }
}

Haruskah saya melakukan ini?

Melihat kembali perubahan, kodenya masih ada, kode dengan fungsi yang sama, tetapi dalam file yang berbeda, nama yang berbeda, tempat, menggunakan gaya berorientasi objek yang lebih daripada prosedural. Sebenarnya itu lucu untuk dicatat bahwa kode refactored terlihat jauh lebih besar meskipun memiliki fungsi yang sama.

Saya memperkirakan beberapa jawaban mengatakan "jika Anda tidak tahu alasan mengapa Anda menolak, jangan lakukan itu", dan mungkin saya mungkin setuju. Alasan saya adalah untuk meningkatkan kualitas kode dari waktu ke waktu (dan harapan saya adalah bahwa saya akan melakukannya dengan mengikuti SRP dan prinsip-prinsip lain).

Apakah itu alasan yang cukup baik atau saya membuang-buang waktu saya pada "menata ulang kode sekitar" dengan cara ini? Secara keseluruhan, refactoring ini terasa seperti menginjak air dengan jujur ​​- ini membutuhkan waktu dan menjadi lebih "terpisah" sejauh SRP berjalan tetapi meskipun ada niat baik saya, saya tidak merasa seperti saya melakukan perbaikan yang luar biasa. Karenanya, berdebat apakah yang terbaik untuk meninggalkan kode seperti sebelumnya dan bukan refactor.

Mengapa saya refactor sejak awal?

Dalam kasus saya, saya menambahkan fungsionalitas baru untuk lini produk baru, jadi saya harus mengikuti struktur kode yang ada untuk lini produk serupa, atau menulis sendiri.

Dennis
sumber
PL tetapi sesuatu yang perlu dipertimbangkan adalah yang Select * from ..dapat dianggap sebagai anti-pola. Lihat stackoverflow.com/q/3639861/31326
Peter M
1
@PeterM: Kecuali jika Anda sedang menulis ORM, dalam hal ini select *menjadi "praktik terbaik."
Robert Harvey
@RobertHarvey Dalam hal ini saya mempertanyakan mengapa Anda menulis ORM Anda sendiri: D
Peter M
Saya telah melakukan refactor untuk alasan yang tidak relevan. Menebang hutang teknis adalah baik segera setelah manfaat melebihi biaya. Sepertinya ini kasusmu. Pertanyaannya adalah: Apakah Anda memiliki tes yang tepat untuk memastikan bahwa kode tersebut masih berfungsi seperti yang diharapkan?
Laiv
1
Reliabilitas harus menjadi metrik utama ketika refactoring IMO, bukan rawatan yang berkaitan dengan kemampuan berubah, karena reliabilitas mengurangi alasan untuk hal-hal yang berubah di tempat pertama. Ini meningkatkan stabilitas, dan kode yang sangat stabil dan dapat diandalkan serta memenuhi semua yang diperlukan untuk melakukan sedikit biaya pemeliharaan, karena sangat sedikit alasan untuk harus berubah. Berupayalah untuk mengurangi alasan hal-hal berubah daripada berusaha membuatnya semudah mungkin untuk diubah. Mencari mantan juga akan cenderung memberikan beberapa yang terakhir.

Jawaban:

13

Dalam contoh konkret yang Anda berikan, refactoring mungkin tidak diperlukan, setidaknya belum. Tetapi Anda melihat bahwa ada potensi kode berantakan di masa depan yang akan mengarah pada refactoring yang lebih lama dan lebih membosankan, jadi Anda mengambil inisiatif dan membersihkan semuanya sekarang.

Saya juga akan mengatakan keuntungan yang Anda peroleh di sini adalah kode yang lebih mudah dipahami, setidaknya dari sudut pandang saya, sebagai seseorang yang tidak tahu basis kode Anda.


Secara umum:

Apakah refactoring memudahkan pengembang lain untuk memahami kode Anda?

Apakah refactoring membuatnya lebih mudah untuk meningkatkan kode?

Apakah refactoring membuatnya lebih mudah untuk mempertahankan kode?

Apakah refactoring membuatnya lebih mudah untuk di-debug?

Jika jawaban untuk semua ini adalah "ya", maka itu layak, dan itu lebih dari sekadar "memindahkan kode?"

Jika jawaban untuk semua ini adalah "tidak", maka mungkin itu tidak perlu di refactored.

Ukuran akhir basis kode mungkin lebih besar dalam hal LoC (meskipun beberapa refactoring dapat mengecilkan basis kode dengan merampingkan kode berlebihan), tetapi itu seharusnya tidak menjadi faktor jika ada keuntungan lain.

FrustratedWithFormsDesigner
sumber
9

Refactoring benar-benar kembung jika Anda membongkar sebuah monolith.

Namun, Anda sudah menemukan manfaatnya.

"Dalam kasus saya, saya menambahkan fungsionalitas baru untuk lini produk baru."

Anda tidak dapat menambahkan fungsionalitas ke monolith dengan mudah tanpa merusaknya.

Anda mengatakan bahwa kode yang sama mendapatkan data dan melakukan markup. Hebat, sampai Anda ingin mengubah kolom mana yang Anda pilih dan manipulasi untuk ditampilkan dalam kondisi tertentu. Tiba-tiba, kode markup Anda berhenti bekerja dalam kasus tertentu dan Anda harus melakukan refactor.

Diaken
sumber
ya, tapi saya juga bisa terus menambahkan ke monolith bahkan untuk fungsi baru :) yaitu saya akan menambahkan if/elseblok baru dan mengikuti gaya kode asli untuk menambahkan pernyataan SQL, dan kemudian saya akan menempatkan markup HTML baru di file monolith yang sama. Dan untuk mengubah kolom saya akan menemukan if / else block yang bertanggung jawab untuk menampung baris SQL, dan mengedit SQL itu untuk membuat perubahan pada kolom, tanpa memecah file itu.
Dennis
Dengan pendekatan refactored, saya kemungkinan pertama pergi ke blok if / else di monolith untuk melihat bahwa saya perlu pergi ke file repositori yang terpisah untuk mengubah SQL. Atau jika saya mengerjakan monolith itu baru-baru ini saya akan tahu untuk langsung masuk ke file repositori, melewati monolith. Atau jika saya mencari basis kode saya untuk SQL spesifik pencarian akan menempatkan saya ke dalam file repositori baru juga melewati monolit
Dennis
2

Saya mempertimbangkan refactoring jika saya tahu bahwa saya harus bekerja berbulan-bulan atau bahkan bertahun-tahun dengan proyek itu. Jika saya harus melakukan perubahan di sana-sini, maka saya menahan diri saya untuk memindahkan kode.

Cara yang disukai untuk melakukan refactoring adalah ketika saya memiliki kode dasar dengan semacam tes otomatis. Meski begitu saya harus sangat berhati-hati dengan apa yang saya ubah untuk memastikan semuanya berjalan seperti sebelumnya. Anda akan kehilangan kepercayaan segera jika Anda memberikan bug di area lain dari yang seharusnya Anda kerjakan.

Saya menghargai refactoring karena alasan berikut:

  • Saya mengerti kode lebih baik
  • Saya menghapus kode duplikat jadi jika saya memiliki bug di satu tempat saya tidak perlu mencari di mana kode telah disalin disalin
  • Saya membuat kelas yang memiliki peran yang jelas. Sebagai contoh, saya dapat menggunakan kembali repositori yang sama untuk membuat halaman HTML, XML feed atau pekerjaan latar belakang. Ini tidak akan mungkin terjadi jika kode akses database hanya hidup di kelas HTML
  • Saya mengganti nama variabel, metode, kelas, modul, folder jika tidak cocok dengan kenyataan saat ini; Saya commentkode melalui nama variabel, nama metode
  • Saya menyelesaikan bug kompleks dengan kombinasi antara unit test dan refactoring
  • Saya memiliki fleksibilitas untuk mengganti seluruh modul, paket. Jika ORM saat ini sudah usang, bermasalah atau tidak terawat, maka lebih mudah untuk menggantinya jika tidak tersebar di seluruh proyek.
  • Saya menemukan kemampuan atau peningkatan baru yang menghasilkan proposal untuk pelanggan.
  • Saya membuat komponen yang dapat digunakan kembali. Ini adalah salah satu manfaat terbesar karena pekerjaan yang dilakukan dalam proyek itu dapat digunakan kembali untuk klien / proyek lain.
  • Saya sering memulai dengan solusi yang paling bodoh, hardcoded, aneh dan saya refactor nanti setelah saya belajar lebih banyak. Momen nanti ini mungkin hari ini atau mungkin setelah beberapa hari. Saya tidak ingin menghabiskan terlalu banyak waktu untuk architectsolusinya. Ini akan datang saat menulis - menulis ulang kode bolak-balik.

Dalam dunia yang sempurna, refactoring harus diverifikasi oleh unit test, tes integrasi seterusnya. Jika tidak ada, coba tambahkan. Juga beberapa IDE mungkin banyak membantu. Saya biasanya menggunakan plugin yang membutuhkan biaya. Saya ingin menghabiskan sedikit waktu dengan refactorings dan menjadi sangat efisien.

Saya juga memperkenalkan bug. Saya dapat melihat mengapa beberapa QA bertanya. are you guys doing refactoring? because everything stopped working!Ini adalah risiko yang harus dihadapi tim dan kami harus selalu transparan tentang hal itu.

Selama bertahun-tahun saya menemukan bahwa refactoring berkelanjutan meningkatkan produktivitas saya. Jauh lebih mudah untuk menambahkan fitur baru. Rekondisi besar juga tidak memerlukan penulisan ulang keseluruhan seperti yang sering terjadi ketika basis kode tidak disesuaikan dengan evolusi produk. Itu juga menyenangkan.

Adrian Iftode
sumber
Ini sangat dekat dengan suara turun - Tidak ada 'I' di 'Computer programmer'. Dengan 'saya', apakah Anda, saya 'saya' (memilih) atau maksud Anda para pengembang yang mengerjakan kode sekarang dan di masa depan?
mattnz
Saya memperhatikannya juga, tetapi saya memakainya. Saya juga bekerja sebagai pengembang solo selama bertahun-tahun dan ketika saya menulis jawaban ini saya mengulangi sebagian besar dari pengalaman itu. Saya bisa mengganti Idengan to.
Adrian Iftode
1

Saya pikir pertanyaan yang harus Anda tanyakan pada diri sendiri adalah tidak begitu banyak "Apakah ada manfaatnya?" tetapi "Siapa yang akan membayar pekerjaan ini?"

Kita semua dapat berdebat tentang manfaat yang dirasakan sampai akhir hari, tetapi kecuali jika Anda memiliki pelanggan yang percaya pada manfaat itu dan menilai mereka cukup untuk membayar perubahan Anda tidak harus melakukannya.

Ini semua terlalu mudah ketika Anda berada di tim pengembang di suatu tempat untuk melihat kode dan ingin mengubahnya menjadi 'lebih baik'. Tetapi memberikan nilai pada 'kode yang lebih baik' ketika produk sudah bekerja sangat sulit.

Hal-hal seperti 'pengembangan fitur baru yang lebih cepat' tidak memotongnya karena hanya mengurangi biaya. Anda perlu menghasilkan penjualan.

Ewan
sumber
1

Menurut saya refactoring adalah investasi yang bagus.

Kalau tidak, Anda akan segera mendapatkan utang teknis (masalah yang tidak terpecahkan, kode buruk yang hanya berfungsi dalam kondisi tertentu, dll.). Utang teknis akan segera menjadi lebih besar dan lebih besar, sampai perangkat lunak tidak lagi dapat dipertahankan.

Tetapi untuk membuat refactoring berfungsi, Anda juga harus berinvestasi dalam tes. Anda harus membuat tes otomatis, idealnya Anda harus memiliki tes unit dan tes integrasi. Ini memudahkan Anda dari melanggar kode yang ada.

Jika Anda harus meyakinkan bos atau kolega Anda, Anda harus membaca beberapa buku tentang metode gesit (misalnya SCRUM) dan pengembangan yang didorong oleh tes.

bernie
sumber