Skip to content

Files

Latest commit

13ecab1 · Feb 28, 2024

History

History

zhoon

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Feb 28, 2024

6장. 함수형 프로그래밍

정수를 제곱하기

  • 클로저 방식
(println (take 25(map (fn [x] (* x x)) (range))))
0..24 |> Enum.map(fn x -> x * x end) |> Enum.each(fn x -> IO.puts(x) end)
  • 자바는 가변 변수를 사용
  • 클로저 (그리고 엘릭서) 에는 가변 변수가 전혀 없음
  • 함수형 언어에서 변수는 변경되지 않음

불변성과 아키텍처

  • 아키텍트는 왜 변수의 가변성을 염려하는가?
  • 경합 조건, 교착 상태 조건, 동시 업데이트 문제가 모두 가변 변수로 인해 발생하기 때문
  • 다시 말해 동시성 애플리케이션에서 마주치는 모든 문제, 즉 다수의 스레드와 프로세스를 사용하는 애플리케이션에서 마주치는 모든 문제는 가변 변수가 없다면 절대로 생기지 않음
  • 아키텍트라면 동시성 문제에 지대한 관심을 가져야만 함
    • 우리는 스레드와 프로세스가 여러 개인 상황에서도 설계한 시스템이 여전히 강건하기를 바람
  • 불변성은 정말로 실현 가능할까?
    • 대답은 대체로 긍정적
      • 단, 저장 공간이 무한하고 프로세서의 속도가 무한히 빠르다고 전제한다면
    • 자원이 무한대가 아니라면 대답은 조금 미묘함
    • 타협이 필요하다.

가변성의 분리

  • 불변성과 관련하여 가장 주요한 타협 중 하나
    • 애플리케이션, 또는 애플리케이션 내부의 서비스를 가변 컴포넌트와 불변 컴포넌트로 분리하는 일
  • 불변 컴포넌트
    • 순수하게 함수형 방식으로만 작업이 처리됨
    • 어떤 가변 변수도 사용되지 않음
    • 변수의 상태를 변경할 수 있는, 즉 순수 함수형 컴포넌트가 아닌 하나 이상의 다른 컴포넌트와 서로 통신함
  • 상태 변경은 컴포넌트를 갖가지 동시성 문제에 노출하는 꼴
    • 흔히 트랜잭션 메모리와 같은 실천법을 사용하여 동시 업데이트와 경합 조건 문제로부터 가변 변수를 보호함
  • 트랜잭션 메모리
    • 데이터베이스가 디스크의 레코드를 다루는 방식과 동일한 방식으로 메모리의 변수를 처리
    • 트랜잭션을 사용하거나 또는 재시도 기법을 통해 이들 변수를 보호함
  • 클로저의 atom 기능
    • CAS 알고리즘을 전략으로 사용
      • 이건 Java 의 Atom~ 과 동일한 알고리즘
  • 애플리케이션을 제대로 구조화하려면 변수를 변경하는 컴포넌트와 변경하지 않는 컴포넌트를 분리해야 함
    • 그리고 이렇게 분리하려면 가변 변수들을 보호하는 적절한 수단을 동원해 뒷받침해야함
  • 현명한 아키텍트라면 가능한 한 많은 처리를 불변 컴포넌트로 옮겨야 하고, 가변 컴포넌트에서는 가능한 한 많은 코드를 빼내야 한다.

이벤트 소싱

  • 이벤트 소싱은 상태가 아닌 트랜잭션을 저장하자는 전략
  • 상태가 필요해지면 단순히 상태의 시작점부터 모든 트랜잭션을 처리
  • 애플리케이션은 CRUD 에서 CR 만 수행
  • 저장 공간과 처리 능력이 충분하면 애플리케이션이 완전한 불변성을 갖도록 만들 수 있고, 완전한 함수형으로 만들 수 있다.

결론

  • 구조적 프로그래밍
    • 제어흐름의 직접적인 전환에 부과되는 규율
  • 객체 지향 프로그래밍
    • 제어흐름의 간접적인 전환에 부과되는 규율
  • 함수형 프로그래밍
    • 변수 할당에 부과되는 규율
  • 소프트웨어, 즉 컴퓨터 프로그램은 순차, 분기, 반복, 참조로 구성된다. 그 이상도 이하도 아니다.