쏙쏙 들어오는 함수형 코딩 - #8

_sw_·2023년 9월 3일
post-thumbnail

계층형 설계

소프트웨어를 계층으로 분리하여 구성하는 기술


계층형 설계 패턴

패턴 1: 직접 구현

계층형 구조를 만드는데 도움이 되고, 적절한 구체화 수준으로 문제를 해결할 수 있다.

패턴 2: 추상화 벽

중요한 세부 구현은 보여주지 않고, 인터페이스를 먼저 제공한다. 인터페이스를 활용하면 더 높은 차원으로 생각할 수 이싿.

패턴 3: 작은 인터페이스

시스템이 커질 수록 중요한 인터페이스는 작고 강력한 동작으로 구성 되어야 한다.

패턴 4: 편리한 계층

잘 구성된 계층을 통해 소프트웨어를 더 빠르고 고품질로 재공하는데 도움을 주어야하며, 구성된 계층은 작업할 때 편리함을 주어야한다.


패턴 1: 직접 구현

  • 특정 문제를 해결하기 위해 도움이 되는 함수를 설계하고 직접 구현하여 개선할 수 있다.
  • 함수가 호출하는 함수를 호출 그래프로 시각화하고, 서로 다른 추상화 계층을 가지고 있는 함수를 개선하여 같은 수준으로 맞춘다. ( → 함수 내부에서 많은 기능을 구체적으로 가지고 있지 않도록, 개선 가능한 뱡항으로 내부 로직을 여러 함수로 분리하는 것을 의미한다고 생각한다.)
  • 계층을 맞추는 과정에서 같은 계층에 있는 함수는 같은 목적을 가지고 있어야 한다. → 예를 들어 ‘장바구니 비즈니스 규칙’ 계층에 해당하는 함수들은 그 목적에만 해당해야하며, 더 낮은 수준, 더 높은 수준에 대해서는 몰라도 된다.

3 단계 줌 레벨

  1. 전역 줌 레벨 → 그래프 전체 중 필요한 부분을 볼 수 있다.
  2. 계층 줌 레벨 → 한 계층과 연결된 바로 아래 계층을 볼 수 있다.
  3. 함수 줌 레벨 → 함수 아래 연결된 함수들만 볼 수 있다.

함수 줌 레벨을 활용하면 함수 하나가 가지고 있는 화살표를 비교할 수 있고, 이 길이를 비교해서 함수의 추상화 수준을 확인할 수 있다.


연습문제 solve

// 참조관계 정리하기
// before
function isInCart(cart, name) {
	for ( var i = 0; i < cart.length; i++) {
		if (cart[i].name === name)
			return true;
	}

	return false;
}

function indexOfItem(cart, name){
	for ( var i = 0; i < cart.length; i++) {
		if (cart[i].name === name)
			return true;
	}

	return null;
}

// after
function isInCart(cart, name) {
	return indexOfItem(cart, name) !== null;
}

function indexOfItem(cart, name){
	for ( var i = 0; i < cart.length; i++) {
		if (cart[i].name === name)
			return true;
	}

	return null;
}
// 함수, 반복문, 배열 인덱스 참조 관계 정리하기
// before
function setPriceByName(cart, name, price) {
	var cartCopy = cart.slice();
	for(var i = 0; i < cart.length; i++) {
		if(cartCopy[i].name === name)
			cartCopy[i] = setPrice(cartCopy[i], price);
	}
	return cartCopy;
}

function indexOfItem(cart, name) {
	for(var i = 0; i < cart.length; i++) {
		if (cart[i].name === name)
			return i;
	}
	return null;
}

// after

function setPriceByName(cart, name, price) {
	var cartCopy = cart.slice();

	const productIndex =  indexOfItem(cart, name);

	if ( productIndex !== null)
		cartCopy[productIndex] = setPrice(cartCopy[productIndex], price);

	return cartCopy;
}

function indexOfItem(cart, name) {
	for(var i = 0; i < cart.length; i++) {
		if (cart[i].name === name)
			return i;
	}
	return null;
}
// setPriceByName 리팩토링하기
// before
function setPriceByName(cart, name, price) {
	var cartCopy = cart.slice();
	var idx = indexOfItem(cart, name);
	if (idx !== null)
		cartCopy[idx] = setPrice(cartCopy[idx], price);
	
	return cartCopy;
}

function arraySet(array, idx, value) {
	var copy = array.slice();
	copy[idx] = value;
	return copy;
}

// after
function setPriceByName(cart, name, price) {
	var idx = indexOfItem(cart, name);
	if (idx !== null)
		return arraySet(cart, idx, setPrice(cart[idx], price));
	return cart;
}

function arraySet(array, idx, value) {
	var copy = array.slice();
	copy[idx] = value;
	return copy;
}

정리

직접 구현 패턴은

  • 하나의 구체화 수준에 대한 문제만 해결한다.
  • 계층형 설계는 특정 구체화 단계에 집중할 수 있게 도와준다.
  • 호출 그래프는 각 함수에 대한 추상화/구체화 정보를 제공해준다.
  • 함수를 추출하는 과정을 통해서 더 일반적인 함수를 만들 수 있다.
  • 일반적인 함수는 재사용하기 좋다.
  • 계층적 구조에서 함수가 다음 아래에 있는 함수만 사용하도록 구성하여 덜 복잡하게 함수를 만들 수 있다.

0개의 댓글