Designing the System

Reviewing and Revising a Technical Design

ReadingPreview

আপনি একটি free preview lesson দেখছেন।

আমরা এখন পর্যন্ত:

  • requirements analyse করেছি
  • domain entities identify করেছি
  • responsibilities define করেছি
  • initial architecture design করেছি
  • RFC-001 লিখেছি
  • major decisions ADR-এ record করেছি

এখন একটি critical step বাকি:

Design review.

একটি technical design author-এর কাছে reasonable মনে হলেই সেটি implementation-ready হয়ে যায় না।

আরেকজন engineer যখন design পড়ে, সে এমন assumption, ambiguity, risk, বা contradiction দেখতে পারে যা author miss করেছে।

Design review-এর goal হলো design-কে attack করা নয়।

Goal:

Implementation শুরু হওয়ার আগে ভুল assumptions, unclear decisions, এবং unnecessary complexity খুঁজে বের করা।


Why Review Before Implementation?

Suppose design-এ একটি ভুল assumption আছে।

RFC stage-এ fix করতে হলে:

edit document
update diagram
clarify decision

কিন্তু একই issue implementation-এর পরে ধরা পড়লে:

change domain model

change database schema

change API

rewrite tests

update migrations

rewrite integration code

লাগতে পারে।

So:

Earlier feedback
=
cheaper feedback

Technical Design Review Is Not Approval Theatre

Bad process:

Author writes RFC

Reviewer says:
"Looks good"

RFC accepted

without actually evaluating anything।

Useful review asks:

Does the design satisfy requirements?

Which assumptions are hidden?

Which failure modes are missing?

Are responsibilities clear?

Are we solving problems we don't have?

Are important decisions still unresolved?

Can this actually be implemented safely?

Reviewer Mindset

A good reviewer does not ask:

How would I personally design this?

Instead:

Given the agreed requirements and engineering context, is this proposal correct, understandable, and appropriately simple?

There may be several valid designs।

Reviewer should distinguish:

incorrect

risky

unclear

different personal preference

These are not the same thing।


Review Against Requirements First

Architecture exists to satisfy requirements।

So first review question:

Does RFC-001 cover every important v1 behaviour?

Our major requirements:

browse products

manage products

manage inventory

create orders

view order history

cancel unpaid orders

pay orders

customer ownership

admin permissions

RFC covers all of them conceptually।

Good।

But review should go deeper।


Review Acceptance Criteria

For Order creation, agreed behaviour includes:

at least one item

product exists

product appears at most once

quantity positive

product orderable

inventory sufficient

backend determines price

backend calculates total

historical price preserved

invalid item fails whole request

order belongs to customer

Now reviewer checks:

Does architecture provide a place
for every one of these rules?

Mostly yes।

But one issue appears:

Where exactly is duplicate-product validation owned?

This is worth clarifying।


Review Comment 1 — Duplicate Products

Reviewer:

RFC says a product may appear only once in an order request,
but responsibility for enforcing this rule is unclear.

Is this transport validation,
CreateOrder workflow validation,
or an Order invariant?

This is a good review comment।


Analyse the Feedback

Request:

{
  "items": [
    {
      "productId": 10,
      "quantity": 2
    },
    {
      "productId": 10,
      "quantity": 3
    }
  ]
}

Structurally valid।

But business rule says duplicate Product entries are not allowed।

This rule involves the collection of requested items।

A reasonable place is:

CreateOrder workflow
or Order construction boundary

rather than an individual OrderItem


Revision 1

We update design:

CreateOrder must reject a request containing the same Product more than once before persistence. Order construction must receive a valid unique Product set.

This keeps responsibility explicit।

We do not need a new architectural layer।

Small clarification, meaningful improvement।


Review Comment 2 — What Does "Available Product" Mean?

Reviewer:

Product browsing says "available products."

Does this mean:
1. Product is ACTIVE,
2. Inventory > 0,
or
3. both?

Excellent comment।

Earlier requirements used "available" broadly।

Our domain design separated:

Product ordering state

from:

Inventory quantity

But API behaviour still needs explicit meaning।


Analyse the Requirement

We already established:

  • only orderable products should be returned
  • inactive products should not be returned as orderable
  • inventory constrains ordering

For browsing intended to show products that can currently be ordered, the most coherent v1 interpretation is:

Product is active/orderable
AND
Inventory quantity > 0

This is not introducing a new feature।

It resolves an ambiguity already present in the requirement।


Revision 2

RFC Product Browsing section becomes:

A product is returned as currently available for ordering only when its Product state permits ordering and its available Inventory quantity is greater than zero.

Important:

This does not mean inventory becomes Product state।

It is a read/use-case decision combining two facts।


Requirement Clarification vs Architecture Decision

Notice this feedback is partly product behaviour clarification।

If business stakeholders had not agreed on what "available" means, engineer should not silently decide it।

In our simulated project, we now clarify the intended v1 meaning based on the existing acceptance criteria।

In a real company, this might require:

Product Manager confirmation

before RFC acceptance।


Review Comment 3 — Customer Model Is Still Vague

Reviewer:

RFC says existing identity capability authenticates users,
but it is unclear whether Order Management Backend
stores a local Customer record.

This is also valid।

Our earlier design intentionally avoided inventing customer-account functionality।

But implementation needs to know whether:

orders.customer_id

references:

a local customers table

or simply stores:

external authenticated identity ID

Do We Need a Local Customer Table?

Current requirements need:

stable customer identity

order ownership

They do not require:

customer profile management

shipping address

customer preferences

password/account state

Therefore a local Customer entity/table would add state without current need।

The simpler design:

Order stores authenticated external customer identifier.

Revision 3

We make this explicit:

v1 will not maintain a separate Customer aggregate solely for ordering. Orders will store the stable customer identifier supplied by the existing authenticated identity context.

This may later change if ordering-specific customer data is introduced।


Why This Is Better Than "Maybe Customer Entity"

The earlier design correctly avoided overcommitting।

But before implementation, some uncertainty must become concrete।

Otherwise one engineer may create:

customers table

while another assumes external IDs only।

Design review is where such ambiguity should be removed।


Review Comment 4 — Order Total Source of Truth

Reviewer:

RFC says Order total is calculated by the backend,
but still lists whether total is stored or derived as open.

Can implementation proceed without deciding this?

Good question।

This decision affects:

database schema

Order model

queries

consistency rules

So before persistence implementation, we should resolve it।


Option A — Derive Order Total

Conceptually:

total
=
sum(unitPrice × quantity)

Advantages:

one underlying source of truth

no stored derived field drift

Cost:

calculation required when needed

For our small Order aggregate, calculation is trivial।


Option B — Persist Order Total

Advantages:

simple summary reads

no repeated calculation

Costs:

must guarantee stored total
matches Order Items

Current Requirement

Our v1 has:

  • no tax
  • no discounts
  • no shipping cost
  • no multiple currencies
  • no complex pricing breakdown

Total is simply:

sum of item price × quantity

So derived total is straightforward।


Revision 4

Decision:

For v1, Order total will be derived from the Order Items' recorded purchase-time unit prices and quantities rather than treated as an independently mutable value.

Persistence may later optimize summary reads if evidence requires it, but domain source of truth remains the items।

This removes a significant open question।


Should This Be an ADR?

Probably not yet।

It is a useful domain/persistence decision, but current trade-off is simple and localized।

We can record it in RFC/domain design।

If later architecture changes to persisted totals with more pricing components, a dedicated ADR may become useful।


Review Comment 5 — Product Price Validation Is Missing

Reviewer:

Product has a current price,
but RFC does not say what constitutes a valid price.
Can a Product have a negative price?

This exposes an invariant we should reasonably define।

A negative product price would violate basic ordering semantics।

We don't need arbitrary pricing limits, but:

price >= 0

or perhaps:

price > 0

requires a business decision।


Should Zero Price Be Allowed?

Zero-price products could be legitimate:

free sample

promotion

but promotions are outside scope।

Still, banning zero without a requirement would also be arbitrary।

Safer minimum domain invariant:

price cannot be negative

This preserves technical validity without inventing that free products cannot exist।


Revision 5

Add Product invariant:

Product price must not be negative.

We still do not invent:

maximum price
minimum €0.01

without requirement।


Review Comment 6 — Inventory Adjustment Semantics

Reviewer:

Admin can "adjust inventory."

Does API set absolute quantity,
or apply a delta?

This is an implementation/API ambiguity।

Examples:

Absolute:

set quantity to 10

Delta:

add +5

They have different concurrency and audit semantics।


Do We Need to Decide It in Initial Architecture?

Yes, before designing the API।

But not necessarily in the high-level architecture RFC if it belongs to feature/API design।

Still, backlog ticket must not remain ambiguous before implementation।

For our current v1, the simplest explicit behaviour can be:

administrator sets the current available quantity

with validation:

quantity >= 0

We don't need inventory movement history or reason codes।


Revision 6

Clarify v1:

Administrative inventory management sets the current available quantity to a non-negative value. Inventory adjustments are not modeled as an audit ledger in v1.

This is bounded and implementable।


Review Comment 7 — Product Deactivation and Existing Unpaid Orders

Reviewer:

If a Product is deactivated after an unpaid Order
was already created, can that existing Order still be paid?

This is an excellent state/lifecycle question।

Order creation has already:

  • validated Product
  • captured purchase-time price
  • reduced inventory
  • created a historical Order

Product state may change later।

Should payment re-check Product active status?


Reason About Ownership

Once Order is successfully created, Product's current state should not rewrite Order eligibility unless requirement explicitly says so।

Otherwise:

Order created validly
    ↓
Admin deactivates Product
    ↓
Customer suddenly cannot pay existing Order

This behaviour was never requested।

Order lifecycle should govern existing Order payment eligibility।


Revision 7

Clarify:

Product activation state is evaluated during creation of new Orders. Deactivating a Product does not invalidate an already-created Order. Existing eligible unpaid Orders may still be paid.

This reinforces historical boundary between Product and Order।


Review Comment 8 — Inventory Restoration After Product Deactivation

Reviewer:

If an unpaid Order is cancelled after its Product
has been deactivated, do we still restore Inventory?

Yes।

Why?

Cancellation requirement says inventory consumed by the Order is restored।

Product deactivation affects future orderability, not whether inventory state exists।

So:

Inactive Product
+
Inventory quantity

can still coexist।


Revision 8

Clarify:

Cancelling an eligible Order restores its Inventory regardless of the Product's current activation state.

The Product remains inactive and therefore still cannot be used for new Orders until reactivated।


Review Comment 9 — Order History Pagination Is Too Vague

Reviewer:

RFC says order history is bounded/paginated,
but no pagination mechanism is selected.
Is this design blocked?

Not necessarily।

Exact REST pagination mechanism belongs to the API design module।

The architectural requirement is:

do not load/return unbounded history

Page-based vs cursor-based pagination is implementation/API contract detail।

We can keep this open until Module 5।


No Revision Needed Yet

This is a good example where review identifies an open detail but not an architecture blocker।

Response:

Confirmed. RFC intentionally requires bounded retrieval but defers exact pagination semantics to REST API design.

Not every review comment requires design change।

Sometimes clarification is enough।


Review Comment 10 — Payment Failure Model Is Not Implementable Yet

Reviewer:

Payment section identifies partial-failure risk,
but the design does not define how we prevent
duplicate payment or recover when provider succeeds
and local state update fails.

Can RFC be Accepted while this remains open?

This is the most serious comment so far।


Is Payment Design a Blocking Issue?

For implementing:

Product

Inventory

Order creation

No।

For implementing:

Payment

Yes।

The exact provider capabilities are not yet defined।

We should not invent provider idempotency semantics।

Therefore RFC can accept the overall architecture while making payment implementation explicitly blocked on provider-specific integration design।


Revision 9

Update RFC:

Payment capability follows the approved architectural boundary, but payment execution implementation is not considered design-complete until provider idempotency, timeout, and payment-reference semantics are confirmed.

And backlog:

BACKEND-117
Implement Payment Provider Client

remains not-ready until those questions are resolved।

This is disciplined planning।


Design Can Be Partially Ready

This is common in real engineering।

We do not need every future feature fully designed before:

BACKEND-101

can start।

We need sufficient design for the work currently being implemented।

Conceptually:

Overall Architecture
    → Ready

Product design
    → Ready

Order foundation
    → Ready

Payment provider semantics
    → Not yet ready

This is better than pretending everything is equally resolved।


Review Comment 11 — Inventory Concurrency Still Has No Mechanism

Reviewer:

Inventory concurrency is a correctness risk.
Shouldn't locking strategy be decided before RFC acceptance?

Answer depends on design level।

High-level architecture has established required property:

concurrent ordering must not oversell inventory

Exact PostgreSQL/JPA mechanism depends on persistence implementation choices।

However, before BACKEND-112 Order Creation Workflow is implemented, mechanism must be selected and tested।

So it is a deferred implementation decision, but not optional।


Add a Decision Gate

Revision:

Order creation implementation cannot be considered Done
until a concurrency-safe Inventory persistence strategy
has been selected, documented, and tested.

This creates accountability without prematurely choosing a technique।


Why This Is Better Than Choosing Pessimistic Locking Immediately

Suppose we arbitrarily choose:

SELECT ... FOR UPDATE

before evaluating actual JPA/persistence design।

Maybe correct।

Maybe unnecessary।

Maybe an atomic SQL update would be simpler।

Design should first state the invariant and decision deadline।

Mechanism follows evidence।


Review Comment 12 — Repository Boundaries Are Inconsistent

Reviewer:

RFC says repository boundaries are pragmatic,
but that could lead to each capability using
a completely different persistence style.
Should we standardize?

This is a trade-off question।

We want consistency but not ceremony।


Reasonable Convention

We can establish:

Application workflows should not contain raw SQL
or EntityManager-level persistence mechanics.

and:

Persistence concerns remain behind repository components
owned by the relevant capability.

Whether the repository is:

direct Spring Data interface

or:

custom repository implementation

can depend on capability complexity।

This is sufficient architecture consistency।


Revision 10

Add repository convention:

Every capability keeps database-specific query and persistence mechanics inside its persistence boundary. Application workflows may depend on repository-level operations but will not contain direct JPA/SQL implementation logic.

This provides consistency without PortAdapterFactoryImpl explosion।


Review Comment 13 — shared/ Is Dangerous

Reviewer:

The proposed `shared/` package may become a dumping ground.
What is allowed there?

Valid concern।


Revision 11

Clarify:

shared/ may contain only genuinely application-wide technical concepts, such as:

consistent API error representation

if such sharing becomes useful।

Domain-specific code must stay with its capability।

We will not create shared/ content before a real shared responsibility exists।

In fact, the package itself does not need to exist at bootstrap if empty।


Good Review Can Remove Architecture

Notice review is not only:

add more components

Good review can say:

don't create this yet

Often the best revision is removing speculative structure।


Review Comment 14 — Does Payment Need Its Own Domain?

Reviewer:

Payment package includes a `domain` area,
but exact Payment entity is still unknown.
Are we creating structure before the model exists?

Correct।

Earlier architecture diagram showed:

payment/
├── application/
├── domain/
└── integration/

But if Payment currently only needs:

PayOrder workflow

PaymentGateway

Provider client

PaymentResult

a dedicated domain/ package may be unnecessary initially।


Revision 12

Simplify:

payment/
├── application/
└── integration/

with provider-independent result/value types placed where they naturally belong।

If a real persistent Payment domain model emerges later, then introduce payment/domain/

Architecture should grow from real responsibilities।


This Is an Important Design Lesson

Before review:

We thought a domain package might be useful.

After review:

No current domain model needs it.
Remove it.

Changing the design before code is cheap।

That's the point।


Review Comment 15 — Are Product and Inventory Truly Separate Modules?

Reviewer:

Product and Inventory are separate concepts,
but product browsing often reads both.
Will strict module isolation make simple reads awkward?

Good concern।

Our modular boundaries are logical, not isolation walls।

Read workflows can compose:

Product
+
Inventory

inside the same application।

We are not enforcing:

Product module cannot know Inventory exists.

The key restriction is ownership of mutation and responsibility।


Clarification

Architecture principle:

Capability boundaries define ownership and organization, not network-style isolation inside the monolith.

Product browsing can query Product and Inventory through appropriate persistence/application boundaries।

No internal REST calls।

No duplicated read database।


Review Comment 16 — Is OrderStatus Enough for Payment?

Reviewer:

If Order status is only UNPAID, PAID, CANCELLED,
how will payment attempts be represented?

Important distinction:

Order lifecycle

and:

Payment attempt lifecycle

are not necessarily the same thing।

An Order can remain:

UNPAID

while:

payment attempt failed

or:

provider timeout occurred

Therefore we should not inflate OrderStatus with provider attempt states like:

PAYMENT_TIMEOUT

PAYMENT_RETRYING

before payment model is designed।


Revision 13

Clarify:

OrderStatus represents the Order lifecycle only. Payment-attempt state, if required, will be modeled separately and must not be encoded as Order lifecycle states unless the product behaviour actually requires it.

This protects domain clarity।


Review Comment 17 — Does Order Store Customer Role?

Reviewer:

If customer identity comes externally,
does Order also store the customer's role?

No。

Order ownership needs:

customer identifier

Role is current authorization context, not historical Order ownership data।

Admin/customer authority may change over time।

Order does not need to preserve it।


Revision 14

Clarify:

Order stores owner customer identifier.

Authorization roles remain part of
authenticated request context.

This avoids mixing security metadata with business ownership।


Review Comment 18 — Should Order Creation Recheck Price After Inventory?

Reviewer:

What happens if Product price changes concurrently
while an order is being created?

This introduces concurrency beyond Inventory।

Important question।

We need a coherent price snapshot for the transaction।

The Order should use the Product price observed as part of the successful creation operation।

We do not need to promise price locking behaviour beyond that unless business says quoted prices must remain valid across earlier client browsing।

Client never supplies trusted price।

So:

price at successful order creation

is authoritative।


Revision 15

Clarify:

Order Item captures the server-side Product price read during the successful Order creation operation. Product price shown during earlier browsing is not a guaranteed quote for a later Order request.

This is a useful API/business semantic clarification।


Why This Matters

Customer may browse:

10:00
Product = €20

Admin changes price:

10:05
Product = €25

Customer submits Order:

10:06

Backend uses:

€25

unless business later introduces quote/price-lock functionality।

We will not invent that system now।


Review Comment 19 — What Does "All-or-Nothing" Include?

Reviewer:

For Order creation, does all-or-nothing include
multiple inventory rows and all order items?

Yes।

This should be explicit।

If request contains:

Product A × 2
Product B × 3
Product C × 1

and C cannot be fulfilled:

no Order

no Order Items

no Inventory reduction for A or B

Revision 16

RFC now explicitly states:

The complete Order creation request is one local atomic operation. Validation or persistence failure for any requested item causes the full operation to fail without partially consuming Inventory or creating a partial Order.

This matches acceptance criteria more precisely।


Review Comment 20 — Are Database Constraints Part of the Design?

Reviewer:

RFC says database constraints may protect invariants,
but does not define which critical invariants
must have database-level protection.

Some exact constraints depend on schema design।

But we can establish policy:

Critical persisted structural invariants should be enforced in PostgreSQL where practical।

Examples:

required foreign relationships

non-null required fields

inventory quantity >= 0

Business lifecycle rules remain primarily in application/domain logic।


Revision 17

Add persistence principle:

PostgreSQL constraints will reinforce critical structural/data-integrity invariants where they can be expressed clearly, while behavioural lifecycle rules remain in application/domain logic.

This guides later schema work without prematurely writing DDL।


What Makes Feedback "Actionable"?

Good review comment points to:

a requirement

an ambiguity

a risk

a trade-off

a contradiction

Weak comment:

I don't like this.

Better:

This component mixes provider-specific HTTP behaviour
with Order lifecycle rules, which makes the Order workflow
depend on an external protocol.

Now author knows what problem to evaluate।


Author Response Matters Too

Bad response:

That's just my style.

or:

This is how I've always done it.

Good response:

The concern is valid.

Given requirement X,
I'll change the design to Y.

Or:

I don't think we should change this because
the proposed alternative would introduce Z,
and our current requirement does not justify it.

Design review is technical reasoning, not obedience।


You Do Not Have to Accept Every Review Comment

Suppose reviewer says:

We should use Kafka so payment can be more scalable.

We ask:

Which current requirement requires Kafka?

None।

What new complexity?

broker operation

async semantics

delivery guarantees

consumer failure

event schema

Current design has no need for it।

Response:

Rejected for v1. No current workflow requires asynchronous messaging, and introducing Kafka would add operational and consistency complexity without solving a confirmed requirement.

This is a valid review outcome।


Review Comment: Split Into Microservices Now

Another reviewer:

Product and Order clearly have different responsibilities. They should be separate microservices.

Responsibility separation does not imply network separation।

Current architecture intentionally benefits from:

local transaction

simple deployment

in-process calls

No independent scaling or ownership requirement exists।

So ADR-001 still holds।

No revision।


Review Comment: Add Redis for Product Browsing

Reviewer:

Product browsing will probably be read-heavy. Let's add Redis now.

"Probably" is not enough।

We have:

no measured load

no latency target requiring cache

no database bottleneck

Caching would introduce consistency complexity।

No revision।

If production metrics later show need, architecture evolves।


Review Comment: Separate Read Database

Same reasoning।

No requirement yet।

PostgreSQL is sufficient for current read/write workload assumption because no scale target says otherwise।

Don't solve imaginary bottlenecks।


Review Comment: Add Event History to Every Entity

No requirement.

We need Order history, not universal audit/event sourcing।

No revision।


Design Review Should Remove Hidden Assumptions

Let's list assumptions that review made explicit:

Before:

"available Product"

After:

Product active AND Inventory > 0

Before:

"Customer"

After:

external authenticated customer ID;
no local Customer aggregate in v1

Before:

"Order total"

After:

derived from historical Order Items

Before:

"admin adjusts inventory"

After:

admin sets non-negative current available quantity

This is exactly what review should accomplish।


Revised Core Design Decisions

After review, our design is more concrete।


Product

Product owns:

stable identity

current product data

current price

active/inactive state

Invariant:

price >= 0

A Product is currently available for customer browsing when:

Product permits ordering
AND
Inventory quantity > 0

Inventory

Inventory is separate from Product।

Owns:

current available quantity

Invariant:

quantity >= 0

Admin v1 behaviour:

set current available quantity
to a non-negative value

Order creation consumes Inventory।

Eligible cancellation restores Inventory।


Customer Context

v1 does not create a local Customer aggregate solely for ordering।

Order stores:

authenticated external customer identifier

Security roles remain request/security context।


Order

Order owns:

owner customer ID

Order Items

Order lifecycle

States:

UNPAID
PAID
CANCELLED

Total:

derived from Order Item
unitPrice × quantity

Order Item

Contains:

Product reference

positive quantity

purchase-time Product price

The same Product cannot appear more than once in one Order creation request।


Product Changes After Order Creation

Current Product price/status changes do not rewrite existing Order meaning।

Therefore:

Product deactivated

does not invalidate already-created unpaid Orders।

They can still be paid if otherwise eligible।

Cancellation still restores Inventory even if Product is inactive।


Payment

Order state and Payment attempt state remain separate concepts।

Payment implementation remains gated on confirmation of:

provider idempotency behaviour

provider payment reference semantics

timeout behaviour

No fake solution will be invented before provider context exists।


Revised Order Creation Semantics

A successful Order creation operation:

1. receives at least one item

2. rejects duplicate Products

3. validates positive quantities

4. loads Products

5. verifies Product ordering state

6. loads relevant Inventory

7. verifies sufficient Inventory

8. uses current server-side Product price

9. constructs Order Items

10. derives Order total from those Items

11. decreases Inventory

12. persists the complete Order

13. commits all local changes together

Any failure:

no partial Order

no partial Order Items

no partial Inventory consumption

Revised Cancellation Semantics

Cancellation:

load Order

verify ownership

verify Order is UNPAID

transition to CANCELLED

restore Inventory

persist both atomically

Current Product activation state does not change the restoration rule।


Revised Payment Semantics

Payment:

load Order

verify ownership

verify Order is UNPAID

invoke provider boundary

process provider result

On confirmed safe success:

UNPAID → PAID

A Product becoming inactive after Order creation does not make existing Order unpayable।


Design Readiness

Now ask:

Is the design ready to implement?

Not every imaginable detail is resolved।

But implementation does not require every future decision upfront।

We need sufficient clarity for the next engineering work։


Ready for Early Implementation

These are sufficiently designed:

BACKEND-101
Bootstrap Application

BACKEND-102
PostgreSQL + Flyway Foundation

BACKEND-103
Product Domain

BACKEND-104
Product Persistence

Product API foundations

Inventory domain foundations

Order domain foundations

Requires Further Implementation-Level Design

Before Order creation persistence is complete:

Inventory concurrency strategy

must be resolved।

Before Payment implementation:

provider idempotency

timeouts

provider reference behaviour

must be resolved।

Before public API contracts finalize:

pagination details

error representation

exact endpoint models

will be designed in the REST module।

This is acceptable।


Design Readiness Is Not "No Open Questions"

A useful distinction:

Bad:

We cannot code until every possible question is answered.

Also bad:

We'll figure everything out while coding.

Better:

Resolve questions before the work that depends on them begins.

This is progressive design with explicit decision gates।


When Is an RFC Ready to Accept?

For our purposes, RFC is ready when:

core requirements are represented

main domain boundaries are clear

responsibilities are clear

architecture direction is clear

major workflows are understandable

important transaction boundaries are known

system boundaries are explicit

major risks are identified

important non-goals are explicit

remaining open questions have clear resolution points

RFC does not need exact method names or SQL।


Updated RFC Status

After incorporating review feedback:

RFC-001
Status: Accepted

Meaning:

The team agrees this is the architecture direction for the initial implementation.

It does not mean:

nothing can ever change.

What Happens to Review Comments?

Useful final design review should leave a record of outcomes।

For example:

Comment:
Clarify Customer persistence.

Resolution:
No local Customer aggregate in v1.
Order stores external customer identity.
Comment:
Inventory concurrency mechanism unresolved.

Resolution:
Accepted as implementation decision gate;
must be resolved before Order creation is Done.

This helps reviewers know comments were considered rather than ignored।


Revision Does Not Always Require a New RFC

Minor clarification:

define available Product

can update RFC-001।

Major architecture reversal:

split Order and Inventory into services

might require:

new RFC
+
new ADR

The size of documentation should match the size of the decision।


Design Review and ADRs

Review may also change ADR candidates।

Our existing ADRs still hold:

ADR-001
Modular Monolith
ADR-002
Separate Inventory from Product
ADR-003
Preserve Purchase-Time Price
ADR-004
Isolate Payment Provider

None were invalidated।

Review actually strengthened their reasoning।


What If Review Invalidates an ADR?

Suppose review proves a proposed ADR is wrong before implementation।

If status was:

Proposed

we can reject it।

No need to preserve a rejected proposal as accepted history unless team process values that record।

If already Accepted and later evidence changes it:

supersede

rather than silently rewrite history।


Design Review vs Code Review

Now the distinction is clear।

Design Review

Focus:

problem

boundaries

responsibilities

trade-offs

failure modes

risks

Code Review

Later focus:

does implementation match the design?

is behaviour correct?

are tests adequate?

is code maintainable?

did implementation introduce new risk?

Both matter।


Design Review Does Not Guarantee Correctness

Even a strong RFC review cannot prove:

no bugs

no incidents

perfect performance

Implementation and production will reveal new information।

Design review reduces avoidable mistakes।

It does not eliminate uncertainty।


A Senior Engineer's Review Questions

When reviewing future technical designs, useful questions include:

What requirement drives this decision?

What happens when this dependency fails?

What state can become inconsistent?

Who owns this data?

Who is allowed to mutate it?

Is this historical or current state?

Where is the transaction boundary?

What happens under concurrent requests?

Are we trusting client-controlled data?

Which assumptions are not confirmed?

Which complexity is required today?

What becomes difficult to change later?

How will we know this fails in production?

These questions generalize far beyond this course project।


Avoid Reviewing Only Diagrams

A beautiful architecture diagram can hide:

unclear ownership

missing failure behaviour

incorrect transactions

unconfirmed assumptions

Review behaviour and invariants first।

Boxes and arrows are supporting tools।


Avoid Reviewing Only Technologies

Weak review:

Why PostgreSQL instead of MongoDB?

Why Spring Boot instead of framework X?

when those are established context।

Better review:

Does the proposed PostgreSQL transaction
cover all local state changes that must be atomic?

Focus effort on real decisions।


Avoid Premature Performance Review

Without scale targets, reviewer should not demand:

Redis

read replicas

sharding

But reviewer can still identify obvious unbounded behaviour।

For example:

load every Order in history

would be clearly risky even without precise traffic numbers।

That's why we already require bounded retrieval।


Review the Failure Path

For every major workflow, ask:

What if step 1 succeeds and step 2 fails?

Order creation:

Inventory updated
but Order persistence fails?

Transaction protects it।

Cancellation:

Order cancelled
but inventory restore fails?

Transaction protects it।

Payment:

Provider succeeds
but local DB update fails?

Still unresolved external consistency problem, intentionally flagged।

Failure-path review exposes architecture quality quickly।


Review the Ownership Path

Ask:

Which component is authoritative for this fact?

Examples:

Current Product price:

Product

Historical purchase price:

Order Item

Current available quantity:

Inventory

Order lifecycle:

Order

Authentication identity:

External identity capability

Customer resource ownership enforcement:

Application workflow

If two components both think they own the same mutable fact, architecture often becomes fragile।


Review the Trust Boundary

Ask:

Which values come from the client, and which values does the backend trust?

Client supplies:

Product ID

Quantity

Backend determines:

Product existence

Product orderability

Inventory

Price

Order total

Customer identity

Client should not determine:

authoritative price

order owner

payment success

order status

This is a useful security and correctness review habit।


Review the Temporal Boundary

Ask:

Is this fact current state or historical state?

Current:

Product price

Product activation

Inventory quantity

Historical:

Order Item purchase-time price

Stable ownership reference:

Order customer ID

Confusing current and historical state causes subtle bugs।


Review the Scope Boundary

Ask:

Did we accidentally design something the requirement never requested?

Examples we avoided:

Cart

Warehouse

Refund

Shipment

Inventory Reservation Entity

Payment Plugin Framework

Kafka

Redis

Design review should actively remove speculative scope।


Final Revised Architecture Snapshot

After review:

Order Management Backend
=
one modular Spring Boot application

Capabilities:

Product

Inventory

Order

Payment Integration

Security Context

Persistent application state:

PostgreSQL

Customer:

external authenticated identity
stored on Order as owner ID

Order total:

derived from historical Order Items

Product browsing availability:

active/orderable Product
+
Inventory > 0

Local atomic workflows:

Order creation

Order cancellation

Payment:

external integration boundary
with provider-specific consistency design pending

Module 2 Deliverables

We have now produced:

Domain model
Responsibility map
Initial architecture
RFC-001
ADR-001 through ADR-004
Design review revisions

This is enough to start building the application foundation deliberately।


What Comes Next?

Module 2 is now complete।

We move into:

Module 3 — Building the Spring Boot Application

The first implementation ticket is:

BACKEND-101
Bootstrap Order Management Backend

We will finally start creating the application।

But now when we create packages, components, and dependencies, we know why they exist।

We are not starting from:

What annotation should I learn first?

We are starting from:

We have an agreed system to build.
Spring Boot is the tool we will use to build it.

Engineering Principle

The core principle from this lesson:

A technical design is not ready because the author finished writing it; it is ready when important assumptions, trade-offs, risks, and responsibilities have survived meaningful review.

Another:

Accept feedback based on the problem it reveals, not because every reviewer preference must become architecture.

And:

Leave uncertainty explicit, but resolve each uncertainty before the implementation that depends on it begins.


Summary

In this lesson, we learned that:

  • Design review happens before implementation to reduce expensive mistakes.
  • Review should evaluate requirements, ownership, boundaries, failures, and risks.
  • Design review is not approval theatre.
  • Reviewer preference and actual design problem are different things.
  • Duplicate Product validation now has an explicit responsibility.
  • "Available Product" now means Product is orderable and Inventory is greater than zero.
  • v1 does not require a local Customer aggregate.
  • Order stores the authenticated external customer identifier.
  • Order total will be derived from historical Order Items.
  • Product price cannot be negative.
  • v1 admin Inventory management sets a non-negative current quantity.
  • Product deactivation does not invalidate already-created Orders.
  • Cancellation restores Inventory even when Product is currently inactive.
  • Order creation uses current server-side Product pricing at successful creation time.
  • The entire multi-item Order creation operation is atomic.
  • Order lifecycle state and Payment attempt state remain separate.
  • Payment implementation remains blocked on actual provider idempotency and failure semantics.
  • Inventory concurrency remains a required decision before Order creation implementation is Done.
  • Persistence mechanics remain inside capability-owned persistence boundaries.
  • shared/ will not become a dumping ground and does not need to exist until truly needed.
  • Payment does not need a speculative domain package before a real Payment domain model exists.
  • Some review comments result in changes, some in clarifications, and some should be rejected.
  • RFC-001 can now be considered Accepted.
  • Module 2 is complete.

Next lesson:

Creating a Spring Boot Application

We will begin BACKEND-101 — Bootstrap Order Management Backend and create the actual Java/Gradle/Spring Boot application that will evolve throughout the rest of the course.