diff --git a/modules/module-01/REFLECTION.md b/modules/module-01/REFLECTION.md index ea9859e7..01407094 100644 --- a/modules/module-01/REFLECTION.md +++ b/modules/module-01/REFLECTION.md @@ -4,8 +4,8 @@ # Module 1 — Reflection -**Team name**: **\*\***\_\_\_**\*\*** -**Branch**: `module-01/` +**Team name**: Bahjat +**Branch**: `module-01/` **Submitted**: before Module 2 lesson --- @@ -22,7 +22,7 @@ You started from a painful monolith. Now you're splitting it into separate servi Think about it from three angles: the developer who has to change code, the team that has to deploy it, and the user who has to live with its failures. You don't need to cover all three, pick the one that felt most real to you today. -> _Your answer:_ +> Splitting the app solves the problem of deployment crashes and tight coupling. From a user's perspective, if the Game Library goes offline because of a bug or an update, the whole platform doesn't crash. They can still log in, view their profile, and chat with friends because the Identity and Activity services are running independently. --- @@ -34,7 +34,7 @@ Look at your service map. Every arrow between two services is a decision someone What would break, slow down, or become harder to manage if you merged those two services back together? -> _Your answer:_ +>I separated the Activity service from the Notification service. In the monolith, these were tightly coupled, meaning when a user logged a game, the system paused to write notifications for all their friends before finishing the request. By separating them and using an async event, logging an activity is instant, and notifications are processed safely in the background. --- @@ -46,7 +46,7 @@ Microservices solve the monolith's problems. But they create new ones. No need to solve it: just name it honestly. This is exactly the tension the rest of the course is about. -> _Your answer:_ +>Data querying is much harder now. In the monolith, if I wanted to show an activity feed, I could just write a single SQL JOIN to get the user's name, the game title, and the activity. Now, that data is locked in three different databases, requiring multiple network calls between services just to render one page. --- diff --git a/modules/module-01/exercise.md b/modules/module-01/exercise.md index d5bf307c..84e781d0 100644 --- a/modules/module-01/exercise.md +++ b/modules/module-01/exercise.md @@ -1,7 +1,7 @@ # Module 1 — Service Decomposition **Duration**: 2h in class -**Branch to submit**: `module-01/` +**Branch to submit**: `module-01/` --- @@ -26,11 +26,13 @@ A bounded context is a part of the system that has a clear responsibility and ow For each bounded context you identify, fill in the table: -| Bounded Context | Responsibilities | Owned Entities | Team | -| --------------- | -------------------------------------------------------- | -------------- | ----------- | -| Identity | Manages who users are, handles registration and profiles | User, Session | Platform | -| Game Library | _(fill in)_ | _(fill in)_ | _(fill in)_ | -| _(add more)_ | | | | +| Bounded Context | Responsibilities | Owned Entities | Team | +| Identity | Manages who users are, handles registration and profiles | User, Session | Platform | +| Game Library | Manages the catalog of games, titles, and genres | Game, Category | Content | +| Activity | Manages social feeds, friendships, and logging what people play | Activity, Friendship | Social | +| Notification | Manages delivering alerts and messages to users | Notification, DeviceToken | Communications | +| Logging | Records system events, checks GDPR consent | Log, ConsentRecord | Infra | + There is no single correct answer: what matters is that you can justify each row. @@ -56,6 +58,24 @@ Payload: { activity_id, user_id, action, game_id, timestamp } Focus on the flows that feel non-obvious. You do not need to document every possible pair. +Contract 1: +identity-service → activity-service +Trigger: a user logs in successfully +Protocol: RabbitMQ message (async) +Payload: { user_id, session_id, timestamp } + +Contract 2: +activity-service → notification-service +Trigger: a user earns an achievement or milestone +Protocol: RabbitMQ message (async) +Payload: { user_id, achievement_id, message, timestamp } + +Contract 3: +gateway → identity-service +Trigger: a client sends a login or registration request +Protocol: REST (sync) +Payload: { username, email, password_hash } + --- ## Task 3 — Draw the service map _(~20 min)_ @@ -69,6 +89,15 @@ Draw the full GameHub service map: This can be a sketch on paper, a whiteboard photo, or ASCII art committed to your branch. + [Client] + | + [Gateway] + _____|__|__|__|_____ + | | | | | + [identity][game][activity][notification][logging] + |_async__| |___async___|___async___| + + --- ## Discussion _(~15 min)_ @@ -76,8 +105,14 @@ This can be a sketch on paper, a whiteboard photo, or ASCII art committed to you Three questions to discuss as a team before you leave: 1. Why does `notification-service` use Node.js instead of Python like the rest? What does that tell you about microservices and technology choices? +Because node handles lots of simultaneous I/O better. Each service can use whatever language fits its job. + 2. What is the risk of `activity-service` calling `logging-service` synchronously — why might you prefer an async event instead? +if logging-service crashes, activity-service crashes too. Async decouples them. + 3. Why does `logging-service` need a GDPR consent check before recording any activity? +you can't store personal data without consent. Logging is the last gate before data is written. + You do not need to write these answers down — they are warm-up for your REFLECTION.md.