Di perusahaan saya, semua pengembangan kami (perbaikan bug dan fitur baru) dilakukan pada cabang terpisah. Ketika sudah selesai, kami mengirimkannya ke QA yang mengujinya di cabang itu, dan ketika mereka memberi kami lampu hijau, kami menggabungkannya ke cabang utama kami. Ini bisa memakan waktu antara hari dan tahun.
Jika kami mencoba memeras setiap refactoring ke dalam cabang, kami tidak tahu berapa lama akan "keluar", sehingga dapat menyebabkan banyak konflik saat digabungkan kembali.
Sebagai contoh, katakanlah saya ingin mengganti nama suatu fungsi karena fitur yang saya kerjakan sangat memanfaatkan fungsi ini, dan saya menemukan bahwa namanya tidak sesuai dengan tujuannya (sekali lagi, ini hanyalah sebuah contoh). Jadi saya berkeliling dan menemukan setiap penggunaan fungsi ini, dan mengubah nama mereka semua menjadi nama baru, dan semuanya berfungsi dengan baik, jadi saya mengirimkannya ke QA.
Sementara itu, pengembangan baru sedang terjadi, dan fungsi berganti nama saya tidak ada pada salah satu cabang yang sedang bercabang main. Ketika masalah saya digabungkan kembali, mereka semua akan rusak.
Apakah ada cara untuk mengatasi ini?
Ini tidak seperti manajemen akan pernah menyetujui masalah hanya refactor sehingga harus diperas dengan pekerjaan lain. Itu tidak dapat dikembangkan langsung pada main karena semua perubahan harus melalui QA dan tidak ada yang ingin menjadi brengsek yang memecahkan main sehingga ia bisa melakukan sedikit refactoring yang tidak penting.
Jawaban:
Ada beberapa masalah yang bercampur bersama untuk membuat refactoring menantang di lingkungan ini. Bercampur dengan ini adalah beberapa masalah non-teknis ("tapi itu masalah manajemen dan pertempuran yang belum saya menangkan").
Masalah pertama yang harus dilihat adalah cabang yang sudah berjalan lama. Cabang-cabang ini mengalami kesulitan melacak perubahan di luar tampilan pengembang. Untuk mengatasi ini:
Masalah lain yang mencampuradukkan hal ini adalah bahwa saya menyinggung poin-poin di atas adalah perubahan peran cabang dari waktu ke waktu. Ini dimulai sebagai cabang pengembangan di mana pengembang melakukan, dan kemudian menjadi area pengujian (pengujian apa yang sedang dilakukan di sini yang dapat bermakna di seluruh aplikasi?), Yang kemudian digabungkan menjadi stabil (dan mungkin dirilis - apakah itu diuji lagi?).
Dengan fitur yang lebih pendek, mulai dari waktu ke waktu, refactoring lebih mudah diambil oleh cabang lain.
Dorong pengembang untuk mendapatkan seluruh lingkungan. Hanya dengan memetik perubahan ceri dapat menyebabkan ... katakanlah lingkungan pengembang yang menarik. Sementara memetik ceri memiliki kegunaannya, untuk itu menjadi mode default dari menarik perubahan ke cabang bisa mengkhawatirkan.
Refactoring adalah sesuatu yang idealnya dilakukan terus-menerus, atau jika tidak terus-menerus setiap kali ada sedikit downtime. Cabang, lakukan refactoring sederhana, jalankan tes unit untuk memverifikasi semuanya masih berfungsi (unitnya diuji, kan? Benar? ) Dan kemudian bergabung kembali menjadi stabil. Sampaikan informasi untuk pengembang lain untuk menarik perubahan yang telah Anda refactored ke cabang mereka sendiri.
Penting bagi pengembang untuk memiliki kualitas kode. Meskipun arah fitur berasal dari luar, dan alokasi waktu seringkali bukan milik kita sendiri, kualitas kode adalah sesuatu yang perlu dibanggakan dan diluangkan waktu.
Anda mungkin menemukan pertanyaan-pertanyaan berikut berguna dalam pencarian untuk mengalokasikan waktu untuk berurusan dengan hutang teknis:
Anda mungkin juga ingin melihat alat-alat seperti sonar yang dapat membantu mengidentifikasi area kode yang paling membutuhkan pekerjaan untuk refactoring. The Plugin utang teknis adalah sesuatu yang dapat digunakan untuk membantu titik keluar akumulasi utang dari waktu ke waktu dalam basis kode.
Seringkali perlu untuk menunjukkan bahwa ROI untuk berurusan dengan utang teknis adalah waktu penyelesaian yang lebih cepat untuk fitur dan perbaikan bug dari tim pengembangan.
sumber
Biasanya saya mengembangkan versi refactored "paralel" dengan arus, yaitu dalam basis kode yang sama, tetapi tidak merujuknya dari aplikasi inti. Dan ketika solusi baru dilakukan dan diuji, saya memulai refactoring yang sebenarnya.
Contoh 1. Anggap saya memiliki benda, biarkan saja fungsi, antarmuka, modul, atau apa pun. Dan saya ingin memperbaikinya. Saya membuat Thing2 dalam basis kode yang sama, itu adalah versi refactored dari Thing. Ketika selesai dan diuji, saya refactoring semua yang mereferensikan Thing, untuk menggantinya dengan Thing2. Biasanya langkah ini membutuhkan waktu yang relatif sedikit.
Jika refactoring yang sebenarnya membutuhkan terlalu banyak waktu untuk tetap sinkron tanpa mengacaukan tim, saya mengambil semua fitur yang relevan, dan juga refactoring mereka secara paralel.
Contoh 2. Saya punya backend rendering baru, yaitu versi lama yang sudah di-refactored. Tapi itu tidak kompatibel dengan frontend rendering lama. Jadi, saya perlu memperbaiki frontend. Dan lagi: dalam basis kode yang sama. Ketika semuanya sudah selesai, saya hanya mengubah kelas instance frontend, idealnya akan membutuhkan satu komit pendek.
Ya, secara rekursif orang dapat menyimpulkan bahwa segala sesuatu harus dilakukan secara paralel. Tapi ini biasanya terjadi ketika ada terlalu banyak kopel dalam basis kode, atau itu berubah terlalu cepat.
Akhirnya, ketika kode baru terintegrasi dan berfungsi dengan baik, fitur lama dapat dihapus dari basis kode, dan fitur baru dapat diganti namanya untuk mendapatkan nama lama.
Secara umum, ide adalah untuk menyiapkan fitur-fitur baru secara paralel dan beralih untuk menggunakannya dengan satu langkah kecil.
John Carmack menggunakan pendekatan ini (atau paling tidak serupa), mungkin posting blognya menjelaskan lebih baik: (tautan)
sumber
Ini mungkin terlihat seperti kesulitan di sisi teknis ketika sebenarnya itu di sisi persyaratan.
Di mana pengembangan berorientasi pada persyaratan yang berbeda di cabang yang berbeda adalah kesulitan nyata. Manajer dan arsitek tim harus membuat keputusan yang dapat memungkinkan kebutuhan Bisnis yang berbeda untuk hidup berdampingan.
Proses ZBB dan Co-Dev "kompromi" ketika dilakukan setelah membuat keputusan yang tepat dengan input yang relevan dari semua pengembang, kata penutup memungkinkan Anda menerapkan apa yang Anda butuhkan tanpa harus berpikir - Bagaimana saya akan menggabungkan kode saya.
ZBB singkatan dari penganggaran berbasis Nol . Dengan mengatakan Co-Dev, saya bermaksud beberapa orang yang bekerja dalam pemrograman paralel.
sumber
Masalahnya bagi saya bahwa Anda bekerja terlalu lama di cabang. Biaya konflik tumbuh secara eksponensial dengan lamanya setiap orang menginap di cabang, jadi dengan konflik yang sangat lama Anda memiliki sedikit peluang untuk melakukan refactoring apa pun.
sumber
Masalah Anda adalah model cabang yang Anda gunakan. Anda bisa berkembang di cabang, dan ketika sudah selesai dan siap untuk QA, cabang akan digabung menjadi 'batang perantara', kadang-kadang disebut Integrasi atau Uji. Saat Anda mengembangkan fitur berikutnya, Anda dapat melakukan percabangan dari batang perantara ini sebagai gantinya.
Model ini memungkinkan Anda untuk mengembangkan beberapa fitur secara paralel pada cabang-cabang yang berbeda, menggabungkan semuanya bersama-sama ke cabang Integrasi untuk dikirim ke QA, dan juga mempertahankan satu batang rilis (Anda menggabungkan basis kode yang diterima QA ke bagasi utama ketika mereka mengesahkannya). )
Anda membuat asumsi bahwa perubahan Anda yang dikirimkan ke QA akan berlalu tanpa modifikasi besar sekalipun - jika kode QA kembali dengan instruksi untuk menghapus setengah dari perubahan, Anda harus mengembalikan tetapi jika itu tidak terjadi itu akan membuat perkembangan Anda jauh lebih lancar. Jadi Anda pada dasarnya mengambil cabang untuk fitur-fitur baru dari apa kode garis utama Anda nantinya (yaitu trunk setelah menggabungkan kode yang dilewatkan ke QA), daripada seperti sekarang ini (yaitu trunk saat ini) dan jadi tidak lagi berkembang terhadap basis kode rilis sebelumnya .
sumber