Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- map
- 프로그래머스
- Java
- 코딩테스트
- java 백준 1차원 배열
- 반복문
- 개발자 회고록
- 코테
- 리눅스
- 명령어
- 리눅스마스터1급
- 백준 javascript
- 고잉버스
- 문자열
- GoingBus
- 카카오
- 백준 java
- 자바스크립트 코딩의 기술
- 스프링 빈
- 리눅스마스터 3과목
- 자바
- JavaScript
- Linux
- Memoir
- 리눅스마스터 1급 정리
- 연습문제
- 월간코드챌린지
- toCharArray
- 스프링 컨테이너
- Kotlin
Archives
- Today
- Total
hoon's bLog
Javascript 자바스크립트 코딩의 기술 7장 유연한 함수를 만들어라 (1) 본문
반응형
7장 유연한 함수를 만들어라
tip32. 테스트하기 쉬운 함수를 작성하라
- 코드를 쉽게 리팩토링 가능
- 오래된 코드를 쉽게 이해 가능
- 마지막으로 명확하고 버그가 적은 코드를 작성 가능
- 너무 당연한 말이 아닐까 싶지만, 현실은 테스트 코드를 작성하는 것 조차 쉽지 않다.
(테스트 작성의 어려움, 코드가 외부 의존성이 강하게 결합, 개발속도가 느림 등...)
import { getTaxInformation } from './taxService';
function formatPrice(user, { price, location }) {
const rate = getTaxInformation(location); // <label id="test.external" />
const taxes = rate ? `추가 세금 $${price * rate}` : '추가 세금';
return `${user}님의 합계 금액: $${price} 및 ${taxes}`;
}
- 위의 코드는 주어진 사용자 정보와 제품 금액 및 위치에 따라서 추가 세금 정보를 계산하여 포맷팅하는 함수
- formatPrice 함수는 user,
{ price, location }
을 매개변수로 받고,{ price, location }
는 객체 구조 분해를 사용하여 price와 location 속성을 각각의 변수로 분리하여 받는다 getTaxInformation(location)
:taxService.js
파일에서 가져온getTaxInformation
함수를 호출하여 해당 위치에 대한 세금 정보를 가져옴. (getTaxInformation() 외부 함수를 호출 할때 시작, 이 함수는 제공된 위치에 대한 세금 비율을 반환)- 우리는 단지 return되는 문자열만 필요할 뿐인데, 이 함수가 외부 서비스, 설정 파일, 네트워크 통신 등에 의존하게 될 경우 복잡해진다.
- 이 문제를 해결하려면
모의 객체(mock)
을 생성해서 함수를 가로채고 명시적인 반환값을 설정!!!
(가짜 함수를 생성해서 가짜 값을 반환한다 라고 이해하면 편할 듯)
import expect from 'expect';
import sinon from 'sinon';
import * as taxService from './taxService';
import { formatPrice } from './problem';
describe('금액 표시', () => {
let taxStub;
beforeEach(() => {
taxStub = sinon.stub(taxService, 'getTaxInformation'); // <label id="test.stub" />
});
afterEach(() => {
taxStub.restore(); // <label id="test.restore" />
});
it('세금 정보가 없으면 세금 추가를 안내해야 한다', () => {
taxStub.returns(null); // <label id="test.stub2" />
const item = { price: 30, location: 'Oklahoma' };
const user = 'Aaron Cometbus';
const message = formatPrice(user, item);
const expectedMessage = 'Aaron Cometbus님의 합계 금액: $30 및 추가 세금';
expect(message).toEqual(expectedMessage);
});
it('세금 정보가 있으면 세금 금액을 알려줘야 한다', () => {
taxStub.returns(0.1);
const item = { price: 30, location: 'Oklahoma' };
const user = 'Aaron Cometbus';
const message = formatPrice(user, item);
const expectedMessage = 'Aaron Cometbus님의 합계 금액: $30 및 추가 세금 $3';
expect(message).toEqual(expectedMessage);
});
});
- 예제에서는 mocha 테스트 프레임워크를 사용했다.
(mocha에 대한 자세한 설명은 나중에 다른 포스팅으로 소개!) - 10 line : taxStub 생성, getTaxInformation 함수를 덮어 써서 간단한 반환값을 반환(taxStub.returns(반환값);)
- 14 line : 테스트 꾸러미가 종료되면 원래의 메서드를 사용하도록 코드를 복구한다.
- 만약 예제 코드보다 더 많은 외부함수를 호출하고 밀접하게 결합된 코드는 의존성 주입(Dependency Injection)을 해야한다.
(의존성을 인수로 전달하는 것이다.)
function formatPrice(user, { price, location }, getTaxInformation) {
const rate = getTaxInformation(location);
const taxes = rate ? `추가 세금 $${price * rate}` : '추가 세금';
return `${user}님의 합계 금액: $${price} 및 ${taxes}`;
}
- 위와 같이 getTaxInformation()을 인수로 전달한다.
- 이제 stub이 필요하지 않게 되었고, 테스트를 작성할 때 불러오기를 생략할 필요 없다.
- 그 대신 필요한 값을 반환하는 간단한 함수를 작성하면 된다.
import expect from 'expect';
import { formatPrice } from './test';
describe('금액 표시', () => {
it('세금 정보가 없으면 세금 추가를 안내해야 한다', () => {
const item = { price: 30, location: 'Oklahoma' };
const user = 'Aaron Cometbus';
const message = formatPrice(user, item, () => null); // 스텁 대신 () => null 로 간단한 함수 반환!!
expect(message).toEqual('Aaron Cometbus님의 합계 금액: $30 및 추가 세금');
});
it('세금 정보가 있으면 세금 금액을 알려줘야 한다', () => {
const item = { price: 30, location: 'Oklahoma' };
const user = 'Aaron Cometbus';
const message = formatPrice(user, item, () => 0.1);
expect(message).toEqual('Aaron Cometbus님의 합계 금액: $30 및 추가 세금 $3');
});
});
- 테스트 코드를 좀 더 작성하기 쉬워졌고, 코드가 단일 책임을 갖도록 책임을 줄이는 면에서도 효율적이다.
- 일어날 수 있는 Test Case를 고려하며, 테스트를 작성하기 쉽게 코드를 변경해야 한다.
tip33. 화살표 함수로 복잡도를 낮춰라
mozila에서 설명하는 화살표 함수는 다음과 같다.
- 화살표 함수(=>, Arrow Function) : 함수 표현식에 대한 간결한 대안으로, 약간의 의미 차이와 의도적인 사용상의 제한을 가진다.
- 화살표 함수에는 자체 바인딩이 this에 없으며, 인수 또는 super로 사용해야 하며, 메서드로 사용 불가
- 화살표 함수는 생성자로 사용할 수 없다.(new로 호출하면 TypeError가 반환)
- 화살표 함수는 함수 내부에서 yield를 사용할 수 없으며 Generator 함수로 생성불가.
- 화살표 함수에서 인수를 해체 할당하는 방법, 객체를 반환하는 방법, 고차함수를 만드는 방법을 알아보자.
- 해체 할당하는 방법과 객체를 반환하는 방법은 아래 코드로 살펴보자.
const name = {
first: 'Kevin',
last: 'De Bruyne',
};
function getName({ first, last }) {
return `${first} ${last}`;
}
const getName = ({ first, last }) => `${first} ${last}`
getName(name) // "Kevin De Bruyne"
- 화살표 함수를 사용하고 매개변수의 객체을 () 감싼다.
- return 값이 객체를 반환할 경우는 꼭 화살표 우측 반환될 객체를 () 감싼다.
- const getName = ({ first, last }) => ({ fullName:${first} ${last}});
- 다른 함수를 반환하는 고차함수 만들기는 다음 팁에서 자세히 알아볼 예정
const discounter = discount => {
return price => {
return price * (1 - discount);
};
};
const tenPercentOff = discounter(0.1); // discount 매개변수에 할당
tenPercentOff(100); // 90 // price 매개변수에 할당
tenPercentOff = (price) => {
return price * (1 - 0.1)
}
const discounter = discount => price => price * (1 - discount);
discounter(0.1)(100);
- line 1~5를 우리가 알던 function 방식으로 바꿔본다면 아래 코드와 같다.(아래코드 참조)
- line 13 : return, 중괄호 생략한 고차 함수 discounter 선언
- line 15 : 고차함수 discounter의 매개변수 discount에 0.1을 받고, 바로 뒤에 괄호로 연결해서 매개변수 price에 100을 전달하면 이어서서 호출한다.
function discounter(discount) {
return function(price) {
return price * (1 - discount);
};
}
엇?! 이게 그래도 보기 편한데...라고 생각할 수 있지만,
그럼에도 불구하고 화살표 함수로 바꾸는 이유는
- 간결한 문법 : 함수 선언을, 특히 중첩된 함수의 경우, 화살표 함수를 사용하면 코드가 더 간결해진다.
- 자동 바인딩 : 화살표 함수는 자신의 this를 바인딩하지 않고, 외부 스코프의 this를 그대로 사용한다.
(이는 일반 함수에서 발생하는 this 오류를 예방할 수 있다.) - 암묵적 반환 : 화살표 함수는 중괄호 {}를 사용하지 않고 한 줄로 표현 가능하여, 암묵적으로 반환한다.
- 메서드에서 사용 : 화살표 함수는 메서드로 사용될 때 객체의 바인딩을 유지하므로, 객체 내부에서 화살표 함수를 사용할 때 유용하다.
사실 레거시 코드나, 실무에서 직관적이고 기존의 방식을 고수하기 때문에,
화살표 함수 사용하기를 꺼려하는 경우도 종종 있다.
필자도 화살표 함수뿐만 아니라 다른 자바스크립트의 기술들 또한
모르고 익숙치 않다는 핑계로 잘 사용하지 않았다.
개발자는 내가 모른다고 해서, 익숙하지 않다고 해서,
익히지 않고 공부하지 않는 것은 옳지 않다.
계속해서 계발하고, 개발하자!
끝.
Reference
- 자바스크립트 코딩의 기술 요약 / 정리
- JavaScript - MDN Web Docs
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions/Arrow_functions
- lexical environment와 closure
728x90
반응형
'IT > Javascript' 카테고리의 다른 글
Javascript 자바스크립트 코딩의 기술 8장 클래스로 인터페이스를 간결하게 유지하라 (1) (2) | 2024.02.28 |
---|---|
Javascript 자바스크립트 코딩의 기술 7장 유연한 함수를 만들어라 (2) (0) | 2024.02.23 |
Javascript 자바스크립트 코딩의 기술 6장 매개변수와 return 문을 정리하라 (14) | 2024.02.15 |
Javascript 자바스크립트 코딩의 기술 5장 반복문을 단순하게 만들어라 (2) (0) | 2024.02.06 |
Javascript 자바스크립트 코딩의 기술 5장 반복문을 단순하게 만들어라 (1) (0) | 2024.01.24 |