티스토리 뷰

728x90

개방/폐쇄 원칙 (Open/Closed  Principle - OCP) 

1. 특정 입출금 내역을 검색할 수 있는 기능. 예를 들어 주어진 날짜 범위 또는 특정 범주의 입출금 내역 얻기

2. 검색 결과의 요약 통계를 텍스트, HTML 등 다양한 형식으로 만들기

 

책을 중간에 읽으면서 어떤 내용이 나올지 예상이 돼서 기뻤다. 이거 이렇게 하면 될 거 같은데?라고 생각했는데 실제로 책에서 그렇게 하니까 진짜 기뻤다..

 

기능이 추가될 때 항상 의문이 드는건 이 메서드를 어디에 정의해야 할까?인데 새 클래스를 만드는 것도 좋지만 새로운 클래스를 계속 만들수록 코드는 복잡해지고 여러 이름이 생기면서 다양한 동작 간의 관계를 이해하기가 어려우므로 처리 기능을 담당하는 이미 만들었던 BankTransactionProcessor 클래스 안에 정의하는 것이 좋다.

 

특정 금액 이상의 은행 거래 내역 찾기

public List<BankTransaction> findTransactions(final int amount) {
    final List<BankTransaction> result = new ArrayList<>();
    for (final BankTransaction bankTransaction : bankTransactions) {
        if (bankTransaction.getAmount() >= amount) {
            result.add(bankTransaction);
        }
    }
    return result;
}

특정 월의 입출금 내역 찾기

public List<BankTransaction> findTransactions(final Month month) {
    final List<BankTransaction> result = new ArrayList<>();
    for (final BankTransaction bankTransaction : bankTransactions) {
        if (bankTransaction.getDate().getMonth() == month) {
            result.add(bankTransaction);
        }
    }
    return result;
}

뭔가 이상하지 않은가?  중복되는 코드가 많고 단순 파라미터만 바뀌고 있다.

이럴때 생각났던 건 모던 자바인 액션에서 봤던 동작 파라미터화 코드 전달하기!! 현재 코드에는 반복 로직과 비즈니스 로직이 결합되어 있으니 인터페이스를 이용해서 이런 결합을 제거하자.

 

인터페이스 생성

@FunctionalInterface
public interface BankTransactionFilter {
    boolean test(BankTransaction bankTransaction);
}

@FunctionalInterface와 자바8에 추가된 추상 메서드가 하나일 때는 람다로 작성할 수 있는 이야기는 생략..

사실 이 책에서는 좀 더 이해가 쉽게 하기위해서 자바 8 function패키지에 추가된 Predicate를 쓰지 않았지만 Predicate<T> 인터페이스를 쓰는 것이 더 효율?적이다. 

 

새로운 인터페이스를 이용해 반복 로직과 비즈니스 로직의 결합을 제거하는 과정은 상당히 중요한 리팩터링이다.

이제 파라미터에 코드를 전달할 수 있다. 람다로!!

final List<BankTransaction> transactions
                = bankStatementProcessor.findTransactions(bankTransaction -> 
				bankTransaction.getDate().getMonth() == Month.FEBRUARY
 				&& bankTransaction.getAmount() >= 1_000);

갓 인터페이스

한 인터페이스에 모든 기능을 추가하는 갓 인터페이스를 만드는 일은 피해야 한다.

자바의 인터페이스는 모든 구현이 지켜야 할 규칙을 정의한다. 즉 구현 클래스는 인터페이스에 정의되어있는 모든 구현 코드를 제공해야 하고 만약 인터페이스에 기능이 추가되면 인터페이스를 구현한 코드를 모두 바꿔줘야 한다.

이런 이유에서 작은 인터페이스를 권장한다.

그런데!!?

지나친 세밀함

그래서 인터페이스를 각 동작하나만 하는 별도의 인터페이스를 계속 만드는 것은 아주 극단적이다. 지나치게 인터페이스가 세밀해도 코드 유지보수에 방해가 되고 안티 응집도 문제가 발생한다. 즉 기능이 여러 인터페이스로 분산되므로 필요한 기능을 찾기가 어렵다.

자주 사용하는 기능을 쉽게 찾을 수 있어야 유지보수성도 좋아진다.

 

아니 그래서 어떻게하라고!!?

명시적 API VS 암묵적 API

책 58쪽인데 음..잘 모르겠다

예외(Exception)

책에서 예외에 관한 설명이 나오는데 김영한 님의 스프링 DB 1편에서 나온 내용이 비슷하게 나온다.

Checked 예외와 Unchecked 예외.

Checked 예외는 컴파일러가 체크해야 하는 예외이므로 반드시 try catch 블록을 쓰거나 throws에 예외를 던지는 처리를 해야 하는 예외이고 Unchecked는 컴파일러가 체크하지 않는 예외이다. 예외를 던지는 throws를 선언하지 않고 생략할 수 있다.

김영한 - 스프링db 그림

이 책에서도 대다수의 예외를 Unchecked 예외로 지정하고 꼭 필요한 상황에서만 Checked 예외로 지정해 불필요한 코드를 줄여야 한다고 한다.

 

728x90
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함