Saat ini kami memiliki satu cabang master untuk aplikasi PHP kami di repositori bersama. Kami memiliki lebih dari 500 klien yang merupakan pelanggan dari perangkat lunak kami, yang sebagian besar memiliki beberapa penyesuaian untuk tujuan yang berbeda, masing-masing di cabang terpisah. Kustomisasi dapat berupa nama bidang teks yang berbeda, fitur atau modul yang sama sekali baru, atau tabel / kolom baru dalam database.
Tantangan yang kami hadapi adalah ketika kami mempertahankan ratusan cabang yang disesuaikan ini dan mendistribusikan kepada klien, dari waktu ke waktu kami menyediakan fitur baru dan memperbarui cabang utama kami, dan kami ingin mendorong perubahan cabang utama ke cabang-cabang khusus untuk memperbarui. mereka ke versi terbaru.
Sayangnya hal ini sering mengakibatkan banyak konflik dalam kode khusus, dan kami menghabiskan banyak waktu melalui setiap cabang untuk menyelesaikan semua konflik. Ini sangat tidak efisien, dan kami menemukan bahwa kesalahan tidak jarang terjadi ketika menyelesaikan konflik ini.
Saya mencari cara yang lebih efisien untuk memperbarui cabang rilis klien kami dengan cabang utama yang akan menghasilkan lebih sedikit upaya selama penggabungan.
sumber
Jawaban:
Anda benar-benar cabang yang menyalahgunakan! Anda harus memiliki penyesuaian yang didukung oleh fleksibilitas dalam aplikasi Anda, bukan fleksibilitas dalam kontrol versi Anda (yang, seperti yang Anda temukan, tidak dimaksudkan / dirancang untuk penggunaan semacam ini).
Misalnya, buat label bidang teks berasal dari file teks, bukan hardcoded ke dalam aplikasi Anda (beginilah cara kerja internasionalisasi). Jika beberapa pelanggan memiliki fitur yang berbeda, buat aplikasi Anda modular , dengan batas-batas internal yang ketat diatur oleh API yang ketat dan stabil, sehingga fitur-fitur dapat dicolokkan sesuai kebutuhan.
Infrastruktur inti, dan semua fitur bersama, maka hanya perlu disimpan, dipelihara, dan diuji sekali .
Anda harus melakukan ini sejak awal. Jika Anda sudah memiliki lima ratus varian produk (!), Memperbaiki ini akan menjadi pekerjaan besar ... tetapi tidak lebih dari pemeliharaan yang berkelanjutan.
sumber
Memiliki 500 klien adalah masalah yang bagus, jika Anda menghabiskan waktu di depan untuk menghindari masalah ini dengan cabang, Anda mungkin tidak akan pernah bisa berdagang cukup lama untuk mendapatkan klien.
Pertama, saya harap Anda membebankan biaya cukup pada klien Anda untuk menutupi SEMUA biaya untuk mempertahankan versi khusus mereka. Saya berasumsi bahwa klien berharap untuk mendapatkan versi baru tanpa harus membayar untuk penyesuaian mereka dilakukan lagi. Saya akan mulai dengan menemukan semua file yang sama di 95% cabang Anda. 95% itu adalah bagian yang stabil dari aplikasi Anda.
Kemudian, cari semua file yang hanya memiliki beberapa baris berbeda di antara cabang-cabang - cobalah untuk memperkenalkan sistem konfigurasi sehingga perbedaan-perbedaan ini dapat dihapus. Jadi, misalnya, daripada memiliki 100-an file dengan label bidang teks yang berbeda, Anda memiliki 1 file konfigurasi yang dapat menimpa label teks apa pun. (Ini tidak harus dilakukan dalam sekali jalan, cukup buat label bidang teks dapat dikonfigurasi saat pertama kali klien ingin mengubahnya.)
Kemudian pindah ke masalah yang lebih sulit menggunakan pola Strategi, injeksi ketergantungan dll.
Pertimbangkan untuk menyimpan json dalam database daripada menambahkan kolom untuk bidang klien sendiri - ini dapat bekerja untuk Anda jika Anda tidak perlu mencari bidang ini dengan SQL.
Setiap kali Anda memeriksa file menjadi cabang, Anda HARUS membedakannya dengan main dan membenarkan setiap perubahan, termasuk ruang putih. Banyak perubahan tidak akan diperlukan dan dapat dihapus sebelum checkin. Ini mungkin hanya tergantung pada satu pengembang yang memiliki pengaturan berbeda di editor mereka untuk bagaimana kode diformat.
Anda bertujuan untuk pertama pergi dari 500 cabang dengan banyak file yang berbeda, untuk sebagian besar cabang hanya memiliki beberapa file yang berbeda. Sementara masih menghasilkan cukup uang untuk hidup.
Anda mungkin masih memiliki 500 cabang dalam waktu bertahun-tahun, tetapi jika mereka jauh lebih mudah dikelola, maka Anda telah menang.
Berdasarkan komentar oleh br3w5:
Hanya lakukan hal di atas setelah Anda mendapatkan biji-bijian yang mudah, dan telusuri dengan beberapa kelas terlebih dahulu.
sumber
Di masa depan, ajukan pertanyaan tes Joel dalam wawancara Anda. Anda akan lebih cenderung untuk tidak berjalan ke kereta api.
Ini adalah, ah, bagaimana kita mengatakan ... masalah yang sangat buruk untuk dimiliki. "Suku bunga" pada utang teknis ini akan menjadi sangat, sangat tinggi. Mungkin tidak dapat dipulihkan ...
Seberapa terintegrasi dengan "inti" perubahan kustom ini? Bisakah Anda menjadikannya perpustakaan mereka sendiri dan memiliki "inti" tunggal dan setiap pelanggan tertentu memiliki "tambahan" sendiri?
Atau apakah ini semua konfigurasi yang sangat kecil?
Saya pikir solusinya adalah kombinasi dari:
Tidak ada yang sepele jika Anda berakhir di sini dengan 500+ klien, Anda mungkin tidak membuat perbedaan nyata dalam hal ini. Saya berharap perubahan Anda dalam memisahkan ini akan menjadi tugas yang sangat memakan waktu.
Saya juga curiga Anda akan memiliki masalah signifikan dengan mudah memisahkan dan mengkategorikan semua kode khusus klien Anda.
Jika sebagian besar perubahan Anda secara khusus menguraikan perbedaan, saya sarankan membaca pertanyaan seperti ini tentang lokalisasi bahasa. Apakah Anda melakukan beberapa bahasa sepenuhnya atau hanya sebagian, solusinya sama. Ini khusus PHP dan lokalisasi.
sumber
Ini adalah salah satu pola anti terburuk yang bisa Anda dapatkan dengan VCS apa pun.
Pendekatan yang benar di sini adalah mengubah kode khusus menjadi sesuatu yang didorong oleh konfigurasi, dan kemudian setiap pelanggan dapat memiliki konfigurasi sendiri, baik yang dikodekan dalam file konfigurasi, atau dalam database atau lokasi lain. Anda dapat mengaktifkan atau menonaktifkan seluruh fitur, menyesuaikan bagaimana respons terlihat, dan sebagainya.
Ini memungkinkan Anda menyimpan satu cabang master dengan kode produksi Anda.
sumber
if(getFeature(FEATURE_X).isEnabled())
seluruh.Tujuan cabang adalah untuk mengeksplorasi satu kemungkinan jalan pengembangan tanpa risiko untuk merusak stabilitas cabang utama. Mereka akhirnya harus digabungkan kembali pada waktu yang tepat, atau dibuang jika mereka mengarah ke jalan buntu. Apa yang Anda miliki tidak begitu banyak cabang, tapi lebih suka 500 garpu dari proyek yang sama dan mencoba untuk menerapkan changesets penting untuk semua dari mereka adalah tugas Sisyphean.
Yang harus Anda lakukan sebagai gantinya adalah memiliki kode inti Anda tinggal di repositori sendiri, dengan titik masuk yang diperlukan untuk mengubah perilaku melalui konfigurasi dan untuk menyuntikkan perilaku sebagaimana diizinkan oleh dependensi terbalik .
Pengaturan berbeda yang Anda miliki untuk klien kemudian dapat hanya membedakan satu sama lain dengan beberapa keadaan yang dikonfigurasikan secara eksternal (misalnya database) atau jika perlu hidup sebagai repositori terpisah, yang menambahkan inti sebagai submodule.
sumber
Semua hal penting telah diajukan oleh jawaban yang baik di sini. Saya ingin menambahkan lima pence saya sebagai saran proses.
Saya ingin menyarankan Anda memecahkan masalah ini dalam jangka panjang atau menengah dan mengadopsi kebijakan Anda, bagaimana Anda mengembangkan kode. Cobalah menjadi tim pembelajaran yang fleksibel. Jika seseorang diizinkan memiliki 500 repo alih-alih membuat perangkat lunak dapat dikonfigurasi, maka sekarang saatnya bertanya pada diri sendiri bagaimana Anda telah bekerja sejauh ini dan Anda akan lakukan mulai sekarang.
Yang berarti:
Ini sama sekali tidak dimaksudkan untuk membuat suasana tekanan buruk di tim Anda. Saya lebih suka menyarankan Anda mengklarifikasi poin-poin ini untuk diri sendiri dan, di mana pun Anda merasakan dukungannya, aturlah ini bersama dengan tim Anda. Undang orang-orang yang ramah ke meja untuk meningkatkan semua pengalaman Anda.
Kemudian, cobalah untuk membuat jangka waktu lama, di mana Anda memasaknya dengan api kecil. Saran: coba gabungkan setidaknya dua repo setiap minggu, jadi hapus setidaknya satu . Anda mungkin belajar bahwa sering, Anda dapat menggabungkan lebih dari dua cabang, saat Anda mendapatkan rutin dan pengawasan. Dengan begitu, dalam satu tahun Anda dapat menangani cabang terburuk (paling mahal?), Dan dalam dua tahun Anda dapat mengurangi masalah ini untuk memiliki perangkat lunak yang jelas lebih baik. Tapi jangan berharap lebih, karena pada akhirnya tidak ada yang akan "punya waktu" untuk ini, tetapi Anda adalah orang yang tidak akan membiarkan ini lebih lama karena Anda adalah arsitek perangkat lunak.
Inilah bagaimana saya akan mencoba menanganinya jika saya berada di posisi Anda. Namun saya tidak tahu bagaimana tim Anda akan menerima hal-hal seperti itu, bagaimana perangkat lunak benar-benar memungkinkan ini, bagaimana Anda didukung dan juga apa yang masih harus Anda pelajari. Anda adalah arsitek perangkat lunak - lakukan saja :-)
sumber
Membandingkan semua penyair, mari kita asumsikan kebutuhan bisnis nyata.
(misalnya, pengiriman adalah kode sumber, pelanggan berasal dari lini bisnis yang sama dan karenanya saling bersaing, dan model bisnis Anda berjanji untuk merahasiakan rahasia mereka)
Lebih jauh, mari kita asumsikan bahwa perusahaan Anda memiliki alat untuk mempertahankan semua cabang, baik tenaga kerja (katakanlah 100 pengembang yang didedikasikan untuk penggabungan, dengan asumsi keterlambatan rilis 5 hari; atau 10 dev dengan asumsi keterlambatan rilis 50 hari adalah OK), atau pengujian otomatis yang begitu mengagumkan sehingga penggabungan otomatis benar-benar diuji baik untuk spesifikasi inti dan spesifikasi ekstensi di setiap cabang, dan dengan demikian hanya perubahan yang tidak menggabungkan "bersih" yang memerlukan campur tangan manusia. Jika pelanggan Anda membayar tidak hanya untuk penyesuaian tetapi untuk pemeliharaannya, ini mungkin model bisnis yang valid.
Pertanyaan saya (dan nay-sayers), adalah, apakah Anda memiliki orang yang berdedikasi yang bertanggung jawab untuk pengiriman ke setiap pelanggan? Jika Anda, katakanlah, perusahaan 10.000 orang, mungkin itu masalahnya.
Ini dapat ditangani oleh arsitektur plugin dalam beberapa kasus, katakanlah inti Anda adalah trunk, plugin dapat disimpan di dalam trunk atau cabang, dan konfigurasi untuk setiap pelanggan adalah file dengan nama unik atau disimpan di cabang pelanggan.
Plugin dapat dimuat pada saat dijalankan, atau dibangun pada waktu kompilasi.
Benar-benar banyak proyek dilakukan seperti ini, masalah yang sama secara fundamental masih berlaku - perubahan inti sederhana sepele untuk diintegrasikan, perubahan konflik harus dibatalkan, atau perubahan diperlukan untuk banyak plugin.
Ada kasus ketika plugin tidak cukup baik, saat itulah begitu banyak internal inti harus di-tweak sehingga jumlah antarmuka plugin menjadi terlalu besar untuk ditangani.
Idealnya ini akan ditangani oleh pemrograman berorientasi aspek , di mana trunk adalah kode inti, dan cabang adalah aspek (yaitu kode tambahan dan instruksi bagaimana menghubungkan ekstra ke inti)
Contoh sederhana, Anda dapat menentukan bahwa kebiasaan
foo
dijalankan sebelum atau setelah intiklass.foo
atau menggantikannya, atau membungkusnya dan dapat mengubah input atau output.Ada banyak perpustakaan untuk itu, namun masalah konflik penggabungan tidak hilang - penggabungan yang bersih ditangani oleh AOP dan konflik masih membutuhkan intervensi manusia.
Akhirnya bisnis seperti itu benar-benar harus memusatkan perhatian pada pemeliharaan cabang , yaitu, apakah fitur khusus pelanggan X begitu umum sehingga lebih murah untuk memindahkannya ke inti, meskipun tidak semua pelanggan membayar untuk itu?
sumber
Anda tidak menyelesaikan akar penyebab penyakit dengan melihat gejalanya. Menggunakan pendekatan 'manajemen kode' adalah gejala, tetapi tidak akan menyelesaikan masalah untuk Anda dalam jangka panjang. Penyebab utamanya adalah kurangnya kapabilitas produk, fitur & ekstensi serta variasinya yang 'dikelola dengan baik'.
Kode 'khusus' Anda hanya mewakili ekstensi fitur & kemampuan produk dan perubahan bidang data pada orang lain.
Seberapa luas fitur kustom, betapa berbedanya, seberapa mirip atau tidaknya kontekstual akan banyak berperan dalam 'membersihkan' basis kode produk Anda.
Lebih dari bagaimana Anda membuat kode dan versi, ini adalah tempat di mana manajemen produk, arsitektur produk, dan arsitektur data ikut berperan. Serius.
Karena, pada akhirnya, kode tersebut tidak lain adalah penawaran bisnis dan fitur / layanan produk Anda kepada klien Anda. Itulah yang dibayar perusahaan Anda.
Mendapatkan pegangan yang lebih baik dalam hal ini harus berasal dari sudut pandang 'kemampuan' dan bukan dari sudut pandang kode.
Anda, perusahaan Anda, dan produk tidak dapat menjadi segalanya bagi semua orang. Sekarang Anda memiliki basis pendapatan yang layak untuk 500 klien, sekarang saatnya untuk membuat produk sesuai dengan yang Anda inginkan.
Dan jika Anda menawarkan beberapa hal, masuk akal untuk memodulasi kemampuan produk Anda secara terorganisir.
Seberapa luas dan dalam produk Anda? Atau kalau tidak, ini akan mengarah pada masalah 'kualitas layanan' & 'dilusi dan fragmentasi produk' saat Anda memulai.
Apakah Anda akan menjadi CRM atau ERP atau pemrosesan pemrosesan / pengiriman atau Microsoft Excel?
Ekstensi yang ada perlu menggulung dan menyelaraskan, cara perangkat lunak utama yang besar tarikan di dan menggabungkan produk yang diperoleh dari startup.
Anda akan perlu memetakan manajemen produk dan arsitektur data yang kuat sebagai berikut:
..untuk membuat peta jalan asimilasi dan harmonisasi semua utas / cabang produk yang longgar ini dalam konteks besar aplikasi inti Anda.
PS: Terhubung dengan saya, saya tahu seseorang yang dapat membantu Anda memperbaiki ini :)
sumber
Saya bisa mengaitkannya dengan ini. Saya telah mengambil banyak proyek. Faktanya, 90% dari pekerjaan pengembangan kami memperbaiki hal-hal seperti itu. Tidak semua orang sempurna, jadi saya sarankan Anda menggunakan kontrol versi dengan cara yang benar dan di mana Anda berada, jika mungkin Anda dapat melakukan hal berikut.
Saya secara pribadi mengimpor repositori dari GitHub dengan 40 cabang ke Bitbucket dan membuat 40 repositori. Hanya butuh empat jam. Ini adalah variasi tema WordPress jadi push dan pull cepat.
Ada banyak alasan untuk "tidak melakukannya dengan benar pertama kali", dan saya pikir mereka yang menerimanya dengan cepat dan beralih ke "melakukannya dengan benar kali ini" akan selalu berhasil.
sumber