[Clean Architecture] 6장. 함수형 프로그래밍
|정수를 제곱하기
- 클로저 방식
|
|
|
|
- 자바는 가변 변수를 사용
- 클로저 (그리고 엘릭서) 에는 가변 변수가 전혀 없음
- 함수형 언어에서 변수는 변경되지 않음
불변성과 아키텍처
- 아키텍트는 왜 변수의 가변성을 염려하는가?
- 경합 조건, 교착 상태 조건, 동시 업데이트 문제가 모두 가변 변수로 인해 발생하기 때문
- 다시 말해 동시성 애플리케이션에서 마주치는 모든 문제, 즉 다수의 스레드와 프로세스를 사용하는 애플리케이션에서 마주치는 모든 문제는 가변 변수가 없다면 절대로 생기지 않음
- 아키텍트라면 동시성 문제에 지대한 관심을 가져야만 함
- 우리는 스레드와 프로세스가 여러 개인 상황에서도 설계한 시스템이 여전히 강건하기를 바람
- 불변성은 정말로 실현 가능할까?
- 대답은 대체로 긍정적
- 단, 저장 공간이 무한하고 프로세서의 속도가 무한히 빠르다고 전제한다면
- 자원이 무한대가 아니라면 대답은 조금 미묘함
- 타협이 필요하다.
- 대답은 대체로 긍정적
가변성의 분리
- 불변성과 관련하여 가장 주요한 타협 중 하나
- 애플리케이션, 또는 애플리케이션 내부의 서비스를 가변 컴포넌트와 불변 컴포넌트로 분리하는 일
- 불변 컴포넌트
- 순수하게 함수형 방식으로만 작업이 처리됨
- 어떤 가변 변수도 사용되지 않음
- 변수의 상태를 변경할 수 있는, 즉 순수 함수형 컴포넌트가 아닌 하나 이상의 다른 컴포넌트와 서로 통신함
- 상태 변경은 컴포넌트를 갖가지 동시성 문제에 노출하는 꼴
- 흔히 트랜잭션 메모리와 같은 실천법을 사용하여 동시 업데이트와 경합 조건 문제로부터 가변 변수를 보호함
- 트랜잭션 메모리
- 데이터베이스가 디스크의 레코드를 다루는 방식과 동일한 방식으로 메모리의 변수를 처리
- 트랜잭션을 사용하거나 또는 재시도 기법을 통해 이들 변수를 보호함
- 클로저의 atom 기능
- CAS 알고리즘을 전략으로 사용
- 이건 Java 의 Atom~ 과 동일한 알고리즘
- CAS 알고리즘을 전략으로 사용
- 애플리케이션을 제대로 구조화하려면 변수를 변경하는 컴포넌트와 변경하지 않는 컴포넌트를 분리해야 함
- 그리고 이렇게 분리하려면 가변 변수들을 보호하는 적절한 수단을 동원해 뒷받침해야함
- 현명한 아키텍트라면 가능한 한 많은 처리를 불변 컴포넌트로 옮겨야 하고, 가변 컴포넌트에서는 가능한 한 많은 코드를 빼내야 한다.
이벤트 소싱
- 이벤트 소싱은 상태가 아닌 트랜잭션을 저장하자는 전략
- 상태가 필요해지면 단순히 상태의 시작점부터 모든 트랜잭션을 처리
- 애플리케이션은 CRUD 에서 CR 만 수행
- 저장 공간과 처리 능력이 충분하면 애플리케이션이 완전한 불변성을 갖도록 만들 수 있고, 완전한 함수형으로 만들 수 있다.
결론
- 구조적 프로그래밍
- 제어흐름의 직접적인 전환에 부과되는 규율
- 객체 지향 프로그래밍
- 제어흐름의 간접적인 전환에 부과되는 규율
- 함수형 프로그래밍
- 변수 할당에 부과되는 규율
- 소프트웨어, 즉 컴퓨터 프로그램은 순차, 분기, 반복, 참조로 구성된다. 그 이상도 이하도 아니다.