객체 지향 SOLID 5원칙

정종일·2023년 9월 25일
0

Develop

목록 보기
5/5
post-thumbnail
💡 SOLID 5원칙이란 객체지향 설계에서 지켜야 할 5가지 소프트웨어 개발 원칙을 의미한다

1. SRP(Single Responsibility Principle)

정의

💡 하나의 클래스(객체)는 단 하나의 책임만 가져야 한다

하나의 클래스는 하나의 기능을 담당해 기능 수행에 있어 하나에 집중하도록 설계하는 원칙

효과

✅ 한 책임의 변경으로부터 다른 책임의 변경으로의 연쇄작용 극복

✅ 프로그램의 유지보수성 증가

다만 책임의 범위는 명확히 정해져있는 것이 아니라 개발자에 따라 기준이 달라질 수 있다

2. OCP(Open Closed Principle)

정의

💡 확장에 열려있고 수정에는 닫혀있어야 한다

기능을 추가할 때 클래스 확장을 통해 손쉽게 구현하며 확장에 따른 클래스 수정은 최소화

효과

✅ 새로운 변경 사항이 발생했을 때 유연하게 코드를 추가함으로써 큰 힘을 들이지 않고 애플리케이션의 기능을 확장할 수 있음

✅ 새로운 변경 사항이 발생했을 때 기능을 사용하는 부분에 대한 직접적인 수정이 필요 없음

즉, 다형성과 확장을 가능하게 하는 객체지향의 장점을 극대화하는 설계 원칙

interface PaymentMethodInterface {
	public function acceptPayment($receipt);
}

class CashPaymentMethod implements PaymentMethodInterface{
	public function acceptPayment($receipt) {
		//
	}
}

class Checkout {
	public function begin(Receipt $receipt, PaymentMethodInterface $payment) {
		$payment->acceptPayment($receipt);
	}
}

3. LSP(Liskov Substitution Principle)

정의

💡 객체의 서브 타입은 언제나 기반(부모) 타입으로 교체할 수 있어야 한다

다형성의 원리를 이용하기 위한 원칙으로 상위 클래스 타입으로 객체를 선언해 하위 클래스의 인스턴스를 받으면 업캐스팅된 상태에서 부모의 메서드를 사용해도 동작이 의도대로 흘러가야 함

효과

✅ 다형성의 원리를 이용해 객체 지향적 개발이 가능하다

✅ OCP 원칙을 준수할 수 있다

부모 객체와 자식 객체의 리턴 타입이 다른 것도 리스코프 치환 원칙에 위배된다.
상속관계에서는 꼭 일반화 관계 (IS-A)가 성립해야 한다

4. ISP(Interface Segregation Principle)

정의

💡 인터페이스를 각 용도에 맞게 잘 분리하자는 설계 원칙

구현체가 필요하지 않은 메서드를 구현하지 않도록 하는 원칙

효과

✅ 인터페이스를 사용하는 클라이언트를 기준으로 분리함으로써, 클라이언트의 목적과 용도에 적합한 인터페이스만을 제공 가능하다

한 번 인터페이스를 분리해 구성하면 이후 수정하거나 분리하는 행위를 하지 말아야 한다

5. DIP(Dependency Inversion Principle)

정의

💡 상위 모듈은 하위 모듈에 의존해서는 안 된다. 단순히 하위 모듈을 추상화시킨 개념에 의존하는 것이 아니라 두 모듈 모두 인터페이스 혹은 추상클래스에 의존해야 한다.

의존 관계를 맺을 때 변화하기 쉬운 것보다는 변화하지 않는 것에 의존하라

효과

✅ 확장하기 용이한 구조를 가지고 있다

✅ 객체 간의 의존도가 느슨해진다

package solid.dip;

class SamsungPay implements Pay {
    @Override
    public String payment() {
        return "samsung";
    }
}
------------------------------------------------

package solid.dip;

public class KakaoPay implements Pay {
    @Override
    public String payment() {
        return "kakao";
    }
}

------------------------------------------------

package solid.dip;

public class PayService {
    private Pay pay;

    public void setPay(final Pay pay) {
        this.pay = pay;
    }

    public String payment() {
        return pay.payment();
    }
}

------------------------------------------------

class PayServiceTest {
    private PayService payService = new PayService();

    @Test
    void 삼성페이가_올바르게_결제되는지_테스트() {
        /* Given */
        Pay samsungPay = new SamsungPay();
        /* When */
        payService.setPay(samsungPay);
        /* Then */
        assertThat(payService.payment()).isEqualTo("samsung");
    }

    @Test
    void 카카오페이가_올바르게_결제되는지_테스트() {
        /* Given */
        Pay kakaoPay = new KakaoPay();
        /* When */
        payService.setPay(kakaoPay);
        /* Then */
        assertThat(payService.payment()).isEqualTo("kakao");
    }
}
profile
제어할 수 없는 것에 의지하지 말자

0개의 댓글