선언적 프로그래밍 이라는 개념을 Dev Matching의 해설을 보며 처음 접했다. 장점이 많은 프로그래밍 패러다임이여서 그것에 대해 알아보고 코드에 어떻게 적용시킬지 알아보자.
선언적 프로그래밍(declarative programming)
- What- What to do
- 무엇을 하는지에 초점을 맞추는 것
명령형 프로그래밍(imperative programming)
- How
- 어떻게 할건지를 순서대로 나열한 것
추상적인 예
집에 가는 경우
- 선언적 방식 : 서울특별시 왕십리역입니다.
- 명령형 방식 : 주차장 북쪽 출구를 나와 왼쪽으로 가세요. 12번가 출구에 도착할 때까지 15번 북쪽 도로를 타세요. 이케아를 끼고 우회전하세요. 직진하여 첫 번째 신호등에서 우회전 하세요. 다음 신호등을 지나 좌회전을 하세요.
선언적 프로그래밍의 장점
- 가독성
- 재사용성
- 참조 투명성
- 대체 가능성
Javascript에서 실제 구현 예제
1. 배열 반복하며 값을 가공할때 - Array.map()
명령형 프로그래밍
// 1
const arr = [1, 2, 3, 4];
const doubleArr = [];
for(let i = 0; i < arr.length; i++){
doubleArr.push(arr[i] * 2);
}
// console.log(doubleArr) // [2, 4, 6, 8]
// 2
const n = [-9, 87, 72, 452, 32, -9]
for(let i = 0; i < n.length; i++) {
console.log(n[i])
}
선언적 프로그래밍
// 1
const arr = [1, 2, 3, 4];
const doubleArr = arr.map(i => i * 2)
console.log(doubleArr) // [2, 4, 6, 8]
// 2
const n = [-9, 87, 72, 452, 32, -9]
const z = n.map(v => (v * 2) - 1)
선언적 프로그래밍이 좀더 가독성이 좋고 선언적이다.
가급적 for loop은 사용하지 말자.
array.map?
array.map의 기본적인 사용법
const numbers = [1, 2, 3, 4];
numbers.map((number, index, source) => {
// number: 요소값
// index: source에서 요소의 index
// source: 순회하는 대상
console.log(number); // 1
console.log(index); // 0
console.log(source); // [1]
return number * number;
});
결과값
1
0
[1, 2, 3, 4]
2
1
[1, 2, 3, 4]
3
2
[1, 2, 3, 4]
4
3
[1, 2, 3, 4]
2. 배열 반복하며 if문 실행할 때 - Array.filter()
명령형 프로그래밍
// 1
const numbers = [1, 2, 3, 4];
const result = [];
for(let i = 0; i < numbers.length; i++) {
if (numbers[i] % 2 === 0) {
result.push(numbers[i]);
}
}
// 2
const numbers = [1, 2, 3, 4, 5];
const result = [];
for (i = 0; i< numbers.length; i++) {
const number = numbers[i];
if (number > 3) {
result.push(number);
}
}
선언적 프로그래밍
// 1
const numbers = [1, 2, 3, 4];
const evenNum = numbers.filter((number) => number % 2 === 0);
// 2
const numbers = [1, 2, 3, 4, 5];
const result = numbers.filter((number) => number > 3);
가독성 업업
array.filter?
array.filter의 기본적인 사용법
const numbers = [1, 2, 3, 4, 5];
numbers.filter((number, index, source) => {
// index: 요소값
// index: 요소의 index
// source: 순회하는 대상
console.log(number)
console.log(index)
console.log(source)
})
결과값
1
0
[1, 2, 3, 4, 5]
2
1
[1, 2, 3, 4, 5]
3
2
[1, 2, 3, 4, 5]
4
3
[1, 2, 3, 4, 5]
5
4
[1, 2, 3, 4, 5]
더 나아가 재사용이 가능하게 만들기
const isNumberEven = (number) => number % 2 === 0;
const fn = (numbers) => numbers.filter(isNumberEven);
let numbers = [1, 2, 3, 4];
console.log(fn(numbers))
console.log(fn([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))
3. 배열의 값을 단일 값으로 줄일때(값 합산) - Array.reduce()
명령형 프로그래밍
const numbers = [1, 2, 3, 4];
let total = 0;
for (let number of numbers) {
total += number;
}
선언적 프로그래밍
const numbers = [1, 2, 3, 4];
const total = numbers.reduce((total, number) => total += number, 0);
array.reduce?
array.reduce의 기본적인 사용법
예시1 - accumulator가 있을 때
// accumulator가 있을 때
const numbers = [1];
const result = numbers.reduce((acc, number, index, source) => {
// accumulator : 누적값(초기값이 정해지지 않은 경우, 배열 인자의 첫번째 값 사용)
// number : 요소값
// index : 요소의 index
// source : 순회하는 대상
console.log(acc);
console.log(number);
console.log(index);
console.log(source);
return acc + number;
}, 10)
console.log(result)
결과값
10
1
0
[1]
11
예시2 - accumulator가 없을 때
// accumulator가 없을 때
const numbers = [1];
const result = numbers.reduce((acc, number, index, source) => {
// accumulator : 누적값( 초기값이 정해지지 않은 경우, 배열 인자의 첫번째 값 사용)
// number : 요소값
// index : 요소의 index
// source : 순회하는 대상
console.log(acc);
console.log(number);
console.log(index);
console.log(source);
return acc + number;
}, 0)
console.log(result)
결과값
0
1
0
[1]
1
Review
명령형 프로그래밍
const numbers = [1, 2, 3, 4];
const numbersDoubled = [];
for (let i = 0; i < numbers.length; i++) {
numbersDoubled.push(numbers[i] * 2);
}
const evenNumbers = [];
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] % 2 === 0) {
evenNumbers.push(numbers[i]);
}
}
let numbersTotal = 0;
for (let number of numbers) {
numbersTotal += number;
}
console.log(numbersDoubled) // [2, 4, 6, 8]
console.log(evenNumbers) // [2, 4]
console.log(numbersTotal) // 10
선언적 프로그래밍
const numbers = [1, 2, 3, 4];
const numbersDoubled = numbers.map(number => number * 2)
const evenNumbers = numbers.filter(number => number % 2 === 0);
const numbersTotal = numbers.reduce((numbersTotal, number) => numbersTotal += number, 0)
console.log(numbersDoubled) // [2, 4, 6, 8]
console.log(evenNumbers) // [2, 4]
console.log(numbersTotal) // 10
일단 배열 위주로 알아보았는데
객체도 같다. for문을 전혀 사용하지 않도 선언형 대체제들이 많이 있다.
이곳을 참고하여 객체 순회 또한 코드에 적용시키는게 좋을듯 싶다.
https://peter-cho.gitbook.io/book/3/3_5#undefined-1
선언형으로 대체 가능한 문법들 정리 - 실용주의 프런트 엔드 개발
range(10) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
peter-cho.gitbook.io
Reference
https://www.bitovi.com/blog/understand-declarative-vs-imperative-code-using-array-functions
https://dev.to/adnanbabakan/declarative-programming-with-javascript-2h97
'개발 > JavaScript' 카테고리의 다른 글
[Javascript] null VS undefined (0) | 2022.03.04 |
---|---|
[JS] 전개구문(Spread Syntax) - ...(three dots) (0) | 2022.02.25 |
JS, CSS, HTML로 만든 슬라이드 (0) | 2021.11.10 |
[ES6] 구조 분해 할당 (let {} 사용방법) (0) | 2021.11.09 |
[Javascript] 변수(const, var, let)와 전역공간 (0) | 2021.07.23 |