CleanCode 12장 창발성

1.  창발적 설계로 깔끔한 코드를 구현하자

  • 모든 테스트를 실행한다.
  • 중복을 없앤다.
  • 프로그래머 의도를 표현한다.
  • 클래스와 메서드 수를 최소로 줄인다.

중요도 순이며 이 4가지 규칙을 따르면, 코드 구조와 설계를 파악하기 쉬워진다.
-> SRP, DIP와 같은 원칙을 적용하기 쉬워져 창발성을 촉진시킬 수 있다.

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

논문이 있는데 그 논문에 주장만 가득하고 주장을 뒷받침 할 실험이나 근거가 없다면 아무도 주장을 믿지 않고, 논문이라고 할 수 없다.
-> 프로그램도 테스트로 증명할 수 없으면 소용이 없다.

  • 문서로는 시스템을 완벽하게 설계했다고 하더라도 의도한 대로 돌아가는지 검증할 방법이 필요
    - 검증할 방법이 없다면 투자한 노력에 대한 가치를 인정 받을 수 없음
  • 테스트가 가능한 시스템이 만들어 짐
    - 테스트가 불가능한 시스템은 검증도 불가능하기 때문에 출시해서는 안됨
  • 수월한 테스트를 위해 SRP를 준수하는 클래스가 나옴
  • 결합도가 높으면 테스트 케이스를 작성하기 어렵기 때문에 이를 낮추는 노력을 하게 됨
    - DIP와 같은 원칙을 적용
    - 의존성 주입, 인터페이스, 추상화 등과 같은 도구 사용

결국, 이 규칙을 따르면 시스템은 낮은 결합도와 높은 응집력이라는 객체 지향 방법론이 지향하는 목표를 달성하게 되고 이를 통해 설계 품질을 높힐 수 있다.

2.  중복을 없애라

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

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

위와 같은 메서드가 있을 때, 각 메서드를 따로 구현할 수도 있다.
(isEmpty는 bool값을 반환하며, size 메서드는 개수를 반환)

-> 하지만 isEmpty 메서드에 size 메서드를 이요하면 중복 구현하지 않아도 된다.

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

아래는 중복된 부분을 추출해서 새로운 메서드로 만드는 예시이다.

// 중복 코드
public void scaleToOneDimension(float desiredDimension, float imageDimension) {
  if (Math.abs(desiredDimension - imageDimension) < errorThreshold)
    return;
  float scalingFactor = desiredDimension / imageDimension;
  scalingFactor = (float)(Math.floor(scalingFactor * 100) * 0.01f);
  
  RenderedOpnewImage = ImageUtilities.getScaledImage(image, scalingFactor, scalingFactor);
  image.dispose();
  System.gc();
  image = newImage;
}

public synchronized void rotate(int degrees) {
  RenderedOpnewImage = ImageUtilities.getRotatedImage(image, degrees);
  image.dispose();
  System.gc();
  image = newImage;
}
// 중복 추출 코드
public void scaleToOneDimension(float desiredDimension, float imageDimension) {
  if (Math.abs(desiredDimension - imageDimension) < errorThreshold)
    return;
  float scalingFactor = desiredDimension / imageDimension;
  scalingFactor = (float) Math.floor(scalingFactor * 10) * 0.01f);
  replaceImage(ImageUtilities.getScaledImage(image, scalingFactor, scalingFactor));
}

public synchronized void rotate(int degrees) {
  replaceImage(ImageUtilities.getRotatedImage(image, degrees));
}

private void replaceImage(RenderedOp newImage) {
  image.dispose();
  System.gc();
  image = newImage;
}

3.  프로그래머의 의도를 표현해라.

자신이 코드를 짤 때는 모든 것을 이해하지만, 코드를 유지보수하는 사람이 이해할 가능성은 희박하다.
어려운 코드는 이해하느라 시간도 잡아먹고, 오해할 가능성이 높아서 위험하다.

이를 방지하기 위해서는

  1. 좋은 이름으로 지어야한다
    • 이름과 기능이 다르면 안된다.
  2. 함수와 클래스 크기를 줄여야한다
    • 이름을 짓기도 쉽고, 구현도 쉽고, 남이 봤을 때 이해도 쉽다!
  3. 표준 명칭을 사용해야 한다
    • 표준 패턴을 사용할 경우, 그 이름을 넣어주면 의도를 알기 쉽다.
  4. 단위 테스트 케이스를 꼼꼼히 작성
    • 테스트 케이스는 예제가 되기도 한다
    • 테스트 케이스를 잘 만들면, 테스트만 봐도 클래스 기능을 이해할 수 있다.

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

아무리 좋은 개념인 SRP도 극단으로 치닫으면 득보다 실이 많아진다.

의미없이 클래스와 메서드 크기를 줄인다고 조그만 클래스와 메서드를 만들지 말고, 클래스와 메서드의 수는 최소한으로 유지해야한다.

-> 정말 필요로 한지 고민하고 필요할 때만 분리를 하는 것!

좋은 웹페이지 즐겨찾기