일급 함수2
May 31, 2024
쏙쏙들어오는 함수형 코딩
# 배열에 대한 카피-온-라이트 리팩터링
앞서 설명했던 카피-온-라이트 함수에 함수 본문을 콜백으로 바꾸기
리팩터링을 적용해 봅시다.
함수 본문을 콜백으로 바꾸기 단계
1. 본문과 앞부분, 뒷부분을 확인하기
2. 함수 빼내기
3. 콜백 빼내기
1. 본문과 앞부분, 뒷부분을 확인하기
앞서 만든 카피-온-라이트 함수를 살펴봅시다:
함수에서 본문의 앞부분, 뒷부분이 같은형식인걸 볼 수 있습니다. 복사하고 리턴하는 것은 같으므로 arraySet() 함수로 리팩터링 해봅시다.
2. 함수 빼내기
이 단계는 리팩터링 할 코드를 함수로 빼는 단계입니다. 이 함수에는 앞부분
과 뒷부분
이 있습니다. 이 함수를 따로 빼서 withArrayCopy() 라는 이름을 붙여주었습니다.
함수 본문을 콜백으로 바꾸기
리팩터링중 2번째 단계까지 했으니 마지막 단계인 콜백 빼내기 단계를 진행해봅시다.
3. 콜백 빼내기
콜백은 배열을 변경하는 일을 하므로 modify라고 합시다.
카피-온-라이트 원칙을 따르고 재사용 할 수 있는 함수로 withArrayCopy() 함수를 만들었습니다. 이제 똑같은 코드를 여기저기 만들지 않아도 됩니다.
# 함수를 리턴하는 함수
함수를 리턴하는 함수는 함수 팩토리와 같습니다. 자동으로 정형화된 코드를 함수로 만들 수 있습니다.
하고자 했던건 서비스에 로그를 남기려고 했습니다. 원래 코드는 이런 모양이였습니다:
Before
try {saveUserData(user);} catch(error) {logToSnapErrors(error);}try {fetchProduct(productId);} catch(error) {logToSnapErrors(error);}
함수의 본문 saveUserData
, fetchProduct
만 빼고 나머지는 모든 코드에서 중복됩니다. 중복되는 코드가 생기지 않는 방법이 있습니다:
function withLogging(f) {try {f()} catch (error) {logToSnapErrors(error);}}
새로 만든 withLogging을 사용하면 아래와 같습니다:
withLogging(function() {saveUserData(user);})withLogging(function() {fetchProduct(productId);})
로그를 남기기 위한 일반적인 시스템이 생겼지만, 여전히 두 가지 문제가 있습니다.
- 어떤 부분에 로그를 남기는 것을 깜빡할 수 있습니다.
- 모든 코드에 수동으로 withLogging() 함수를 적용해야 합니다.
에러를 잡아 로그를 남길 수 있는 기능이 추가된 함수를 일반 함수처럼 그냥 호출 할 수 있으면 좋겠습니다.
function wrapLogging(f) {return function(arg) {try {f(arg);} catch(error) {logToSnapErrors(error);}}}var saveUserDataWithLogging = wrapLogging(saveUserDataNoLogging);var fetchProductWithLogging = wrapLogging(fetchProductNoLogging)
위의 코드처럼 사용하면 일반 함수처럼 호출 할 수 있습니다. 그리고 중복코드도 많이 없앴습니다.
# 좋은 코드를 만드는데 해야하는 고민
다양한 목적으로 다양한 곳에 고차함수를 적용해보세요. 끊임없이 탐구하고 실험해야 합니다. 하지만 프로덕션 코드에서 실험하면 안되겠죠. 실험은 배우기위해 한다는 것을 명심 하세요.
만약 고차 함수로 만든 좋은 방법을 찾았다면 직관적인 방법과 항상 비교해보세요. 어떤 방법이 더 좋을까요? 코드가 더 읽기 쉬운가요? 얼마나 많은 중복 코드를 없앨 수 있나요? 코드가 하는 일이 무엇인지 쉽게 알 수 있나요? 이런 질문들을 놓치면 안됩니다.
고차 함수를 많은 중복 코드를 없애 주지만 가독성을 해칠 수 있습니다. 고차 함수를 능숙하게 쓸 수 있도록 연습을 많이하고 꼭 필요한 곳에 쓰거나, 더 좋은 코드를 만드는 데 써야 합니다.