728x90
chapter 8-9 계층형 설계
소프트웨어 설계 : 코드를 만들고, 테스트하고, 유지보수하기 쉬운 프로그래밍 방법을 선택하기 위해 미적 감각을 사용하는 것
계층형 설계 : 소프트웨어를 계증을 구성하는 기술, 각 계층에 있는 함수는 바로 아래 계층에 있는 함수를 이용해 정의합니다.
tip : 같은 계층에 있는 함수는 같은 목적을 가져야 합니다.
계층형 설계 패턴
- 직접구현
- 추상화 벽
- 작은 인터페이스
- 편리한 계층
직접구현
- 직접 구현한 코드는 한 단계의 구체화 수준에 관한 문제만 해결합니다.
- 계층형 설계는 특정 구체화 단계에 집중할 수 있게 도와줍니다.
- 호출 그래프는 구체화 단계에 대한 풍부한 단서를 보여줍니다.
- 호출 그래프는 함수가 서로 어떻게 연결되어 있는지 보여줍니다.
- 함수를 추출하면 더 일반적인 함수로 만들 수 있습니다.
- 함수가 더 구체적인 내용을 다루지 않도록 함수를 일반적인 함수로 빼내는 것입니다.
- 구체적인 애용을 하나만 다루기 때문에 테스트하기 쉽습니다.
- 명확한 코드와 알맞은 이름이 중요합니다.
- 일반적인 함수가 많을수록 재사용하기 좋습니다.
- 중복 코드를 찾기 위해서 빼는 것과는 다릅니다.
- 구현을 명확하게 하기 위해 일반적인 함수를 빼내는 것입니다.
- 사용할 곳을 따로 찾지 않아도 재사용할 수 있는 곳을 발견할 수 있습니다.
- 복잡성을 감추지 않습니다.
- 계층형 설계에서 모든 계층은 바로 아래 계층에 의존해야 합니다.
- 복잡한 코드를 같은 계층으로 옮기면 안 됩니다.
- 더 낮은 구체화 수준을 가진 일반적인 함수를 만들어 직접구현 패턴에 적용해야 합니다.
직접구현의 예시
function freeTieClip(cart){
let hasTie = false;
let haseTieClip = false;
for(let i=0; i < cart.length; i ++){
let item = cart[i];
if(item.name === "tie")
hasTie = true;
if(item.name === "tie Clip")
haseTieClip = true;
}
if(hasTie && !hasTieClip){
let tieClip = make_itme("tie Clip", 0)
return add_item(cart, tileClip)
}
return cart;
}
- 반복문은 장바구니에 넥타이와 넥타이 클립이 있는지 확인하고 있습니다.
- 반복문을 추출해 새로운 함수를 만들어서 사용하도록 합니다.
function isInCart(cart, name){
for(let i=0; i < cart.length; i ++){
if(cart[i].name === name){
return true;
}
}
return false
}
다이어그램
- 함수가 호출하는 것을 있는 그대로 표현한 것으로 함수를 어떤 계층에 놓을지 바로 알수 있습니다.
- 높은 차원에서 볼수 있는 좋은 도구 입니다.
3단계 줌 레벨
다이어그램에는 너무 많은 정보가 있어 어느 곳에 문제가 있는지 찾기 어렵습니다.
- 전역 줌 레벨 = 기본 줌 레벨 : 그래프 전체 중 필요한 부분을 살펴보기
- 계층 줌 레벨 : 한 층과 바로 아래 계층을 볼 수 있는 줌 레벨, 계층이 어떻게 구현 되어있는지 알 수 있습니다.
- 함수 줌 레벨 : 함수 하나와 바로 아래 연결된 함수를 볼수 있어, 함수 구현의 문제를 찾아낼 수 있습니다
추상화 벽
- 세부 구현을 감춘 함수로 이루어진 계층
- 추상화 벽에 있는 함수를 사용할 때는 구현을 전혀 몰라도 함수를 쓸 수 있어야 합니다.
- 책임을 명확하게 나눠주는 추상화 벽은 API와 비슷하다
- 추상화벽은 "어떤 것을 신경 쓰지 않아도 되지?"라는 말을 거창하게 하는 것과 같습니다. 즉 필요하지 않은 것은 무시할 수 있도록 간접적인 단계를 만드는 것입니다.
- 추상화 벽을 사용함으로써 서로 신경 쓰지 않아도 되는 구체적인 것을 벽을 기준으로 나눠 의존하지 않게 합니다.
추상화 벽의 예시
추상화 벽 위에 있는 함수를 사용하는 사람에게 장바구니 구조가 배열에서 객체로 바뀌었다는 것은 알리지 않아도 된다!
언제 사용하면 좋은지?
- 쉽게 구현을 바꾸기 위해
- 구현에 대한 확신이 없는 경우 추상화 벽을 사용하면 나중에 구현을 바꾸기 쉽습니다.
- 프로토타이핑과 같이 최선의 구현을 확신할 수 없는 작업에 유용합니다
- 서버에서 데이터를 받아서 처리해야 하지만 아직은 준비되지 않아 임시 데이터를 사용하는 것을 알지만 준비가 되어있지 않은 경우에 사용하기 유용합니다.
- 만약을 대비해 코드를 만드는 경우가 있는데 쓸데없는 코드는 줄이는 것이 좋습니다. 오히려 오지 않는 미래를 위해서 불필요한 코들 작성하는 것은 좋은 습관이 아니기 때문입니다.
- 코드를 읽고 쓰기 쉽게 만들기 위해
- 때로 너무 구체적인 것이 오히려 버그를 만드는 경우가 생기게 되는데 추상화벽을 사용하면 세부적인 것을 신경 쓰지 않아도 됩니다.
- 팀 간에 조율해야 할 것을 줄이기 위해
- 주어진 문제에 집중하기 위해
작은 인터페이스
- 새로운 코드를 추가할 위치에 관한 것으로 인터페이스를 최소화하면 하위 계층에 불필요한 기능이 커지는 것을 방지할 수 있습니다.
- 새로운 기능을 만들 때 하위 계층에 기능을 추가하거나 고치는 것보다 상위 계층에 만드는 것이 더 작은 인터페이스 패턴이라고 할 수 있습니다.
- 추상화 벽에 만든 함수 = 인터페이스
- 추상화 벽에 있는 인터페이스로 어떤 값의 집합에 접근하거나 조작할 수 있습니다.
- 추상화 벽에 코드가 많을수록 구현이 변경 되었을때 고쳐야 할 것이 많습니다.
- 추상화 벽에 있는 코드는 낮은 수준의 코드 이기 때문에 더 많은 버그가 있을 수 있습니다.
- 낮은 수준의 코드는 이해하기 더 어렵습니다.
- 추상화 벽에 코드가 많을 수록 팀 간 조율해야 할 것도 많아집니다.
- 추상화 벽에 인터페이스가 많으면 알아야 할 것이 많아 사용하기 어렵습니다.
- 추상화 벽뿐만 아니라 모든 계층에서도 작은 인터페이스를 사용할 수 있습니다.
- 이상적인 계층은 필요한 함수만 가지고 있어야 합니다.
- 계층이 가진 함수는 완전하고 , 적고, 시간이 지나도 바뀌지 않아야 하는 게 작은 인터페이스가 전체 계층에서 사용되는 이상적인 모습입니다!
편리한 계층
- 언제 패턴을 적용하고 또 언제 멈춰야 하는지 실용적인 방법을 알려줍니다.
호출 그래프
호출 그래프 구조는 세 가지 중요한 비기능적 요구사항을 보여줍니다
기능적 요구사항 : 소프트웨어가 정확히 해야 하는 일
비기능적 요구사항 : 테스트를 어떻게 할 건지, 재사용을 잘할 수 있는지, 유지보수는 어렵지 않은지와 같은 요구 사항들
- 그래프의 최 상단의 코드가 가장 고치기 쉽습니다.
- 시간이 지나도 변하지 않는 코드는 가장 아래 계층에 있어야 합니다. (카피-온-라이트 함수 같은)
- 아래에 있는 코드는 테스트가 중요합니다.
- 아래에 있는 코드가 더 재사용하기 좋습니다.
- 코드를 재사용하면 코드를 다시 만들지 않아도 되며, 고치거나, 테스트도 필요 없어 시간과 비용의 절감 효과가 있습니다.
- 계층형 구조를 만들면서, 낮은 계층으로 함수를 추출하면 재사용할 가능성이 높아집니다.
그래프가 코드에 대해 알려주는 것
- 유지 보수성
- 함수는 위로 많이 연걸되지 않으면 바꾸기 쉽습니다.
- 자주 바뀌는 코드는 가능한 위에 위치해야 합니다
- 테스트 가능성
- 위 계층과 많이 연결된 함수를 테스트하는 것이 더 가치 있습니다.
- 위 계층보다는 아래 계층의 함수를 테스트하는 것이 더 가치 있습니다.
- 재사용성
- 아래 계층으로 함수를 빼내면 더 재사용성이 높아집니다.
728x90
'FE > 함수형 코딩 스터디' 카테고리의 다른 글
[함수형코딩] chapter 10 , 11 정리본 (0) | 2023.07.02 |
---|---|
[함수형코딩] chapter 4 , 5 정리본 (0) | 2023.06.11 |
[함수형코딩] chapter 1 , 2 , 3 정리본 (0) | 2023.06.06 |