Halo semuanya!
Jadi, bagian baru dari holivar yang dijanjikan tentang monorepositori. Pada bagian pertama, kami membahas terjemahan sebuah artikel oleh seorang insinyur terkemuka dari Lyft (dan sebelumnya Twitter) tentang apa saja kerugian dari monorepositori dan mengapa mereka meratakan hampir semua kelebihan dari pendekatan ini. Secara pribadi, saya sangat setuju dengan argumen yang disajikan dalam artikel asli. Tetapi, seperti yang dijanjikan, untuk mengakhiri diskusi ini, saya ingin menyuarakan beberapa poin lagi, menurut saya bahkan lebih penting dan lebih praktis.
Saya akan bercerita sedikit tentang diri saya - saya bekerja di kedua proyek kecil dan yang relatif besar, saya menggunakan polirepositori dalam proyek dengan lebih dari 100 layanan mikro (dan SLA 99,999%). Saat ini saya sedang terlibat dalam terjemahan mono-repositori kecil (sebenarnya tidak, hanya js + java backend depan) dari maven ke bazel. Tidak berfungsi di Google, Facebook, Twitter, mis. Saya tidak merasa senang menggunakan repositori yang dikonfigurasi dan disetel dengan benar.
Jadi, sebagai permulaan, apa itu monorepositori? Komentar pada terjemahan artikel asli menunjukkan bahwa banyak yang percaya bahwa mono-repositori adalah ketika semua 5 pengembang perusahaan bekerja pada satu repositori dan menyimpan frontend dan backend di dalamnya bersama-sama. Tentu saja tidak demikian. Mono-repositori adalah cara menyimpan semua proyek perusahaan, pustaka, alat bangun, plug-in untuk IDE, skrip penempatan, dan semua lainnya dalam satu repositori besar. Detail di sini adalah
trunkbaseddevelopment.com .
Apa pendekatan yang disebut ketika perusahaan kecil, dan itu tidak memiliki begitu banyak proyek, modul, komponen? Ini juga merupakan monorepositori, hanya yang kecil.
Secara alami, artikel asli mengatakan bahwa semua masalah yang dijelaskan mulai muncul pada skala tertentu. Oleh karena itu, mereka yang menulis bahwa repositori mono dengan 1,5 digger berfungsi dengan baik tentu saja benar.
Jadi, fakta pertama yang ingin saya perbaiki:
monorepositori adalah awal yang baik untuk proyek baru Anda . Menempatkan semua kode dalam satu tumpukan, pada awalnya Anda hanya akan mendapatkan satu keuntungan, karena mendukung banyak repositori tentu akan menambah sedikit overhead.
Lalu apa masalahnya? Dan masalahnya, seperti disebutkan dalam artikel asli, dimulai pada skala tertentu. Dan yang paling penting, jangan lewatkan momen ketika skala seperti itu telah tiba.
Oleh karena itu, saya cenderung untuk menegaskan bahwa pada dasarnya masalah yang muncul bukan masalah dari "menempatkan semua kode Anda dalam satu tumpukan" pendekatan itu sendiri, tetapi ini adalah masalah repositori kode sumber yang cukup besar. Yaitu dengan asumsi bahwa Anda menggunakan polrepositori untuk berbagai layanan / komponen, dan salah satu layanan ini menjadi sangat besar (seberapa besar, kita akan membahas sedikit kemudian), maka Anda kemungkinan besar akan mendapatkan masalah yang sama persis, tetapi juga tanpa kelebihan repositori mono (jika mereka Tentu saja ada).
Jadi, seberapa besar repositori mulai dianggap bermasalah?
Pasti ada 2 indikator yang tergantung pada ini - jumlah kode dan jumlah pengembang yang bekerja dengan kode ini. Jika proyek Anda memiliki kode terabyte, tetapi 1-2 orang bekerja dengannya, maka kemungkinan besar mereka hampir tidak akan melihat masalah (well, atau setidaknya akan lebih mudah untuk tidak melakukan apa-apa, bahkan jika mereka memperhatikan :)
Bagaimana menentukan bahwa sudah saatnya memikirkan bagaimana meningkatkan repositori Anda? Tentu saja, ini adalah indikator subjektif, kemungkinan besar pengembang Anda akan mulai mengeluh bahwa ada sesuatu yang tidak sesuai dengan mereka. Tetapi masalahnya adalah mungkin sudah terlambat untuk mengubah sesuatu. Biarkan saya memberi Anda beberapa angka pribadi: jika kloning repositori Anda membutuhkan lebih dari 10 menit, jika membangun proyek membutuhkan lebih dari 20-30 menit, jika jumlah pengembang melebihi 50, dan seterusnya.
Fakta menarik dari praktik pribadi:Saya bekerja pada monolit yang agak besar dalam tim yang terdiri dari sekitar 50 pengembang, dibagi menjadi beberapa tim kecil. Pengembangan dilakukan dalam fitur brunch, dan penggabungan terjadi tepat sebelum fitur membeku. Suatu hari saya menghabiskan 3 hari di gabungan cabang tim kami setelah 6 tim lain membeku di depan saya.
Sekarang mari kita melihat daftar masalah-masalah yang muncul dalam repositori besar (beberapa dari mereka disebutkan dalam artikel asli, beberapa tidak).
1) Waktu pengunduhan repositori
Di satu sisi, kita dapat mengatakan bahwa ini adalah operasi satu kali yang dilakukan pengembang selama pengaturan awal workstation-nya. Secara pribadi, saya sering mengalami situasi di mana saya ingin mengkloning proyek ke folder tetangga, menggali lebih dalam, dan kemudian menghapusnya. Namun, jika kloning membutuhkan waktu lebih dari 10-20 menit, ini tidak akan nyaman.
Tetapi di samping itu, jangan lupa bahwa sebelum membangun proyek pada server CI, Anda perlu mengkloning repositori untuk setiap agen build. Dan di sini Anda mulai mencari tahu cara menghemat waktu ini, karena jika setiap perakitan memakan waktu 10-20 menit lebih lama, dan hasil perakitan muncul 10-20 menit kemudian, ini tidak cocok untuk siapa pun. Jadi repositori mulai muncul dalam gambar mesin virtual dari mana agen ditempatkan, kompleksitas tambahan dan biaya tambahan untuk mendukung solusi ini muncul.
2) Bangun waktu
Ini adalah poin yang cukup jelas yang telah dibahas berkali-kali. Bahkan, jika Anda memiliki banyak kode sumber, maka perakitan dalam hal apa pun akan memakan waktu yang cukup lama. Situasi yang umum adalah ketika setelah mengubah satu baris kode Anda harus menunggu setengah jam sampai perubahan disusun kembali dan diuji. Bahkan, hanya ada satu jalan keluar - untuk menggunakan sistem build yang dibangun di sekitar hasil caching dan build tambahan.
Tidak ada banyak pilihan di sini - meskipun fakta bahwa fitur caching ditambahkan ke tingkat yang sama (sayangnya, saya tidak menggunakannya dalam praktik), mereka tidak membawa manfaat praktis karena fakta bahwa sistem pembangunan tradisional tidak memiliki hasil yang dapat diulang (build direproduksi). Yaitu karena efek samping dari build sebelumnya, bagaimanapun, pada beberapa titik akan perlu untuk memanggil pembersihan cache (pendekatan standar standar
maven clean build
). Oleh karena itu, hanya ada opsi untuk menggunakan Bazel / Buck / Pants dan yang lainnya menyukainya. Kenapa ini tidak terlalu bagus, kita akan bahas nanti.
3) Pengindeksan IDE
Proyek saya saat ini diindeks di Intellij IDEA selama 30 hingga 40 menit. Bagaimana dengan milikmu? Tentu saja, Anda dapat membuka hanya sebagian dari proyek atau mengecualikan semua modul yang tidak perlu dari pengindeksan, tapi ... Masalahnya adalah pengindeksan ulang terjadi setiap kali Anda beralih dari satu cabang ke cabang lainnya. Itu sebabnya saya ingin mengkloning proyek di direktori tetangga. Beberapa orang mulai melakukan cache cache IDE :)
<Gambar DiCaprio dengan mata menyipit>
4) Buat log
Server CI apa yang Anda gunakan? Apakah ini menyediakan antarmuka yang nyaman untuk melihat dan menavigasi beberapa gigabytes log bangunan? Sayangnya milik saya bukan :(
5) Sejarah komitmen
Apakah Anda suka menonton komit sejarah? Saya suka, terutama di alat dengan antarmuka grafis (saya melihat informasi yang lebih baik secara visual, jangan dimarahi :).
Ini adalah apa yang tampak seperti komit sejarah di repositori saya Apakah kamu menyukainya? Apakah itu nyaman? Secara pribadi, saya tidak!
6) Tes yang rusak
Apa yang terjadi jika seseorang dapat menjalankan tes yang rusak / kode yang tidak dikompilasi ke master? Anda tentu akan mengatakan bahwa CI Anda tidak memungkinkan Anda untuk melakukan ini. Bagaimana dengan tes tidak stabil yang penulis lewati, dan tidak ada orang lain? Sekarang bayangkan kode ini menyebar ke mesin-mesin 300 pengembang, dan tidak satu pun dari mereka dapat merakit proyek? Apa yang harus dilakukan dalam situasi seperti itu? Tunggu penulis untuk memperhatikan dan memperbaiki? Benar untuknya? Kembalikan perubahan? Tentu saja, idealnya, hanya layak melakukan kode yang baik, dan menulis segera tanpa bug. Maka masalah seperti itu tidak akan muncul.
(bagi mereka yang tidak memahami petunjuk dalam tangki, pembicaraannya adalah bahwa efek negatif jika ini terjadi di repositori dengan 10 pengembang dan dalam repositori dengan 300 akan sedikit berbeda)
7) Gabungkan bot
Pernah mendengar hal seperti itu? Apakah Anda tahu mengapa Anda membutuhkannya? Anda akan tertawa, tetapi ini adalah alat lain yang seharusnya tidak ada :) Bayangkan saja waktu pembangunan proyek Anda adalah 30 menit. Dan 100 pengembang sedang mengerjakan proyek Anda. Misalkan masing-masing dari mereka mendorong 1 komit per hari. Sekarang bayangkan CI jujur, yang memungkinkan Anda untuk menggabungkan perubahan pada master hanya setelah mereka diterapkan pada komit terbaru dari master (rebase).
Perhatian, pertanyaannya adalah: berapa jam harus dalam sehari untuk server CI yang jujur untuk mencekik perubahan dari semua pengembang? Jawaban yang benar adalah 50. Mereka yang menjawab dengan benar dapat mengambil wortel dari rak. Nah, atau bayangkan bagaimana Anda baru saja memotong komit Anda ke komit terakhir ke master, memulai perakitan, dan ketika sudah selesai, master sudah pergi 20 komit di depan. Semua lagi?
Jadi menggabungkan bot atau menggabungkan antrian adalah layanan yang mengotomatiskan proses rebasing semua permintaan menggabungkan master baru, menjalankan tes dan menggabungkan itu sendiri, dan juga dapat menggabungkan komit ke dalam batch dan mengujinya bersama-sama. Hal yang sangat berguna. Lihat
mergify.io ,
k8s test-infra Prow dari Google,
bors-ng , dll. (Saya berjanji untuk menulis lebih banyak tentang ini di masa depan)
Sekarang untuk masalah yang kurang teknis:
8) Menggunakan alat build tunggal
Sejujurnya, masih menjadi misteri bagi saya mengapa merakit seluruh repositori mono menggunakan satu sistem pembangunan umum. Mengapa tidak membangun javascript dengan Benang, java dengan gradle, Scala dengan sbt, dll? Jika seseorang mengetahui jawaban untuk pertanyaan ini (tidak menebak atau menyarankan, yaitu tahu), tulis di komentar.
Tentu saja, tampak jelas bahwa menggunakan sistem satu bangun lebih baik daripada beberapa yang berbeda. Tetapi mereka masih memahami bahwa segala hal universal jelas lebih buruk daripada yang khusus, karena kemungkinan besar hanya memiliki subset dari semua fungsi khusus. Tetapi lebih buruk lagi, bahasa pemrograman yang berbeda mungkin memiliki paradigma yang berbeda dalam hal perakitan, manajemen ketergantungan, dll., Yang akan sangat sulit untuk dibungkus dalam satu pembungkus umum. Saya tidak ingin membahas detail, saya akan memberikan satu contoh tentang bazel (lihat detail dalam artikel terpisah) - kami menemukan 5 implementasi independen aturan perakitan javascript untuk bazel dari 5 perusahaan berbeda di GitHub, bersama dengan yang resmi dari Google. Ini layak dipertimbangkan.
9) Pendekatan umum
Menanggapi artikel asli, CTO dari Chef menulis jawabannya,
Monorepo: tolong lakukan! . Dalam tanggapannya, ia berpendapat bahwa "hal utama dalam monorepo adalah membuat Anda berbicara dan membuat kekurangan terlihat." Maksudnya adalah ketika Anda ingin mengubah API Anda, Anda harus menemukan semua penggunaannya dan mendiskusikan perubahan Anda dengan pengelola potongan kode ini.
Jadi pengalaman saya justru sebaliknya. Jelas bahwa ini sangat tergantung pada budaya rekayasa dalam tim, tetapi saya melihat minus yang kuat dalam pendekatan ini. Bayangkan Anda menggunakan pendekatan tertentu yang telah melayani Anda dengan setia selama beberapa waktu. Jadi Anda memutuskan untuk beberapa alasan, memecahkan masalah yang sama, untuk menggunakan metode yang sedikit berbeda, mungkin lebih modern. Apa kemungkinan bahwa menambahkan pendekatan baru akan melalui tinjauan?
Di masa lalu saya, saya menerima komentar beberapa kali seperti "kami sudah memiliki jalur yang terbukti, gunakan itu" dan "jika Anda ingin menerapkan pendekatan baru, perbarui kode di semua 120 tempat di mana pendekatan lama digunakan dan dapatkan pembaruan dari semua tim yang bertanggung jawab untuk potongan kode ini. " Biasanya antusiasme "inovator" berakhir di sini.
Dan berapa banyak, menurut pendapat Anda, akankah biaya untuk menulis layanan baru dalam bahasa pemrograman baru? Dalam repositori - tidak sama sekali. Anda membuat repositori baru dan menulis, dan bahkan mengambil sistem build yang paling cocok. Dan sekarang hal yang sama di monorepositori?
Saya mengerti betul bahwa "standardisasi, penggunaan kembali, berbagi kode", tetapi proyek harus dikembangkan. Menurut pendapat subjektif saya, monorepositori agak mencegah ini.
10) Sumber terbuka
Baru-baru ini saya ditanya: “
adakah alat sumber terbuka untuk repositori mono? ” Saya menjawab: “Masalahnya adalah alat repositori mono, anehnya, dikembangkan di dalam repositori mono itu sendiri. Oleh karena itu, memasukkannya ke sumber terbuka cukup sulit! ”
Sebagai contoh, lihat proyek di Github dengan
plugin bazel untuk Intellij IDEA . Google mengembangkannya dalam repositori internal, dan kemudian "memercikkan" bagian-bagiannya di Github dengan hilangnya riwayat komit, tanpa kemampuan untuk mengirim permintaan tarik, dan sebagainya. Saya tidak berpikir itu open source (di sini adalah contoh
PR kecil saya , yang ditutup, bukan penggabungan, dan kemudian perubahan muncul di versi berikutnya). Ngomong-ngomong, fakta ini disebutkan dalam artikel asli bahwa mono-repositori mencegah mereka memposting di sumber terbuka dan membuat komunitas di sekitar proyek. Saya pikir banyak yang tidak mementingkan argumen ini.
Alternatif
Nah, jika kita berbicara tentang apa yang harus dilakukan untuk menghindari semua masalah ini? Tepat ada satu saran - berusaha keras untuk memiliki repositori sekecil mungkin.
Tapi apa hubungannya monorepositori dengan itu? Dan meskipun pendekatan ini menghalangi Anda untuk memiliki repositori yang kecil, ringan dan independen.
Apa kerugian dari pendekatan polyrepository? Saya melihat tepat 1: ketidakmampuan untuk melacak siapa yang menjadi konsumen API Anda. Ini terutama benar dari pendekatan dalam layanan microservices
"tidak berbagi" , di mana kode tidak meraba-raba antara layanan microser. (Omong-omong, apakah Anda pikir ada orang yang menggunakan pendekatan ini di mono-repositori?) Sayangnya, masalah ini perlu diselesaikan baik dengan cara organisasi, atau mencoba menggunakan alat penelusuran kode yang mendukung repositori independen (misalnya,
https://sourcegraph.com / ).
Bagaimana dengan komentar seperti
“kami mencoba polyrepositories, tetapi kemudian kami harus terus-menerus mengimplementasikan fitur dalam beberapa repositori sekaligus, yang melelahkan, dan kami menggabungkan semuanya menjadi satu boiler” ? Jawabannya sangat sederhana:
"jangan bingung masalah pendekatan dengan dekomposisi yang tidak tepat .
" Tidak ada yang mengklaim bahwa repositori harus berisi tepat satu layanan microser dan hanya itu. Ketika saya menggunakan polyrepository, kami dengan sempurna mengumpulkan satu keluarga dengan layanan microser yang terkait erat dalam satu repositori. Namun demikian, dengan mempertimbangkan bahwa ada lebih dari 100 layanan, ada lebih dari 20 repositori seperti itu. Hal yang paling penting untuk dipikirkan dalam hal dekomposisi adalah bagaimana layanan ini akan digunakan.
Tapi bagaimana dengan argumen tentang versi itu? Lagi pula, repositori mono memungkinkan Anda untuk tidak memiliki versi dan menyebarkan semuanya dari satu komit! Pertama, versi adalah yang paling sederhana dari semua masalah yang disuarakan di sini. Bahkan dalam hal lama seperti maven ada plugin versi maven yang memungkinkan Anda untuk menurunkan versi dengan hanya satu klik. Dan kedua, dan yang paling penting, apakah perusahaan Anda memiliki aplikasi seluler? Jika demikian, maka Anda sudah memiliki versi, dan Anda tidak akan mendapatkan apa-apa dari ini!
Yah, masih ada argumen utama yang mendukung repositori tunggal - ini memungkinkan Anda untuk melakukan refactoring di seluruh basis kode dalam satu komit! Bahkan tidak. Sebagaimana disebutkan dalam artikel asli, karena keterbatasan yang diterapkan penyebaran. Anda harus selalu ingat bahwa untuk waktu yang lama (durasinya tergantung pada bagaimana proses Anda dibangun), Anda akan memiliki 2 versi layanan yang sama secara paralel. Misalnya, pada proyek terakhir saya, sistem kami berada di negara ini selama beberapa jam di setiap penyebaran. Ini mengarah pada fakta bahwa tidak mungkin untuk melakukan refactoring global yang mempengaruhi antarmuka interaksi dalam satu komit, bahkan dalam repositori tunggal.
Alih-alih kesimpulan:
Jadi, beberapa rekan yang dihormati dan sedikit yang bekerja di Google, Facebook, dll. dan datang ke sini untuk mempertahankan repositori mono mereka, saya ingin mengatakan: "Jangan khawatir, Anda melakukan segalanya dengan benar, nikmati penyetelan Anda, yang menghabiskan ratusan ribu atau jutaan jam manusia. Mereka sudah dibelanjakan, jadi jika Anda tidak menggunakan, maka tidak ada yang mau. "
Dan untuk semua orang:
"Anda bukan Google, jangan gunakan repositori tunggal!"P.S. seperti yang dicatat oleh Bobuk yang disegani di podcast
radio-T ketika membahas artikel aslinya: “Ada ~ 20 perusahaan di dunia yang dapat menggunakan repositori tunggal.
Sisanya seharusnya tidak mencoba . ”