Capstone Project: Complete Logistics System
Welcome to your capstone project! You'll build a complete order processing system that integrates all the design patterns you've learned throughout this course.
Project Overview
You're building a production-ready logistics order processing system for an e-commerce platform. The system handles the complete workflow from order placement to shipment tracking:
- Order receipt and validation
- Address validation through multiple checks
- Shipping rate calculation from multiple carriers
- Optimal carrier selection
- Label generation
- Order state management
- Real-time tracking notifications
Business Requirements
Core Workflow
1Order Created2 ↓3Address Validation (Chain of validators)4 ↓5Rate Calculation (Multiple strategies)6 ↓7Carrier Selection (Factory-based)8 ↓9Shipping Options (Decorators for insurance, signature, etc.)10 ↓11Label Generation12 ↓13Order State Transitions (Pending → Processing → Shipped → Delivered)14 ↓15Tracking Notifications (Observer pattern)
Functional Requirements
FR1: Address Validation
- Validate address format (required fields)
- Verify postal code format by country
- Check address against geocoding service
- Identify undeliverable addresses
- Accumulate all validation errors
FR2: Rate Calculation
- Calculate rates based on package weight and dimensions
- Support multiple pricing strategies:
- Standard rates (weight-based tiers)
- Zone-based pricing (distance calculations)
- Volumetric weight pricing (dimensional weight)
- Compare rates across carriers
- Apply business rules (minimum charges, surcharges)
FR3: Carrier Selection
- Create carrier-specific shipping services
- Support USPS, FedEx, UPS, DHL
- Generate carrier-specific labels
- Handle carrier-specific requirements
FR4: Shipping Options
- Add insurance (based on declared value)
- Require signature confirmation
- Enable Saturday delivery
- Add tracking notifications
- Support combinations of options
FR5: Order State Management
- Track order through lifecycle states
- Enforce valid state transitions
- Trigger actions on state changes
- Maintain state history
FR6: Tracking Notifications
- Notify subscribers of tracking updates
- Support multiple notification channels (email, SMS, webhook)
- Batch notifications efficiently
- Handle notification failures gracefully
FR7: Unified Interface
- Provide simple facade for complex operations
- Hide subsystem complexity from clients
- Coordinate between multiple subsystems
- Handle errors consistently
Non-Functional Requirements
NFR1: Extensibility
- Easy to add new carriers
- Easy to add new validation rules
- Easy to add new pricing strategies
- Easy to add new shipping options
NFR2: Testability
- All components independently testable
- Mock external services (geocoding, carrier APIs)
- Integration tests for complete workflow
NFR3: Type Safety
- Strong TypeScript typing throughout
- No
anytypes - Compile-time validation of contracts
NFR4: Performance
- Efficient rate comparison (parallel calculations)
- Caching for repeated lookups
- Minimize object creation overhead
Design Patterns to Apply
You'll integrate 7 different design patterns in this project:
1. Chain of Responsibility - Address Validation
typescript1// Multiple validators in a chain2FormatValidator → PostalCodeValidator → GeocodingValidator → DeliverabilityValidator
Why this pattern:
- Each validator handles one concern
- Easy to add/remove validators
- Validators can be reordered
- All validators run (accumulate errors)
2. Strategy Pattern - Rate Calculation
typescript1interface RateCalculationStrategy {2 calculateRate(shipment: ShipmentDetails): Money;3}45class StandardRateStrategy implements RateCalculationStrategy { }6class ZoneBasedRateStrategy implements RateCalculationStrategy { }7class VolumetricRateStrategy implements RateCalculationStrategy { }
Why this pattern:
- Different carriers use different pricing models
- Strategies can be swapped at runtime
- Easy to test each strategy independently
- Business logic encapsulated
3. Factory Method - Carrier Creation
typescript1abstract class CarrierFactory {2 abstract createShippingService(): ShippingService;3 abstract createLabelGenerator(): LabelGenerator;4}56class USPSFactory extends CarrierFactory { }7class FedExFactory extends CarrierFactory { }
Why this pattern:
- Each carrier has specific requirements
- Factory encapsulates carrier complexity
- Easy to add new carriers
- Consistent interface across carriers
4. Decorator Pattern - Shipping Options
typescript1interface Shipment {2 getCost(): Money;3 getDescription(): string;4}56class BaseShipment implements Shipment { }7class InsuranceDecorator extends BaseShipment { }8class SignatureDecorator extends BaseShipment { }9class SaturdayDeliveryDecorator extends BaseShipment { }
Why this pattern:
- Options can be combined flexibly
- New options added without modifying base
- Each decorator has single responsibility
- Cost calculation composes naturally
5. State Pattern - Order Lifecycle
typescript1interface OrderState {2 process(context: OrderContext): void;3 cancel(context: OrderContext): void;4 ship(context: OrderContext): void;5}67class PendingState implements OrderState { }8class ProcessingState implements OrderState { }9class ShippedState implements OrderState { }10class DeliveredState implements OrderState { }11class CancelledState implements OrderState { }
Why this pattern:
- Complex state transitions
- State-specific behavior
- Prevents invalid state changes
- Clear state machine representation
6. Observer Pattern - Tracking Notifications
typescript1interface TrackingObserver {2 update(event: TrackingEvent): void;3}45class EmailNotifier implements TrackingObserver { }6class SMSNotifier implements TrackingObserver { }7class WebhookNotifier implements TrackingObserver { }89class TrackingSubject {10 private observers: TrackingObserver[] = [];11 notify(event: TrackingEvent): void { }12}
Why this pattern:
- Multiple subscribers to tracking events
- Loose coupling between event source and handlers
- Easy to add new notification types
- Subscribers independently manage their logic
7. Facade Pattern - Unified Interface
typescript1class ShippingFacade {2 constructor(3 private addressValidator: ValidationChain,4 private rateCalculator: RateService,5 private carrierFactory: CarrierFactoryRegistry,6 private orderStateMachine: OrderStateManager,7 private trackingNotifier: TrackingNotifier8 ) {}910 async processOrder(order: Order): Promise<ShipmentResult> {11 // Coordinates all subsystems12 }13}
Why this pattern:
- Simplifies complex subsystem interactions
- Provides high-level API for clients
- Reduces coupling to subsystems
- Easier to understand and use
System Architecture
Domain Model
typescript1// Core entities2interface Order {3 id: string;4 customerId: string;5 items: OrderItem[];6 shippingAddress: Address;7 billingAddress: Address;8 createdAt: Date;9}1011interface OrderItem {12 productId: string;13 quantity: number;14 weight: Weight;15 dimensions: Dimensions;16 declaredValue: Money;17}1819interface Address {20 street: string;21 street2?: string;22 city: string;23 state: string;24 postalCode: string;25 country: string;26}2728interface ShipmentDetails {29 totalWeight: Weight;30 dimensions: Dimensions;31 origin: Address;32 destination: Address;33 declaredValue: Money;34}3536interface ShippingRate {37 carrier: string;38 service: string;39 cost: Money;40 estimatedDays: number;41 features: string[];42}4344interface TrackingEvent {45 orderId: string;46 trackingNumber: string;47 status: string;48 location: string;49 timestamp: Date;50 description: string;51}
Value Objects
typescript1class Money {2 constructor(3 public readonly amount: number,4 public readonly currency: string = 'USD'5 ) {}67 add(other: Money): Money { }8 multiply(factor: number): Money { }9 toString(): string { }10}1112class Weight {13 constructor(14 public readonly value: number,15 public readonly unit: 'lb' | 'kg' | 'oz'16 ) {}1718 toLbs(): number { }19 toKg(): number { }20}2122class Dimensions {23 constructor(24 public readonly length: number,25 public readonly width: number,26 public readonly height: number,27 public readonly unit: 'in' | 'cm'28 ) {}2930 getVolume(): number { }31 getVolumetricWeight(): Weight { }32}
Integration Points
How Patterns Work Together
typescript1// Client code using the facade2const facade = new ShippingFacade(3 new ValidationChainBuilder()4 .add(new FormatValidator())5 .add(new PostalCodeValidator())6 .add(new GeocodingValidator())7 .build(),8 new RateService([9 new StandardRateStrategy(),10 new ZoneBasedRateStrategy()11 ]),12 CarrierFactoryRegistry.getInstance(),13 new OrderStateManager(),14 new TrackingNotifier()15);1617// Process an order18const result = await facade.processOrder(order);1920// Facade internally:21// 1. Validates address (Chain of Responsibility)22// 2. Calculates rates (Strategy)23// 3. Selects carrier (Factory)24// 4. Applies options (Decorator)25// 5. Transitions state (State)26// 6. Sends notifications (Observer)
Success Criteria
Your implementation must:
- Pass all unit tests (each pattern tested independently)
- Pass integration tests (complete workflow)
- Demonstrate proper pattern usage (no pattern misuse)
- Use TypeScript types effectively (no
any) - Handle edge cases (empty orders, invalid addresses, etc.)
- Be extensible (easy to add new validators, strategies, carriers)
What You'll Build
In the upcoming workshop, you'll implement:
- 8 classes for address validation chain
- 4 strategies for rate calculation
- 4 carrier factories with their services
- 5 decorators for shipping options
- 5 state classes for order lifecycle
- 4 observer implementations for notifications
- 1 facade to coordinate everything
- Complete integration tests for the workflow
Time Estimate
- Reading requirements: 30 minutes (this lesson)
- Architecture review: 20 minutes (next lesson)
- Implementation guide: 20 minutes
- Workshop implementation: 90 minutes
- Quiz: 10 minutes
- Total: ~3 hours
Next Steps
In the next lesson, we'll dive deep into the architecture design, showing you:
- Detailed class diagrams
- Interface definitions
- Data flow through the system
- Extension points for future features
Then you'll get a step-by-step implementation guide before tackling the complete workshop.
Ready to build a production-quality system? Let's go!