SOLID

JJ·2024년 7월 15일

backEnd

목록 보기
8/16
post-thumbnail

SOLID란,

객체지향을 배우다보면 마주치게 되는 SOLID 무슨 의미일까?
간단하게 말하면 객체지향 설계에서 지켜야하는 5가지 소프트웨어 개발 원칙이다.
여러 디자인패턴들의 기반이 되는만큼 알아둬야 할 가치가 있는 개념이다.

SOLID 구성

주문자약어
SSRP(single responsibility principle)
단일책임 원칙한 클래스는 하나의 책임만 가져야한다.
OOCP(open/closed principle)
개방/폐쇄 원칙소프트웨어 요소는 확장에는 열려있으나 변경에는 닫혀있어야 한다.
LLSP(liskov substitution principle)
리스코프 치환 원칙프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으며 하위타입의 인스턴스로 바꿀 수 있어야 한다.
IISP(interface segregation principle)
인터페이스 분리 원칙특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.
DDIP(dependency inversion principle)
의존관계 역전 원칙프로그래머는 추상화에 의존해야지 구체화에 의존하면 안된다. 의존성 주입은 이 원칙을 따르는 방법 중 하나다.

SRP(single responsibility principle)

한 클래스는 하나의 책임(기능)만 가져야 한다.
내가 작성한 코드를 참고해보면,

[계산을 담당하는 Calculate 클래스]

public class Calculate {
    public int calculateSum(int firstNum, int secondNum) {
        int sum = firstNum + secondNum;
        return sum;
    }
}

[계산기의 입출력을 담당하는 View 클래스]

public class View {
    int firstNum;
    int secondNum;

    public int[] insertNumbers() {
       Scanner sc = new Scanner(System.in);

        System.out.print("정수 두 개를 입력해주세요: ");

        firstNum = sc.nextInt();
        secondNum = sc.nextInt();
        
        int[] numbers = {firstNum, secondNum};
        return numbers;
    }

    
    public void printSum(int sum) {
        System.out.println("결과는 " + sum);

    }
}

연산 기능과 입출력을 담당하는 기능을 클래스를 분리함으로써 기능 수정으로 인한 연쇄작용을 예방할 수 있다. 한마디로 유지보수가 용이해진다.

OCP(open closed principle)

소프트웨어 요소는 변경에는 닫혀있어야하지만 확장에는 열려있어야 한다는 원칙이다.
확장(기능 추가 등)은 손쉽게 할 수 있어야 하지만, 그 과정에서 기존의 코드의 수정은 되도록 하지 말아야 한다는 원칙이다.

[Animal.java]

public abstract class Animal {
	public abstract void sayHello();
}

[Cat.java]

public class Cat extends Animal {
	@Override
    public void sayHello() {
    	System.out.println("meow i'm cat");
    }
}

위 코드를 보면 추상화 클래스 Animal을 상속받은 Cat은 기능 확장을 손쉽게 하고 있고 Animal 코드의 수정은 하지 않고 있다. ocp 원칙을 지킨 코드라고 볼 수 있다.

LSP(liskov substitution principle)

자료형 A가 자료형 B의 하위형이면, 자료형 B의 객체는 자료형 A의 객체로 교체할 수 있어야 한다는 원칙이다.
자바에서 예시를 찾아보면 상속관계에서 부모 클래스를 자식 클래스로 교체할 수 있어야 LSP 원칙을 지켰다고 볼 수 있다.

[Shape.java]

public class Shape {
    private int width;
    private int height;
    
    public void setWidth(int width) {
        this.width = width;
    }

    public int getWidth() {
        return width;
    }
    
    public void setHeight(int height) {
        this.height = height;
    }
    
    public int getHeight() {
        return height;
    }
    
    public int getArea() {
        return width * height;
    }
}

[Retangle.java]

public class Rectangle extends Shape {
    public Rectangle(int width, int height) {
        setWidth(width);
        setHeight(height);
    }

}

[Square.java]

public class Square extends Shape{
    public Square(int length) {
        setWidth(length);
        setHeight(length);
    }
}

[Main.java]

public class Main {
    public static void main(String[] args) {
        Shape rectangle = new Rectangle(10, 5);
        Rectangle rectangle2 = new Rectangle(10, 5);
        Shape square = new Square(5);
        Square square2 = new Square(5); 
        
        System.out.println(rectangle.getArea()); //50 출력
        System.out.println(rectangle2.getArea()); //50 출력
        System.out.println(square.getArea()); //25 출력
        System.out.println(square2.getArea()); //25 출력
    }
}

ISP(interface segregation principle)

인터페이스는 가능한 작게 최소한의 기능만 담게 잘라야 한다는 원칙이다. 어느정도로 작게인지를 생각해보면 그 인터페이스를 사용하는 객체가 원하는 기능만을 담고 있을 정도로 작게라고 나는 생각한다.
ISP를 지킬 경우 불필요한 코드 작성을 줄일 수 있으며 인터페이스 수정 시에 연쇄적으로 이어지는 코드 수정을 줄일 수 있다.

DIP(dependency inversion principle)

고수준 모듈(인터페이스/추상 클래스)은 저수준 모듈(객체)에 의존해서는 안되는데 그를 위해서는 구체화 말고 추상화에 집중해야 한다고 말하는 원칙이다.
더 자세히 얘기해보면 저수준 모듈이 고수준 모듈의 추상 타입에 의존해야 한다는 말이다.

일상생활에서 예시를 들어보면,
사람이 노란색 모자를 쓴다고 할 때 Person이 yellowHat이라는 구체적인 객체에 의존하면 DIP을 지키지 못한 것이다.

public class Person {
    private YellowHat hat;

    public void wearYellowHat(YellowHat hat) {
        this.hat = hat;
    }
}

위 코드를 봐보면 빨간색이나 초록색 등 다른 색 모자를 쓰고 싶으면 Person에 GreenHat, RedHat 등의 요소와 wearGreenHat() 등의 메소들을 추가해주는 등 코드 수정을 해줘야 한다.

DIP을 지켜서 YellowHat, RedHat 등 구체적인 객체말고 Hat이라는 추상 클래스와 Person이 의존 관계를 갖고 YellowHat, RedHat 등의 구체적인 객체들도 Hat에 의존하면 Person의 수정없이 구체적인 객체를 추가해줄 수 있다.

profile
🎀👩🏻‍💻✨🐾🌷🦅

0개의 댓글