티스토리 뷰

728x90

velog 블로그에서 tistory로 이전한 데이터 입니다.

들어가기 전,

대다수가 가장 원하는 "깔끔한 코드" 하지만 과연 내 코드가 깔끔한 지 쉽게 알 수가 없다. 정확한 의사를 표현해 코드리뷰를 받으면 낫다고 판단했다.

깔끔한 코드를 구현하자

  1. 켄트 벡이 제시한 단순한 설계 규칙 (아래로 갈수록 우선순위 낮음)
    • 모든 테스트를 실행한다.
    • 중복을 없앤다.
    • 프로그래머의 의도를 표현한다.
    • 클래스와 메서드 수를 최소로 줄인다

단순한 설계 규칙을 따르면 저절로 소프트웨어 품질을 크게 높여줄 것 같다고 생각한다. 왜 그게 가능할까?
아마도 "모든 테스트를 실행한다" 부터가 SRP를 지킨 코드이기 때문이라고 본다.

1. 모든 테스트를 실행하라

설계를 해서 코드를 작성하면 당연히 의도대로 돌아가야 한다.

하지만 검증방법이 없다면, 그 노력 가치를 인정받기는 어렵다.

테스트를 철저히 거쳐 모든 테스트 케이스를 항상 통과하는 시스템은 "테스트가 가능한 시스템"이다

github에서도 보면 code coverage가 나와있다. 당연히 높을 수록 견고하다고 생각하지만 80 ~ 95% 정도가 적당하다고 본다.

결합도가 높으면 테스트 케이스를 작성하기 어렵다.

DIP: 개발자는 추상화에 의존해야지 구체화에 의존하면 안된다. 구체화에 집중할 수록 결합도는 당연히 커지게 된다.

테스트 케이스를 만들고 계속 돌려라

단순한 규칙을 따르면 시스템은 낮은 결합도와 높은 응집력을 갖는 객체 지향 방법론이 지향하는 목표를 달성한다.

2 ~ 4. 리팩터링

코드 몇 줄 추가할 때, 잠시 멈추고 설계를 조감해라.

지금 설계를 이렇게 하면 다음번에는 좀 더 쉽게 할 수 있을까? 등

새로 추가하는 코드가 설계 품질을 낮춘다고 생각하나?

지금까지 만든 테스트 케이스를 다시 돌려봐라. 이미 검증된 일이다. 대신 살충제 패러독스에 빠지지 말자.

리팩터링 단계는 소프트웨어 설계 품질을 높이는 기법이면 무엇이든 좋다.

응집도를 높이고, 결합도를 낮추고, 관심사를 분리하고, 시스템 관심사를 모듈로 나누고, 함수와 클래스 크기를 줄이고, 더 나은 이름을 선택하자.

여기서 관심사는 SRP 측면으로 보는게 좋을 것 같다. '어떤 기능이 이 클래스에 있어야 맞는가?' 이 고민을 하면 관심사를 분리하면서 클래스의 크기를 줄일 수 있을 것이다.

2. 중복을 없애라

중복은 불필요한 복잡도, 추가 작업, 추가 위험을 뜻한다.

ex1)

int size() {}
boolean isEmpty() {}

를 구현할 때, isEmpty에 0인지 확인할 것이다.

boolean isEmpty() {
    return 0 == size();
}

ex2)

public class vacationPolicy {
    public void accrueUSDivisionVacation() {
            // 지금까지 근무한 시간으로 휴가 일수 계산
               // 휴가 일수가 미국 최소 법정 일수에 만족하는 지 확인
               // 휴가 일수를 급여 대장에 적용
        }
        public void accrueUSDivisionVacation() {
            // 지금까지 근무한 시간으로 휴가 일수 계산
            // 휴가 일수가 유럽 최소 법정 일수에 만족하는 지 확인
            // 휴가 일수를 급여 대장에 적용
        }
 }

vacationPolicy에 대해 미국과 유럽에 대해 계산을 따로 하는 함수다. 근데 중복이 발생한다.

이럴 때, 아래 처럼하면 간단하다.

abstract public class vacationPolicy {
    public void accrueVatation() {
        // 지금까지 근무한 시간으로 휴가 일수 계산
         // 휴가 일수를 급여 대장에 적용 
         // 휴가 일수가 최소 법정 일수에 만족하는 지 확인
    }
}

public class USvacationPolicy extends vacationPolicy {
    @Override 휴가 일수가 미국 법정 일수에 만족하는지
}
public class EUvacationPolicy extends vacationPolicy {
    @Override 휴가 일수가 유럽 법정 일수에 만족하는지
}

3. 표현하라

  1. 좋은 이름을 선택한다. (Arr, List 등 애매모호한 것은 조심히 써라.)
  2. 함수와 클래스 크기를 가능한 줄인다
  3. 표준 명칭을 사용한다.
  4. 단위 TC를 꼼꼼히 작성한다.

표현력을 높이는 가장 중요한 방법은 노력이다. 코드만 돌린 후 넘어갈 것이 아니라 나중에 읽을 사람들을 고려하자.

4. 클래스와 메서드 수를 최소로 줄여라

제일 낮은 우선순위다.
때로 앞에서 말한 1 ~ 3 을 수행하다보면 클래스 수와 메서드 수가 늘어나기도 한다.

나쁜 예)
클래스마다 인터페이스를 생성하라고 요구하는 구현 표준,
자료 클래스와 동작 클래스를 무조건 분리해야 한다는 주장,

이 때, 무조건 만들기 보다는 의도가 비슷한 애들이 있다면 합치고 중복을 제거하고 TC를 성실하게 만들어 객체지향 프로그래밍을 하자.

반응형