wldnswldnswl / IknowJS

You Don't Know JS 스터디
1 stars 1 forks source link

[쏙쏙] 11장. 일급함수2 #166

Closed wldnswldnswl closed 1 year ago

wldnswldnswl commented 1 year ago

일급함수1에서의 리팩토링 요소

  1. 함수 이름에 있는 암묵적인 인자 -> 암묵적 인자 드러내기 image

    • 함수 이름에 있는 암묵적인자 -> 위처럼 거의 똑같이 구현된 함수가 있고, 함수 이름이 구현에 있는 다른 부분을 가리킨다.
    • 리팩터링 방법 1) 함수 이름에 있는 암묵적 인자를 확인한다. 2) 명시적인 인자를 추가한다. 3) 함수 본문에 하드코딩된 값을 새로운 인자로 바꾼다. 4) 함수 호출부를 고친다.
  2. 함수 본문을 콜백으로 바꾸기 1) 본문 앞부분, 뒷부분 확인 2)리팩터링할 코드를 함수로빼내기 3) 빼낸 함수의 인자로 넘길 부분을 또 다른 함수로 빼낸다. 예시 -> function withLogging(f) try { f();} catch(e) {logToSnapErrors(e);} -> 호출부: withLogging(function() { saveUserData(user);}} // 본문을 인자로 전달!

카피-온-라이트 리팩터링

배열에 대해 카피-온-라이트 단계

*카피-온-라이트: 원본을 복사하고 복사본에 수정하여 원본이 훼손되지 않는 복사방법 (6장)

  1. 본사본 만들기
  2. 본사본 변경
  3. 복사본 리턴

1) 함수 빼내기

image

2) 콜백 빼내기

image

리팩토링으로 얻은것

  1. 배열에 쓸 수 있는 카피-온-라이트 원칙을 코드로 만듦
  2. 재사용성 높아짐
  3. 배열 여러개를 변경할때 최적화되었다. -> 카피온라이트는 실행할때마다 새로운 복사본을 만들기때문에 느리고 메모리를 많이 사용. 리팩터링한 withArrayCopy를 쓰면 하나의 복사본만 사용할 수 있다.

함수를 리턴하는 함수

try-catch로 감싸는 중복구문은 없앴지만 여전히 withLogging을 여러번 호출하고 있다. (10장. 일급함수 1)

ex1) try { fetchProduct(productId); // 다른부분} catch(e){ logToSnapErrors(e);} ex2) try { saveUserData(user);// 다른부분} catch(e){ logToSnapErrors(e);} -> 이런식으로 여러 코드들 try~catch로 감싸서 snaperror로 보낸다. -> 이 역할을 해주는 함수를 만들 수 있을까?

sol) 반복되는 코드를 캡슐화

function withLoggin(f) { // 다른부분을 콜백으로, 나머지는 공통으로 뺀다. try { // (공통 앞부분) f(); // ** (본문) }catch (e){ // (공통 뒷부분) logToSnapErrors(e); } }

적용 ex1) withLogging(function(){saveUserData(user);}); ex2) withLogging(function(){fetchProduct(productId);});

문제점

  1. 어떤부분에 로깅을 남기는걸 깜빡할수있다. -> withLogging없이 saveUserData만 쓸수도 있다.
  2. 모든 코드에 수동으로 withLogging 함수를 적용해야한다. -> 에러를 잡아 로그를 남기는 기능이 추가된 함수를 일반함수처럼 호출할 수 있으면 좋겠다.

sol) 함수명 변경하여

image
  1. 이름을 명확하게 바꾼다. (로그를 남기는 함수를 공통으로 제공하기 위함.) saveUserData -> saveUserDataWithNoLogging
  2. 로그를 남기지 않는 함수를 로그를 남기는 기능을 하도록 하여 함수로 뺀다.

-> 중복코드가 많다.

image

sol) 함수 본문을 콜백으로 바꾸기 (콜백 인자를 추가하는 대신, 함수를 새로운 함수로 감싸는 방식)

function wrapLogging(f) { // 함수를 인자로 받는다. return function(arg){ // 함수로 감싸서 나중에 실행되도록한다. try { // (공통 앞부분) f(arg); // ** (본문) }catch (e){ // (공통 뒷부분) logToSnapErrors(e); } } }

var saveUserDataWithLogging = wrapLogging(saveUserDataWithNoLogging); var fetchProductWithLogging = wrapLogging(fetchProductWithNoLogging); -> 중복을 없앴고, 어떤함수라도 같은 방식으로 로그를 남길 수 있게됨

뭐가 더 편리해진거지?! (개인적인 생각)

as-is) try-catch 수천번

image

to-be) ~~WithLogging메서드를 한줄로 만들어서 사용하면됨. var saveUserDataWithLogging = wrapLogging(saveUserDataWithNoLogging);