8~9장. 계층형 설계 패턴

1. 직접 구현

  • 직접 구현한 코드는 한 단계의 구체화 수준에 관한 문제만 해결한다.
  • 계층형 설계는 특정 구체화 단계에 집중할 수 있게 도와준다.
  • 호출 그래프는 구체화 단계에 대한 풍부한 단서를 보여준다.
  • 함수를 추출하면 더 일반적인 함수로 만들 수 있다.
  • 일반적인 함수가 많을수록 재사용하기 좋다.
  • 복잡성을 감추지 않는다.

2. 추상화 벽

  • 세부 구현을 감춘 함수로 이루어진 계층
  • 추상화 벽에 있는 함수를 사용할 때는 구현을 전혀 몰라도 함수 사용 가능

3. 작은 인터페이스

  • 인터페이스를 최소화하면 하위 계층에 불필요한 기능이 쓸데없이 커지는 것을 방지
  • 추상화 벽에 만든 함수는 인터페이스라고 할 수 있음
  • 즉, 계층형 설계에서 최소한의 인터페이스를 위해 추상화 벽을 작게 만드는 것을 지향함
    • 추상화 벽에 있는 코드가 많을수록, 구현 변경 시 고쳐야 할 것이 많음
    • 추상화 벽에 있는 코드가 많을수록, 팀 간 조율할 것들이 많아짐
    • 버그 가능성 및 낮은 코드 이해도

4. 편리한 계층

  • 작업하고 있는 코드가 편리하다고 느낀다면 설계를 멈춰라

계층형 설계 패턴과 비기능적 요구사항

  1. 유지보수성 : 요구 사항이 바뀌었을 때 가장 쉽게 고칠 수 있는 코드는 어떤 코드인가?
  2. 테스트성 : 어떤 것을 테스트하는 것이 가장 중요한가?
  3. 재사용성 : 어떤 함수가 재사용하기 좋은가?

이러한 비기능적 요구사항은 계층형으로 설계된 호출 그래프(다이어그램)를 통해 쉽게 파악 가능하다.

  • 유지보수성 → 위로 연결된 것이 적은 함수가 바꾸기 쉬움 → 자주 변경하는 코드는 가능한 위쪽에
  • 테스트성 → 위쪽으로 많이 연결된 함수를 테스트하는 것이 더 가치있음 → 아래쪽에 있는 함수를 테스트하는 것이 더 가치있음
  • 재사용성 → 아래쪽에 함수가 적을수록 더 재사용하기 좋음

이야기해보기

p.171 직접 구현된 함수를 읽을 때, 함수 시그니처가 나타내고 있는 문제를 함수 본문에서 적절한 구체화 수준에서 해결해야 합니다.

→ 함수 시그니처는 어떤 문제를 나타내고, 구체화를 통해 어떻게 해결될까?


p.194 arraySet() 함수를 이용해 setPriceByName() 함수를 구현하고 다이어그램을 그려보세요.

→ 해설에 나온 다이어그램의 계층 분리 기준이 궁금함

(setPriceName() / indexOfItem(), setPrice() / arraySet() / for loop, array index, .slice())


나의 경우, 기존에 나눈 6계층을 기준으로 계층을 분리해 다이어그램을 그림

스크린샷 2023-11-25 오후 7 27 02

기존에 계층을 분리할 때, indexOfItem() 함수는 카피-온-라이트 동작 계층에 속함.

계층 분리의 기준이 ‘카피-온-라이트’ 동작인가 ‘제품에 관한’ 기본 동작인가에 따라 나눈다면,

function arraySet(array, idx, value) {
  const copy = array.slice(); // 1. 복사본 만들기
  copy[idx] = value; // 2. 복사본 변경하기
  return copy; // 3. 복사본 리턴하기
}

arraySet() 함수는 indexOfItem() 함수와 계층이 같다고 판단해, 다이어그램을 아래와 같이 작성함.

스크린샷 2023-11-25 오후 7 41 34