# SOLID Principles (Series) [PART 5]

> If get to know something new by reading my articles, don't forget to endorse me on [LinkedIn](https://www.linkedin.com/in/rommansabbir/)

Previous articles on **SOLID Principles**

* [Single Responsibility Principle](https://rommansabbir.com/solid-part-1)
    
* [Open Closed Principle](https://rommansabbir.com/solid-part-2)
    
* [Liskov's Substitution Principle](https://rommansabbir.com/solid-part-3)
    
* [Interface Segregation Principle](https://rommansabbir.com/solid-part-4)
    

### What is DIP?

DIP (**Dependency Inversion Principle**) states that:

> * `High-level` modules should not depend on `low-level` modules. Both should depend on `abstractions`.
>     

* `Abstractions` should not depend on details. Details should depend on `abstractions`.
    

### Things to remember

* Design by `contract`.
    
* Every `dependency` in the design should target an `interface` or an `abstract` class. No `dependency` should target a concrete class.
    
* `Factories` and `Abstract Factories` can be used as dependency frameworks, but there are specialized frameworks for that such as `Spring IOC (Inversion of Control Container)`.
    

Let's take an simple `Songs Repository` example. Where `Data Source` could be `Remote` or `Local`. When device is connected to the internet, data should be fetched from `Remote`, else it should return whatever has been `Cached` to the `Local`.

### Example

```kotlin
interface SongsRepository {
    fun searchSongs(query : String) : MutableList<SongObject>
}
```

```kotlin
class SongsRepositoryImpl constructor (private val dataSource : DataSource)  : SongsRepository {
    @override fun searchSongs(query : String) : MutableList<SongObject> {...}
}
```

Here, the `implementation` depends on `abstraction` (`DataSource interface`) that can be `injected` through its `constructor`.

Let's create the `DataSource` interface with two `implementations` of `DataSource`.

```kotlin
interface DataSource {
    fun createConnection(config : DataSourceConfig) : Boolean
    fun getConnection() : DataSourceConnection
}
```

```kotlin
interface RemoteDataSource {
    @override fun createConnection(config : DataSourceConfig) : Boolean {...}
    @override fun getConnection() : DataSourceConnection {...}
}
```

```kotlin
interface LocalDataSource {
    @override fun createConnection(config : DataSourceConfig) : Boolean {...}
    @override fun getConnection() : DataSourceConnection {...}
}
```

Based on device internet connectivity, we can switch from `RemoteDataSource` to `LocalDataSource` (when device is not connected to the internet) then we only need to pass this `object` from the `client`.

What's has been done through the example?

* `SongsRepositoryImpl` class depends on the `DataSource` interface, not the concrete class.
    
* Now due to `abstraction`, `Client` can change `implementation` at any time. For example, when device is connected to the internet, client can pass an `instance` of `RemoteDataSource` else `LocalDataSource`.
    

### Recap

> * `High-level` modules should not depend on `low-level` modules. Both should depend on `abstractions`.
>     

* `Abstractions` should not depend on details. Details should depend on `abstractions`.
    

That's it for this series. Happy Coding...
