Interview frequency: …
Short answer
DIP is an architectural principle requiring both high-level modules and low-level details to depend on abstractions. DI is a coding pattern for passing dependencies from outside.
Explanation
In a traditional architecture, the business layer (high-level business logic) directly depends on the data layer (SQL database client). DIP reverses this direction: the business layer defines an abstraction (a port or contract) that meets its needs, and the data layer implements it (an adapter). Business rules then become independent of database or cloud-provider details.
Code example
// The business layer owns the contract:
interface NotificationSender {
send(message: string): Promise<void>;
}
// The business layer depends on the abstraction:
class OrderService {
constructor(private notifier: NotificationSender) {}
}Common mistakes
- Believing that using libraries such as Inversify or Dagger automatically applies DIP, when the principle is really about who owns the interface and the direction of architectural dependencies.