콘텐츠로 이동

2021 03 01

2021-03-01

설계 원칙: SOLID

  • Single Responsibility Principle (단일 책임 원칙) - 클래스는 단 한 개의 책임을 가져야 한다 - "클래스를 변경하는 이유는 단 한 개여야 한다" - 한 클래스에 섞여 있던 책임을 두 클래스로 분리해, 변경의 여파를 줄이자 - SRP가 위배 된다면... - 재사용이 어렵다 - 한 책임의 구현 변경에 의해 다른 책임과 관련된 코드가 변경될 가능성이 높아진다
  • Open-Closed Principle (개방 폐쇄 원칙) - 확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 한다 - 기능을 변경하거나 확장할 수 있으면서, - 그 기능을 사용하는 코드는 수정하지 않는다. - 추상화와 다형성을 이용해 개방 폐쇄 원칙을 구현한다 - 상속/인터페이스 등을 통해서 확장에 유리한 코드 작성 가능 - 변화되는 부분을 추상화 함으로써, 변화를 고정시킨다 - 변화가 예상되는 것을 추상화해서 변경의 유연함을 얻도록 해줌
  • Liskov Substitution Principle (리스코프 치환 원칙) - 상위 타입의 객체를 하위 타입의 객체로 치환해도, 상위 타입을 사용하는 프로그램은 정상적으로 동작해야 한다. - 다형성에 관한 원칙 - 정사각형 vs 직사각형... 클래스를 상속받아 구현하기 보다는 별개의 타입으로 구현해줄 것! - 위반 사례 - 명시된 명세에서 벗어난 값을 리턴 - 명시된 명세에서 벗어난 익셉션을 발생 - 명시된 명세에서 벗어난 기능을 수행 - 하위 타입은 상위 타입에서 정의한 명세를 벗어나지 않는 범위에서 구현해야 한다! - LSP는 확장에 대한 것... 위배시 OCP도 위배하는 경우 다수 - instanceof 연산자를 사용한다는 것은 확장에 닫혀있다는 뜻... BAD smell - 이는 곧 추상화가 덜 되었다는 뜻 - 변화되는 부분을 상위 타입에 추가하여, instanceof를 줄여보자!
  • Interface Segregation Principle (인터페이스 분리 원칙) - 인터페이스는 그 인터페이스를 사용하는 클라이언트를 기준으로 분리해야 한다. (C계열에서 더 돋보임) - 자신이 사용하는 메서드에만 의존해야 한다! - 클라이언트가 사용하는 기능을 중심으로 인터페이스를 분리할 것 - 클라이언트로 부터 발생하는 인터페이스 변경의 여파가 다른 클라이언트에게 미치지 않도록 할 것!
  • Dependency Inversion Principle (의존 역전 원칙) - 고수준 모듈은 저수준 모듈의 구현에 의존해서는 안 된다 - 저수준 모듈이 고수준 모듈에서 정의한 "추상 타입"에 의존해야 한다. - 전략 패턴 생각하면 좋음 - 런타임의 의존이 아닌, 소스 코드의 의존을 역전시킴으로써 변경의 유연함을 확보 - 고수준 모듈 - 어떤 의미 있는 단일 기능을 제공하는 모듈 - ex) 바이트 데이터를 읽어와 암호화 하고, 결과 바이트 데이터를 쓴다 - 저수준 모듈 - 고수준 모듈의 기능을 구현하기 위해 필요한 하위 기능의 구현 - ex) 파일에서 바이트 데이터 읽기 / AES 알고리즘으로 암호화 / 파일에 바이트 데이터 작성 - 타입 소유 역전을 하지 않을 경우, 상세 구현의 독립적 배포가 안 됨
  • SOLID 정리 - 정의: 변화에 유연하게 대처할 수 있는 설계 원칙 - SRP, ISP: 객체가 커지지 않도록 막아줌... 객체가 많은 기능을 가지면, 변경 여파가 다른 기능에까지 번지고 영향 - LSP, DIP: OCP 지원... 변화되는 부분을 추상화하고, 다형성을 이용해 기능을 확장하면서, 기존 코드를 수정하지 않도록 함
    - 사용자 입장에서의 기능 사용을 중시!