[프로그래밍] 프로그래밍 패러다임

Dev_Honey·2022년 11월 7일
0

프로그래밍

목록 보기
1/1

좋은 코드를 짜기 위한 고찰

프로그래밍에 대한 다양한 패러다임의 이해와 활용은 좋은 코드를 짤 수 있는 힘을 만들어 준다.

프로그래밍 패러다임

명령형 프로그래밍

무엇을 할 것인지 나타내기보다 어떻게 할 건지를 설명하는 패러다임

1. ⌨️절차지향프로그래밍⌨️

수행되어야 할 순차적인 처리 과정을 포함하는 방식 >> C, C++


2. ⌨️객체지향프로그래밍⌨️

객체들의 집합으로 프로그램의 상호작용을 표현 >> C++,Java,C#
객체지향 프로그래밍 패러다임은 객체를 중심으로 사고하고 프로그램을 작성하는 것


선언형 프로그래밍

어떻게 할 것인지 나타내기보다 무엇을 할 것인지를 설명하는 방식

3. ⌨️함수형프로그래밍⌨️

3-1.왜 주목받기 시작하였는가?

  • 함수형 프로그래밍?

Functional Programming is programming without assignment satements
-Rober C.Martin -
== 함수형 프로그래밍은 대입문이 없는 프로그래밍이다 라고 정의

명령형 프로그래밍을 기반으로 개발했던 개발자들은 개발하는 소프트웨어의 크기가 커짐에 따라, 복잡하게 엉켜있는 스파게티 코드를 유지보수하는 것이 매우 힘들다는 것을 깨닫게 되었다. 그래서 이를 해결하기 위해 나온 것이 함수형 프로그래밍!!
자료처리를 수학적 함수의 계산으로 취급하고 상태와 가변 데이터를 멀리하는 프로그래밍 패러다임
문이 아닌 식이나 선언으로 수행되는 선언형 프로그래밍 패러다임을 따른다.
다수의 함수형 프로그래밍 언어들은 람다 연산을 발전시킨 것으로 볼 수 있다.

  • 대표 언어
    클로저, 스칼라, 하스켈 ...
    최근, 자바스크립트,코틀린,파이썬 등에도 함수형 프로그래밍 문법이 추가
  • 불변성
    불변이 아닌 변수는 예상치 못한 상황에 예기치 못한 값으로 변경될 가능성이 있다. 그러나, 함수형 프로그램은 대입문이 없기 때문에 기본적으로 한 번 값이 변수에 할당 되고 나면 이후에 값이 변경되지 않는다.
    Side effect
    (변수의 값이 변경,자료 구조를 제자리에서 수정,객체의 필드랎을 설정,예외나 오류가 발생하며 실행이 중단,콘솔 또는 파일 I/O가 발생,메일보내기,DOM의 변화,서버와의 통신)
    가 발생하지 않기때문에 표현식을 언제 어느 때 실행하더라도 문제가 발생하지 않으므로 프로그래머에게 편의를 제공한다. 이러한 부분을 참조 투명성이 있다고하는데, 함수형 프로그래밍은 이 참조 투명성이 있기때문에 Multicore Processs에서 교착상태에 빠지지 않는다는 장점이 있다.따라서, 동시성 프로그래밍에서 강력한 패러다임으로 작용하고 있다.
  • 참조투명성 == 참조 투명성와 참조 투명도는 컴퓨터 프로그램의 일부 속성이다. 프로그램 동작의 변경없이 관련 값을 대체할 수 있다면 표현식을 참조 상 투명하다고 할 수 있다. 그 결과, 참조 상 투명한 함수를 평가하게 되면 동일한 인자에 대해 동일한 값을 반환해야 한다. 그러한 함수를 순수 함수라고 부른다. 참조상 투명하지 않은 표현식은 참조상 불투명 하다고 한다.
  • 명확성
    함수가 하는 process는 명확하게 정의되기때문에 코드의 가독성이 좋다. 또한 함수를 parameter로 사용할 수도 있다. 이해하기 쉬운 표현식에 의해 함수의 결합을 통한 고차함수를 사용할 때도 간결하게 표현할 수 있다. 익명함수의 사용도 가능
    Java8의 StreamAPI를 통해 명확성을 살펴보자!
List<Integer> values = Arrays.asList(7, 5, 123, 5, 42, 95, 68, 30, 42);
//숫자 리스트
        List<Integer> result = values.stream()
            // result = 숫자가 담긴 리스트 스트림
            .filter(number -> number < 50)
            //필터링은 50미만의 숫자
            .distinct()
            //중복제거
            .sorted(Integer::compare)
            //정렬(Integer 타입의 compare 매서드로)
            .collect(Collectors.toList());
            //연산결과를 합치는데 collectors의 tolist 매서드로 리스트 반환

순수 함수(Pure Function)
이러한 부수 효과(Side Effect)들을 제거한 함수들을 순수 함수(Pure Function)이라고 부르며, 함수형 프로그래밍에서 사용하는 함수는 이러한 순수 함수이다.

  • Memory or I/O의 관점에서 부수효과가 없는 함수
  • 함수의 실행이 외부에 영향을 끼치지 않는 함수
  • 순수 함수의 장점
    • 함수 자체가 독립적, 부수효과가 없기 때문에 Thread에 안정성을 보장
    • Thread에 안정성을 보장 받기에 병렬 처리를 동기화 없이 진행

1급 객체(Pure Function)의 장점

  • 변수나 데이터 구조 안에 담을 수 있음
  • 파라미터로 전달 할 수 있음
  • 반환값으로 사용가능
  • 할당에 사용된 이름과 무관하게 고유한 구별이 가능
  • 동적으로 프로퍼티 할당이 가능하다.

고계 함수
고계 함수(higher-order function)란 함수를 다루는 함수를 뜻한다. 함수형 언어에서 함수도 value로 취급한다. 정수를 함수의 인수로 전달할 수 있듯이 어떤 함수도 다른 함수의 인수로 전달할 수 있다. 마찬가지로 함수의 결과로 함수를 반환할 수 있다.
고계 함수인 map(arg1,arg2)은 첫 번째 인수르 주어진 함수를 두 번째 인수로 주어진 리스트의 각 원소에 적용한 결과의 리스트를 반환한다.

명령형 프로그래밍 코드

// 1 ~ 10까지의 값이 i에 할당된다
for(int i = 1 ; i < 10; i++){
    System.out.println(i);
}

위 코드와 아래 코드의 차이점을 보면, 위는 변수가 할당되고 값이 대입되는 코드!
아래는, 대입문을 사용하지 않는 것이 특징인 함수형 코드
출력을하는 print()함수를 process 함수의 인자로 넘겼다.이는, 함수형 프로그래밍의 원리 중 1급 객체(Fist-Class Object)로 관리하는 특징을 이용

process(10, print(num));

즉!! 함수형 프로그래밍에서 가장 중요한 3요소???
순수함수->"코드를 액션과 계산, 데이터로 분리. 특히, 액션에서 계산을 분리하는 코드를 작성하자!",
불변성->"Copy On Write 와 방어적복사를 이용하여 불변성 유지",
선언적 패턴->"계층형 설계와 추상화 벽을 이용하여 무엇과 어떻게를 구분하여 좋은 설계를 유지"`

장점

  • 혼동되는 오류와 문제를 피할 수 있다.
  • 테스트와 디버깅이 용이함
  • 더 나은 모듈화와 Short 코드를 제공
  • 개발 생산성을 Up
  • 가독성이 높은 코드
  • 부수효과 제거
  • 함수 단위의 코드 재사용이 쉽다.
  • 프로그램의 동작을 예측하기 쉽다.

한계

  • 함수형 프로그램의 개념이 어렵다
  • 프로그래밍을 진행하며 산출된 모든 함수를 파악하고 유지하기가 쉽지않다.
  • 광범위의 환경 설정이 필요할 수 있다.
  • 함수가 많아지면 조합하기가 복잡해지고 지속적인 리팩토링이 필요할 수 있다.

액션, 계산, 데이터로 분리하자!

  • Action : 호출 시점과 실행 횟수에 의존
  • Calc : 입력과 출력으로 이루어짐
  • Data : 이벤트에 대한 사실

이것을 F.E관점에서 풀어보면
DATA : 이벤트에 대한 사실. 데이터는 화면에 보여줄 수 있음
Action : 실행시점이나 횟수에 의존. 버튼 클릭에 의해 숫자의 증가 또는 다회 클릭으로 인한 output의 변화
Calc : 입력값을 통해 출력값을 만들어 내는 것. 클릭으로 숫자를 더해 숫자를 만들어내는 것과 같은 것
Action -> 정의된 Calc -> Data Change

// 함수형 프로그래밍 관점에서 분리해보자.
function App() {
  // 데이터
  const [count, setCount] = useState(0)
  // 계산
  const increase = (value) => value + 1
  // 액션
  const onClick = () => setCount(increase(count))
  // 선언적 패턴
  return <button onClick={onClick}>{count}</button>
}

단순한 함수 쪼개기는 action,data,calc의 분리가 아니다

  • Calc : 계산은 반드시 I/O로 이루어져야 하며, 같은 입력 값에 대해서는 항상 같은 출력값을 내놓아야 합니다. 즉, f(x)를 리턴하는 것 과 같음
  • 함수형 프로그래밍은 액션과 계산을 확실하게 분리하여 액션을 최소화, 계산함수를 많이 만들어 관리를 하는 것을 목표로 한다.
    ex)
const increase = (count, offset) => {
  const result = count + offset // count와 offset을 명시적 입력으로 변경합니다.
  // setState와 같은 명시적 출력은 사용하지 않습니다.
  return result
}
// 계산이 바로 순수함수, 부수효과 없음
// 암묵적인 입출력은 별도의 action에 모아줍니다.
const action = () => {
  setState(increase(count, 1)) // 외부에서 필요한 모든 입력을 넣어줍니다.
}

불변성

pass by reference -> pass by value
함수형 프로그래밍에서는 pass by value 모델과 같이 함수의 동작이 외부세계에 영향을 미쳐서는 안된다.

// 1씩 증가하는 계산 함수
const increase = (value) => value + 1
// 1씩 증가하는 값을 배열에 넣는 함수 ex) [1] -> [1,2] -> [1,2,3]
const increase = (arr) => {
  const value = arr[arr.length - 1]
  arr.push(value + 1)
  return arr
}
//위에서 아래로의 코드 변화 !! 엄청 간결해진다.
const increase = (arr) => {
  arr = arr.slice() // array를 조작하기 전에 복사해서 사용한다.
  const value = arr[arr.length - 1]
  arr.push(value + 1)
  return arr
}
// spread 표기법을 쓴다면 더 간결하게 작성할 수 있다.
const increase = (arr) => [...arr, arr[arr.length - 1]]

Line Game Cloud가 함수형 프로그래밍을 선택한 이유

  • keyWord
    동시성,코드의간결,개발 시간을 단축,Clojure,불변성,1급객체
    https://engineering.linecorp.com/ko/blog/functional-programing-language-and-line-game-cloud/
  • Thread : 스레드(thread)란 프로세스(process) 내에서 실제로 작업을 수행하는 주체를 의미
  • 피보나치 수열
    수학에서 피보나치 수(영어: Fibonacci numbers)는 첫째 및 둘째 항이 1이며 그 뒤의 모든 항은 바로 앞 두 항의 합인 수열이다. 처음 여섯 항은 각각 1, 1, 2, 3, 5, 8이다. 편의상 0번째 항을 0으로 두기도 한다.

Javascript
함수형 패러다임을 기반으로 하면서 객체지향의 문법을 쓰는 독특한 언어!! 즉, 완전한 함수형 언어도 객체지향 언어도 아닌 멀티 패러다임의 언어이다.
일정한 체계없이도 돌아가는 코드를 짤 수 있다 === 무분별하게 나쁜 코드로 작성 할 수 도 있다.
즉, 코드를 짤 때 javascript는 객체지향스럽게 작성을 하면서도 함수형 프로그래밍 패러다임으로 개발하는 것이 좋다!
Array Method,Promise,Event Listener,setTimeout,React의 hook,Redux 등이 함수형 패러다임이 녹아있는 js Library and Api !

코드 분리의 좋은 점

  • 재사용성이 UP
  • 유지보수가 좋다
  • 테스트가 쉽다

계층적 구조
계층이 견고해지는 구조로 작성을 하게 되면 유연하면서도 변화에 국지적인 형태의 좋은 설계를 가져가게 된다. 상위에는 기획서에 가까운 무엇을 해야할지만 기술을 하는 선언적 패턴으로 코드를 가져갈 수 있게 되고 하위에는 태스트가 쉬운 코드 조각들로 구성이 된다.


출처 및 참고

https://ko.wikipedia.org/wiki/%ED%95%A8%EC%88%98%ED%98%95_%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D

https://velog.io/@teo/functional-programming 함수형 프로그래밍

profile
자습서 같은 공부 블로그 만들기!

0개의 댓글