SOLID
SOLID
Readable Code: 읽기 좋은 코드를 작성하는 사고법를 듣고 요약한 내용입니다.
객체 설계하기
객체로 추상화하기
- 비공개 필드(데이터), 비공개 로직(코드)
- 공개 메서드 선언부를 통해 외부 세계와 소통
- 각 메서드의 기능은 객체의 책임을 드러내는 창구이다.
- 객체의 책임이 나뉨에 따라 객체간 협력이 발생
객체가 제공하는 것
- 절차 지향에서 잘 보이지 않았던 개념을 가시화
- 관심사가 한 군데로 모이기 때문에, 유지보수성이 올라간다.
- ex) 객체 내부에서 객체가 가진 데이터의 유효성 검증 책임을 가질 수 있다.
- 여러 객체를 사용하는 입장에서는, 구체적인 구현에 신경 쓰지 않고 보다 높은 추상화 레벨에서 도메인 로직을 다룰 수 있다.
새로운 객체를 만들 때 주의할 점
- 1개의 관심사로 명확하게 책임이 정의되었는지 확인하기
- 메서드를 추상화 할 때와 유사.
- 객체를 만듦으로써 외부 세계와 어떤 소통을 하려고 하는지 생각해야함.
- 생성자, 정적 팩토리 메서드에서 유효성 검증이 가능
- 도메인에 특화된 검증 로직이 들어갈 수 있다.
- 밖에서 도메인을 사용하는 입장에서는 유효성에 대해 신경 쓸 필요 없다.
- setter 사용 자제
- 데이터는 불변이 최고다.(변하는 데이터는 사이드 이펙트가 존재) 데이터가 변하더라도 객체가 핸들링할 수 있어야 한다.
- 객체 내부에서 외부 세계의 개입 없이 자체적인 변경/ 가공으로 처리할 수 있는지 확인해야함.
- 외부에서 가지고 있는 데이터로 변경해야하는 경우,
set~
보다는update~
같이 의도를 드러내야 한다.
- getter 사용 자제
- 외부에서 객체 내 데이터가 필요하다고 판단될 때 사용하자.
- BAD :
person.get지갑().get신분증().findAge() ≥ 19
- GOOD :
person.isAgeGreaterThanOrEqualTo(19)
- getter 가 남발되면 캡슐화가 무의미해진다.
- 필드의 수는 적을수록 좋다.
- 불필요한 데이터가 많을수록 복잡도가 높아지고 대응할 변화가 많아진다.
- 필드 A를 가지고 계산할 수 있는 A필드가 있다면, 메서드 기능으로 제공
- 단, 미리 가공하는 것이 성능 상 이점이 있다면, 필드로 가지고 있는 것이 좋을 수도 있다.
- 상황에 맞게 잘… 어렵군…
SRP: Single Responsibility Principle
- 하나의 클래스는 단 한 가지의 변경 이유(책임)만을 가져야 한다.
- 객체가 가진 공개 메서드, 필드, 상수 등은 해당 객체의 단일 책임에 의해서만 변경되는가?
- 관심사의 분리
- 높은 응집도
- 응집도란 클래스나 모듈내의 요소들이 서로 긴밀하게 연관되어 있는 정도
- 낮은 결합도
- 결합도란 두 개 이상의 객체가 협력 관계에 있을 때, 한 객체가 다른 객체가 영향받는 정도
- 책임을 발견하는 것이 어렵다. 경험의 영역
OCP: Open-Closed Principle
- 확장에는 열려있고, 수정에는 닫혀야 한다.
- 기존 코드의 변경 없이, 시스템의 기능을 확장할 수 있어야 한다.
- 추상화와 다형성을 활용하여 OCP를 지킬 수 있다.
LSP: Liskov Substitution Principle
- 상속 구조에서, 부모 클래스의 인스턴스를 자식 클래스의 인스턴스로 치환할 수 있어야 한다.
- 자식 클래스는 부모 클래스의 책임을 준수하며, 부모 클래스의 행동을 변경하지 않아야 한다.
- LSP를 위반하면, 상속 클래스를 사용할 때 오동작, 예상 밖의 예외가 발생하거나, 이를 방지하기 위한 불필요한 타입 체크가 동반될 수 있다.
ISP: Interface Segregation Principle
- 클라이언트는 자신이 사용하지 않는 인터페이스에 의존하면 안된다.
- 인터페이스를 쪼개야한다.
- ISP를 위반하면, 불필요한 의존성으로 인해 결합도가 높아지고, 특정 기능의 변경이 여러 클래스에 영향을 미칠 수 있다.
DIP: Dependency Inversion Principle
- 상위 수준의 모듈은 하위 수준의 모듈에 의존해서는 안된다. 둘 모두 추상화에 의존해야 한다.
- 의존성이란? 어떤 한 모듈이 다른 모듈을 참조하는 것
- 의존성의 순방향: 고수준 모듈이 저수준 모듈을 참조하는 것
- 의존성의 역방향: 고수준, 저수준 모듈이 모두 추상화에 의존하는 것
- 저수준 모듈이 변경되어도, 고수준 모듈에는 영향이 가지 않는다.
This post is licensed under CC BY 4.0 by the author.