본문 바로가기
Computer Science/Software Engineering

[Software Engineering] Object-Oriented Design Concepts

by __K.Jun__ 2025. 2. 4.

The 5 Basic Design Priciple for Object-Oriented Design (aka SOLID)

1. SRP: Single-Responsibility Principle

2. OCP: Open-Closed Principle

3. LSP: Liskov Substitution Principle

4. ISP: Interface Segregation Principle

5. DIP: Dependency Inversion Principle

 

The Single-Responsibility Principle (SRP)

클래스는 하나의 책임만 가져야하며, 이를 변경하는 이유도 하나뿐이어야 한다.

The Open-Closed Principle (OCP)

소프트웨어 요소는 확장에는 열려있고, 변경에는 닫혀있어야 한다.

다음은 OCP의 위반 사례이다.

새로운 도형이 추가(확장)되면, DrawAllShapes 함수에 변경도 필요하다.

OCP을 지킨 코드는 다음과 같다.

새로운 도형이 추가(확장)되었지만, DrawAllShape의 함수는 변경이 일어나지 않았다.

The Liskov Substitution Principle (LSP)

자식 클래스는 부모 클래스를 대체하여 사용할 수 있어야 한다.

다음은 LSP의 위반 사례이다.

Square는 Rectangle을 상속받았기 때문에 Rectangle 타입에 대입이 가능하다. 하지만 g함수의 매개변수로 Squere를 넘겨준다면 r.SetHeight(4)로 인해 istWidth와 itsHeight가 같은 값이 되어버리기 때문에 Assertion error가 발생한다. 이는 부모 클래스였으면 에러가 발생하지 않았을 상황이기 때문에, 자식 클래스가 부모 클래스를 대체할 수 없는 상황이다.

이를 고칠 수 있는 방법은 Square와 Rectangle이 모두 Shape라는 클래스를 상속 받도록 하거나, 너비 변경 함수가 높이를 변경하지 않고, 높이 변경 함수가 너비를 변경하지 않도록 하여 각각을 호출하게 하는 것이다. 그리고 사전 조건과 사후 조건을 잘 고려하여 에러가 발생하지 않도록 코딩해야한다.

The Interface Segregation Principle (ISP)

클라이언트는 자신이 사용하지 않는 인터페이스에 의존하지 않아야 한다.

다음은 ISP의 위반 사례이다.

CDServletQuery와 BookServletQuery는 Query 인터페이스에 있는 메서드를 모두 구현할 필요가 없다. 이런 상황에서는 다음과 같이 Query 인터페이스를 상속받는 구체적인 인터페이스를 만들어서 이를 구현하도록 한다.

 

The Dependency Inversion Principle (DIP)

고수준의 모듈은 저수준의 모듈에 의존하지 않고, 둘 다 추상화에 의존해야 한다.

다음은 고수준의 모듈이 저수준의 모듈에 의존하는 DIP 위반 사례이다.

밑에 있는 두 저수준 모듈은 재사용 가능하지만, 상위 모듈은 재사용하기 어렵다.

이 예에서는, Copy라는 고수준 모듈(구현체)이 WitePrinter와 WriteDisk라는 저수준 모듈(구현체)에 의존하고 있는데, 이렇게 되면 저수준의 모듈의 변화가 발생한다면 고수준의 변화도 발생할 가능성이 커진다.

상위의 고수준 모듈이 재사용 가능하고, 저수준 모듈의 변화에 영향을 받지 않도록 하는 방법은 고수준 모듈과 저수준 모듈이 서로 추상화에 의존하도록 하는 방법으로, 다음과 같다.

Copy는 Reader와 Writer라는 추상적인 모듈을 사용하고, 그것의 구현체들은 각각 Keyboard Reader와 Printer Writer가 된다. Copy는 Reader와 Writer가 구체적으로 어떻게 작동하는지 알 필요가 없다. Copy는 Reader와 Writer의 역할만 간단히 아는 상태고, 그것의 구체적 구현을 담당하는 것은 각각 Keyboard Reader와 Printer Writer가 된다. Copy는 Keyboard Reader와 Printer Writer의 구체적 구현에 전혀 신경쓰지 않아도 된다.

이렇게 DIP를 준수하면 고수준 모듈은 구체적 모듈보다 추상적 모듈을 사용하기 때문에 재사용성이 증가하고, 저수준 모듈 변화에 영향을 받지 않는다.

728x90