Mathlife
Mathlife의 학습 노트
Mathlife
전체 방문자
오늘
어제
  • 분류 전체보기
    • CS
      • 알고리즘
      • 자료구조
      • 운영체제
      • 네트워크
      • 데이터베이스
    • 프로그래밍 언어
      • Java
      • JavaScript
      • C·C++
      • Python
    • Backend
      • Spring
    • Frontend
      • HTML
      • CSS
    • Math
      • Linear Algebra
      • Calculus
    • AI
      • ML
      • DL
      • RL
    • Git

블로그 메뉴

  • 홈
  • 관리
  • 글쓰기
  • 태그
  • 방명록

공지사항

인기 글

태그

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Mathlife

Mathlife의 학습 노트

SOLID
Backend/Spring

SOLID

2023. 1. 8. 23:40

SOLID는 올바른 객체 지향 설계를 위해 지켜야 할 5가지 원칙이다.

 

SRP (Single Responsibility Principle)

하나의 객체는 하나의 책임만을 가져야 한다.

 

OCP (Open-Closed Principle)

객체는 확장에 대해서는 열려있어야 하고 변경에 대해서는 닫혀있어야 한다. 

 

LSP (Liskov Substitution Principle)

상위 타입 객체를 하위 타입 객체로 완전히 대체할 수 있어야 한다. 

즉, 클라이언트가 상위 클래스의 선언만 보고도 하위 클래스의 객체를 무리 없이 사용할 수 있어야 한다.

 

다음과 같이 자동차 인터페이스가 선언되어 있다고 해보자.

interface Car {
	void moveForward();
    void stop();
}

클라이언트는 Car 인터페이스의 선언부를 보고 'moveForward 메소드를 실행하면 자동차가 앞으로 나아가겠지'라고 기대할 것이다.


따라서 자동차 인터페이스의 구현체를 만드는 사람도 클라이언트의 기대에 부합하도록 moveForward 메소드를 구현해야 한다.

 

예를 들어, 자동차가 대각선 방향으로 나아간다거나 점프를 하면서 앞으로 나아간다면 클라이언트의 기대와 실제 코드의 동작 사이의 차이로 인해 버그가 발생할 수 있을 것이다.

 

 

Bad Example

interface Bird {
    void fly();
}

class Ostrich implements Bird{
	int height;
    
    public void fly() {}
    
    public void getHeight() {
    	return height;
   	}
}

class Eagle implements Bird {
	int height;
    
	public void fly() {
    	height = 10;
    }
    
    public void getHeight() {
    	return height;
   	}
}

class Client {
	public void test {
    	Bird[] birds = new Bird[2];
        birds[0] = new Ostrich();
        birds[1] = new Eagle();
        
        for (Bird bird : birds) {
        	bird.fly();
            System.out.println(bird.getHeight());
        }
    }
}

 

Bird 타입 birds[1] 객체를 Ostrich 객체로 대체할 수 없다.

 

 

Good Example

interface Bird {}

interface FlyingBird extends {
	void fly();
}

class Ostrich implements Bird{}

class Eagle implements FlyingBird {
	int height;
    
	public void fly() {
    	height = 10;
    }
    
    public void getHeight() {
    	return height;
   	}
}

class Owl implements FlyingBird {
	int height;
    
	public void fly() {
    	height = 5;
        height = 10;
    }
    
    public void getHeight() {
    	return height;
   	}
}

class Client {
	public void test {
    	FlyingBird[] birds = new FlyingBird[2];
        birds[0] = new Eagle();
        birds[1] = new Owl();
        
        for (FlyingBird bird : birds) {
        	bird.fly();
            System.out.println(bird.getHeight());
        }
    }
}

FlyingBird 타입 birds[0] 객체를 Owl 객체로 대체할 수 있다.

 

ISP(Interface Segregation Principle)

인터페이스를 잘게 쪼개서 되도록 클라이언트가 자신이 사용하지 않는 메서드에 노출되지 않도록 해야 한다.

 

Bad Example

interface IShape {
	int getRadius();
    int getWidth();
}

class Shape implements IShape {
	int width;
    int radius;
    
    public Shape(int width, int radius) {
    	this.width = width;
        this.radius = radius;
    }
    
    public int getWidth() {
    	return width;
    }
    
    public int getRadius() {
    	return radius;
    }
}

class Client {
	public void useSquare() {
   		IShape sqaure = new Shape(10, 0);
        System.out.println("정사각형의 너비: " + square.getWidth());
    }
}

클라이언트는 정사각형만 사용하지만 radius 필드와 getRadius 메소드에 대해서도 알게 된다.

 

Good Example

interface ISquare {
    int getWidth();
}

interface ICircle {
	int getRadius();
}

class Square implements ISquare {
	int width;
    
    public Square(int width) {
    	this.width = width;
    }
    
    public int getWidth() {
    	return width;
    }
}

class Circle implements ICircle {
	int radius;
    
    public Circle(int radius) {
    	this.radius = radius;
    }
    
    public int getRadius() {
    	return radius;
    }
}

class Client {
	public void useSquare() {
   		ISquare sqaure = new Square(10);
        System.out.println("정사각형의 너비: " + square.getWidth());
    }
}

 

DIP(Dependency Inversion Principle)

implementation에 의존하지 않고 abstraction에 의존해야 한다.

 

예를 들어, 어떤 연극 작가가 특정 배우의 이미지에 딱 맞는 각본을 작성했다고 해보자.

이때 해당 배우가 하차한다면 큰 문제가 발생할 수 있다.

 

따라서 작가는 이런 경우를 대비해 배역 자체에만 충실한 각본을 작성해야 한다.

즉, 작가는 배우가 아닌 배역에 의존해야 하는 것이다.

 

'Backend > Spring' 카테고리의 다른 글

다형성 (Polymorphism)  (0) 2023.01.07
    'Backend/Spring' 카테고리의 다른 글
    • 다형성 (Polymorphism)
    Mathlife
    Mathlife

    티스토리툴바