개발 공부/아키텍처

SOLID 원칙을 알아보자 5 : 의존성 역전 원칙 - kotlin

yong_DD 2023. 8. 25. 14:28

SOLID 원칙이란?

Single Responsibility Principle

→ 

단일 책임 원칙

Open-Closed Principle 

→ 

개방-폐쇄 원칙

Liskov Substitution Principle 

→ 

리스코프 치환 원칙

Interface Segregation Principle 

→ 

인터페이스 분리 원칙

Dependency Inversion Principle

→ 

의존성 역전 원칙


Dependency Inversion Principle 

 의존성 역전 원칙 

높은 수준의 코드(모듈)는 낮은 수준의 코드(모듈) 구현에 의존해서는 안된다.
낮은 수준의 모듈보다 높은 수준의 모듈에 의존해야한다.
높은 수준의 모듈인터페이스, 추상 클래스라고 생각하면 되고, 
낮은 수준의 모듈구현된 객체라고 생각하면 된다.

즉, 객체는 객체 자체보다 인터페이스, 추상 클래스에 의존해야한다고 생각할 수 있다.

의존성 역전 원칙 위반 예시

class User(private val name:String){
   private val textMessage = TextMessage()

   fun send(message:String) {
       textMessage.sendMessage("$name : $message")
   }
}

class TextMessage() {
    fun sendMessage(message: String) {
        println(message)
    }
}

fun main(arg: Array<String>) {
    val user = User("ABC")
    user.send("안녕하세요")
}

누군가에게 간단하게 메시지를 보내는 상황이라고 할 때 User가 text로 메시지를 보내면 위와 같이 작성할 수 있다.

위 코드의 문제점은 우선 메시지를 text가 아닌 이모티콘이나 사진 등을 보낼 수도 있는 것이고, 이미 구현된 하위 모듈인 TextMessage에 의존하게 된다.

 

수정 코드

class User(private val name:String){
   lateinit var message : Message
  
   fun send() {
       message.send(name)
   }
}

interface Message {
    fun send(name:String) {}
}

class TextMessage(private val message: String) : Message {
    override fun send(name: String) {
        println("$name : $message")
    }
}

class ImageMessage(private val img:Image) : Message {
  // ...
}

class EmoticonMessage(private val emo:Emoticon) : Message {
    // ...
}

fun main(arg: Array<String>) {
    val user = User("ABC")
    user.message = TextMessage("안녕하세요")
    user.send()
}

interface Message로 각각의 TextMessage, ImageMessage 등을 상속받아 구현을 한다.

User에서 TextMessage 대신 Message를 받도록 하여 여러 메시지를 보낼 수 있도록 하는 것과 동시에 고수준 모듈에 의존하게 되면서 의존성 역전 원칙에 위배가 되지 않도록 할 수 있다.

  

앞선 포스팅의 코드들을 보게 되면 알겠지만, 인터페이스 분리 원칙이나 개방 폐쇄 원칙을 따르다 보면 자연스럽게 의존성 역전의 원칙을 따르게 된다.


참고 및 출처

https://blog.itcode.dev/posts/2021/08/17/dependency-inversion-principle

https://inpa.tistory.com/entry/OOP-%F0%9F%92%A0-%EC%95%84%EC%A3%BC-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-DIP-%EC%9D%98%EC%A1%B4-%EC%97%AD%EC%A0%84-%EC%9B%90%EC%B9%99