Post

SOLID 원칙

객체지향 설계의 5대 원칙인 SOLID

SOLID 원칙이란?

SOLID is a mnemonic acronym for five design principles intended to make object-oriented designs more understandable, flexible, and maintainable.
SOLID 원칙은 마틴 파울러(Martin Fowler)가 제안한 객체지향 5가지 설계 원칙. \ 이 원칙들은 객체지향 프로그래밍에서 코드의 가독성, 유지보수성, 확장성을 높이기 위함임.


1. SRP (Single Responsibility Principle) - 단일 책임 원칙

  • 클래스는 하나의 책임만 가져야 하며, 변경 이유는 하나뿐이어야 한다.
    • “A class should have only one reason to change.”
1
2
3
4
5
6
7
8
9
10
11
class ReportPrinter {
    fun print(report: String) {
        println("Printing report: $report")
    }
}

class ReportSaver {
    fun save(report: String) {
        println("Saving report: $report")
    }
}

2. OCP (Open-Closed Principle) - 개방-폐쇄 원칙

  • 소프트웨어 요소는 확장에는 열려 있고, 수정에는 닫혀 있어야 한다.
    • “Software entities should be open for extension, but closed for modification.”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
interface Notification {
    fun send(message: String)
}

class EmailNotification : Notification {
    override fun send(message: String) {
        println("Email: $message")
    }
}

class SMSNotification : Notification {
    override fun send(message: String) {
        println("SMS: $message")
    }
}

class NotificationService(private val notifier: Notification) {
    fun notifyUser(message: String) {
        notifier.send(message)
    }
}

3. LSP (Liskov Substitution Principle) - 리스코프 치환 원칙

  • 자식 클래스는 부모 클래스를 대체할 수 있어야 한다.
    • “Objects of a superclass should be replaceable with objects of its subclasses.”
1
2
3
4
5
6
7
8
9
10
11
12
13
open class Bird {
    open fun fly() = println("Flying")
}

class Sparrow : Bird()

class Ostrich : Bird() {
    override fun fly() {
        throw UnsupportedOperationException("Ostrich can't fly")
    }
}

// 위의 예시는 LSP 위반. Ostrich는 Bird의 대체가 되지 않음.

4. ISP (Interface Segregation Principle) - 인터페이스 분리 원칙

  • 클라이언트는 자신이 사용하지 않는 메서드에 의존하지 않아야 한다.
    • “Clients should not be forced to depend upon interfaces that they do not use.”
  • Kotlin 예시: ```kotlin interface Printer { fun print() }

interface Scanner { fun scan() }

class BasicPrinter : Printer { override fun print() = println(“Printing…”) }

class AllInOnePrinter : Printer, Scanner { override fun print() = println(“Printing…”) override fun scan() = println(“Scanning…”) }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
---

### 5. DIP (Dependency Inversion Principle) - 의존성 역전 원칙
- 고수준 모듈은 저수준 모듈에 의존해서는 안 되며, 추상화에 의존해야 한다.
  - “Depend on abstractions, not on concretions.”

- Kotlin 예시:
```kotlin
interface AuthService {
    fun login(username: String, password: String): Boolean
}

class FirebaseAuthService : AuthService {
    override fun login(username: String, password: String) = true
}

class LoginManager(private val authService: AuthService) {
    fun authenticateUser(username: String, password: String) {
        if (authService.login(username, password)) {
            println("Login success")
        } else {
            println("Login failed")
        }
    }
}

SOLID 원칙의 장점

  • 팀 개발에서 설계 일관성과 유지보수를 강화하고 싶을 때
  • 대규모 코드베이스에서 유연한 구조를 설계하고 싶을 때
  • 테스트 가능한 코드와 변경에 강한 구조를 원할 때
  • 코드의 가독성과 이해도를 높이고 싶을 때
  • 객체지향 프로그래밍의 원칙을 따르고 싶을 때
  • 코드의 재사용성을 높이고 싶을 때
This post is licensed under CC BY 4.0 by the author.