객체 지향 5대 원칙 - SOLID
단일 책임의 원칙 (SRP, Single Responsibility Principle)
[!info] 한 클래스는 하나의 책임만 가져야 한다.
- 어떤 코드를 어디에 두어야 하는가?를 결정할 때 많이 도움이 되는 원칙.
- ‘그 클래스를 변경해야 하는 상황,원인,이유가 딱 한가지 인지’ 를 보면, 단일 책임으로 제대로 분리되었는지를 확인할 수 있다.
- 지키지 않는 경우 3.7 뒤엉킨 변경 문제가 발생한다.
- 클래스는 그 책임을 완전히 캡슐화해서 제공해야 한다.
- 어떤 클래스에 변경이 발생했을 때, 변경이 발생했다는 그 이유만으로 다른 클래스에도 변경이 발생해야하는 상황이 있어서는 안된다는 것이다. (어떤 사유로 내부 로직을 변경했다면, 거기서 끝나야 한다는 의미)
- 지키지 않는 경우 3.8 산탄총 수술 문제가 발생한다.
- 아무튼 가장 기본이 되는 원칙은 ‘함께 변경할 대상을 한데 모으는 것 ‘ 이다.
인터페이스 분리 원칙 (ISP, Interface Segregation Principle)
[!info] 클라이언트 코드는 자신이 사용하지 않는 메서드에 의존하지 않아야 한다.
- 이를 위해서는 프로그램을 작은 단위의 인터페이스들로 구성해야 한다.
- 그래야 클라이언트가 자신이 필요한 인터페이스로 객체를 참조하여 사용할 수 있으니까. (= 필요 없는 메서드 의존 X)
- 그래서,특정 클라이언트를 위한 (작은) 인터페이스 여러 개가 범용 인터페이스 하나 보다 낫다.
의존성 역전 원칙 (DIP, Dependency Inversion Principle)
[!info] 일반적인 의존성 설정 방향과 반대로, 역방향 의존성을 가지도록 해서 상위 모듈이 하위 모듈에서 완전히 독립 할 수 있도록 한다.
- 상위 모듈이 하위 모듈을 use 하는 일반적인 구조에서, 상위 모듈은 하위 모듈을 참조 (의존) 한다.
이 때 상위 모듈이 인터페이스 없이 하위 모듈을 직접 참조하면, 상위 모듈은 하위 모듈의 구현에 의존하게 된다.
- 반면 DIP를 따라 하위모듈이 상위모듈에서 필요로 하는 기능을 참조(의존) 하게끔 설계하게 된다면, 상위 모듈은 하위 모듈의 구현이 어떻게 되어 있든 그로부터 완전히 자유롭다.
- 이처럼 상위 계층이 하위 계층에 의존하는 전통적인 의존 관계를 반전 시킴으로써, 상위 계층이 하위 계층의 구현으로부터 독립하기 위한 원칙이기 때문에, 의존성 역전 원칙 이라는 이름을 가지고 있다.
- 꼭 클래스 단위에 국한된 얘기는 아니고, 모듈이나 계층, 설계 전반적으로도 적용할 수 있는 원칙이다.
개방 폐쇄의 원칙 (OCP, Open/Closed Principle)
[!info] 소프트웨어 구성요소(모듈, 클래스, …)는
확장에는 열려 있어야 하고(쉬운 확장),
변경에는 닫혀 있어야 한다.(내부 구조를 변경할 필요 X)
- 예를 들어, 어떤 라이브러리가 인터페이스를 참조하고 있다면, 그 인터페이스를 구현한 클래스를 내가 직접 만들 수 있다.
- 이런 설계가 확장에는 열려 있고, 내부 구조는 변경할 필요 없는 닫혀있는 구조다.
리스코프 치환의 원칙 (LSP, Liskov Substitution Principle)
- 넓게는 다형성, 즉 “상위 타입 변수를 사용하는 곳에 하위 타입을 넘겨도 문제 없이 동작 할 수 있어야 한다 .” 의미라고 보면 된다.
- 단순히 타입 치환 뿐만 아니라, 프로그램의 정확성을 깨뜨리지 않기 위한 몇 가지 제약조건 이 있다.
- 예시 : 직사각형을 상속한 정사각형
- 정사각형은 직사각형이다. (true) 그러나 정사각형이 직사각형을 상속하는 상황을 생각해보면…
- 정사각형의 width, height setter는 어떻게 될 것 같은가?
- setter를 고려했을 때, 정사각형 인스턴스가 직사각형 변수에 담기면 어떻게 되는가?
- 직사각형을 파라미터로 받아 높이를 늘려주는 메서드에 정사각형을 넘기면 어떻게 되는가?
- 정사각형은 개념적으로는 직사각형이지만, 직사각형을 상속하면 LSP 위반 한다는 것을 알 수 있다.
- 단, 정사각형, 직사각형이 불변 객체라면 이런 문제가 발생하지 않으므로 LSP 위반이 아니다.
- 자식클래스에서 부모클래스의 메서드를 override 할 때, 더 느슨한 가시성 접근자로 open하는 것은 가능하지만, 더 엄격한 가시성 접근자를 사용하여 close하는 것은 불가능한 것은 이 때문이다.
- https://stackoverflow.com/questions/17510152/why-cant-we-assign-weaker-privilege-in-subclass
- 만약 자식클래스에서 더 엄격한 가시성 접근자를 써서 닫을 수 있다고 가정하면…
SuperClass obj = new SubClass()
처럼 담아,java obj.부모는_public_자식은_private()
호출하게 되면?- 실제 인스턴스는 자식클래스이기 때문에 private인 자식 클래스의 메서드가 호출되어야 한다. => private이지만 외부 호출이 가능하게 되므로 모순.
This post is licensed under CC BY 4.0 by the author.