Java 프로그래밍기초 230223 #11 객체지향 설계의 5원칙 SOLID

김춘복·2023년 2월 22일
0

Java 공부

목록 보기
14/20

SOLID

  • 객체지향 설계의 5원칙(SOLID)

    SRP(Single Responsibility Principle): 단일 책임 원칙
    OCP(Open-Closed Principle): 개방-폐쇄 원칙
    LSP(Liskov Substitution Principle): 리스코프 치환 원칙
    ISP(Interface Segregation Principle): 인터페이스 분리 원칙
    DIP(Dependency Inversion Principle): 의존성 역전 원칙

절차적/구조적 프로그래밍

  • 절차적 프로그래밍 : 개체를 순차적으로 처리해 프로그램 전체가 유기적으로 연결되도록 개발
    대표적으로 C언어가 절차적 프로그래밍이다.

  • 장점 : 컴퓨터의 작업 처리 방식과 유사해 실행속도가 빠르다.

  • 단점
    : 모든 구성요소가 유기적으로 연결되어 유지보수가 어렵다. 하나가 고장나면 시스템 전체가 고장.
    실수했을때 모든 코드에 영향이 간다. 융통성이 떨어져 효율이 떨어진다.
    순서가 정해져있어 가독성이 떨어지고 비효율적이다. 코드 순서가 바뀌면 결과가 달라진다.

  • 구조적 프로그래밍 : '함수를 사용해서 개발'. 중복코드를 한 곳에 모아 관리할 수 있다.

객체지향

: 우리가 주변사물을 인지하는 것 처럼 프로그래밍하기 위해 고안. java, C++, 파이썬 등
프로그램을 다수의 객체로 만들고 서로 상호작용하도록 만드는 프로그래밍 언어.

  • 장점
    : 생산성증가(문제 생긴 객체만 고치면 되니 유지보수 용이)
    재사용성(상속이 가능). 자연스러운 모델링(실제 세상과 닮아있음)
  • 단점 : 느린 개발속도. 느린 실행속도. 높은 난이도.

객체지향의 4대 특성
캡슐화 : 정보의 은닉.
상속 : 코드의 재사용성 증가. 상속관계로 묶어 체계화된 구조
추상화 : 공통되고 중요한것 모델링. 복잡한 내부를 안보고 외부에 노출된 코드에 집중 가능.
다형성 : 사용의 편의. 하나의 행위가 각 객체가 가진 고유 특성에 따라 여러형태로 재구성.


단일 책임 원칙

: Single Responsibility Principle, SRP

  • 하나의 객체는 단 하나의 책임을 가져야 한다.
    하나의 클래스는 단 한개의 책임을 가져야한다. 클래스를 변경하는 이유는 단 하나여야한다.
    한 클래스에 여러 책임이 따르면 클래스의 변경이 너무 많은 영향을 끼칠 수 있다.
    유지보수의 효율성을 위해 책임을 쪼개어 분리시킬 필요가 있다.

개방-폐쇄 원칙

: Open-Closed Principle, OCP

  • 자신의 확장에 있어서는 열려있어야 하고, 주변의 변경에 대해서는 닫혀있어야 한다.
    확장에 대해서 열려있다 : 요구사항이 변경될 때 새로운 동작을 추가해 기능을 확장할 수 있다.
    변경에 대해서 닫혀있다 : 기존 코드를 수정하지 않고 동작을 추가하거나 변경할 수 있다.
    즉, 기존 코드를 바꾸지않고 기능을 수정하거나 추가할 수 있도록 설계해야한다.

  • ex) java의 DB연결
    java에는 db에 접속할 수 있게 도와주는 JDBC라는 API가 있다.
    개발 진행중 db를 다른 업체로 변경하더라도 개발하던 코드를 변경할 필요 없이 connection을 담당하는 id pwd url만 바꾸면 쉽게 db를 바꿀 수 있다.

  • 추상화(인터페이스)와 다형성(상속)을 통해 구현할 수 있다. 자주 바뀌는 부분을 추상화함으로써 기존 코드를 바꾸지 않고 기능을 확장시킬 수 있게해 유연함을 높이는 것이 핵심.


리스코프 치환 원칙

: Liskov Substitution Principle, LSP

  • 서브타입은 언제나 자신의 기반 타입(base type)으로 교체할 수 있어야 한다.
    하위클래스의 인스턴스는 상위형 객체 참조변수에 대입해 상위클래스의 인스턴스 역할을 하는데 문제가 없어야 한다.

  • 즉, 하위타입은 상위타입을 대체할 수 있어야 한다.
    상위타입을 하위타입으로 대체해도 클라이언트가 차이점을 인식하지 못해야 한다.
    하위 타입 객체는 상위 타입 객체에서 가능한 행위를 수행할 수 있어야 한다.
    대체가능성을 결정하는건 해당 객체를 이용하는 클라이언트의 기준이다.

  • 상속관계가 아닌 클래스들을 상속관계로 설정하면 이 원칙이 위배된다.
    결국 LSP를 지키지 않으면 OCP가 위반된다. 기능확장을 위해 기존 코드를 여러번 수정해야하니까.
    애초에 설계할때 상속관계를 잘 정의해 LSP가 위배되지 않게 해야한다.


인터페이스 분리 원칙

: Interface Segregation Principle, ISP

  • 클라이언트는 자신이 사용하지 않는 메서드에 의존관계를 맺으면 안된다.
    '특정 클라이언트를 위한 인터페이스 여러개가 범용 인터페이스 하나보다 낫다'
    클라이언트가 필요하지 않는 기능을가진 인터페이스에 의존하면 안되고 최대한 인터페이스를 작게 유지해야한다.

  • 목적과 관심이 각기 다른 클라이언트가 있다면 인터페이스를 통해 적절하게 분리해줄 필요가 있다. 클라이언트의 목적과 용도에 적합한 인터페이스 만을 제공해야한다.

  • SRP와 ISP는 같은 문제에 대한 두가지 다른 해결책. 특별한경우가 아니면 SRP가 우선.
    상위클래스는 풍성할수록 좋다. 하위클래스에게 많은 기능을 확장시켜주고 형변환, 코드중복을 줄여준다.

  • 인터페이스 내에 메소드는 최소한일수록 좋다.
    인터페이스는 하위클래스에게 구현을 강제하는 역할. 최소한의 기능만 제공하고 하나의 역할에 집중해라


의존성 역전 원칙

: Dependency Inversion Principle, DIP

고차원 모듈은 저차원 모듈에 의존하면 안된다. 두 모듈 모두 다른 추상화된 것에 의존해야 한다.
추상화된 것은 구체적인것에 의존하면 안된다. 구체적인 것이 추상화된 것에 의존해야 한다.
자주 변경되는 구체적인 클래스에 의존하지 마라.

  • 세부적인 사항은 추상화에 의존해야 한다.
    변하기쉬운 것(구체적인 것)보다 변하기 어려운 것(추상적인 것)에 의존해야 한다.
    하위클래스보다 상위 클래스나 인터페이스에 의존하게 함으로써, 하위클래스의 변화가 생겨도 영향을 받지 않게해야 한다. 상위클래스일수록, 인터페이스일수록, 추상클래스일수록 변하지 않을 가능성이 높기때문이다.

  • 자신보다 변하기 쉬운 것에 의존하던 것을 추상화된 인터페이스나 상위 클래스를 두어 변하기 쉬운 것의 변화에 영향받지 않게 하는 것

SOLID 총 정리

참고 사이트

OCP : 1. 자주 변하는 부분을 추상화하고 2. 다형성을 이용3. 기존 코드는 안건들이면서 기능확장에는 용이하게 한다.
DIP : 1. 자주 변하는 부분을 추상화할 수 있도록 도와주는 원칙.
LSP : 2. 다형성을 이용하는데 도움을 주는 원칙.

SRP : 객체가 하나의 책임만 갖도록 한다.
ISP : 클라이언트마다 특화된 인터페이스를 구현하게 한다.
SRP와 ISP는 객체가 커지는 것을 막아 한 기능의 변경이 끼치는 영향을 최소화하면서
3. 기존 코드는 안건들이면서 기능확장에는 용이하게 하는데 도움을 주는 원칙.

profile
Backend Dev / Data Engineer

0개의 댓글