Ciągłe dostarczanie
oprogramowania w języku Java
Najlepsze narzędzia i
praktyki wdrażania kodu
W
ciągu ostatnich lat radykalnie zmieniły się wymagania i oczekiwania
biznesowe wobec oprogramowania. Kluczowymi wartościami są
innowacyjność, szybkość i czas wejścia na rynek. Do spełnienia tych
wymagań konieczne okazały się nowe architektury i modele tworzenia
kodu. Metodyka ciągłego dostarczania, zwanego też CD, polega na
tworzeniu w krótkich cyklach wartościowych i solidnych
produktów. Funkcjonalności są dodawane w małych krokach, a
oprogramowanie można wydawać niezawodnie w dowolnej chwili. To sprawia,
że można też szybko otrzymywać informacje zwrotne. Jednak taki
sposób pracy wymaga odpowiednich ram organizacyjnych, a
zespół projektowy musi przyswoić nieco inny od tradycyjnego
styl pracy.
Ta
książka jest praktycznym przewodnikiem, dzięki któremu
programiści Javy opanują techniki potrzebne do pomyślnego zastosowania
metody ciągłego dostarczania. Opisano tu najlepsze zasady budowy
architektury oprogramowania, automatycznej kontroli jakości, pakowania
aplikacji i wdrażania ich w różnych środowiskach
produkcyjnych. Szczególną uwagę poświęcono testowaniu
oprogramowania: przedstawiono całą gamę metodyk testowania, opisano ich
zastosowanie i znaczenie w cyklu życia aplikacji. Ciekawym elementem
książki są informacje o złych praktykach i antywzorcach wraz ze
wskazówkami dotyczącymi rozwiązywania tego rodzaju
problemów.
W tej książce między innymi:
- solidne podstawy ciągłego
dostarczania oprogramowania
- migracja do ciągłego
dostarczania oprogramowania
- narzędzia: Jenkins, PMD i
FindSecBugs
- zasady testowania
funkcjonalności i jakości oprogramowania
- techniki obserwacji
aplikacji w środowisku produkcyjnym
Słowa
wstępne 13
Wstęp 17
1.
Ciągłe
dostarczanie? Dlaczego? Czym jest? 21
Ogólny zarys 21
Dlaczego? Bo daje możliwości programistom 22
Szybka informacja zwrotna pozwala ograniczyć zmiany kontekstu 22
Automatyczne, powtarzalne i niezawodne wydania 22
Uściślenie definicji ukończenia 23
Czym jest? Badamy typowy potok budowy 24
Podstawowe etapy potoku budowy 24
Wpływ technologii kontenerów 28
Zmiany we współczesnych architekturach 29
Podsumowanie 29
2.
Ewolucja programowania w języku Java 31
Wymagania współczesnych aplikacji Java 31
Potrzeba szybkości i stabilności biznesowej 32
Rozwój ekonomii interfejsów API 32
Szanse i koszty chmury 33
Przywrócenie modularności: wykorzystanie niewielkich usług 33
Wpływ na ciągłe dostarczanie 34
Ewolucja platform wdrożeniowych w języku Java 35
Archiwa WAR i EAR: era dominacji serwerów aplikacji 35
Wykonywalne pliki JAR z zależnościami: powstanie metodologii dwunastu
aspektów 36
Obrazy kontenerów: ulepszenie przenośności (i zwiększenie
złożoności) 37
Funkcja jako usługa: pojawienie się przetwarzania "bezserwerowego" 37
Wpływ platform na ciągłe dostarczanie 38
Metodyki DevOps, SRE oraz Release Engineering 39
Rozwój i utrzymanie 39
Site Reliability Engineering 40
Inżynieria wydawnicza oprogramowania 42
Współodpowiedzialność, metryki i wgląd 43
Podsumowanie 44
3.
Projektowanie
architektury pod kątem ciągłego dostarczania 45
Fundamenty dobrej architektury 45
Luźne sprzężenie 45
Wysoka spójność 47
Sprzężenie, spójność i ciągłe dostarczanie 47
Architektura nakierowana na elastyczność biznesową 49
Zła architektura ogranicza dynamikę biznesową 49
Złożoność i koszt zmian 50
Najlepsze rozwiązania dla aplikacji zorientowanych na API 50
Tworzenie interfejsów API metodą od zewnątrz do wewnątrz 51
Dobre interfejsy API pomagają w ciągłym testowaniu i dostarczaniu 51
Platformy wdrażania a architektura 52
Projektowanie aplikacji natywnych dla chmury według metodologii 12
aspektów 52
Doskonalenie wyczucia mechaniki 55
Projektowanie i ciągłe testowanie pod kątem awarii 56
Podążanie w kierunku niewielkich usług 57
Wyzwania w dostarczaniu aplikacji monolitycznych 57
Mikrousługi: architektura zorientowana na usługi spotyka się z
projektowaniem dziedzinowym 58
Funkcje, architektura Lambda i nanousługi 59
Architektura: "wszystko to, co trudno zmienić" 60
Podsumowanie 60
4.
Platformy wdrożeniowe, infrastruktura i ciągłe dostarczanie aplikacji
Java 63
Funkcje zapewniane przez platformę 63
Niezbędne procesy programistyczne 64
Platformy oparte o tradycyjną infrastrukturę 65
Komponenty tradycyjnej platformy 65
Wyzwania platform opartych o tradycyjną infrastrukturę 66
Korzyści z bycia tradycyjnym 66
Ciągła integracja i dostarczanie na platformach opartych o tradycyjną
infrastrukturę 67
Platforma chmury (IaaS) 67
Zaglądamy w chmurę 68
Wyzwania chmury 69
Korzyści z chmury 70
Ciągłe dostarczanie w chmurze 71
Platforma jako usługa 72
Zaglądamy w usługę PaaS 72
Wyzwania platformy PaaS 73
Korzyści z platformy PaaS 75
Ciągła integracja i dostarczanie a model PaaS 75
Kontenery (Docker) 75
Komponenty platformy kontenerów 76
Wyzwania technologii kontenerów 76
Korzyści z kontenerów 78
Ciągłe dostarczanie kontenerów 78
Kubernetes 78
Podstawowe koncepcje platformy Kubernetes 79
Wyzwania platformy Kubernetes 80
Korzyści z platformy Kubernetes 81
Ciągłe dostarczanie na platformie Kubernetes 81
Funkcja jako usługa (funkcje bezserwerowe) 81
Koncepcje platformy FaaS 82
Wyzwania platformy FaaS 83
Korzyści z platformy FaaS 84
Ciągła integracja i dostarczanie a model FaaS 84
Praca z infrastrukturą jako kodem 85
Podsumowanie 86
5.
Budowanie aplikacji w języku Java 87
Podział procesu budowania 87
Automatyzacja budowania 88
Zależności budowania 89
Zależności zewnętrzne 92
Projekty wielomodułowe 93
Wiele repozytoriów (czy jedno)? 93
Wtyczki 94
Wydawanie i publikacja artefaktów 95
Przegląd narzędzi do budowania kodu Java 95
Ant 95
Maven 98
Gradle 102
Bazel, Pants i Buck 105
Inne narzędzia do budowania oparte o JVM: SBT i Leiningen 107
Make 107
Wybór narzędzia do budowania 108
Podsumowanie 109
6.
Dodatkowe
narzędzia i umiejętności wykorzystywane do budowania aplikacji 111
Polecenia Linuksa, powłoki Bash i podstawowego interfejsu wiersza
poleceń 111
Użytkownicy, uprawnienia i grupy 112
Praca z systemem plików 115
Przeglądanie i edycja tekstu 117
Wszystko razem: przekierowania, potoki i filtry 118
Wyszukiwanie tekstu i manipulowanie nim: grep, awk i sed 119
Narzędzia diagnostyczne: top, ps, netstat i iostat 120
Wywołania HTTP i manipulacja danymi JSON 121
Narzędzie curl 121
Narzędzie HTTPie 124
Narzędzie jq 127
Podstawy pisania skryptów 128
Narzędzie xargs 128
Potoki i filtry 128
Pętle 129
Warunki 129
Podsumowanie 130
7.
Pakowanie
aplikacji do wdrożenia 131
Budowanie archiwum JAR krok po kroku 131
Budowanie wykonywalnego fat JAR (uber JAR) 135
Wtyczka Maven Shade 135
Budowanie plików uber JAR przy użyciu projektu Spring Boot
138
Skinny JAR - gdy zdecydujesz się nie budować plików uber JAR
139
Budowanie plików WAR 140
Pakowanie dla chmury 141
Gotowanie konfiguracji: wypiekanie lub smażenie maszyn 142
Budowanie pakietów RPM i DEB systemu operacyjnego 142
Dodatkowe narzędzia kompilowania pakietów systemu
operacyjnego (z obsługą systemu Windows) 145
Tworzenie obrazów maszyn dla wielu chmur za pomocą programu
Packer 147
Dodatkowe narzędzia do tworzenia obrazów maszyn 149
Budowanie kontenerów 150
Tworzenie obrazów kontenerów za pomocą narzędzia
Docker 150
Fabrykowanie obrazów Docker za pomocą fabric8 151
Pakowanie aplikacji Java FaaS 153
Podsumowanie 155
8.
Praca
w lokalnym odpowiedniku środowiska produkcyjnego
157
Wyzwania związane z lokalnym tworzeniem oprogramowania 157
Imitacje, atrapy i wirtualizacja usług 158
Wzorzec 1.: profile, imitacje i atrapy 158
Imitowanie usług za pomocą biblioteki Mockito 159
Wzorzec 2.: wirtualizacja usług i symulacja interfejsu API 161
Wirtualizacja usług za pomocą narzędzia Hoverfly 162
Maszyny wirtualne oraz narzędzia Vagrant i Packer 165
Instalacja narzędzia Vagrant 166
Utworzenie pliku Vagrantfile 166
Wzorzec 3.: pudełkowe środowisko produkcyjne 168
Kontenery: Kubernetes, minikube i Telepresence 169
Przykładowa aplikacja Docker Java Shop 169
Tworzenie aplikacji Java i obrazów kontenerów 170
Wdrożenie kontenera na platformie Kubernetes 172
Prosty test usługi 174
Utworzenie pozostałych usług 174
Wdrożenie całej usługi Java na platformie Kubernetes 174
Kontrola wdrożonej aplikacji 175
Telepresence: praca zdalna i lokalna 176
Wzorzec 4.: dzierżawa środowiska 178
Funkcja jako usługa: AWS Lambda i SAM Local 179
Instalacja narzędzia SAM Local 179
Tworzenie funkcji AWS Lambda 179
Testowanie obsługi zdarzeń za pomocą funkcji AWS Lambda 182
Testowanie funkcji za pomocą narzędzia SAM Local 185
FaaS: usługa Azure Functions i edytor Visual Studio Code 186
Instalacja najważniejszych komponentów Azure Functions 186
Lokalne kompilowanie i testowanie funkcji 189
Testowanie lokalnych i zewnętrznych funkcji za pomocą edytora Visual
Studio Code 191
Podsumowanie 192
9.
Ciągła
integracja: pierwsze kroki w tworzeniu procesu kompilacji kodu 193
Co to jest ciągła integracja oprogramowania? 193
Implementacja ciągłej integracji oprogramowania 194
Centralny i rozproszony system kontroli wersji 194
Przewodnik po systemie Git 196
Najważniejsze polecenia systemu Git 196
Hub: podstawowe narzędzie w systemach Git i GitHub 198
Efektywne korzystanie z systemu DVCS 200
Programowanie pniowe 200
Odgałęzienia funkcjonalne 201
Gitflow 201
Nie ma recepty na wszystko, czyli jak wybrać odpowiednią strategię
odgałęziania 202
Przeglądanie kodu 204
Cele przeglądania kodu 205
Automatyzacja przeglądu kodu: analizatory PMD, Checkstyle i FindBugs 207
Przeglądanie wniosków o zmiany 210
Automatyzacja kompilacji 211
Jenkins 212
Zaangażowanie zespołu 213
Regularne konsolidowanie kodu 214
"Zatrzymać produkcję!", czyli obsługa nieudanych kompilacji 214
Nie ignoruj testów 214
Kompilacja musi być szybka 215
Ciągła integracja platformy (infrastruktura jako kod) 215
Podsumowanie 216
10.
Proces
wdrażania i wydawania oprogramowania 217
Wprowadzenie do aplikacji Extended Java Shop 217
Rozdzielenie wdrożenia i wydania aplikacji 220
Wdrażanie aplikacji 220
Utworzenie obrazu kontenera 221
Mechanizm wdrażania 224
Wszystko zaczyna się (i kończy) na kontroli stanu 233
Strategie wdrożeniowe 237
Praca z niezarządzanymi klastrami 246
Modyfikacje baz danych 249
Wydawanie funkcjonalności 252
Flagi funkcjonalności 253
Wersjonowanie semantyczne 255
Kompatybilność wsteczna i wersje interfejsu API 257
Wielofazowe aktualizacje 261
Zarządzanie konfiguracją i poufnymi danymi 262
"Zaprasowana" konfiguracja 263
Zewnętrzna konfiguracja 264
Przetwarzanie poufnych danych 265
Podsumowanie 266
11.
Testy
funkcjonalne: sprawdzenie poprawności i akceptacja oprogramowania 267
Po co testować oprogramowanie? 267
Co testować? Wprowadzenie do kwadrantów zwinnego testowania
267
Ciągłe testowanie oprogramowania 269
Utworzenie odpowiedniej pętli zwrotnej 270
Żółwie są wszędzie, aż po sam koniec 270
Transakcje syntetyczne 272
Testy kompleksowe 272
Testy akceptacyjne 274
Programowanie zorientowane na działanie 275
Imitowanie i wirtualizowanie zewnętrznych usług 278
Wszystko razem 278
Testy kontraktów klienckich 279
Kontrakty REST API 280
Kontrakty komunikatów 283
Testy komponentów 285
Wbudowane magazyny danych 285
Kolejki komunikatów umieszczane w pamięci 286
Dublerzy testowi 287
Tworzenie wewnętrznych zasobów lub interfejsów 288
Testy wewnątrz- i zewnątrzprocesowe 289
Testy integracyjne 291
Weryfikowanie zewnętrznych interakcji 291
Testy odporności na błędy 292
Testy jednostkowe 293
Towarzyskie testy jednostkowe 294
Samotne testy jednostkowe 295
Niestabilne testy 296
Dane 296
Tymczasowo niedostępne zasoby 296
Niedeterministyczne zdarzenia 297
Gdy nic nie można zrobić 297
Testy "do wewnątrz" i "na zewnątrz" 298
Testy "do wewnątrz" 298
Testy "na zewnątrz" 299
Zebranie wszystkiego w jeden proces 301
Jak dużo testów trzeba wykonać? 301
Podsumowanie 303
12.
Testy
jakościowe systemu: weryfikacja wymagań niefunkcjonalnych
305
Po co testować wymagania niefunkcjonalne? 305
Jakość kodu 306
Jakość architektury 306
ArchUnit: testy jednostkowe architektury 307
Wyliczanie wskaźników jakościowych projektu za pomocą
biblioteki JDepend 308
Testy wydajnościowe i obciążeniowe 310
Testowanie wydajności przy użyciu Apache Benchmark 311
Testy obciążeniowe z użyciem narzędzia Gatling 312
Bezpieczeństwo, podatności i zagrożenia 317
Weryfikacja bezpieczeństwa na poziomie kodu 318
Weryfikacja zależności 322
Luki w bezpieczeństwie platform wdrożeniowych 325
Kolejny krok: modelowanie zagrożeń 329
Testowy chaos 332
Wywoływanie chaosu w środowisku produkcyjnym 333
Wywoływanie chaosu w środowisku przedprodukcyjnym 334
Jak dużo testów wymagań niefunkcjonalnych trzeba wykonać? 335
Podsumowanie 336
13.
Obserwowalność aplikacji: monitorowanie, logowanie i śledzenie
337
Obserwowalność i ciągłe dostarczanie oprogramowania 337
Po co obserwować aplikację? 338
Obiekty obserwacji: aplikacja, sieć, serwer 338
Metody obserwacji: monitorowanie, logowanie i śledzenie 340
Alarmy 340
Projektowanie obserwowalnych systemów 341
Wskaźniki 342
Rodzaje wskaźników 343
Dropwizard Metrics 343
Spring Boot Actuator 344
Micrometer 345
Dobre praktyki tworzenia wskaźników 346
Logowanie 347
Formaty logów 347
SLF4J 348
Log4j 2 349
Dobre praktyki logowania 350
Śledzenie zapytań 351
Ślady, przęsła i bagaże 352
Śledzenie aplikacji Java: OpenZipkin, Spring Cloud Sleuth i OpenCensus
353
Dobre praktyki śledzenia systemów 353
Śledzenie wyjątków 354
Airbrake 355
Narzędzia do monitorowania systemu 356
collectd 356
rsyslog 356
Sensu 357
Zbieranie i zapisywanie danych 357
Prometheus 358
Elastic-Logstash-Kibana 358
Wizualizacja danych 359
Wizualizacja dla biznesu 359
Wizualizacja dla administratorów 360
Wizualizacja dla programistów 361
Podsumowanie 362
14.
Migracja
do ciągłego dostarczania 365
Czynniki ciągłego dostarczania 365
Wybór projektu migracji 366
Świadomość sytuacyjna 367
Framework Cynefin i ciągłe dostarczanie 368
Wszystkie modele są złe, ale niektóre są przydatne 369
Wstępne organizowanie ciągłego dostarczania 370
Pomiar ciągłego dostarczania 371
Zacznij od niewielkich rzeczy, eksperymentuj, ucz się, udostępniaj i
powtarzaj 372
Szersze wdrożenie: kierowanie wprowadzaniem zmian 374
Dodatkowe porady i wskazówki 375
Złe praktyki i typowe antywzorce 375
Brzydka architektura: naprawiać czy nie naprawiać 376
Podsumowanie 379
15.
Ciągłe
dostarczanie i ciągłe doskonalenie 381
Zacznij od punktu, w którym jesteś 381
Opieraj się na solidnych podstawach technicznych 382
Ciągłe dostarczanie wartości (Twój najwyższy priorytet) 382
Zwiększenie współodpowiedzialności za oprogramowanie 383
Promuj szybką informację zwrotną i eksperymentowanie 384
Rozwijaj ciągłe dostarczanie w organizacji 385
Ciągłe doskonalenie 385
Podsumowanie 386
Skorowidz 389
400
stron, oprawa miękka