반응형
https://giken.tistory.com/entry/Java-SOLID
인터페이스 분리 원칙 (Interface segregation principle, ISP)
클라이언트별로 세분화된 인터페이스를 만들어야한다.
인터페이스를 분리한다는 점에서 앞서 살펴보았던 단일책임원칙과 동일하다.
그러나 분리하는 관점 자체가 다르다.
인터페이스 분리 원칙이 깨진 상황
public interface Repository {
void createUser();
User findUserById(Long id);
void createArticle();
Article findArticleById(Long id);
}
public class UserRepository implements Repository {
@Override
public void createUser() {
// 의미 있는 어떤 로직
}
@Override
public User findUserById(Long id) {
// 의미 있는 어떤 로직
return null;
}
@Override
public void createArticle() {
// do nothing
}
@Override
public Article findArticleById(Long id) {
// do nothing
return null;
}
}
public class ArticleRepository implements Repository {
@Override
public void createUser() {
// do nothing
}
@Override
public User findUserById(Long id) {
// do nothing
return null;
}
@Override
public void createArticle() {
// 의미 있는 어떤 로직
}
@Override
public Article findArticleById(Long id) {
// 의미 있는 어떤 로직
return null;
}
}
두 개의 Repository 구현체에서 필요없는 메서드들을 Override 해와서 사용하지 않고 있다.
-> 문제가 있어보인다.
이번엔 repository 를 사용하는 Service 를 보자.
public class UserService {
private Repository repository = new UserRepository();
public void createUser() {
repository.createUser();
}
public User findByUser(Long id) {
return repository.findUserById(id);
}
}
public class ArticleService {
private Repository repository = new ArticleRepository();
public void createArticle() {
repository.createArticle();
}
public Article findByArticle(Long id) {
return repository.findArticleById(id);
}
}
언뜻 보기에는 문제가 없어보인다.
하지만 다음 화면을 보면 UserService 가 절대 사용하지 않는 메서드가 불필요하게 노출되는 것을 볼 수 있다.
유지보수하기가 어려울 것이다.
이를 해결하기 위해서
하나의 커다란 인터페이스를 두 개의 인터페이스로 분리하자.
인터페이스 분리 원칙을 지키는 코드
public interface UserRepositoryInterface {
void createUser();
User findUserById(Long id);
}
public interface ArticleRepositoryInterface {
void createArticle();
Article findArticleById(Long id);
}
public class UserRepository implements UserRepositoryInterface {
@Override
public void createUser() {
// 의미 있는 어떤 로직
}
@Override
public User findUserById(Long id) {
// 의미 있는 어떤 로직
return null;
}
}
public class ArticleRepository implements ArticleRepositoryInterface {
@Override
public void createArticle() {
// 의미 있는 어떤 로직
}
@Override
public Article findArticleById(Long id) {
// 의미 있는 어떤 로직
return null;
}
}
인터페이스 분리 원칙을 지키는 코드는
1. 구현 클래스에는 불필요한 메서드를 구현하지 않도록 만들고,
2. 인터페이스를 사용하는 클래스에게는 불필요한 메서드를 노출시키지 않아
유지보수하기 좋은 코드를 만들어준다.
의존관계 역전 원칙 (Dependency inversion principle, DIP)
고수준 컴포넌트는 저수준 컴포넌트에 의존하지 않아야한다.
https://giken.tistory.com/entry/Java-%EC%9D%98%EC%A1%B4-%EC%97%AD%EC%A0%84
간접적으로 의존 역전 원칙이 깨지는 상황과 그 해결 방법
public interface Repository {
Object findById(Long id);
}
public class Service {
private Repository repository;
public Object findById(Long id) {
Object obj = null;
try {
obj = repository.findById(id);
} catch (RecordNotFoundException recordNotFoundException) {
// 예외에 대한 처리
} catch (TextNotFoundException textNotFoundException) {
// 예외에 대한 처리
} catch (NoSuchElementException noSuchElementException) {
// 예외에 대한 처리
}
return obj;
}
}
Repository 를 상속한 구현체들이
Database Repository, File Repository, ArrayList Repository 가 있다고 해보자.
Service 에서 구현체가 늘어남에 따라서
예외처리하는 코드를 추가해야함을 볼 수 있다.
고수준 컴포넌트인 Service 가 저수준 컴포넌트인 Repository 구현체에 의존하고 있는 것이다.
의존역전원칙을 지키는 코드는
인터페이스를 통해 고수준 컴포넌트가 더 이상 저수준 컴포넌트에 의존하지 않도록 만드는 것이다.
이 때 의존 방향이 역전되기 때문에 의존 역전이라고 한다.
반응형
'백엔드 데브코스' 카테고리의 다른 글
[Java] 디자인패턴과 안티 패턴 (0) | 2023.10.08 |
---|---|
[Java] 도서관리 프로그램을 만들면서 배운것들 - Enum, Builder 디자인패턴 (0) | 2023.10.06 |
[Java] SOLID란? (1) - 객체 지향 프로그래밍의 5가지 기본 원칙 (0) | 2023.09.27 |
[Java] 의존성을 주입해주는 주체 - jar, @Profile, @Order (0) | 2023.09.27 |
[Java] 의존 주입 패턴 (0) | 2023.09.27 |