Jak utrzymujesz kod rozwojowy i produkcyjny? [Zamknięte]

136

Jakie są najlepsze praktyki i praktyczne zasady, których należy przestrzegać podczas utrzymywania kodu? Czy dobrą praktyką jest posiadanie tylko gotowego kodu produkcyjnego w gałęzi programistycznej, czy też powinien być dostępny nieprzetestowany najnowszy kod w gałęzi programistycznej?

W jaki sposób utrzymujesz kod programistyczny i produkcyjny?

Edycja - Pytanie dodatkowe - Czy Twój zespół programistów postępuje zgodnie z protokołem „zatwierdzaj-jak najszybciej-i-często-nawet-jeśli-kod-zawiera-drobne-błędy-lub-jest-niekompletny- Protokół ONLY-perfect-code podczas wysyłania kodu do gałęzi DEVELOPMENT?

Mohit Ranka
źródło
Odpowiedziałem już wcześniej na podobne pytanie (lub pytanie w tej samej przestrzeni / kierunku), więc możesz sprawdzić to pytanie: Jakie są dobre strategie, aby umożliwić poprawianie wdrożonych aplikacji?
Do
@revo: czekaj ... moja odpowiedź z 2008 roku jest nieaktualna? :) Myślę, że tak jest. Minęło ponad 10 lat: zredagowałem odpowiedź.
VonC

Odpowiedzi:

114

Aktualizacja 2019:

Te dni, sprawa byłaby postrzegana w kontekście używając Git i 10 lat stosowania, które dystrybuowane rozwoju przepływu pracy (współpracujący głównie poprzez GitHub ) przedstawia ogólne najlepsze praktyki:

  • masterto gałąź gotowa do wdrożenia w dowolnym momencie: następna wersja z wybranym zestawem gałęzi funkcji scalonych master.
  • dev(lub gałąź integracji lub „ next”) to ta, w której gałąź funkcji wybrana do następnego wydania jest testowana razem
  • maintenance(lub hot-fix) gałąź to ta, w której znajduje się ewolucja bieżącego wydania / poprawki błędów, z możliwymi połączeniami z powrotem do devi lubmaster

Tego rodzaju przepływu pracy (gdzie nie połączyć devsię master, ale gdzie można połączyć tylko do funkcji oddział dev, a następnie, jeśli wybrany, aby master, aby móc łatwo spaść wyposażone oddziały nie są gotowe do następnego wydania) jest realizowany w Git repo, z gitworkflow (jedno słowo, zilustrowane tutaj ).
Zobacz więcej na rocketraman/gitworkflow. Historia robienia tego w porównaniu z rozwojem opartym na ruchu jest odnotowana w komentarzach i dyskusjach do tego artykułu autorstwa Adama Dymitruka .

https://github.com/rocketraman/gitworkflow/raw/master/docs/images/topicgraduation.png

(źródło: Gitworkflow: A Task-Oriented Primer )

Uwaga: w tym rozproszonym przepływie pracy możesz zatwierdzać, kiedy tylko chcesz i przesyłać do gałęzi osobistej niektóre WIP (Work In Progress) bez problemu: będziesz w stanie zreorganizować (git rebase) swoje commity przed uczynieniem ich częścią gałęzi funkcji.


Oryginalna odpowiedź (październik 2008, ponad 10 lat temu)

Wszystko zależy od sekwencyjnego charakteru zarządzania wydaniami

Po pierwsze, czy wszystko w twoim bagażniku jest naprawdę potrzebne do następnego wydania ? Może się okazać, że niektóre z obecnie rozwijanych funkcji to:

  • zbyt skomplikowane i nadal wymagają dopracowania
  • nie gotowy na czas
  • interesujące, ale nie do następnego wydania

W takim przypadku linia główna powinna zawierać wszystkie bieżące prace programistyczne, ale gałąź wydania zdefiniowana wcześniej przed następną wersją może służyć jako gałąź konsolidacyjna w której tylko odpowiedni kod (sprawdzony pod kątem następnego wydania) jest łączony, a następnie naprawiany w fazie homologacji, i ostatecznie zamrożone, gdy trafiają do produkcji.

Jeśli chodzi o kod produkcyjny, musisz również zarządzać gałęziami łatek , pamiętając, że:

  • pierwszy zestaw łat może faktycznie rozpocząć się przed pierwszym wydaniem do produkcji (co oznacza, że ​​wiesz, że wejdziesz do produkcji z kilkoma błędami, których nie możesz naprawić na czas, ale możesz rozpocząć pracę nad tymi błędami w osobnej gałęzi)
  • inne gałęzie łat będą miały luksus, aby rozpocząć od dobrze zdefiniowanej etykiety produkcyjnej

Jeśli chodzi o gałąź deweloperską, możesz mieć jedną linię główną, chyba że masz inne działania programistyczne, które musisz wykonać równolegle, takie jak:

  • masowa refaktoryzacja
  • testowanie nowej biblioteki technicznej, która może zmienić sposób wywoływania rzeczy w innych klasach
  • początek nowego cyklu wydawniczego, w którym należy wprowadzić ważne zmiany architektoniczne.

Teraz, jeśli twój cykl rozwoju i wydania jest bardzo sekwencyjny, możesz po prostu postępować tak, jak sugerują inne odpowiedzi: jeden główny i kilka gałęzi wydania. Działa to w przypadku małych projektów, w których cały rozwój z pewnością przejdzie do następnej wersji i może zostać po prostu zamrożony i służyć jako punkt wyjścia dla gałęzi wydania, w której mogą mieć miejsce poprawki. To jest nominalny proces, ale gdy masz bardziej złożony projekt ... to już nie wystarcza.


Aby odpowiedzieć na komentarz Ville M.:

  • pamiętaj, że gałąź deweloperska nie oznacza `` jednej gałęzi na programistę '' (co spowodowałoby `` szaleństwo scalania '', w którym każdy programista musiałby łączyć prace innych, aby zobaczyć / pobrać swoją pracę), ale jedną gałąź deweloperską na rozwój wysiłek.
  • Kiedy te wysiłki muszą zostać połączone z powrotem w trunk (lub jakąkolwiek inną "główną" lub inną gałąź wydania, którą zdefiniujesz), jest to praca programisty, a nie - powtarzam NIE - menedżera SC (który nie wiedziałby, jak rozwiązać wszelkie sprzeczne scalanie). Lider projektu może nadzorować połączenie, co oznacza, że ​​powinno się ono rozpocząć / zakończyć na czas.
  • kogokolwiek wybierzesz, aby dokonać scalenia, najważniejsze jest:
    • mieć testy jednostkowe i / lub środowisko montażowe, w którym można wdrożyć / przetestować wynik scalania.
    • zdefiniowanie znacznika przed rozpoczęciem scalania, aby móc wrócić do poprzedniego stanu, jeśli wspomniane scalanie okaże się zbyt złożone lub zbyt długie, aby można było je rozwiązać.
VonC
źródło
1
@Adam Dziękuję za edycję i przepraszam, że wcześniej nie ustawiłam właściwego źródła.
VonC
Ha! Nie martw się tym. Zrobiłeś tak wiele dla społeczności tutaj, że nie można cię za nic winić. Po prostu cieszę się, że ludzie tacy jak Ty wykonują tak wiele pracy dla dobra wszystkich na całym świecie!
Adam Dymitruk
43

Używamy:

  • wyłącznie gałąź rozwoju

aż projekt dobiega końca lub tworzymy wersję z kamieniem milowym (np. demo produktu, wersja prezentacyjna), następnie (regularnie) rozgałęziamy naszą obecną gałąź rozwojową na:

  • gałąź wydania

Żadne nowe funkcje nie trafiają do gałęzi wydania. Tylko ważne błędy są naprawiane w gałęzi wydania, a kod naprawiający te błędy jest ponownie integrowany z gałęzią programistyczną.

Dwuczęściowy proces z gałęzią deweloperską i stabilną (wydaną) znacznie ułatwia nam życie i nie sądzę, abyśmy mogli ulepszyć jakąkolwiek jej część, wprowadzając więcej gałęzi. Każda gałąź ma również swój własny proces kompilacji, co oznacza, że ​​co kilka minut pojawia się nowy proces kompilacji, więc po sprawdzeniu kodu mamy nowy plik wykonywalny wszystkich wersji kompilacji i gałęzi w ciągu około pół godziny.

Czasami mamy również oddziały dla jednego programisty pracującego nad nową i nie sprawdzoną technologią lub tworzącego proof of concept. Ale generalnie jest to wykonywane tylko wtedy, gdy zmiany dotyczą wielu części bazy kodu. Dzieje się to średnio co 3-4 miesiące, a taka gałąź jest zwykle ponownie integrowana (lub złomowana) w ciągu miesiąca lub dwóch.

Generalnie nie podoba mi się pomysł, aby każdy programista pracował we własnym oddziale, ponieważ „pomijasz drogę i przechodzisz bezpośrednio do piekła integracji”. Zdecydowanie odradzam to. Jeśli masz wspólny kod, wszyscy powinniście nad nim pracować razem. To sprawia, że ​​programiści są bardziej nieufni co do swoich zameldowań, a dzięki doświadczeniu każdy koder wie, które zmiany mogą potencjalnie zepsuć kompilację, dlatego w takich przypadkach testowanie jest bardziej rygorystyczne.

W sprawie wczesnego pytania o odprawę:

Jeśli potrzebujesz tylko PERFEKCYJNEGO KODU do wpisania, tak naprawdę nic nie powinno zostać wpisane. Żaden kod nie jest doskonały, a kontrola jakości w celu jego weryfikacji i przetestowania musi znajdować się w gałęzi programistycznej, aby można było zbudować nowy plik wykonywalny.

Dla nas oznacza to, że gdy funkcja zostanie ukończona i przetestowana przez programistę, zostanie ona zarejestrowana. Może nawet zostać sprawdzona, jeśli są znane (niekrytyczne) błędy, ale w takim przypadku osoby, na które może mieć wpływ ten błąd, to zwykle poinformowany. Kod niekompletny i będący w toku można również zarejestrować, ale tylko wtedy, gdy nie powoduje to żadnych oczywistych negatywnych skutków, takich jak awarie lub uszkodzenie istniejącej funkcjonalności.

Od czasu do czasu niemożliwe do uniknięcia połączone sprawdzanie kodu i danych spowoduje, że program będzie bezużyteczny do czasu zbudowania nowego kodu. Przynajmniej musimy dodać „CZEKAJ NA BUDOWANIE” w komentarzu do zameldowania i / lub wysłać e-mail.

steffenj
źródło
1
Głosowałem za tym. Jest to podobne do tego, co robimy, ale wprowadzamy wszystkie zmiany w rozwoju, a następnie próbujemy scalić te poprawki błędów w gałęzi wydania. Nie działa. Jednak myślę, że jeśli zmienimy się na wszystkie poprawki błędów w wydaniu i włączymy do rozwoju, to naprawi to.
TheCodeMonk
2
Sugerujesz, że kontrola jakości testuje gałąź programistyczną, czy nie byłoby lepiej, gdyby sprawdzili gałąź wydania? W ten sposób mógłbym rozpocząć pracę nad moją nową szaloną funkcją, która nie zostanie uwzględniona w następnej wersji (i może coś zepsuć), podczas gdy w tym czasie kontrola jakości przetestuje istniejący kod bez interwencji mojej nowej funkcji?
BornToCode
15

To, co jest warte, tak to robimy.

Większość rozwoju jest wykonywana w bagażniku, chociaż funkcje eksperymentalne lub rzeczy, które mogą znacząco uszkodzić system, mają zwykle własną gałąź. Działa to całkiem nieźle, ponieważ oznacza, że ​​każdy programista zawsze ma najnowszą wersję wszystkiego w swojej kopii roboczej.

Oznacza to, że ważne jest, aby bagażnik był w niejasnym stanie, ponieważ można go całkowicie zepsuć. W praktyce nie zdarza się to często i rzadko stanowi poważny problem.

W przypadku wydania produkcyjnego rozgałęziamy linię trunk, przestajemy dodawać nowe funkcje i pracujemy nad naprawieniem błędów i testowaniem gałęzi (regularnie łącząc się z powrotem w trunk), dopóki nie będzie gotowa do wydania. W tym momencie dokonujemy ostatecznego scalenia w bagażnik, aby upewnić się, że wszystko tam jest, a następnie zwolnimy.

W razie potrzeby można następnie przeprowadzić konserwację w gałęzi wydania, a poprawki te można łatwo scalić z powrotem do linii głównej.

Nie twierdzę, że jest to doskonały system (i nadal ma pewne dziury - nie sądzę, że nasze zarządzanie wydaniami jest jeszcze wystarczająco wąskim procesem), ale działa wystarczająco dobrze.

Dan
źródło
działa dostatecznie dobrze i jest również wystarczająco prosty dla programistów, którzy tylko kodują i nie korzystają z druidów vcs.
Matthieu
12

Dlaczego nikt jeszcze o tym nie wspomina? Udany model rozgałęziania Git .

To dla mnie najlepszy model rozgałęziający!

Jeśli twój projekt jest mały, nie używaj cały czas wszystkich różnych gałęzi (być może możesz pominąć gałęzie funkcji dla małych funkcji). Ale poza tym jest to sposób na zrobienie tego!

model rozgałęziony

Philippe
źródło
4
Tak, z wyjątkiem sytuacji, gdy często jest to zbyt skomplikowane / kompletne, jak ilustruje to scottchacon.com/2011/08/31/github-flow.html .
VonC,
Zgadzam się. Zapoznaj się z modelem rozgałęziania przepływu git (który rozwiązuje wiele problemów) i uprość go, aby dopasować go do swoich potrzeb. Przepływ GitHub wymaga szybkiego wdrożenia, ale nie zawsze jest to możliwe ... Jest to mniej więcej model rozgałęziania, którego używamy w moim projekcie (aby uprościć sprawę), ale stanęliśmy przed przypadkiem, w którym chcielibyśmy użyć modelu git-flow: (i to wprawiło nas w naprawdę duże gówno :(
Philippe
1
Tak jak ja to widzę, to w zasadzie kopiuje wszystko, co VonC powiedział mniej więcej rok wcześniej (w jego odpowiedzi), ale w bardziej szczegółowy sposób iz ładnymi zdjęciami!
cregox
6

Kod deweloperski w oddziałach, kod na żywo oznaczony na Trunk

Nie musi istnieć zasada „zatwierdzaj tylko doskonały kod” - wszystko, czego deweloper przeoczy, powinno zostać zebrane w czterech miejscach: przegląd kodu, testy gałęzi, testy regresji, końcowe testy QA.

Oto bardziej szczegółowe wyjaśnienie krok po kroku:

  1. Wykonuj wszystkie prace rozwojowe w gałęzi, regularnie zobowiązując się.
  2. Niezależny przegląd kodu zmian po zakończeniu całego rozwoju.
  3. Następnie przekaż gałąź do Testowania.
  4. Po zakończeniu testowania gałęzi połącz kod z gałęzią Release Candidate.
  5. Gałąź Release Candidate jest testowana regresji po każdym indywidualnym scaleniu.
  6. Końcowe testy jakości i UA przeprowadzone na RC po połączeniu wszystkich gałęzi deweloperskich.
  7. Po przejściu QA i UAT scal gałąź release do gałęzi MAIN / TRUNK.
  8. Na koniec oznacz Trunk w tym miejscu i wdróż ten tag w Live.
Peter Boughton
źródło
4

dev przechodzi do linii głównej (styl svn), a wydania (kod produkcyjny) otrzymują własne gałęzie

Jest to „Model rozgałęziający według celu” (rysunek 3 w sekcji Znaczenie modeli rozgałęziających /! \ Pdf)

PW.
źródło
3

Rozwiązujemy ten problem, całkowicie oddzielając kod produkcyjny (główny tor) od kodu programistycznego (gdzie każdy programista ma własną gałąź).

Żaden kod nie jest dopuszczany do kodu produkcyjnego, zanim nie zostanie dokładnie sprawdzony (przez QA i recenzentów kodu).

W ten sposób nie ma wątpliwości, który kod działa, zawsze jest to główna gałąź.

Grimtron
źródło
2

O tak - jeszcze jedno - w cvs HEAD trzymamy kod nieprodukcyjny (czyli taki, który NIGDY nie zostanie wydany - np. Skrypty narzędziowe, narzędzia testujące). Zwykle musi być wyraźnie oznaczony, aby nikt „przypadkowo” go nie zwolnił.

MarkR
źródło
2
może byłoby to lepsze jako zmiana poprzedniej odpowiedzi.
Richard Harrison,
6
Powiedział CVS. :-)
Do
2

Rozwijamy się na pniu, który jest następnie rozgałęziany co dwa tygodnie i wprowadzany do produkcji. Tylko krytyczne błędy są naprawiane w gałęzi, reszta może poczekać kolejne dwa tygodnie.

W przypadku linii trunk jedyną zasadą jest to, że zatwierdzenie nie powinno niczego przerywać. Aby zarządzać kodem wip-code i kodem nieprzetestowanym, po prostu dodajemy odpowiednie instrukcje if, aby ułatwić włączanie i wyłączanie.

Zasadniczo istnieje możliwość rozgałęzienia pnia w dowolnym momencie i wprowadzenia go do produkcji.

John Nilsson
źródło
0

Używam git i mam 2 gałęzie: master i maint

  • master - kod programistyczny
  • maint - kod produkcji

kiedy zwolnić kod do produkcji otagować go i scalić pana do maint gałęzi. Zawsze wdrażam z oddziału maint . Łaty z gałęzi deweloperskiej Wybieram je najlepiej, aby utrzymywać gałąź i wdrażać poprawki.

Vitalie
źródło
0

Mamy gałąź "wydania", która zawiera to, co jest obecnie w produkcji lub zostanie wkrótce wdrożone (już przeszło większość kontroli jakości)

Każdy projekt lub w niektórych przypadkach inna jednostka ma własną gałąź, która jest rozgałęziona od momentu wydania.

Zmiany są wprowadzane przez deweloperów projektu do własnej gałęzi projektu. Okresowo wydanie jest scalane z powrotem w gałąź programistyczną.

Gdy wszystkie pakiety robocze w gałęzi zostaną poddane kontroli jakości (testy jednostkowe, testy systemowe, przegląd kodu, kontrola jakości itp.), Gałąź jest scalana z gałęzią wydania. Nowe kompilacje są budowane z gałęzi wydania, a ostateczna weryfikacja odbywa się na tej wersji.

Proces jest w zasadzie OK, dopóki problem nie zostanie wykryty po zakończeniu scalania. Jeśli pakiet WP „utknie” po scaleniu, zatrzymuje wszystko po nim, dopóki nie zostanie naprawiony (nie możemy zrobić kolejnego wydania, dopóki zablokowane wydanie nie zostanie zwolnione).


Jest również dość elastyczny - bardzo trywialna zmiana mogłaby nastąpić bezpośrednio w gałęzi wydania, jeśli byłaby wydana w bardzo krótkim czasie (np. 1-2 dni).

Jeśli z jakiegoś powodu zmiana została wprowadzona bezpośrednio do produkcji (krytyczny problem produkcyjny mający wpływ na klienta, który wymagał natychmiastowej zmiany kodu w celu naprawy), zmiany te zostaną przywrócone do BRANCH_RELEASE. To prawie nigdy się nie zdarza.

MarkR
źródło
0

To zależy od projektu. Nasz kod sieciowy jest sprawdzany dość konsekwentnie, podczas gdy nasz kod aplikacji jest sprawdzany tylko wtedy, gdy się kompiluje. Zauważyłem, że jest to bardzo podobne do tego, jak wydajemy rzeczy. Rzeczy w Internecie idą w górę, kiedy tylko jest to możliwe, podczas gdy aplikacje osiągają napięty termin. Nie zauważyłem jednak utraty jakości w żadnej z metod.

icco
źródło