Czy scrum i stabilny rozwój stanowią sprzeczność?

11

Należę do grupy programistów z 5 zespołami, w sumie około 40 programistów. Postępujemy zgodnie z metodologią Scrum, z 3-tygodniowymi sprintami. Mamy ciągłą konfigurację integracji (Jenkins), a proces kompilacji zajmuje kilka godzin (z powodu obszernych automatycznych testów). Zasadniczo proces rozwoju działa dobrze.

Obserwujemy jednak, że po kilku dniach od nowego sprintu nasza kompilacja często staje się niestabilna i pozostaje chwiejna, dopóki nie zakończy się „zatwierdzenie zatrzymania”. Negatywnym skutkiem tego jest to, że kroki kompilacji daleko w dół potoku, zwłaszcza testy interfejsu użytkownika / sieci Web nie są wykonywane przez kilka dni (ponieważ są uruchamiane tylko w przypadku „zielonej” kompilacji). W związku z tym nowo wprowadzone błędy są często wykrywane bardzo późno podczas sprintu.

  • Każde zatwierdzenie jest weryfikowane na podstawie podstawowego zestawu testów. Po zweryfikowaniu zmiana jest przekazywana do master po przejrzeniu kodu (Gerrit)
  • Podstawowe testy jednostkowe są uruchamiane co 30 minut, a czas trwania jest krótszy niż 10 minut
  • Testy integracyjne przeprowadzane są co 2 godziny, czas trwania 1 godzinę
  • Testy interfejsu użytkownika / sieci Web działają na udanych testach integracyjnych i trwają kilka godzin

W zależności od tego, kto jest odpowiedzialny za stabilność kompilacji podczas sprintu (ta odpowiedzialność jest przekazywana podczas sprintu), mogą istnieć pośrednie, „zatrzymania zatwierdzenia” ad hoc, aby przywrócić kompilację do stabilnej.

Chcemy więc:

  1. Nasze zespoły programistów opracowują i zatwierdzają zmiany podczas sprintu bez przeszkód
  2. Nasz proces kompilacji ma zostać porzucony, jeśli krok kompilacji zakończy się niepowodzeniem, ponieważ kolejne wyniki kompilacji mają niewielkie znaczenie
  3. Nasz proces kompilacji w celu dostarczenia programistom wysokiej jakości informacji zwrotnych na czas

Biorąc pod uwagę (2), punkty (1) i (3) wydają się ze sobą sprzeczne. Czy ktoś ma dobrą praktykę, jak sobie z tym poradzić?

( Obecnie tracimy punkt (2) i zezwalamy na kontynuowanie kompilacji nawet w przypadku nieudanych kroków kompilacji. Nie mam jeszcze żadnych informacji zwrotnych na temat tego, jak wpływa to na naszą jakość )

Dzięki, Simon

Szymon
źródło
3
Powiedziałbym, że jeśli trwa kompilacja, to several hoursjest prawdziwy problem. oznacza to, że połączone rozwiązanie jest zbyt duże i zbyt szerokie. Powinieneś szukać rozwiązania tego komponentu, a następnie mieć małe fragmenty kodu jako pakiety (dostępne w ten lub inny sposób we wszystkich głównych językach na wszystkich platformach). Tak więc wszelkie zmiany zostałyby wprowadzone tylko w komponentach i zostaną wykryte znacznie szybciej. Pełna wersja zasadniczo po prostu połączy już połączone elementy, a także będzie szybsza. Następnie można by tylko uruchomić niektóre testy, aby upewnić się, że właściwe komponenty zostały rozwiązane.
zaitsman
Czy Twoje środowisko kompilacji jest lokalne czy oparte na chmurze?
Lauri Laanti
@LauriLaanti, nasze środowisko kompilacji jest lokalne, 1 instancja Jenkins z 3 niewolnikami.
Simon

Odpowiedzi:

7

Najpierw kilka podstawowych zasad: - Poważne zmiany powinny zawsze dotyczyć gałęzi funkcji w VCS - Gałęzie cech powinny przejść wszystkie testy przed scaleniem w pień. Dodano - Zawsze należy budować zatwierdzenia - Złamana kompilacja wymaga natychmiastowego działania ze strony zlecającego i / lub reszty zespołu. - Nieudany test powinien przerwać pozostałe testy, jeśli jest to test krytyczny .

Jeśli jako zespół postępujesz zgodnie z tymi praktykami i egzekwujesz je, np .: „nazwa i wstyd”, gdy kompilacja jest zepsuta, powinieneś zacząć, ponieważ wszelkie zatwierdzenia, które mogłyby ją przerwać, będą dotyczyły gałęzi funkcji. Inne zatwierdzenia, które przerywają kompilację, będą musiały zostać natychmiast zaadresowane, a następnie otrzymasz wyniki dalszych testów.

Możesz również dodać automatyczny test najnowszej „udanej” kompilacji (niekoniecznie pozytywnej dla testów integracyjnych), dla testów interfejsu użytkownika / sieci jako codzienne uruchamianie raportów z samego rana.

Steve Barnes
źródło
3
Dobrą praktyką do dodania tutaj jest to, że gałęzie funkcji powinny przejść wszystkie testy, zanim zostaną połączone z linią główną
Bart van Ingen Schenau
@BartvanIngenSchenau - dodano dobry punkt!
Steve Barnes,
@ SteveBarnes, dzięki za wkład. Zatwierdzenie w Gerrit jest zawsze w gałęzi i jest scalane tylko w przypadku sukcesu (mój pierwszy punkt w procesie kompilacji). Po tym zaczyna się problem. Z 30 deweloperami popełniającymi zmiany wiele razy dziennie, musimy wcześniej połączyć, a następnie zweryfikować. Nie jest natychmiastowe działanie po złamanym kompilacji, ale jako czas pomiędzy popełnić i budować zwrotne wynosi 2 godziny, nie będzie kilka innych commity w międzyczasie. Możliwe, że złamie następną wersję.
Simon
@Simon celem „imienia i wstydu” jest sprawienie, by programiści przestali popełniać uszkodzony kod! W większości systemów możliwe jest wykonanie kompilacji testowej w krótkim czasie przy użyciu narzędzi takich jak mrówka, marka, scons itp. Jeśli twój projekt jest dobrze skonstruowany, większość języków pozwala na częściowe przebudowy w celu przetestowania, czy coś się zbuduje (pełne / czyste kompilacje wciąż muszą być oczywiście wykonane).
Steve Barnes,
8

Nie ma to nic wspólnego ze Scrumem. Niezależnie od tego twoja kompilacja powinna być stabilna.

Nikt nie powinien niczego zameldować, chyba że wykonał lokalną kompilację i nie uruchomił testów jednostkowych lokalnie (i oba przeszły, oczywiście). Lokalny proces kompilacji i testowania powinien być wrażliwy na modyfikacje i może pomijać testy kodu, który się nie zmienił.

Każdy, kto wprowadza coś, co powoduje niepowodzenie kompilacji lub niepowodzenie testu jednostkowego, powinien być publicznie zawstydzony . Jeśli kompilacja jest zepsuta, należy ją natychmiast naprawić.

John Wu
źródło
2
Z jednej strony należy podkreślić, że odpowiedzialność za budowanie stabilności spoczywa na wszystkich. Z drugiej strony odradzam publiczne zawstydzanie, ponieważ (1) bardziej doświadczeni członkowie zespołu ponoszą większą odpowiedzialność za pomoc młodszym członkom w osiągnięciu stabilności kompilacji (poprzez przegląd kodu, programowanie par lub po prostu ścisłą współpracę przed zatwierdzeniem lub przez naprawianie zepsutej wersji), (2) zawstydzanie odbiera zespołowi bezpieczeństwo psychiczne .
rwong
1
Jeśli ludzie nie chcą się zawstydzić, nie powinni przerywać kompilacji. To nie tak, że to nieuzasadniony wysoki standard. Jeśli masz deweloperów, którzy nie potrafią go zhakować, pozwól im mieć własną gałąź do gry, dopóki nie wymyślą, jak nie złamać krytycznego Commons zespołu. (Biorąc to pod uwagę, wszelkie rzeczywiste zawstydzanie powinno być w dobrym guście).
John Wu,
W naszym procesie każde zatwierdzenie jest rozgałęzione (w Gerrit) i musi przejść podstawowy zestaw testów przed połączeniem z master. Te podstawowe testy nie mogą działać przez godzinę, ponieważ chcemy szybko przeglądać i scalać kod. Problem pojawia się po scaleniu, patrz mój komentarz do @SteveBarnes
Simon
6

Problem polega na tym, że testy trwają zbyt długo. Na szczęście prawo Moore'a dostarczyło nam rozwiązanie tego problemu. Obecnie wysokiej klasy procesory serwerowe mogą mieć łatwo ponad 10 rdzeni (i ponad 10 HyperThreads). Na jednym komputerze może znajdować się wiele takich procesorów.

Gdybym miał tak długo trwające testy, rozwiązałbym problem z większą ilością sprzętu. Kupiłbym wysokiej klasy serwer, a następnie równolegle przeprowadzał testy, aby w pełni wykorzystać wszystkie rdzenie procesora. Jeśli twoje testy są dziś jednowątkowe, skorzystanie z 10 rdzeni i 10 HyperThredów prawdopodobnie spowoduje, że testy przebiegną 15 razy szybciej. Oczywiście oznacza to, że używają 15 razy więcej pamięci, więc komputer musi mieć wystarczającą ilość pamięci RAM.

Kilka godzin zamieni się w 10-30 minut.

Nie powiedziałeś, ile czasu zajmuje kompilacja, ale standardowe narzędzia kompilacji, takie jak make, umożliwiają równoległe tworzenie kompilacji. Jeśli równolegle przeprowadzisz testy jednostkowe, a typowy komputer programisty ma 4 rdzenie i 4 HyperThreads, mniej niż 10 minut testów jednostkowych zmieni się w mniej niż 2 minuty. Być może mógłbyś narzucić zasadę, że każdy powinien przeprowadzić testy jednostkowe przed zatwierdzeniem?

O niepowodzeniu testu zatrzymującego dalsze testy: nie rób tego na serwerze kompilacji! Chcesz uzyskać jak najwięcej informacji o awarii, a dalsze testy mogą ujawnić coś ważnego. Oczywiście, jeśli sama kompilacja się nie powiedzie, nie można uruchomić testów jednostkowych. Jeśli programista przeprowadza testy jednostkowe na swoim komputerze, możesz chcieć przerwać przy pierwszej awarii.

Nie widzę żadnego związku między Scrumem a twoimi problemami. Problemy mogą naprawdę wystąpić przy każdym procesie programowania.

juhist
źródło
Zgadzam się, że przy szybszej kompilacji byłoby znacznie łatwiej. Nasz TechTeam spędził kilka dni na poprawianiu szybkości procesu kompilacji, w przeciwnym razie czekalibyśmy dni zamiast godzin. Na razie czas trwania sprzężenia zwrotnego podawany jest w przybliżeniu. 2 godziny. Więc szukam podejścia, które potraktuje to jako „dane”. (Oczywiście, ciągle staramy się przyspieszyć kompilację. Ale w najbliższej przyszłości potrwa to 2 godziny)
Simon
Niektóre testy mogą kolidować z równoległym uruchomieniem
deFreitas
Można wrzucić do niego więcej sprzętu tylko wtedy, gdy testy są napisane w taki sposób, aby mogły działać niezależnie od siebie bez wprowadzania efektów ubocznych. Im dalej od sprzętu, tym trudniej się robi ... większość programistów nie robi tego dobrze to zrozumiem, więc chociaż zgadzam się z tobą, najpierw skupię się na ustrukturyzowaniu testów we właściwy sposób.
c_maker
2

Czy nie jest możliwe posiadanie większej liczby instalacji Jenkinsa i sprawdzenie przez programistów osobnej instancji Jenkins?

Wydaje mi się, że najlepszym rozwiązaniem jest, aby kod przeszedł wszystkie testy, zanim zostanie sprawdzony w gałęzi master i skompilowany / przetestowany przez główną instancję Jenkins. Nie pozwól, aby ludzie sprawdzali kod, który psuje kompilację.

Sprawdzam kod w gałęzi programistycznej, sprawdzam, czy pomyślnie przejdzie testy i tworzę żądanie ściągnięcia. Ale możesz oczywiście poprosić jenkinsa o pociągnięcie gałęzi funkcji i przetestowanie tej.

xyious
źródło
1

Punkt 2 wydaje się najbardziej bolesny, więc skupię się na tym.

Być może nadszedł czas, aby podzielić projekt na wiele modułów.

https://en.wikipedia.org/wiki/Dependency_inversion_principle

A. Moduły wysokiego poziomu nie powinny zależeć od modułów niskiego poziomu. Oba powinny zależeć od abstrakcji.

B. Abstrakcje nie powinny zależeć od szczegółów. Szczegóły powinny zależeć od abstrakcji.

Jeśli jeden moduł nie powiedzie się, kompilacja dla innych modułów będzie mogła być kontynuowana, o ile te inne moduły mogą zależeć od interfejsu, a kod tworzący ten interfejs został pomyślnie zbudowany.

Dzięki temu otrzymasz informacje zwrotne na temat innych awarii kompilacji, dzięki czemu będziesz mieć czas na naprawę więcej niż jednego uszkodzonego modułu, zanim nastąpi kolejna kompilacja.

Ogólnie rzecz biorąc, zasady SOLID mają na celu radzenie sobie z bibliotekami i budowanie problemów. Innymi słowy - ten zestaw zasad ma na celu rozwiązanie dokładnie tego rodzaju problemów, z którymi się borykasz.


Na marginesie (patrz odpowiedź Juhist'a), nie możesz przyspieszyć kompilacji (przez równoległość), jeśli nie podzielisz kompilacji na osobne moduły.

rwong
źródło
0

Myślę, że Twojemu zespołowi brakuje jednej z kluczowych zasad scrum: gotowe, działające oprogramowanie. PBI nie powinno być oznaczane jako wykonane, dopóki nie przejdzie do Definicji ukończenia ustalonej przez zespół. Definicja Gotowości jest inna dla każdej drużyny, ale prawdopodobnie obejmuje takie rzeczy jak:

  • Kod zawiera testy jednostkowe
  • Zdać test jednostkowy jako część automatycznej kompilacji
  • Kod został scalony w główny (i konflikty zostały rozwiązane)
  • itp.

Zasadniczo dzieje się tak, że Twój zespół zaznacza rzeczy zrobione, których w rzeczywistości nie zrobiono. To problem sam w sobie.

Poza tym sprowadza się do właściwego zarządzania kontrolą wersji. Jeśli używasz Git, cała praca jest wykonywana w lokalnym repozytorium dewelopera i nie powinni oni wypychać niczego na odległość, chyba że jest to zrobione i potencjalnie możliwe do zwolnienia. Niekompletne prace nie powinny być nigdy przekazywane do głównego repozytorium. Jeśli deweloper musi pracować nad dłuższą gałęzią funkcji i chce naciskać na zdalne, aby upewnić się, że nie stracą swojej pracy, powinni pracować z rozwidlenia, a następnie połączyć widelec w główny, gdy funkcja jest „gotowa” i potencjalnie można ją wydać - nie wcześniej.

W przypadku TFVC jest to nieco bardziej skomplikowane, ponieważ wszystko dzieje się na „zdalnym”. Oznacza to, że deweloperzy powinni zawsze pracować z gałęzi, chyba że jest to szybka poprawka. Obowiązują tu jednak te same zasady, co w przypadku Git: niekompletne oprogramowanie nie zostaje popełnione. Kropka. W odpowiednio zarządzanej kontroli wersji „main” powinien zawsze być zwalniany. Jeśli dokonano zatwierdzenia, że ​​borsy są „główne”, to nie robisz tego dobrze.

Chris Pratt
źródło