관리 메뉴

김종권의 iOS 앱 개발 알아가기

[Clean Architecture] 6. 함수형 프로그래밍 본문

Clean Architecture/Clean Architecture 기초

[Clean Architecture] 6. 함수형 프로그래밍

jake-kim 2021. 3. 24. 01:47

함수형 프로그래밍

  • 함수형 프로그래밍의 핵심은 가변 변수: 가능한 가변 변수를 지양
  • race condition, deadlock, concurrent update 문제 해결을 위한 프로그래밍
  • 람다(lambda) 계산법이 핵심 (Alonzo Church, 1930년대에 발명)
    cf) 1958년 최초 함수형 프로그래밍 List, 1972년 절자치향 프로그래밍 c언어
  • 클로저 표현식 존재
  • 4가지 특징

1. Pure Functions

  • 외부의 상태값을 참조 or 변경할수 없는 것
// x

let num = 1

func add(a: Int) {
    return a + num 
}

2. Statesless, Immutability (= no sideEffect)

  • multi thread 환경에서도 안정적으로 동작 가능
// x

let person = Person(name: "kim", age: 99)

func increaseAge(person) -> Person {
    return Person(name: person.name, age: person.age + 1) // 자바 스크립트에서는 불변성을 위해 Object.freeze(person + 1) 사용하여 해결
}

3. Expressions only

  • if, swift, for 문 사용 x (되도록 map, filter, reduce 사용)
// x

multiply(numbers: [1, 2, 3], multiplier: 3) // [3, 6, 9]

func multiply(numbers: [Int], multiplier: Int) {
    var newNumbers = [Int]()
    
    for i in 0..<numbers.count {
        newNumbers.append(0)
        let index = newNumbers.index(0, offsetBy: i)
        newNumbers[index] = numbers[index] * multiplier
    }
}
// o

multiply(numbers: [1, 2, 3], multiplier: 3) // [3, 6, 9]

func multiply(numbers: [Int], multiplier: Int) -> [Int] {
    return numbers.map { (value) -> Int in
        return value * multiplier
    }
}

4. first-class and higher-order functions

  • first-class(함수 밖에서 일어나는 특징): 함수를 변수로 할당
  • higher-order functions(함수 내부에서 일어나는 특징): 함수를 인자로 받는 함수, 함수를 리턴하는 함수
// first-class: 함수를 변수에 할당
let completion = {
    print("completion")
}

plusPrint(3, 5, completion: completion) 

// higher-order function: 함수를 인자로 받는 함수
func plusPrint(_ a: Int, _ b: Int, completion: () -> Void) {
    print(a + b)
    completion()
}

함수형 프로그래밍의 개념

  • 함수형 프로그래밍은 가변 변수(mutable variable)을 사용하지 않는 특징
  • 가변 변수는 프로그램 실행 중에 상태가 변화 가능 (for문의 i가 대표적인 가변 변수)
  • 가변성을 고려하는 이유: race condition, deadlock, concurrent update 문제가 모두 가변 변수로 인해 발생
  • 아키텍처라는 것은 동시(concurrency) 문제에 관심 필요: 스레드와 프로세스가 여러 개인 상황에서도 시스템이 여전히 강건하기 위한 조건

가변성의 분리 (Event Sourcing)

  • 예시- transactional memory: 불러오기, 저장하기 명령의 집합이 원자적(atom) 방법으로 실행할 수 있게 함으로써 병렬 프로그래밍을 단순하게 하는 방식
(def counter (atom 0)); // counter를 0으로 초기화
(swap! counter inc); // counter를 안전하게 증가

출처: Clean Architecture

  • Event Sourcing (가변 변수 지향) 예제 - 은행 앱: 잔고를 변경하는 트랜잭션
    - 함수형o: 누군가 잔고를 조회할 요청할 때마다 개설 시점부터 발생한 모든 트랜잭션을 단순히 더하는 작업
    - 함수형x: 가변 변수 하나를 두고, 그 변수에 값을 업데이트

구조적 vs 객체 지향 vs 함수형 프로그래밍

  • 구조적 프로그래밍: 제어흐름의 직접적인 전환에 부과되는 규율
  • 객체 지향 프로그래밍: 제어흐름의 간접적인 전환에 부과되는 규율
    (핵심: 다형성을 이용하여 전체 시스템의 모든 소스 코드 의존성에 대한 절대적인 제어 권한을 획들할 수 있는 능력)
  • 함수형 프로그래밍: 변수 할당에 부과되는 규율

 

* 참고: Clean Architecture

Comments