[D] The Dependency Inversion Principle
- March 18, 2023
- Reading time . 3 min
- Author: Yuniel Acosta
The Dependency Inversion Principle (DIP) is the fifth principle of the SOLID design principles. It states that high-level modules should not depend on low-level modules, but both should depend on abstractions. This means that a class should depend on abstractions rather than on specific implementations. This principle promotes a design where high-level modules, such as the business logic, are not tightly coupled to low-level modules, such as the data access layer. This makes the code more flexible and easier to maintain.
An example of a bad practice that violates the Dependency Inversion Principle (DIP) is a class that depends on a specific implementation of a low-level module.
class Order {
private val database = MySQLDatabase()
fun saveOrder() {
database.save("orders", "order_data")
}
}
In this example, the Order
class has a dependency on a specific implementation of a low-level module, namely the MySQLDatabase
class. This violates the Dependency Inversion Principle (DIP), because the Order
class is tightly coupled to a specific implementation of the MySQLDatabase class. If we want to change the database to PostgreSQL or any other database, we would need to modify the Order
class as well.
A better practice would be to create an abstraction for the low-level module and have the high-level module depend on the abstraction.
interface Database {
fun save(table: String, data: String)
}
class MySQLDatabase: Database {
override fun save(table: String, data: String) {
println("Saving data to MySQL database")
}
}
class PostgreSQLDatabase: Database {
override fun save(table: String, data: String) {
println("Saving data to PostgreSQL database")
}
}
class Order {
private lateinit var database: Database
fun setDatabase(database: Database) {
this.database = database
}
fun saveOrder() {
database.save("orders", "order_data")
}
}
The Order
class depends on the abstraction provided by the Database
interface, rather than a specific implementation of a low-level module. This approach adheres to the Dependency Inversion Principle (DIP), which makes the code more flexible and maintainable. With this design, it is possible to switch to a different database by creating a new implementation of the Database
interface and injecting it into the Order
class.
In conclusion, the Dependency Inversion Principle (DIP) is an important principle of the SOLID design principles that promotes a flexible and maintainable codebase. By depending on abstractions rather than specific implementations, high-level modules can remain decoupled from low-level modules, which makes it easier to modify and extend the system. By following this principle, developers can create software that is more adaptable to change and easier to test and maintain over time.