kok202
쏙쏙 들어오는 함수형 코딩

2022. 5. 29. 23:00[공부] 독서

http://www.yes24.com/Product/Goods/108748841

 

쏙쏙 들어오는 함수형 코딩 - YES24

소프트웨어의 복잡성을 다루기 위해 꼭 읽어야 할 책이 책은 함수형 사고를 통해 의도하지 않은 복잡성이 코드 전체로 퍼져나가는 것을 막고 프로그래밍을 간단하게 하는 법을 담았다. 시스템

www.yes24.com

코드 레벨에 대한 설명이 많아 이는 생략하고 보편적인 가치 위주로 정리합니다.

(😛) 은 사견입니다.

 

함수형 프로그래밍

  1. 수학 함수를 사용하고 부수 효과를 피하는 것이 특징인 프로그래밍 패러다임
  2. 부수효과 없이 순수 함수마 사용하는 프로그래밍 스타일

 

부수효과

부수효과는 함수가 리턴 값 이외에 하는 모든 일을 의미한다.

부수효과는 소프트웨어를 사용하는 근본적인 이유다.

😛 가급적이면 부수 효과를 사용하지 않으려 해야하는 것이지 부수효과 자체를 부정해서는 안된다.

 

부수효과의 예시

  • 이메일 보내기
  • 파일 읽기
  • 불빛을 깜빡이기
  • 웹 요청을 하기

 

함수형 사고를 위한 중요 개념 2가지

  1. 액션 / 계산 / 데이터를 구분해서 생각하기
  2. 일급 추상

 

액션 / 계산 / 데이터

  • 액션: 암묵적 입출력 갖는 함수
  • 계산: 명시적 입출력 만을 갖는 함수
  • 데이터: 수동적이고 투명한 value

 

불변 데이터를 위한 두가지 원칙

  1. 카피 온 라이트: 데이터를 변경할 때 복사본을 만들어 수정하고 반환하는 것.
  2. 방어적 복사: 안전하지 않은 코드(서드파티 or 레거시 코드)를 사용하기 전 / 후에 데이터를 복사해서 사용하는 것.

 

액션과 계산을 구분하면 좋은 이유

계산은 외부에 영향을 주지 않기 때문에 쉽게 테스트가 가능하다.

😛 CQRS 와 같은 맥락이고 단어만 다르다라는 느낌을 받음.

 

함수형 프로그래머는 액션을 가급적 사용하려하지 않아야한다.

😛 인터페이스를 이용하면 액션도 런터임에 따라 계산이 될 수 있게 할 수 있다. 테스트 환경에서는 SUT 를 계산으로 동작하고, 실행 환경에서는 액션으로 동작하게 만들 수 있음. 계산의 가장 큰 장점은 deterministic 하다는 점인 듯

 

함수에 암묵적 입력과 출력이 있으면 액션이 된다.

  • 명시적 입력: 매개변수
  • 명시적 출력: 리턴값
  • 암묵적 입력: 전역변수 get (매개 변수 외 다른 입력)
  • 암묵적 출력: 전역변수 수정 (리턴값 외 다른 출력)

 

불변 데이터를 쓰면 데모리를 더 쓰고 느릴까?

분명 불변 데이터를 사용하지 않는 것보다 메모리를 더쓰고 느릴 수 있다. 하지만 불변 데이터를 사용해도 대용량 고성능 시스템의 구현 사례가 많다. 불변 데이터 구조를 사용하고 속도가 느린 부분을 최적화하면 된다. 

가비지 콜렉터는 생각보다 빠르며, 생각보다 복사는 많이 일어나지 않는다.

함수형 프로그래밍에서 map, filter, reduce 같은 체인을 최적화 하는 것을 스트림 결합이라고 부른다.

 

구조적 공유

두개의 중첩된 데이터 구조가 어떤 참조를 공유한다면 구조적 공유라고한다. 데이터가 바뀌지 않는 불변 데이터 구조라면 구조적 공유는 안전하지만 불변이 아니라면 불안전하다.

Object test = new Object();
List<Object> listA = List.of(test);
List<Object> listB = List.of(test);
// 구조적 공유 listA 와 listB 는 test 참조값을 둘다 갖고 있다.

 

오프 바이 원

주로 배열을 반복해서 처리할 때 "크다" 또는 "크거나 같다"와 같은 비교문을 잘못 선택해 의도하지 않게 마지막 항목을 처리하지 못하거나 처리하는 오류.

 

추상화 벽을 만들어야하는 이유 (😛 인터페이스를 만들어야 하는 이유)

  • 추상화 벽에 코드가 많을수록 구현이 변경되었을 때 고쳐야 할 것이 많습니다.
  • 추상화 벽에 있는 코드는 낮은 수준의 코드이기 때문에 더 많은 버그가 있을 수 있습니다.
  • 낮은 수준의 코드는 이해하기 더 어렵습니다.
  • 추상화 벽에 코드가 많을수록 팀 간 조율해야할 것도 많아집니다.
  • 추상화 벽에 인터페이스가 많으면 알아야할 것이 많아 사용하기 어려워집니다.

 

비기능적 요구사항

😛 소프트웨어의 기능적 요구사항 외 프로그래머가 챙겨야할 가치. 소프트웨어 설계가 필요한 이유와 맥락을 같이 한다. 

  • 테스트성: 어떤 것을 테스트하는 것이 가장 중요한가
  • 유지보수성: 요구사항이 바뀌었을 때 가장 쉽게 고칠 수 있는 코드는 어떤 코드인가
  • 재사용성: 어떤 함수가 재사용하기 좋은지

 

의존성 트리

의존성 트리 상단에 있는 코드는 자주 변경될 것이고 테스트가 오래가지 않을 수 있다.

의존성 트리 하단에 있는 코드는 덜 변경될 것이고 테스트가 오래갈 수 있다.

=> 트리 하단에 있는 테스트들이 더 가치가 있습니다.

=> 트리 하단에 있을 수록  재사용하기 좋습니다.

=> 트리 하단에 있을 수록 덜 변경되어 유지보수하기 좋습니다.

 

고차함수

(😛 함수를 값으로 갖는 함수)

고차함수를 이용한 카피 온 라이트 예제

const copyOnWrite = (array, delegate) => {
  let copy = array.slice();
  delegate(copy);
  return copy;
}

const setValue = (array, index, value) => {
  return copyOnWrite(array, (copy) => {
    copy[index] = value;
  });
}

 

서평

부푼 기대를 안고 읽었으나, 후반부는 사실상 Stream, Stream 이 어떤 식으로 구현 되어있는지가 주된 내용입니다. 이미 stream 에 익숙하다면 사실상 읽을 필요가 없어서 책의 절반만 유용했습니다. 일급 추상을 왜 일급 추상이라고 부르는지와 고차 함수를 왜 고차 함수라고 부르는지 궁금해서 읽었는데, 뭔가 명확한 설명은 얻기 어려웠고, 그냥 위키피디아 수준의 지식을 얻어갈 수 있었습니다. 책 내용은 어렵지 않아서 입문용으로는 좋아보입니다.

'[공부] 독서' 카테고리의 다른 글

애자일 & 스크럼 프로젝트 관리  (0) 2022.03.05
소프트웨어 장인  (0) 2020.04.17
서평  (0) 2019.03.24