정의
SOLID 중 I에 해당한다.
ISP는 Interface Segregation Principle의 약자로, 인터페이스 분리 원칙이다.
클라이언트가 자신이 이용하지 않는 메서드에 의존하지 않아야 한다는 원칙이다. (인터페이스의 SRP)
ISP의 장점
- 소프트웨어를 디커플링된 상태로 유지하게 해준다.
- 리팩토링, 변경, 재배포를 더 쉽게 할 수 있게 해준다.
이 글을 쓰다가 문득, “그럼 인터페이스에 메소드를 하나씩만 넣으면 되지 않을까?” 생각했는데, 생각만 해도 끔찍하더라, 뭐든 적당한 게 좋다. 일단 코드 크기부터가 미칠 것 같다.
위반 사례
인터페이스가 클라이언트가 사용하지 않는 메소드를 가지는 경우 어떻게 될까?
아래 예시는 프린터가 스캔과 출력 메소드를 가지는 경우이다.
type Printer interface {
Scan()
Print()
}
type APrinter struct{}
func NewAPrinter() Printer {
return &APrinter{}
}
func (A *APrinter) Scan() {
log.Println("A가 스캔한다.")
}
func (A *APrinter) Print() {
log.Println("A가 프린트한다.")
}
type BPrinter struct{}
func NewBPrinter() Printer {
return &BPrinter{}
}
func (B *BPrinter) Scan() {
}
func (B *BPrinter) Print() {
log.Println("B가 프린트한다.")
}
func main() {
printer := NewAPrinter()
printer.Scan()
printer.Print()
printer = NewBPrinter()
printer.Scan()
printer.Print()
}
이때, BPrinter가 ISP를 위반하는 경우이다. Scan 메소드에 내용이 없다. 솔직히 여기까지는 문제가 없다. 그냥 없으면 없는 대로 살아도 뭐...
문제는 Scan의 시그니처가 Read로 변경이 된다면 BPrinter도 같이 변경을 해줘야 한다. 귀찮다. BPrinter는 쓰지도 않는 메소드인데 귀찮지만 바꿔줘야 한다. 1
그걸 방지하기 위해서 나누면 아래와 같이 된다.
type Printer interface {
Print()
}
type Scanner interface {
Scan()
}
type AllInOnePrinter struct{}
func NewAllInOnePrinter() *AllInOnePrinter {
return &AllInOnePrinter{}
}
func (A *AllInOnePrinter) Scan() {
log.Println("AllInOne 가 스캔한다.")
}
func (A *AllInOnePrinter) Print() {
log.Println("AllInOne 가 프린트한다.")
}
type OnlyPrinter struct{}
func NewOnlyPrinter() *OnlyPrinter {
return &OnlyPrinter{}
}
func (o *OnlyPrinter) Print() {
log.Println("Only 가 프린트한다.")
}
func main() {
a := NewAllInOnePrinter()
a.Scan()
a.Print()
o := NewOnlyPrinter()
o.Print()
}
위 코드에서는 Scanner의 Scan 메소드의 이름을 변경하더라도 AllInOnePrinter 구현체만 영향을 받는다.
물론, 인터페이스는 만들었으면 안 바꾸는 게 제일 좋다. 하지만, 인터페이스가 처음부터 잘 만들어질 리가 없다.
마치며...
아무리 생각해도 인터페이스를 정의하는 것이 너무 어렵다. 그래서 요즘에는 초기 코딩할 때, 인터페이스에 대해서 생각 자체를 안 한다. 일단 만들고, 겹치는 부분이 생길 때가 되어서야 인터페이스를 정의하고 리팩토링을 시작한다. 일단 동작하는 거부터 만드는 것이 먼저다.
- 메소드 명과 입력, 출력 [본문으로]
'술(述) > 풀이' 카테고리의 다른 글
OCP (0) | 2022.01.04 |
---|---|
SRP (0) | 2021.12.13 |
LSP (0) | 2021.12.10 |
bash 설정 파일 (0) | 2021.12.05 |
code bloat(코드 비대화) (0) | 2021.11.24 |