부수효과 다루는 방법을 적용해서 리팩터링하는 예제

Raymond Yoo·2023년 12월 11일
0
post-thumbnail

앞에서 본 bind, flatMap, >=> 원리를 적용하는
아주 간단한 예제코드를 살펴보자.

예제코드 링크

사칙연산 + 로그적재 예제코드 1

간단한 함수부터 시작해보자.
square 함수는 입력받는 정수값을 제곱한 결과를 반환한다.
add_one 함수는 입력받는 정수값에 +1 한 결과를 반환한다.

기존에 만들어둔 함수를 호출할 때마다 로그를 남겨야 한다

추가적인 요구조건이 도착했다.
기존에 만들어둔 함수를 호출할 때마다
어떤 입력값을 받았고 연산 결과가 무엇이었는지
사람이 읽기 편한 형태로 로그를 남긴다.

계산결과값과 로그를 함께 다루는
number_with_logs 라는 데이터 클래스를 만들었다.
그리고 이걸 파라미터로 전달하거나 반환값으로 받아서
일관성있게 코드를 작성할 수 있도록 수정한다.

다른 함수들도 추가해보자. 똑같이 로그를 남긴다

다른 함수들도 추가로 구현해야 한다.
기존과 마찬가지로 함수가 호출될때마다 로그를 남겨야 한다.
minus_five 함수는 입력 정수에 -5 한 결과를 반환한다.
multiply_three 함수는 입력 정수에 x3 한 결과를 반환한다.
add_twelve 함수는 입력 정수에 +12 한 결과를 반환한다.

Normal World 와 Wrapper World 왕복하는 코드 제거 01
Normal World 와 Wrapper World 왕복하는 코드 제거 01

위의 코드를 계속해서 읽다보니 반복되는 부분을 발견했다.
우선은 정수값 연산하는 부분을 보면
number_with_logs 에서 result 필드에 접근해서
값을 얻어낸 후 실제로 필요한 연산을 한다.
로그메시지를 남기는 부분에서도
number_with_logs 에서 logs 필드에 접근해서
기존에 로그가 쌓여있는 배열을 얻어내고 거기에
로그메시지를 한 줄 추가한다.

Normal World, Wrapper World 왕복 횡단

여기서 number_with_logs 라는
wrapper 타입의 항목에서 실제 필요한 값을 꺼내는 코드가
바로 Normal World 와 Wrapper World 를 왕복하는 부분이다.

Normal World 에서는 시작과 끝에만 접근하고 중간 과정에서 Wrapper World 에만 있음

이런 모양으로 가기 위해서는 앞선 포스팅에서 알아본
bind, >=>(kleisli arrow), flatMap 에
해당하는 함수를 구현해야 한다.
여기서는 run_with_logs 함수가 그 역할을 한다.

이를 통해서 코드는 처음 시작할때만
Normal World 에서 Wrapper World 로 진입한 후
중간 과정에서는 내내
Wrapper World 에 머무르는 코드가 되었다.
이 코드가 함수형 프로그래밍 Monad 의 개념을 적용한 예시이다.

<참조>
유뷰트 영상, The Absolute Best Intro to Monads For Software Engineers

profile
세상에 도움이 되고, 동료에게 도움이 되고, 나에게 도움이 되는 코드를 만들고 싶습니다.

0개의 댓글