Czas: 90–120 minut zajęć; przygotowanie środowiska przed zajęciami, ewentualne dokończenie testów i README po zajęciach (około 30–60 minut)
Technologia: Python + FastAPI
Forma: praca indywidualna lub w parach
Rezultat: działająca pierwsza usługa własnego projektu, testy i uzasadnienie decyzji
Po laboratorium powinieneś:
Najważniejsze: nie chodzi o przepisanie kodu. Kod jest środkiem do rozwiązania problemu.
| Efekt | Co ćwiczysz na LAB1 | Dowód wykonania |
|---|---|---|
| EK_03 — implementacja funkcjonalności z wykorzystaniem dokumentacji | Własna usługa, reguła biznesowa, obsługa błędów i testy | Działający kod, testy oraz dwa wykorzystane fragmenty dokumentacji opisane w README |
| EK_04 — projektowanie i komunikacja kilku usług | Pierwszy etap: podział własnego systemu i szkic przyszłej komunikacji | Dwie planowane usługi, właściciele danych i jeden kontrakt komunikacji; implementujesz teraz tylko pierwszą usługę |
| EK_01 i EK_02 — pojęcia oraz narzędzia | Porównanie architektur i rozróżnienie FastAPI, Uvicorna oraz klienta HTTP | Krótkie uzasadnienie architektury i samodzielne uruchomienie |
LAB1 realizuje pierwszy temat laboratoryjny: podstawowa mikrousługa, API, porty i przechowywanie danych. Pełne EK_04 będzie weryfikowane w kolejnych etapach projektu. EK_05 oraz wiedza z EK_01 i EK_02 są również rozwijane i weryfikowane na wykładzie. DDD wprowadzamy przez pojęcia domeny, jej reguły i granice odpowiedzialności; pełne modelowanie jest tematem dalszych zajęć.
Mikrousługa to niezależnie uruchamiana i wdrażana część systemu, która:
Moduł:
- działa wewnątrz jednej aplikacji,
- komunikuje się przez wywołania funkcji,
- zwykle jest wdrażany razem z całością.
Mikrousługa:
- działa jako osobna aplikacja,
- komunikuje się przez HTTP, RPC albo komunikaty,
- może być wdrażana i restartowana niezależnie.
Sam podział kodu na foldery nie tworzy mikroserwisów.
Osobny port także nie wystarcza: znaczenie mają spójna odpowiedzialność, własność danych i możliwość niezależnego wdrożenia. Na LAB1 budujesz pierwszą samodzielną usługę przyszłego systemu; nie uruchamiasz jeszcze całej architektury rozproszonej.
Nie. Mały system może lepiej działać jako monolit albo modularny monolit. Mikroserwisy mają sens wtedy, gdy korzyści z niezależnego rozwoju, wdrażania i izolowania awarii uzasadniają dodatkową złożoność komunikacji sieciowej.
W pierwszej części laboratorium pytania odnoszą się do wspólnego przykładu Locker Service. Nie musisz jeszcze wymyślać własnego tematu — zrobisz to w części B.
Temat systemu: system paczkomatów
Planowana nazwa usługi: Locker Service
Jednozdaniowy opis usługi: obsługuje paczkomaty i ich skrytki
Dla Locker Service odpowiedz:
Locker Service?Dla systemu paczkomatów można zaprojektować kilka poprawnych wariantów.
Klient
|
v
Jedna aplikacja
├── obsługa paczkomatów
├── obsługa paczek
├── śledzenie
├── powiadomienia
└── użytkownicy
|
v
Jedna baza danych
Wszystkie funkcje działają w jednym procesie. Wywołanie funkcji odbywa się bezpośrednio w kodzie, np. moduł paczek może wywołać metodę modułu skrytek.
Klient
|
v
Jedna aplikacja i jeden proces
├── moduł paczkomatów
├── moduł paczek
├── moduł śledzenia
├── moduł powiadomień
└── moduł użytkowników
|
v
Jedna baza danych
Moduły mają wyraźne granice i osobny kod, ale nadal są uruchamiane i wdrażane razem. Komunikacja odbywa się zwykle wewnątrz procesu.
Klient
|
v
API Gateway
|
+--> Locker Service --> Locker DB
+--> Parcel Service --> Parcel DB
+--> Tracking Service --> Tracking DB
+--> Notification Service --> Notification DB
Każda usługa może działać jako osobny proces, mieć własny port, własne wdrożenie i własne dane. Komunikacja odbywa się przez HTTP albo brokera wiadomości.
Kurier umieszcza paczkę w skrytce.
W monolicie:
ParcelModule.placeParcel()
├── LockerModule.occupyCompartment()
├── TrackingModule.recordEvent()
└── NotificationModule.sendMessage()
W mikroserwisach:
Parcel Service
├── HTTP: zajmij skrytkę ──> Locker Service
| <── potwierdzenie ────────┘
|
└── po potwierdzeniu: zdarzenie ParcelPlaced ──> RabbitMQ
├──> Tracking Service
└──> Notification Service
Locker Service odpowiada za stan skrytki, a Parcel Service za operację dotyczącą paczki i publikację ParcelPlaced. To szkic docelowego przepływu, nie zadanie implementacyjne LAB1. Obsługę częściowych awarii i niezawodną publikację zdarzeń omówimy później.
| Cecha | Monolit | Modularny monolit | Mikrousługi |
|---|---|---|---|
| Uruchomienie | jeden proces | jeden proces | wiele procesów lub kontenerów |
| Komunikacja | wywołania w kodzie | wywołania modułów | HTTP, RPC lub komunikaty |
| Wdrożenie | całość razem | całość razem | usługi niezależnie |
| Baza danych | zwykle wspólna | zwykle wspólna | preferowana osobna dla usługi |
| Awaria procesu | może wyłączyć całość | może wyłączyć całość | wyłącza daną instancję; skutki mogą objąć zależne usługi |
| Złożoność początkowa | mała | średnia | duża |
W tych porównaniach monolit i modularny monolit oznaczają aplikacje działające w jednym procesie. Izolacja awarii w mikroserwisach wymaga odpowiedniego zaprojektowania zależności; sam podział na procesy nie gwarantuje dostępności całego systemu.
Laboratorium ma dwie części:
Locker Service dla systemu paczkomatów,Przykład wspólny ma pokazać technikę. Własny projekt ma sprawdzić, czy potrafisz zastosować ją bez kopiowania gotowego modelu domenowego.
Pełne rozwiązanie referencyjne jest dostępne do analizy. Prowadzący pokazuje wybrane fragmenty, a student buduje własną usługę ze startera. Nie trzeba odtwarzać całego Locker Service przed rozpoczęciem własnego projektu.
Przygotuj środowisko z sekcji 3 przed zajęciami. Proponowany podział 120 minut: 10 minut pojęć, 15 minut przykładu, 15 minut projektu domeny i API, 45 minut implementacji, 25 minut testów oraz 10 minut podsumowania. Przy bloku 90 minut dopracowanie testów i dokumentacji wykonaj po zajęciach. Termin oddania wskazuje prowadzący; komplet wymagań obowiązuje niezależnie od długości bloku.
Pracując w parze, zamieniajcie się rolami osoby piszącej i osoby sprawdzającej kod. W README zapiszcie wkład każdej osoby. Każda osoba samodzielnie wyjaśnia rozwiązanie i wykonuje drobną zmianę podczas odbioru.
Cały projekt semestralny wymaga co najmniej dwóch różnych mikrousług na osobę oraz pozostałych wymaganych komponentów. Jedna wspólna usługa na LAB1 jest dopuszczalnym etapem pracy w parze, ale nie wyczerpuje indywidualnego wymagania semestralnego. Własną domenę będziesz rozwijać również na kolejnych laboratoriach.
Możesz korzystać z AI do:
Musisz jednak:
Kod, którego nie potrafisz uruchomić ani wyjaśnić, nie jest poprawnym rozwiązaniem.
Użyj Pythona 3.12 lub nowszego. Polecenia poniżej są przeznaczone dla PowerShella. Sprawdź wersję:
python --version
Pobierz starter ZIP i rozpakuj go. Otwórz terminal w katalogu zawierającym requirements.txt, app i tests. Możesz też skopiować katalog lab1-template poza katalog materiałów i nadać kopii własną nazwę.
Utwórz środowisko i zainstaluj zależności:
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
Nie musisz aktywować środowiska: jawna ścieżka do jego Pythona działa także wtedy, gdy PowerShell blokuje Activate.ps1.
Starter ma już app/main.py z endpointem /health. Uruchom go:
.\.venv\Scripts\python.exe -m uvicorn app.main:app --reload --port 8101
Pozostaw serwer w pierwszym terminalu. W drugim sprawdź Invoke-RestMethod http://localhost:8101/health, a w przeglądarce otwórz dokumentację API. Starter zwraca nazwę replace-me — zmienisz ją na nazwę własnej usługi. Serwer zatrzymasz przez Ctrl+C.
Z katalogu projektu uruchom też test startowy:
.\.venv\Scripts\python.exe -m pytest -q
app.main:app wskazuje obiekt app w pliku app/main.py. Port 8101 wybiera lokalny adres usługi. --reload restartuje proces po zmianie kodu i służy do pracy programistycznej; przy danych w pamięci taki restart usuwa wprowadzone zmiany. Dla przykładu wspólnego używamy 8000, dla własnej usługi np. 8101. Porty muszą być różne dla procesów nasłuchujących na tym samym adresie na jednym komputerze; studenci na różnych komputerach mogą używać tego samego numeru.
FastAPI jest frameworkiem, w którym definiujemy aplikację, endpointy, modele danych i walidację.
Uvicorn jest serwerem ASGI, który uruchamia aplikację FastAPI i nasłuchuje na określonym adresie oraz porcie. Sam plik Python nie wystarczy — potrzebujemy procesu serwera, który będzie przyjmował żądania HTTP.
ASGI (Asynchronous Server Gateway Interface) to standard komunikacji pomiędzy serwerem uruchamiającym aplikację Pythona a samą aplikacją webową.
Przeglądarka / klient HTTP
|
v
Uvicorn — serwer ASGI
|
v
FastAPI — aplikacja ASGI
ASGI określa, w jaki sposób serwer przekazuje aplikacji:
W drugą stronę aplikacja przekazuje:
ASGI jest następcą starszego standardu WSGI i został zaprojektowany z myślą o obsłudze kodu asynchronicznego. Umożliwia również obsługę WebSocketów i zdarzeń związanych z uruchamianiem oraz zamykaniem aplikacji.
Na tym laboratorium wystarczy zapamiętać:
FastAPI tworzy aplikację zgodną z ASGI, a Uvicorn jest serwerem, który tę aplikację uruchamia i udostępnia przez HTTP.
Jeżeli mamy plik:
app/main.py
└── app = FastAPI(...)
uruchamiamy go poleceniem:
.\.venv\Scripts\python.exe -m uvicorn app.main:app --reload --port 8101
Zapis app.main:app oznacza:
app.main — moduł, czyli plik app/main.py
app — obiekt aplikacji FastAPI znajdujący się w tym module
Parametr --port 8101 wybiera port, na którym działa usługa. Parametr --reload powoduje automatyczne ponowne uruchomienie serwera po zapisaniu zmian w kodzie. Jest wygodny podczas nauki, ale nie powinien być używany jako ustawienie produkcyjne.
W przykładzie wspólnym używamy portu 8000; własny projekt powinien używać innego portu, np. z zakresu 8101–8199.
Po uruchomieniu powyższego polecenia nie zamykaj terminala — działający proces zajmuje port.
W terminalu powinien pojawić się komunikat podobny do:
Uvicorn running on http://127.0.0.1:8101
W drugim terminalu sprawdź endpoint zdrowia:
Invoke-RestMethod http://localhost:8101/health
Jeśli usługa działa, otrzymasz odpowiedź JSON, np.:
status service
------ -------
ok my-service
Możesz też otworzyć dokumentację API w przeglądarce:
http://localhost:8101/docs
Get-NetTCPConnection -LocalPort 8101 -State Listen
Jeżeli polecenie zwróci rekord, na porcie działa jakiś proces. Identyfikator procesu znajduje się w kolumnie OwningProcess.
Możesz sprawdzić nazwę procesu:
Get-Process -Id <PID>
Zastąp <PID> numerem z poprzedniego polecenia.
Jeżeli port jest zajęty, uruchom usługę na innym porcie:
.\.venv\Scripts\python.exe -m uvicorn app.main:app --reload --port 8102
Własny port sprawdza się więc na trzy sposoby:
http://localhost:8101/health,Get-NetTCPConnection.Brak rekordu (lub komunikat o braku pasujących obiektów) oznacza, że polecenie nie znalazło nasłuchującego procesu na tym porcie.
System paczkomatów może mieć między innymi następujące usługi:
Locker Service — paczkomaty i skrytki
Parcel Service — paczki i ich statusy
Tracking Service — historia zdarzeń
Notification Service — powiadomienia
Delivery Service — transport i dostawy
W tej części analizujemy tylko Locker Service.
Locker Service:
Nie zajmuje się:
id — identyfikator skrytki
locker_id — identyfikator paczkomatu
size — S, M albo L
status — free, reserved, occupied albo out_of_service
| Metoda | Endpoint | Znaczenie |
|---|---|---|
| GET | /health |
Sprawdzenie działania usługi |
| GET | /lockers |
Lista paczkomatów |
| GET | /lockers/{locker_id} |
Jeden paczkomat |
| POST | /lockers |
Dodanie paczkomatu |
| GET | /lockers/{locker_id}/compartments |
Lista skrytek |
| POST | /lockers/{locker_id}/compartments |
Dodanie skrytki — rozszerzenie przykładu |
| PATCH | /compartments/{id}/status |
Zmiana statusu skrytki |
Przykład przechowuje dane w pamięci. Przy starcie tworzy paczkomat KRK-1024 i dwie wolne skrytki. Reguła biznesowa określa przejścia: free → reserved → occupied → free oraz free ↔ out_of_service. Ustawienie aktualnego statusu ponownie jest dozwolone i nie zmienia stanu. Inne przejście zwraca 409, nieznana wartość statusu — 422, a brak skrytki — 404.
W osobnym terminalu, zaczynając od katalogu głównego materiałów, przejdź do rozwiązania referencyjnego:
cd 2026_2027/lab1-reference/locker-service
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe -m uvicorn app.main:app --reload --port 8000
Otwórz:
Sprawdź:
Invoke-RestMethod http://localhost:8000/health
Invoke-RestMethod http://localhost:8000/lockers
Invoke-RestMethod http://localhost:8000/lockers/KRK-1024/compartments
Przetestuj też:
curl.exe -i http://localhost:8000/lockers/UNKNOWN
Zwróć uwagę, że nieistniejący zasób kończy się kodem 404, a nie pustą odpowiedzią 200.
curl.exe -i pokazuje także status i nagłówki odpowiedzi. Jeśli nie masz curl.exe, wykonaj żądanie w /docs i odczytaj pole „Code”. Nie używamy skrótu curl, którego znaczenie może zależeć od wersji PowerShella.
W /docs wykonaj PATCH zmieniający status KRK-1024-L1 z free na reserved, a następnie osobnym GET sprawdź skrytki. Spróbuj zmiany reserved → out_of_service: oczekuj 409 i sprawdź ponownym GET, że status nadal wynosi reserved. Instrukcję pełnego scenariusza i testów znajdziesz w README rozwiązania referencyjnego.
Odpowiedz krótko:
Locker Service?Locker Service musi znać dane użytkownika?To jest główna część laboratorium.
Wybierz prostą, znaną domenę albo zaproponuj własną:
Nie tworzysz całej aplikacji. Wybierasz jeden ograniczony obszar.
Przykład:
Temat: system uczelniany
Usługa: Room Reservation Service
Uzupełnij:
Nazwa usługi:
Usługa odpowiada za:
-
-
-
Usługa nie odpowiada za:
-
-
-
Jeśli nie potrafisz jasno opisać granicy, temat jest jeszcze niedopracowany.
Zaproponuj co najmniej dwie usługi przyszłego systemu. Teraz zaimplementujesz tylko pierwszą. Uzupełnij tabelę:
| Usługa | Odpowiedzialność biznesowa | Własne dane | Operacje | Informacje potrzebne od innej usługi |
|---|---|---|---|---|
| Pierwsza — implementowana na LAB1 | … | … | … | … |
| Druga — planowana na później | … | … | … | … |
Wypisz 3–5 pojęć używanych w swojej domenie i krótko je zdefiniuj. Wskaż, kto może zmieniać poszczególne dane. Wyjaśnij, dlaczego podział wynika z odpowiedzialności biznesowej, a nie wyłącznie z tabel w bazie. Granica modelu i znaczenia jego pojęć jest punktem wyjścia do poznania bounded context w DDD; nie oznacza automatycznie osobnej usługi dla każdej encji.
Naszkicuj jedno przyszłe wywołanie HTTP między usługami: nadawca, odbiorca, metoda, ścieżka, przykładowe żądanie i odpowiedź oraz zachowanie przy niedostępności odbiorcy. To projekt kontraktu — nie implementuj jeszcze komunikacji ani sprawdzania danych w drugiej usłudze.
Narysuj trzy małe warianty własnego systemu: monolit, modularny monolit i mikrousługi. Wystarczą prostokąty i strzałki z podpisami „wywołanie w kodzie” lub „HTTP”. Zaznacz granice odpowiedzialności, procesy i właścicieli danych. Schematy umieść w README; wykorzystasz je w podsumowaniu.
Checkpoint przed kodowaniem: wyjaśnij prowadzącemu zakres pierwszej usługi, rolę drugiej i jedną regułę, za którą odpowiada pierwsza.
Zdefiniuj minimum jeden główny obiekt domenowy.
Przykład:
RoomReservation
- id
- room_id
- reserved_by
- starts_at
- ends_at
- status
Samodzielnie zdecyduj:
Zapisz co najmniej jedną regułę biznesową wykraczającą poza wymagane pola, typy i unikalność identyfikatora. Przykłady:
Wybierz jedną regułę, podaj przykład dozwolonej i niedozwolonej operacji oraz oczekiwany kod błędu. Reguła ma dotyczyć danych należących do twojej usługi, żeby dało się ją sprawdzić bez uruchamiania drugiej usługi.
Zaprojektuj minimum trzy endpointy domenowe oraz osobny GET /health, czyli co najmniej cztery operacje API:
| Metoda | Endpoint | Znaczenie | Sukces |
|---|---|---|---|
| GET | /... |
odczyt listy | 200 |
| GET | /.../{id} |
odczyt jednego elementu | 200 |
| POST albo PATCH | /... albo /.../{id} |
utworzenie albo modyfikacja | odpowiednio 201 albo 200 |
Wybierz co najmniej jedną operację zapisu. Jeżeli wybierasz wyłącznie PATCH, przygotuj dane początkowe i wskaż modyfikowane pola. Przykładowe ścieżki zastąp nazwami własnych zasobów. /health zwraca status działania i nazwę usługi, bez danych domenowych.
Ustal również:
Dla każdej operacji opisz pola i typy żądania, odpowiedź sukcesu oraz możliwe błędy. Dołącz przykładowy JSON. Przyjmij 404 dla nieistniejącego zasobu, 409 dla konfliktu z aktualnym stanem i 422 dla niepoprawnych danych. Rozróżnij pustą listę (200 i []) od brakującego elementu (404).
Możesz zachować standardowy format FastAPI: {"detail": "opis"} dla HTTPException i listę szczegółów w detail dla walidacji 422. Opisz oba formaty zamiast deklarować identyczną strukturę wszystkich błędów. Sprawdź zgodność działającego API z tabelą i przykładami w README.
Minimalna struktura:
my-service/
├── app/
│ └── main.py
├── tests/
├── requirements.txt
└── README.md
Zacznij od zmiany nazwy usługi w starterze i sprawdzenia /health. Dodawaj kolejne elementy w małych krokach: model, odczyt, zapis, reguła biznesowa, błędy i testy.
Przechowuj dane w słowniku lub liście w pamięci procesu. Utwórz magazyn raz dla danej instancji aplikacji, a nie od nowa w każdym żądaniu. Zmiana wykonana przez POST lub PATCH musi być widoczna w następnym GET. Każda nowa instancja aplikacji powinna otrzymać własny magazyn; wykorzystaj funkcję create_app() ze startera, aby testy zaczynały od znanego stanu.
Na LAB1 nie potrzebujesz bazy danych, zapisu do pliku ani cache. Restart, również wywołany przez --reload, usuwa zmiany z pamięci i przywraca ewentualne dane początkowe. Dwie instancje uruchomione na różnych portach mają osobne magazyny. Te ograniczenia opisz w README.
Nie kopiuj modelu Locker Service. Możesz używać tego samego mechanizmu technicznego, ale domena, nazwy, dane i reguły muszą wynikać z twojego tematu.
Obsłuż minimum trzy przypadki:
Przykładowe kody:
200 OK
201 Created
404 Not Found
409 Conflict
422 Unprocessable Entity
Nie wybieraj kodów mechanicznie. W README zapisz, dlaczego użyłeś danego kodu.
Zaimplementuj także regułę biznesową z kroku 3. Wszystkie warunki odrzucenia operacji sprawdź przed zmianą danych. Niepoprawna operacja nie może pozostawić częściowo zmienionego stanu. Naruszenie reguły może być jednym z wymaganych przypadków 409 lub 422, zależnie od jej znaczenia; nie musi tworzyć czwartej kategorii błędu.
Wykorzystaj co najmniej dwa konkretne fragmenty oficjalnej dokumentacji, np. modele żądań FastAPI, obsługę błędów albo testowanie. W README podaj odnośnik, problem, który rozwiązywałeś, zastosowane rozwiązanie i sposób jego sprawdzenia. Sam wykaz linków lub zapis rozmowy z AI nie wystarcza.
Przygotuj powtarzalne scenariusze:
| Scenariusz | Co należy wykazać |
|---|---|
/health |
200 i poprawna nazwa usługi |
| Lista i szczegóły | 200, właściwe pola i dane znanego zasobu |
| Zapis → odczyt | Poprawny POST/PATCH, a następnie osobny GET potwierdzający zapisaną zmianę |
| Brak zasobu | 404 i opis błędu |
| Niepoprawne dane | 422, informacja o błędzie i brak zmiany magazynu |
| Konflikt | 409, opis przyczyny i brak zmiany magazynu |
| Reguła biznesowa | Przykład dozwolony oraz niedozwolony; po odrzuceniu stan pozostaje bez zmian |
| Restart procesu | Zmiana znika, a dane początkowe wracają, jeśli je przewidziano |
Reguła biznesowa może być sprawdzana w scenariuszu konfliktu lub niepoprawnych danych. Nie musisz powielać identycznego testu.
Napisz co najmniej trzy własne testy automatyczne w pytest: zapis i odczyt, błędne dane bez zmiany stanu oraz konflikt bez zmiany stanu. Co najmniej jeden z nich ma sprawdzać regułę biznesową; dodaj kolejny, jeśli wybrane trzy jej nie obejmują. Test /health dostarczony w starterze nie zalicza się do tych trzech.
W testach sprawdzaj zarówno kod HTTP, jak i istotne pola JSON. Każdy test rozpoczynaj od świeżej aplikacji i znanych danych, np. przez fixture wywołującą create_app(). Testy nie mogą zależeć od kolejności uruchomienia. TestClient nie wymaga działającego Uvicorna; osobno trzeba sprawdzić rzeczywisty port i restart procesu.
Pozostałe przypadki możesz sprawdzić ręcznie w /docs, Postmanie lub przez curl.exe. Dla każdego ręcznego scenariusza zapisz: stan początkowy, dokładne żądanie, oczekiwany status i treść, wynik rzeczywisty oraz sposób przywrócenia stanu. Zrzut ekranu bez tych informacji nie wystarcza.
Eksperyment z restartem: dodaj zasób lub zmień dane początkowe, potwierdź zmianę osobnym GET, zatrzymaj Uvicorna przez Ctrl+C, uruchom go ponownie i powtórz GET. Wyjaśnij, dlaczego dane przetrwały między żądaniami, ale nie między uruchomieniami. Nie edytuj kodu w trakcie eksperymentu, bo --reload może wykonać dodatkowy restart.
README musi zawierać:
Na zakończenie odpowiedz własnymi słowami.
| Pytanie | Monolit | Mikrousługi | Modularny monolit |
|---|---|---|---|
| Czy wszystkie funkcje są wdrażane razem? | Tak | Mogą być wdrażane niezależnie | Tak |
| Czy moduły komunikują się przez sieć? | Zwykle nie | Tak | Zwykle nie |
| Czy moduły/usługi działają w osobnych procesach? | Nie, przyjęliśmy jeden proces | Tak | Nie, przyjęliśmy jeden proces |
| Czy awaria procesu może objąć cały system? | Tak | Może dotknąć także zależnych usług | Tak |
| Czy dane mogą być rozdzielone? | Często wspólne | Zwykle rozdzielone | Mogą być logicznie rozdzielone |
| Czy wdrożenie jest niezależne? | Zwykle nie | Tak | Zwykle nie |
Odpowiedz:
Poprawną odpowiedzią może być również stwierdzenie, że dla małego systemu lepszy byłby monolit lub modularny monolit.
Przy odbiorze pokaż poniższe elementy. Przy pracy w parze każda osoba odpowiada indywidualnie.
Student potrafi wyjaśnić, za co odpowiada usługa, jakie dane posiada i jaką rolę pełni planowana druga usługa.
Student potrafi wyjaśnić metodę, ścieżkę i kod odpowiedzi każdego endpointu.
Student pokazuje działające 404, 422 i 409, wyjaśnia regułę biznesową oraz wykazuje, że odrzucona operacja nie zmieniła danych.
Student uruchamia testy, wyjaśnia ich warunki początkowe i wyniki oraz pokazuje zapis i odczyt przez HTTP. Potrafi wyjaśnić wynik restartu procesu.
Student wskazuje zastosowane fragmenty dokumentacji oraz sposób weryfikacji pomocy AI, jeśli jej używał. Samodzielnie wykonuje drobną zmianę zadaną przez prowadzącego, np. dodaje ograniczenie długości pola i odpowiadający mu test. Zmiana powinna zajmować około 3–5 minut i dotyczyć zakresu LAB1.
Punktacja LAB1 służy ocenie tego etapu i informacji zwrotnej. Zachowuje podział 60 punktów za kod i 40 za dokumentację. Ocena końcowa przedmiotu dotyczy całego rozwijanego projektu według sylabusa; nie jest automatyczną średnią punktów z laboratoriów.
| Obszar | Element | Maksimum |
|---|---|---|
| Kod | Uruchomienie, /health, lista, szczegóły i zapis widoczny w kolejnym odczycie |
20 |
| Kod | Model, walidacja, reguła biznesowa oraz poprawne 404, 409, 422 bez uszkodzenia stanu |
20 |
| Kod | Własne testy automatyczne, sensowne asercje i niezależność testów | 20 |
| Dokumentacja | Domena, granice i właściciele danych, druga usługa oraz przyszły kontrakt komunikacji | 10 |
| Dokumentacja | Powtarzalna instrukcja uruchomienia, kontrakt API, przykłady i błędy | 10 |
| Dokumentacja | Scenariusze testowe, wyniki i wyjaśnienie restartu oraz ograniczeń | 10 |
| Dokumentacja | Porównanie architektur, wykorzystanie dokumentacji, informacja o AI i autorach | 10 |
| Razem | Kod 60 + dokumentacja 40 | 100 |
W każdej pozycji punkty przyznaje się za poprawność i kompletność przedstawionych dowodów. Sam nagłówek w README albo test bez istotnych asercji nie potwierdza wykonania wymagania.
Zaliczenie etapu: co najmniej 50 punktów oraz spełnienie wszystkich warunków minimum:
/health oraz trzy wymagane operacje domenowe;Brak warunku minimum oznacza konieczność poprawy, nawet jeśli suma punktów przekracza 50. Termin poprawy ustala prowadzący.
Oddaj repozytorium lub katalog zawierający:
my-service/
├── app/
├── tests/
├── requirements.txt
├── README.md
└── .gitignore
W następnym laboratorium własna usługa zostanie rozbudowana o trwałe przechowywanie danych i cache.
Nie dołączaj .venv, __pycache__, .pytest_cache ani sekretów. Przed oddaniem sprawdź instalację zależności i wykonanie testów w nowym środowisku. Starter jest pomocą techniczną; gotowy projekt musi zawierać twoją domenę, regułę i testy. W kwestii zakresu LAB1 obowiązuje ta instrukcja; przykład paczkomatów pokazuje jedną z możliwych implementacji.