리팩토링 하며 생각한 것들
- 컨트롤러 레이어에서 다른 서비스에 대해 의존성을 많이 갖는것보다는 서비스 레이어에서 다른 서비스 레이어에 대해 의존성을 갖는게, 변경사항 발생시 같은 레이어에서만 수정하면 되니까 조금 더 나아보인다 (의존성은 곧 변경사항에 대한 영향)
- 구조 설계시, 처음부터 너무 나눠놓으면 그게 나중에 많이 안쓰일수도 있기때문에 처음에는 간단하게 해두고 기능이 많아지면 리팩토링, 리팩토링
- 객체를 설계하기 위한 가장 기본적인 아이디어는 변경의 정도에 따라 구현과 인터페이스를 분리하고 외부에서는 인터페이스에만 의존하도록 관계를 조절하는 것!
- JPA를 이용한다고 했을 때, Repository 까지는 객체에 강하게 연관이 되지만 Service layer에서는 그 의존을 없앨 수 있다(getById -> getBy 형태로 메서드 이름 변경)
- 지금까지는 엔티티가 바뀌면 전체적으로 코드 근간이 흔들리게 되었어서 객체지향적 설계가 잘 안되어 있어 보인다.
- 엔티티 중심으로 설계하다 보니 책임 중심의 설계가 아니라 데이터 중심의 설계로 자연스럽게 코딩을 하게 됨. -> 만들면서 배우는 클린 아키텍쳐 책에서도 말하는 부분임
- 클린 아키텍처에는 대가가 따른다. 도메인 계층이 영속성이나 UI같은 외부 계층과 철저하게 분리돼야 하므로 애플리케이션의 엔티티에 대한 모델을 각 계층에서 유지보수해야 한다. 가령 영속성 계층에서 ORM 프레임워크를 사용할 때 , 도메인 계층은 영속성 계층을 모르기 때문에 도메인 계층에서 사용한 엔티티 클래스를 영속성 계층에서 함께 사용할 수 없고 두 계층에서 각각 엔티티를 만들어야 한다. 각각의 계층이 데이터 주고 받을 때 두 엔티티를 서로 변환해야 한다는 뜻. 그러나 이것은 바람직한 일이다. 이것이 바로 도메인 코드를 프레임워크에 특화된 문제로부터 해방시키고자 했던, 결합이 제거된 상태임.
- 가령 JPA 에서는 ORM이 관리하는 엔티티에 인자가 없는 기본 생성자를 추가하도록 강제하는데 이는 도메인 모델에는 포함해서는 안 될 프레임워크에 특화된 결합의 예임.
- 결국 서비스 레이어에서 JPA에 의존성을 갖지 않도록 구성하려면 중간에 인터페이스를 두고 그 인터페이스로만 서비스는 영속성 레이어를 호출하고, 영속성 레이어는 그 인터페이스를 구현하는 식으로 코딩을 해야 한다.
- 지금까지, DB의 컬럼이름과 엔티티 필드 사이의 결합이 있었음. 그리고 DB에 필드를 추가하면 엔티티에 필드가 추가되고 그로 인해 서비스 레이어, 컨트롤러 레이어에도 영향을 미치게 됐었음. 일단 DB 필드와 클래스 필드 사이의 결합 제거(entity는 annotation으로 결합 제거 가능. redis object mapper 쪽은 @JsonProperty 이용하여 의존성 제거 )
- 단순 CRUD에서는 서비스레이어가 영속성 레이어(JPA)를 그대로 의존해도 큰 문제가 발생하지 않아 보임(그러나 이 상황에서도 엔티티 필드 바뀌면 서비스, 컨트롤러 레이어까지 ripple effect 가 전달됨
- 계층형 아키텍처에서 계층 간 의존성은 항상 다음 계층인 아래 방향을 가리킨다. 단일 책임 원칙을 고수준에서 적용할 때 상위 계층들이 하위 계층들에 비해 변경할 이유가 더 많다는 것을 알 수 있음
내가 한 실수
- DB 컬럼과 클래스 필드 사이의 의존성. 웹 통신 필드이름과 dto 필드이름 의존성
- 데이터 캡슐화가 부족하여 각 객체의 데이터를 다 뽑아내서 절차지향적으로 코드를 짜고 있었음. 각 객체에게 역할을 부여하지 않고 중심 객체에서 모든 로직을 처리하려고 하였음 (내부의 상태를 이용해 어떤 결정을 내리는 로직이 객체 외부에 존재하는 것. 묻지 말고 시켜라 위반한 것)
- 메서드 응집도가 떨어졌었음. ChannelManagerServiceImpl. 룸 리스트를 가져오는 책임은 RoomInstanceService에 있으니 거기서 로직 처리를 하는게 맞는데 바깥에서 하고 있더보니 코드가 지져분해짐
적용점
- 책임 할당 패턴 (정보전문가). 이 책임을 누가 맡으면 좋을지에 대해서 생각하고 코드 작성하기q
- 오브젝트 예시를 보면 DateTimeInterval 과 같이 통화 시간을 관리하기 위한 클래스를 생성함. JPA 에서 EmbededType 처럼 객체를 하나의 타입으로 보는 방식으로 클래스를 관리 많이 함