SOLID Principles • Dependency Inversion PrincipleMedium⏱️ ~3 min
Applying DIP: Parking Lot Payment System
Consider a parking lot system where the payment processor needs to charge customers and store transaction records. Without DIP, the high-level payment logic directly depends on specific payment gateway and database implementations.
Before (Violation)
ParkingPaymentService creates StripeClient and PostgresDB objects directly. Changing payment providers requires modifying business logic.→
After (DIP Applied)
ParkingPaymentService depends on IPaymentGateway and ITransactionRepository. Implementations are injected at runtime.ParkingPaymentService
- gateway: IPaymentGateway
- repository: ITransactionRepository
- repository: ITransactionRepository
+ processPayment(ticket): Receipt
«interface»
IPaymentGateway
+ charge(amount, card): Result
△
StripeGateway
RazorpayGateway
«interface»
ITransactionRepository
+ save(transaction): Boolean
△
PostgresRepo
MongoRepo
Implementation Flow:
processPayment(ticket):
fee = calculateFee(ticket.duration)
result = gateway.charge(fee, ticket.card)
if result.success:
transaction = createTransaction(ticket, fee)
repository.save(transaction)
return createReceipt(transaction)
else:
throw PaymentFailedException
fee = calculateFee(ticket.duration)
result = gateway.charge(fee, ticket.card)
if result.success:
transaction = createTransaction(ticket, fee)
repository.save(transaction)
return createReceipt(transaction)
else:
throw PaymentFailedException
Benefits in This Design:
First, switching from Stripe to Razorpay requires zero changes to
Second, testing becomes straightforward. Create
Third, the service can support multiple payment gateways simultaneously. A factory or strategy can select the appropriate implementation at runtime based on customer preference or region.
Fourth, database migration from PostgreSQL to MongoDB happens independently of business logic changes.
ParkingPaymentService. Only the concrete gateway implementation changes.Second, testing becomes straightforward. Create
MockPaymentGateway and InMemoryRepository implementations for unit tests without touching external services.Third, the service can support multiple payment gateways simultaneously. A factory or strategy can select the appropriate implementation at runtime based on customer preference or region.
Fourth, database migration from PostgreSQL to MongoDB happens independently of business logic changes.
Interview Tip: Explain that the interfaces are defined in the same module as
ParkingPaymentService, not in the gateway or repository modules. This package structure ensures the inversion.💡 Key Takeaways
✓Business logic defines payment and storage contracts through interfaces
✓Concrete payment gateways and databases implement these contracts
✓Payment service logic remains unchanged when switching implementations
✓Testing uses mock implementations without modifying production code
✓Multiple implementations can coexist and be selected at runtime
📌 Examples
1Switching from Stripe to Razorpay without changing payment service code
2Adding MongoDB support alongside PostgreSQL for A/B testing
3Using in-memory repository for integration tests while production uses PostgreSQL