함수형 프로그래밍

theonde·2022년 11월 8일
0

함수형 프로그래밍

  • 순수 함수를 사용한 프로그래밍이다.

  • 모든 입출력은 메소드 이름, 인수, 반환 타입으로 구성된 메소드 시그니처에 명시해야 한다.

  • 순수 함수는 호출 횟수에 상관없이 주어진 입력에 대해 동일한 출력을 생성한다.

public class PriceEngine {

    public BigDecimal calculateDiscount(Product... products) {
        BigDecimal discount = BigDecimal.valueOf(products.length * 0.01);
        return discount.min(BigDecimal.valueOf(0.2));
    }
}
  • 위 calculateDiscount메소드는 하나의 입력(products)과 하나의 출력(Bigdecimal 타입)이 있으며, 둘 다 메소드 시그니처에 명시되어 있다. 이 메소드는 순수 함수에 해당한다.

  • 메소드 시그니처

public BigDecimal calculateDiscount(Product... products)
          출력           이름                입력   

calculateDiscount는 입력과 출력 모두 메소드 시그니처에 명시되어있으므로 순수 함수다.

  • 입출력을 명시한 순수 함수는 이에 따르는 테스트가 짧고 간결하며 이해하고 유지 보수하기 쉬우므로 테스트하기가 매우 쉽다.

  • 출력 기반 테스트를 적용할 수 있는 메소드 유형은 순수 함수뿐이다. 유지 보수성이 뛰어나고 거짓 양성 빈도가 낮다.

  • 숨은 입출력은 코드를 테스트하기 힘들게 하며, 가독성도 떨어진다.

숨은 입출력 유형

  • 부작용: 메소드 시그니처에 표시되지 않은 출력이다. 클래스 인스턴스의 상태 변경, 디스크 파일 업데이트 등

  • 예외: 메소드가 예외를 던지면, 프로그램 흐름에 메소드 시그니처에 명시되지 않는 경로를 만드는 것이기 때문에 숨은 출력이다.

  • 내외부 상태에 대한 참조: 정적 속성(static)를 사용해 가져오는 메솓, 데이터 베이스, 비공개 변경 가능 필드 참조 등 의 작업들은 모두 메소드 시그니처에 없는 입력이다. (숨은 입력)

참조 투명성

  • 메소드가 순수 함수인지 판별하는 가장 좋은 방법은 프로그램의 동작을 변경하지 않고 해당 메소드에 대한 호출을 반환 값으로 대체할 수 있는지 확인하는 것이다.

  • 메소드 호출을 해당 값으로 바꾸는 것을 "참조 투명성" 이라고 한다.

순수 함수 예제

public class PureFunction {

    public int increment(int x) {
        return x + 1;
    }
}
  • 위 increment 메소드는 순수 함수다.
int y = increment(4);
int y = 5;
  • 위 두개의 구문처럼 해당 메소드에 대한 호출(incerement(4))을 반환 값(5)으로 대체할 수 있기 때문에 위의 increment메소드는 순수 함수다.

비순수 함수 예제

public class ImpureFunction {

    int x = 0;

    public int increment() {
        x++;
        return x;
    }
}
  • 위 incerement메소드는 순수 함수가 아니다.

  • 반환 값이 메소드의 출력을 모두 나타내지 않으므로 반환 값으로 대체할 수 없다.

  • 위 예제에서 숨은 출력은 필드 x의 변경(부작용)이다.

public class Comment {
    
    private String text;

    private List<Comment> comments = new ArrayList<>();

    public Comment(String text) {
        this.text = text;
    }

    public Comment addComment(String text) {
        Comment comment = new Comment(text);
        comment.comments.add(comment);
        return comment;
    }
}
  • 비순수 함수다. comments에 comment를 add하는 숨은 출력이 있다.

함수형 아키텍처

  • 어떤 부작용도 일으키지 않는 애플리케이션을 만드는 것은 불가능하다.

  • 함수형의 목표는 비즈니스 로직을 처리하는 코드와 부작용을 일으키는 코드를 분리하는 것이다.

  • 부작용을 비즈니스 연산 끝으로 몰아서 비즈니스 로직을 부작용과 분리한다.

  • 결정을 내리는 코드(함수형 코어): 부작용이 필요 없기 때문에 수학적 함수를 사용하여 작성

  • 해당 결정에 따라 작용하는 코드(가변 셸): 데이터베이스 변경 등

  • 함수형 코어와 가변 셸의 협력

    • 가변 셸은 모든 입력을 수집한다.

    • 함수형 코어는 결정을 생성한다.

    • 셸은 결정을 부작용으로 변환한다.

profile
개발자ㅋ.ㅋ

0개의 댓글