tło
Pracuję w zespole, który chce wdrożyć wdrożenia bez przestojów. Aby to osiągnąć, planujemy zastosować niebiesko-zieloną strategię wdrażania. Jedną z rzeczy, które zdaję sobie sprawę z przeprowadzania badań, jest to, jak skomplikowane jest wprowadzanie zmian w bazie danych. Prosta operacja, taka jak zmiana nazwy kolumny, może potrwać 3 pełne cykle wydania, aż do jej zakończenia!
Wydaje mi się, że pełne wdrożenie zmiany wymagającej wielu cykli wydawniczych wprowadza wiele potencjalnych błędów ludzkich. W połączonym artykule pokazuje, że zmiany kodu są konieczne dla 2 wydań, a migracja bazy danych jest wymagana dla 3 wydań.
Czego szukam
Obecnie, jeśli chcemy coś zrobić, możemy utworzyć bilet w naszym systemie zarządzania problemami, który tworzy bałagan, a także może zostać przeniesiony do późniejszego sprintu lub zaległości przez kierownictwo; lub możemy utworzyć komentarz do zrobienia TODO, o którym prawdopodobnie całkowicie zapomnimy.
To, czego szukam, to sposób, w jaki komentarz TODO może mieć przed sobą termin, a nasz system ciągłej integracji (obecnie niezdecydowany, którego użyjemy) odrzuci kompilację, jeśli ten termin upłynie.
Na przykład, jeśli zmienimy nazwę kolumny, możemy utworzyć dla niej początkową migrację, a następnie dwa komentarze DO ZROBIENIA, aby zapewnić utworzenie pozostałych dwóch migracji:
// TODO by v55: Create migration to move constraints to new column, remove references to old column in app
// TODO by v56: Create migration to drop old column
Wydaje się to dość proste do wdrożenia, ale zastanawiam się, czy coś takiego już istnieje, ponieważ nie chcę ponownie wymyślać koła.
Dodatkowe przemyślenia
Wydaje mi się, że mogę tu mieć problem z XY, biorąc pod uwagę, że wdrażanie cykliczne i wdrożenia niebiesko-zielone są uważane za najlepszą praktykę, wydaje się dziwne, że nie mogę znaleźć rozwiązania, które sprawi, że aktualizacje bazy danych będą mniej bolesne. Jeśli uważasz, że szukam całkowicie złej rzeczy, daj mi znać w komentarzu! To powiedziawszy, przykład bazy danych, który podałem, jest tylko jednym przykładem i myślę, że komentarze TODO z terminami byłyby przydatne również w innych sytuacjach, więc nawet jeśli podejdę do tej konkretnej sytuacji zupełnie źle, naprawdę chciałbym odpowiedzieć na moje aktualne pytanie. Dzięki!
EDYCJA: Właśnie pomyślałem o innej sytuacji, w której może to być pomocne. Jeśli używasz funkcji przełączania funkcji do włączania części aplikacji, gdy są one gotowe, musisz uważać, aby je wyczyścić, w przeciwnym razie możesz skończyć z funkcją przełączania długu . Komentarze z terminami mogą być dobrym sposobem na zapamiętanie tego.
źródło
TODO <Bug#>:
do śledzenia obejść problemów z innymi komponentami. Po usunięciu błędu w jednym z tych elementów można łatwo znaleźć i rozwiązać odpowiednie obejścia. Nie zastępuje narzędzia do śledzenia problemów, ułatwia konserwację.Odpowiedzi:
To pytanie to tak naprawdę dwa pytania w jednym.
Komentarze Todo
Ze wszystkich sposobów śledzenia przedmiotów akcji jest to najgorsze. Komentarze do zrobienia TODO są dobre podczas aktywnej pracy lub jako sugestia dla opiekuna: „oto coś, co można poprawić w przyszłości”. Ale jeśli polegasz na komentarzach TODO do wykonania pracy, jesteś skazany na porażkę.
Co z tym zrobić
Komentarze do zrobienia TODO są zasadniczo długiem technicznym, dlatego należy traktować je jak każdy inny dług techniczny. Zajmij się nimi od razu, jeśli masz czas, lub umieść je w zaległościach, aby można je było śledzić i ustalać priorytety.
Ogólnie rzecz biorąc, i to jest całkowicie opiniotwórcze i otwarte na debatę, komentarze TODO można uznać za zapach kodu. Jeśli komentarz do zrobienia pozwala na sprawdzenie wersji, musisz zadać sobie pytanie, czy naprawdę zamierzasz teraz to zrobić? Jeśli nie, to w porządku. Bądź ze sobą szczery i umieść go w zaległościach.
Sposób zarządzania tym zaległościami sprowadza się do procesów biznesowych, polityki firmy i być może osobistej autonomii. Ale nadal potrzebujesz śledzonego i nadanego priorytetowi zaległości, aby mieć pewność, że tak się stanie.
Zmiany w bazie danych
Tak, zmiany w bazie danych są trudne przy zastosowaniu zasady zerowego przestoju. Kilka sztuczek, dzięki którym będzie mniej bolesne:
Proces po wdrożeniu
Utwórz proces po wdrożeniu, który działa jako część tej samej wersji. Jakkolwiek chcesz, żeby to działało. W ostatnim systemie, nad którym pracowałem, zaprojektowałem wdrożenie 4-fazowe:
Pomysł polegał na tym, że tam, gdzie to możliwe, wprowadzaliśmy jak najwięcej zmian w bazie danych do preappa.
Postapp był zarezerwowany dla nietypowych przypadków, w których musieliśmy wprowadzić niezgodne zmiany schematu. W takich przypadkach preapp wprowadziłby wystarczającą zmianę, aby nowy kod aplikacji był kompatybilny (być może stworzenie tymczasowego widoku zgodności), a postapp wyczyściłby wszelkie tymczasowe artefakty.
Faza okna konserwacji była zarezerwowana dla zmian, które naprawdę wymagały przestoju lub w których ryzyko lub koszt wdrożenia na żywo nie było tego warte. Na przykład skrypty zmieniające ogromne ilości danych mogą wymagać zablokowania całej tabeli.
Wdrażaj często
Jeśli wdrażasz nowe wersje wystarczająco często, możesz osiągnąć punkt, w którym przenoszenie zmian w 2 lub 3 wersjach jest banalne. Długie cykle wydawnicze zwiększają koszty zmian w bazie danych.
źródło
Nie używaj TODO. Masz już listę rzeczy do zrobienia w swoim projekcie. Nazywa się to śledzeniem problemów.
Myślę, że prawdziwy problem tkwi w tym zdaniu:
Jeśli narzędzie do śledzenia problemów tworzy dużo bałaganu, znajdź sposoby, aby to naprawić. Może specjalny typ / tag wydania, który wymaga mniej ceremonii. Może pod-problemy. Może w sumie mniej ceremonii. Naprawdę nie możemy powiedzieć. Ale jeśli narzędzie do śledzenia problemów tworzy tyle pracy, że ludzie raczej formułują skomplikowane pytania na forum publicznym niż po prostu dodają ten problem, coś jest naprawdę nie tak.
Jeśli kierownictwo nadmiernie opóźnia ostatnią część zadania, masz dwie opcje:
porozmawiaj z kierownictwem, dlaczego to zły pomysł.
traktuj to jako jedno zadanie. To może być złoty standard rozwiązania. W idealnym świecie powinieneś być w stanie wprowadzić trzy zmiany potrzebne na każdym kroku. Zastosuj jedną do gałęzi głównej, pozwól jej zbudować i wdrożyć. W międzyczasie zastosuj drugą gałąź master, pozwól jej zbudować i wdrożyć itd., Aby wszystko działo się w tym samym sprincie, a jeśli tak się nie stanie, nie zostanie to zrobione. Może nawet coś automatycznego ma sens, gdy logicznie wykonujesz jedno wdrożenie, ale tak naprawdę jest ono podzielone na 3.
źródło
// TODO(#12345): Frobnicate the sprocket before passing it along
, pod warunkiem, że błąd nr 12345 jest „prawdziwym” numerem problemu, a problem został komuś przypisany. Ułatwia to odczytanie źródła, wyjaśniając: „Nie, krok odszyfrowania nie ukrywa się w jednej z metod pomocniczych, jest po prostu niezaimplementowany. Przejdź do błędu # 12345, aby uzyskać więcej kontekstu”. Idealnie byłoby, gdybyś codziennie przeglądał linijkę po bazie kodu, szukając oczywiście zamkniętych lub nieprawidłowych numerów problemów.To, o co prosisz, jest wykonalne, jeśli chcesz wykonać pracę i postępować zgodnie z nią.
grep,
//TODO by v55
kiedy nadszedł czas na wdrożenie v55. Wdróż kompilację uruchamia skrypt, który robi to jako test integracji.Możesz powiązać 55 ze śledzeniem wersji lub po prostu o to poprosić.
Interesujące staje się, jeśli chcesz sprawdzić // TODO do v54 podczas wykonywania 55. Zamiast tego przeszukaj 55 razy bazę kodu, po prostu wyszukaj // TODO według. Następnie odfiltruj ten wynik od 1 do 55. Teraz 56 nie spowoduje niepowodzenia.
Możesz pomyśleć „och, nie będziemy tego potrzebować. Naprawimy je za każdym razem, dopóki będziemy mieli czek”. Nie, nie będziesz.
źródło
W naszym zespole mieliśmy bardzo podobny problem. Aby rozwiązać ten problem, napisaliśmy kontrolę analizy statycznej, która obsługuje te TODO, sprawdzając problem JIRA lub problem Git, do którego się odnoszą. Nasza kompilacja kończy się niepowodzeniem, gdy określony problem przesuwa się poza kolumnę „W fazie rozwoju”.
Dlatego możemy wygodnie mieć TODO, nie martwiąc się, że zostaną zapomniani.
Stworzyłem implementację tego typu open source w Javie. Tak, zastrzeżeniem jest to, że napisałem to, ale tak jak powiedziałem, jest to całkowicie otwarte źródło i licencja.
Narzędzie nazywa się Westie, a przykład sprawdzania problemów Jira znajduje się na README.md. Zobacz także GitIssueAnalyser.
Aby zapobiec autopromocji w przypadku dalszych pytań, wyślij mi wiadomość. Jeśli zdecydujesz się go użyć i masz jakieś sugestie, prosimy o zgłaszanie problemów na github.
źródło
Nie rób tego. Zrób to teraz.
TLDR: Napisz (i przetestuj) skrypty DB teraz, nie później; wystarczy je zakodować, aby ich wykonanie zależało od wersji DB.
Przykład
Na przykład wyobraźmy sobie, że chcesz zmienić nazwę kolumny z
SSN
naTaxID
, co jest powszechnym wymogiem podczas podróży międzynarodowych.Aby tak się stało, być może tymczasowo będziesz mieć zarówno kolumnę, jak
TaxID
iSSN
kolumnę. Obsługując obie wersje, będziesz mieć wyzwalacz do aktualizacji jednej z drugiej. Ale nie chcesz utrzymywać tego wyzwalacza w nieskończoność, więc później, gdy zgodność wsteczna nie jest już potrzebna, chcesz, aby ten wyzwalacz został usunięty (iSSN
kolumna została usunięta). Zamierzamy zakodować to wszystko z góry bez potrzeby wykonywania czynności do wykonania.W naszym przykładzie będziemy wdrażać kompilację 102 (która ma nową kolumnę), zachowując zgodność z kompilacją 101 (która nie ma).
Oto kroki.
1. Skonfiguruj tabelę wersji
Dodaj pojedynczą tabelę
Configuration
z dwiema kolumnamiName
iValue
.Dodaj wiersz z
Name
„TargetVersion” i ustawValue
wersję nowej kompilacji do wdrożenia.Dodaj wiersz z
Name
„CompatibleWith” i ustawValue
minimalną liczbę wersji, z którą wdrożenie musi być zgodne.Sprawdź i zaktualizuj te wiersze przed każdym wdrożeniem.
2. Zmodyfikuj skrypty wdrażania
Dodaj skrypt, który tworzy nową kolumnę
TaxID
obok siebieSSN
i wypełnia ją zSSN
kolumny. Umieść ten kod wIf
instrukcji, która sprawdza TargetVersion; jeśli wersja docelowa jest zbyt niska (tzn.TaxID
nie jest jeszcze potrzebna), pomiń.Dodaj skrypt, który tworzy wyzwalacz, który zapełnia się
TaxID
podczas wstawiania lub aktualizacjiSSN
i odwrotnie. Umieść ten kod wIf
instrukcji, która sprawdza wersję docelową i wersję zgodną; pomiń, jeśli wartość TargetVersion jest zbyt niska (TaxID
nie jest potrzebna) lub jeśli wersja CompatibleWith jest zbyt wysoka (SSN
pole nie jest potrzebne).Dodaj skrypt, aby usunąć
SSN
kolumnę. Dodaj doIf
instrukcji, która usuwa kolumnę tylko wtedy, gdy wersja CompatibleWith jest wystarczająco wysoka (SSN
nie jest już potrzebna).3. Testowanie
Przetestuj swoje wdrożenie przy użyciu dowolnej kombinacji numerów wersji niebiesko-zielonej, którą chcesz obsługiwać w produkcji. Możesz przetestować, gdy tylko kod będzie gotowy, manipulując
Configuration
tabelą w środowisku kontroli jakości.4. W podręczniku wdrażania
Dodaj krok dla inżyniera, aby zaktualizował wiersze CompatibleWith wersji i TargetVersion. W przypadku wdrażania w kolorze niebieskim ustaw opcję TargetVersion na numer wersji Blue, a wersję CompatibleWith na numer wersji Green; odwróć je, jeśli wdrażasz zielony.
Pułapki
Jest OK dla twoje skrypty wdrażania odwoływać i powoływać się na te numery wersji przechowywanych w tej tabeli DB. NIE kod środowiska wykonawczego.
Jeśli zaczniesz pisać kod środowiska wykonawczego w celu sprawdzenia numerów wersji, wprowadzasz w aplikacji nowy poziom złożoności, który może potencjalnie stać się poważnym problemem w zakresie konserwacji. Każda ścieżka wykonania środowiska wykonawczego musi zostać przetestowana; jeśli będziecie sobie radzić z tymi warunkami, QA będzie musiała zebrać matrycę bólu, aby potwierdzić je przy każdym uwolnieniu. Radzę zachować takie warunki tylko w skryptach wdrażania.
Wynik tego wszystkiego
Ostatecznie powinieneś być w stanie napisać cały kod z góry (i przetestować go również) bez obawy, że będzie on wykonywany zbyt wcześnie. Ponadto kod wyczyści wyzwalacz zgodności wstecznej, gdy nadejdzie czas, bez potrzeby martwienia się o to dalej.
W ten sposób możesz napisać i przetestować cały kod, gdy myślisz o tym, i nie musisz radzić sobie z tymi niechlujnymi komentarzami do zrobienia.
źródło
Dostajesz wiele zwrotów od swojego pomysłu do zrobienia, ale osobiście nie widzę z tym problemu. Ostatecznie najlepszym (i najłatwiejszym) sposobem upewnienia się, że migracja trafi do produkcji, jest niepowodzenie testu jednostkowego. Wytarcie pustej funkcji migracji, która zgłasza wyjątek, jeśli wersja ma 55 lub więcej (lub cokolwiek są wymagane), zajmie dosłownie mniej niż minutę.
Następnie, jeśli spróbujesz go zwolnić, zakończysz się niepowodzeniem testu i ktoś będzie musiał zamienić ten wyjątek w rzeczywisty kod migracji.
źródło
Wydaje się, że nikt nie koncentruje się na źródłach jego skargi, a mianowicie na tym, że zmiany w bazie danych mogą zająć zbyt wiele cykli wydań. Chce kontynuować swój niebieski / zielony harmonogram wdrażania i rozwiązanie powinno już tam być, ale chyba, że coś mi brakuje, jego opis wydaje się wskazywać, że istnieje tylko jedna baza danych, która jest współdzielona przez oba systemy. W takim przypadku nie jest to prawdziwy system niebiesko-zielony. Ponieważ wydaje się, że baza danych jest długim biegunem w namiocie, należy ją również zduplikować, aby bez względu na to, ile czasu i ile cykli wydania zajmie wdrożenie zmian w bazie danych w systemie offline, nie zostaną one uruchomione, dopóki nie zostaną zakończone i w pełni przetestowane. Tymczasowe skrypty systemowe offline mogą codziennie aktualizować bazę danych offline.
źródło