Monorepositories: mangyaring, dapat

Monorepositories: mangyaring, dapat

Pagsasalin ng artikulong inihanda para sa mga mag-aaral ng kurso "Mga kasanayan at tool ng DevOps" sa proyektong pang-edukasyon ng OTUS.

Dapat kang pumili ng isang monorepository dahil ang pag-uugali na itinataguyod nito sa iyong mga koponan ay transparency at magkabahaging responsibilidad, lalo na habang lumalaki ang mga koponan. Sa alinmang paraan, kakailanganin mong mamuhunan sa tooling, ngunit palaging mas maganda kung ang default na gawi ay ang gawi na gusto mo sa iyong mga utos.

Bakit natin ito pinag-uusapan?

Isinulat ni Matt Klein ang artikulo "Monorepos: Huwag naman sana!"  (tala ng tagasalin: pagsasalin sa Habré "Monorepositories: mangyaring huwag"). I like Matt, I think he's very smart and you should read his point of view. Siya ay orihinal na nag-post ng poll sa Twitter:

Monorepositories: mangyaring, dapat

Pagsasalin:
Ngayong Araw ng Bagong Taon, makikipagtalo ako tungkol sa kung gaano katawa-tawa ang mga monorepositories. Nagsimula ang 2019 nang tahimik. Sa diwa nito, nag-aalok ako sa iyo ng isang survey. Sino ang mga malalaking panatiko? Mga tagasuporta:
- Monorepo
- Kalawang
- Maling poll / pareho

Ang sagot ko ay, "Ako ay literal na pareho ng mga taong iyon." Sa halip na pag-usapan kung paanong gamot si Rust, tingnan natin kung bakit sa tingin ko ay mali siya tungkol sa mga monorepositories. Medyo tungkol sa iyong sarili. Ako ang CTO ng Chef Software. Mayroon kaming humigit-kumulang 100 mga inhinyero, isang code base na bumalik noong mga 11-12 taon, at 4 na pangunahing produkto. Ang ilan sa code na ito ay nasa isang polyrepository (ang aking panimulang posisyon), ang ilan ay nasa isang monorepository (ang aking kasalukuyang posisyon).

Bago ako magsimula: bawat argumento na gagawin ko dito ay mailalapat sa parehong uri ng mga repositoryo. Sa palagay ko, walang teknikal na dahilan kung bakit dapat kang pumili ng isang uri ng repository sa iba. Magagawa mong gumana ang anumang diskarte. Natutuwa akong pag-usapan ito, ngunit hindi ako interesado sa mga artipisyal na teknikal na dahilan kung bakit ang isa ay nakahihigit sa isa pa.

Sumasang-ayon ako sa unang bahagi ng punto ni Matt:

Dahil sa sukat, lulutasin ng isang monorepository ang lahat ng parehong problema na nalulutas ng isang polyrepository, ngunit kasabay nito ay pinipilit kang mahigpit na pagsasama-samahin ang iyong code at nangangailangan ng hindi kapani-paniwalang pagsisikap upang mapataas ang scalability ng iyong version control system.

Kakailanganin mong lutasin ang parehong mga problema hindi alintana kung pipiliin mo ang isang monorepository o isang polyrepository. Paano mo ilalabas ang mga release? Ano ang iyong diskarte sa mga update? Paatras na pagkakatugma? Cross project dependencies? Anong mga istilo ng arkitektura ang katanggap-tanggap? Paano mo pinamamahalaan ang iyong build at pagsubok na imprastraktura? Ang listahan ay walang katapusan. At malulutas mo silang lahat habang lumalaki ka. Walang libreng keso.

Sa tingin ko ang argumento ni Matt ay katulad ng mga pananaw na ibinahagi ng maraming mga inhinyero (at mga tagapamahala) na aking iginagalang. Nangyayari ito mula sa pananaw ng engineer na nagtatrabaho sa component o ng team na nagtatrabaho sa component. Naririnig mo ang mga bagay tulad ng:

  • Napakalaki ng codebase - hindi ko kailangan ang lahat ng basurang ito.
  • Mas mahirap subukan dahil kailangan kong subukan ang lahat ng basurang ito na hindi ko kailangan.
  • Mas mahirap magtrabaho sa mga panlabas na dependency.
  • Kailangan ko ng sarili kong virtual version control system.

Siyempre, ang lahat ng mga puntong ito ay makatwiran. Nangyayari ito sa parehong mga kaso - sa polyrepository mayroon akong sarili kong junk, bilang karagdagan sa kailangan para sa build... Maaaring kailangan ko rin ng iba pang basura. Kaya ako ay "simple" na lumikha ng mga tool na sumusuri sa buong proyekto. O lumikha ako ng isang pekeng monorepository na may mga submodules. Kaya naming maglakad-lakad dito buong araw. Ngunit sa palagay ko ang argumento ni Matt ay nakakaligtaan ang pangunahing dahilan, na binaligtad ko nang husto pabor sa monorepository:

Nagdudulot ito ng komunikasyon at nagpapakita ng mga problema

Kapag naghiwalay kami ng mga repositoryo, gumagawa kami ng de facto na problema sa koordinasyon at transparency. Ito ay tumutugma sa paraan ng pag-iisip natin tungkol sa mga koponan (lalo na sa paraan ng pag-iisip ng mga indibidwal na miyembro tungkol sa kanila): responsable tayo para sa isang partikular na bahagi. Nagtatrabaho kami sa relatibong paghihiwalay. Ang mga hangganan ay naayos sa aking koponan at ang (mga) bahagi na aming ginagawa.

Habang nagiging mas kumplikado ang arkitektura, hindi na ito kayang pamahalaan ng isang koponan nang mag-isa. Napakakaunting mga inhinyero ang may buong sistema sa kanilang ulo. Sabihin nating pinamamahalaan mo ang isang nakabahaging bahagi A na ginagamit ng Mga Koponan B, C, at D. Nagre-refactor ang Team A, pinapahusay ang API, at binabago rin ang panloob na pagpapatupad. Bilang resulta, ang mga pagbabago ay hindi tugma sa likuran. Anong payo ang mayroon ka?

  • Hanapin ang lahat ng lugar kung saan ginagamit ang lumang API.
  • Mayroon bang mga lugar kung saan hindi magagamit ang bagong API?
  • Maaari mo bang ayusin at subukan ang iba pang mga bahagi upang matiyak na hindi sila masira?
  • Maaari bang subukan ng mga team na ito ang iyong mga pagbabago sa ngayon?

Pakitandaan na ang mga tanong na ito ay hiwalay sa uri ng repositoryo. Kakailanganin mong maghanap ng mga koponan B, C at D. Kakailanganin mong makipag-usap sa kanila, alamin ang oras, maunawaan ang kanilang mga priyoridad. At least umaasa kami na gagawin mo.

Wala talagang gustong gawin ito. Ito ay hindi gaanong masaya kaysa sa pag-aayos lamang ng mapahamak na API. Ito ay lahat ng tao at magulo. Sa isang polyrepository, maaari kang gumawa ng mga pagbabago, ibigay ito sa mga taong nagtatrabaho sa bahaging iyon (marahil hindi B, C o D) para sa pagsusuri, at magpatuloy. Ang mga Team B, C at D ay maaari lamang manatili sa kanilang kasalukuyang bersyon sa ngayon. Mare-renew sila kapag napagtanto nila ang iyong galing!

Sa isang monorepository, ang responsibilidad ay inililipat bilang default. Binago ng Team A ang kanilang component at, kung hindi maingat, agad na sinira ang B, C at D. Ito ay humahantong sa B, C at D na lumabas sa pintuan ni A, na nagtataka kung bakit sinira ng Team A ang assembly. Ito ay nagtuturo sa A na hindi nila maaaring laktawan ang aking listahan sa itaas. Dapat silang mag-usap tungkol sa kung ano ang kanilang gagawin. Maaari bang lumipat ang B, C at D? Paano kung maaari ang B at C, ngunit ang D ay malapit na nauugnay sa isang side effect ng pag-uugali ng lumang algorithm?

Pagkatapos ay kailangan nating pag-usapan kung paano tayo aalis sa sitwasyong ito:

  1. Suporta para sa maraming panloob na API, at mamarkahan ang lumang algorithm bilang hindi na ginagamit hanggang sa mahinto na ni D ang paggamit nito.
  2. Suporta para sa maraming bersyon ng release, isa na may lumang interface, isa sa bago.
  3. Iantala ang pagpapalabas ng mga pagbabago ni A hanggang sa matanggap ito ng B, C, at D nang sabay-sabay.

Sabihin nating pumili kami ng 1, ilang mga API. Sa kasong ito mayroon kaming dalawang piraso ng code. Luma at bago. Medyo maginhawa sa ilang mga sitwasyon. Sinusuri namin muli ang lumang code, minarkahan ito bilang hindi na ginagamit, at sumasang-ayon sa isang iskedyul ng pag-aalis kasama ang D team. Talagang magkapareho para sa mga poly at mono repository.

Upang maglabas ng maraming bersyon, kailangan namin ng isang sangay. Ngayon mayroon kaming dalawang bahagi - A1 at A2. Ang mga pangkat B at C ay gumagamit ng A2 at D ay gumagamit ng A1. Kailangan naming maging handa ang bawat bahagi para sa paglabas dahil maaaring kailanganin ang mga update sa seguridad at iba pang mga pag-aayos ng bug bago magpatuloy ang D. Sa isang polyrepository, maaari nating itago ito sa isang mahabang buhay na sangay na masarap sa pakiramdam. Sa isang monorepository, pinipilit naming gawin ang code sa isang bagong module. Kakailanganin pa rin ng Team D na gumawa ng mga pagbabago sa "lumang" bahagi. Nakikita ng lahat ang halaga na binabayaran namin dito - mayroon na kaming dobleng dami ng code, at anumang mga pag-aayos ng bug na nalalapat sa A1 at A2 ay dapat na malapat sa kanilang dalawa. Gamit ang sumasanga na diskarte sa isang polyrepository, ito ay nakatago sa likod ng cherry-pick. Itinuturing naming mas mababa ang gastos dahil walang duplication. Mula sa praktikal na pananaw, pareho ang gastos: bubuo ka, ilalabas, at mapanatili ang dalawang magkaparehong codebase hanggang sa matanggal mo ang isa sa mga ito. Ang pagkakaiba ay na sa isang monorepository ang sakit na ito ay direkta at nakikita. Ito ay mas masahol pa, at iyon ay mabuti.

Sa wakas, nakarating kami sa ikatlong punto. Pagkaantala sa pagpapalabas. Posibleng mapapabuti ng mga pagbabagong ginawa ni A ang buhay ng Team A. Mahalaga, ngunit hindi apurahan. Pwede bang i-delay na lang natin? Sa isang polyrepository, itinutulak namin ito upang i-pin ang artifact. Syempre sinasabi namin ito sa Team D. Manatili lang sa lumang bersyon hanggang sa makahabol ka! Ito ay nagse-set up sa iyo upang maglaro ng duwag. Ang Team A ay patuloy na gumagawa sa kanilang bahagi, hindi pinapansin ang katotohanan na ang Team D ay gumagamit ng lalong luma na bersyon (iyan ang problema ng Team D, sila ay tanga). Samantala, hindi maganda ang pinag-uusapan ng Team D tungkol sa pabaya ng Team A sa pagiging matatag ng code, kung pinag-uusapan man nila ito. Lumipas ang mga buwan. Sa wakas, nagpasya ang Team D na tingnan ang posibilidad ng pag-update, ngunit mayroon lamang mas maraming pagbabago ang A. Halos hindi naaalala ng Team A kung kailan o kung paano nila sinira ang D. Ang pag-upgrade ay mas masakit at mas magtatagal. Na nagpapadala nito nang higit pa pababa sa priority stack. Hanggang sa dumating yung araw na may security issue kami sa A na pinipilit kaming gumawa ng branch. Kailangang bumalik ang Team A sa nakaraan, maghanap ng punto kung kailan naging stable ang D, ayusin ang problema doon, at ihanda itong ilabas. Ito ang de facto na pagpipiliang ginagawa ng mga tao, at ito ang pinakamasama. Mukhang maganda para sa Team A at Team D basta hindi natin pansinin ang isa't isa.

Sa isang monorepository, ang pangatlo ay talagang hindi isang opsyon. Napipilitan kang harapin ang sitwasyon sa isa sa dalawang paraan. Kailangan mong makita ang mga gastos sa pagkakaroon ng dalawang release branch. Matutong protektahan ang iyong sarili mula sa mga update na sumisira sa backward compatibility. Ngunit ang pinakamahalaga: hindi mo maiiwasan na magkaroon ng mahirap na usapan.

Sa aking karanasan, kapag ang mga koponan ay lumalaki, hindi na posible na panatilihin ang buong sistema sa isip, at iyon ang pinakamahalagang bahagi. Dapat mong pagbutihin ang visibility ng hindi pagkakasundo sa system. Dapat kang aktibong magtrabaho upang maalis ang tingin ng mga koponan sa kanilang mga bahagi at tingnan ang gawain ng iba pang mga koponan at mga mamimili.

Oo, maaari kang lumikha ng mga tool na sumusubok na lutasin ang problema sa polyrepository. Ngunit ang aking karanasan sa pagtuturo ng tuluy-tuloy na paghahatid at automation sa malalaking negosyo ay nagsasabi sa akin nito: ang default na gawi nang walang paggamit ng mga karagdagang tool ay ang gawi na inaasahan mong makita. Ang default na pag-uugali ng isang polyrepository ay paghihiwalay, iyon ang buong punto. Ang default na pag-uugali ng isang monorepository ay ibinahaging responsibilidad at transparency, iyon ang buong punto. Sa parehong mga kaso, gagawa ako ng isang tool na magpapakinis sa mga magaspang na gilid. Bilang isang pinuno, pipili ako ng isang monorepository sa bawat oras dahil kailangan ng mga tool na palakasin ang kultura na gusto ko, at ang kultura ay nagmumula sa maliliit na desisyon at araw-araw na gawain ng koponan.

Ang mga rehistradong user lamang ang maaaring lumahok sa survey. Mag-sign in, pakiusap

Sino ang pinakamalaking panatiko? Mga tagasuporta:

  • Monorepo

  • Kalawang

  • Maling poll / pareho

33 na user ang bumoto. 13 user ang umiwas.

Pinagmulan: www.habr.com

Magdagdag ng komento