티스토리 뷰
SOLID란
컴퓨터 프로그래밍에서 SOLID란 로버트 마틴이 2000년대 초반에 명명한 객체 지향 프로그래밍 및 설계의 다섯 가지 기본 원칙을 마이클 페더스가 두문자어 기억술로 소개한 것이다. 프로그래머가 시간이 지나도 유지 보수와 확장이 쉬운 시스템을 만들고자 할 때 이 원칙들을 함께 적용할 수 있다. SOLID 원칙들은 소프트웨어 작업에서 프로그래머가 소스 코드가 읽기 쉽고 확장하기 쉽게 될 때까지 소프트웨어 소스 코드를 리팩터링하여 코드 냄새를 제거하기 위해 적용할 수 있는 지침이다. 이 원칙들은 애자일 소프트웨어 개발과 적응적 소프트웨어 개발의 전반적 전략의 일부다.
https://ko.wikipedia.org/wiki/SOLID_(%EA%B0%9D%EC%B2%B4_%EC%A7%80%ED%96%A5_%EC%84%A4%EA%B3%84)
SOLID (객체 지향 설계) - 위키백과, 우리 모두의 백과사전
ko.wikipedia.org
SOLID 5대 원칙
- 단일 책임 원칙(Single Responsibility Principle) : SRP
- 개방 폐쇄 원칙(Open/Closed Principle) : OCP
- 리스코프 치환 원칙(Liskov Substitution Principle) : LSP
- 인터페이스 분리 원칙(Interface Segregation Principle) : ISP
- 의존관계 역전 원칙(Dependency Inversion Principle) : DIP
5가지의 원칙
단일 책임 원칙(Single Responsibility Principle)
SOLID의 S에 해당하는 원칙은 모든클래스는 단 한개의 책임을 가져야 함
SRP 에서 이야기하는 책임이란, '기능' 정도로 생각하면 된다. 만약 한 클래스가 수행할 수 있는 기능 (책임) 이 여러 개라면, 클래스 내부의 함수끼리 강한 결합을 발생할 가능성이 높아진다.
SRP원칙을 적용하면 응집도는 높고 결합도는 낮은 프로그램을 설계할 수 있을 뿐만 아니라 책임을 적절하게 분배함으로써 코드의 가독성이 높아지고, 유지보수가 용이해지고 다른원칙들을 적용하는데 기초가 된다.
개방 폐쇄 원칙(Open/Closed Principle) : OCP
SOLID의 O에 해당하는 원칙은 확장에는 열려있어야 하고, 변경에는 닫혀 있어야 한다는 원칙이다.
즉 요구사항의 변경이 있더라도 기존 코드를 변경하지 않고 기능 쉽게 확장이 가능하게하여 재사용 할 수 있어야한다.
OCP는 다형성을 활용하여 인터페이스를 구현한 새로운 클래스를 하나 만들어서 새로운 기능을 구현
코드로 예시
class 야스오 extend 캐릭터{
void 찌르기(){
System.out.println("찌르기");
}
void 점멸(){
System.out.println("점멸");
}
}
//game
public void playGame(캐릭터 c){
c.찌리기();
c.점프();
}
위의 캐릭터에 수정이 생기고 찌르기 스킬이 강철 폭풍으로 바뀐다면?
class 야스오 extend 캐릭터{
/*void 찌르기(){
System.out.println("찌르기");
}*/
void 강철폭풍(){
System.out.println("강철폭풍");
}
void 점멸(){
System.out.println("점멸");
}
}
//game
public void playGame(캐릭터 c){
c.찌리기(); //에러가 발생합니다.
c.점프();
}
스킬이 변화에 코드가 문제가 발생한다.
인터페이스로 캐릭터의 스킬
interface 캐릭터(){
public void q();
public void f();
}
interface로 구현을 명령받은 클래스로 캐릭터 구현
class 야스오 implement 캐릭터{
@Override
public void q(){
강철 폭풍();
}
@Override
public void f(){
점멸();
}
private 찌리기(){
System.out.println("찌르기");
}
private 강철 폭풍(){
System.out.println("강철 폭풍");
}
private 점멸(){
System.out.println("점멸");
}
}
interface로 구현을 명령하여 변하는 부분과 변하지 않은 부분을 정확히 나눌 수 있고 이렇게 하면 확장에는 열려있고, 변경에는 닫히게 된다.
리스코프 치환 원칙(Liskov Substitution Principle) : LSP
SOLID의 L에 해당하는 원칙은 하위 타입 객체는 상위 타입 객체에서 가능한 행위를 수행할 수 있어야 한다. 즉 상위타입의 객체를 하위타입의 객체로 치환하더라도 정상적으로 작동해야한다.
인터페이스 분리 원칙(Interface Segregation Principle) : ISP
SOLID의 I의 해당하는 원칙은 한 클래스는 자신이 사용하지 않는 인터페이스는 구현하지 말아야 한다. 하나의 일반적인 인터페이스보다는, 여러 개의 구체적인 인터페이스가 낫다.
ISP와 SRP는 동일한 문제에 대해 다른 해결책을 제시하고 있는 것과 비슷하다. 하나의 클래스가 기능이 비대하다면 책임을 분할하여 이를 갖게하는 것이 SRP이고 비대한 기능을 인터페이스로 분할하여 사용하는 것이 ISP를 의미한다.
ISP에서 주의해야할 사항은 기존 클라이언트에 변화를 주지 않으면서 인터페이스만을 분리하여 구현해야 한다는 점입니다. 그렇게 인터페이스를 분리함으로서 의존성을 약화시켜 리팩토링 및 구조 변경에 용이하게 만들어줍니다.
의존관계 역전 원칙(Dependency Inversion Principle) : DIP
프로그래머는 “추상화에 의존해야지, 구체화에 의존하면 안된다.” 의존성 주입은 이 원칙 을 따르는 방법 중 하나이다.
구체적인 클래스에 의존하지 말고 최대한 추상화한 클래스,인터페이스에 의존하라는 뜻입니다.
즉 클라이언트가 인터페이스에 의존해야 유연하게 구현체를 변경할 수 있다. 만약 구현 클래스에 의존하면 변경이 어려워진다.
public interface Alarm {
String beep();
}
상속받을 Alarm 인터페이스를 만들어줌
/**
* A사의 알람 서비스
*/
public class A implements Alarm {
@Override
public String beep() {
return "beep!";
}
}
/**
* B사의 알림 서비스
*/
public class B implements Alarm {
@Override
public String beep() {
return "beep";
}
}
그후 클래스들이 Alarm을 구현하게 하면 됩니다. 그렇게 되면 서비스 코드를 아래와 같이 변경할 수 있다.
/**
* 서비스 코드
*/
public class AlarmService {
private Alarm alarm;
public AlarmService(Alarm alarm) {
this.alarm = alarm;
}
public String beep() {
return alarm.beep();
}
}
알람 객체는 인터페이스인 Alarm에 의존하기 때문에 AlarmService 기능을 온전히 테스트할수 있다는 장점을 가지게 된다.
정리
이번에 정리하면서 많은것을 다시 되새길 수 있어 좋았습니다.
다향성을 이용하여 애플리케이션 설계를 언제든지 유연하게 변경할 수 있도록 만들도록하고 100% 적용하기엔 어려울지라도 좋은 객체지향프로그래밍을 해야겠다.
'프로그래밍 > 자바-스프링' 카테고리의 다른 글
DTO와 VO (0) | 2022.05.07 |
---|---|
OOP(객체지향프로그래밍)정의 4가지 특성 (0) | 2022.04.24 |