Post
EN

Java 함수형 프로그래밍 기초

Java 8부터 함수형 인터페이스 (Functional Interface)를 제공하면서, 함수형 프로그래밍을 지원하게 되었다.

함수형 프로그래밍을 사용하면 확장성에 좋고, 함수로서 단일 기능을 강조, 함수를 조합 할 수 있다.

개인적인 함수형 프로그래밍의 기초는 다음과 같다.

1. 함수는 입력과 출력을 가지고 있다.

간단하게 input이 있으면 output이 있다는 것이다.

y = f(x)

2. 함수는 합성이 가능하다.

두개의 함수를 합성하여, 위에서 말했던 입력과 출력을 표현할 수 있다.

y = g(f(x))

3. 확장성에 용이하다. (변화에 영향을 크게 받지 않는다.)

작성된 함수형 프로그래밍에 추가적인 계산이 필요하면, 함수를 추가 하면 된다.

단순하게 생각하면 함수란 입력이 있으면 출력이 있다.

어떤 연산을 할 경우 일정한 순서가 존재한다.

예를 들어보자.

  1. 1줄의 텍스트 데이터를 받는다.

  2. 라인 데이터를 Tab으로 구분하여 나눈다.

  3. 나눠진 텍스트들을 원하는 객체에 맵핑 시킨다.

3가지 작업을 하기 위하여 위에서 말했던 함수로 작성하면 아래처럼 정리된다.

1. 1줄의 텍스트 데이터를 받아 tab으로 구분하여 나눈다. Input -> String Output -> String[] 2. 나눠진 택스트를 내가 원하는 객체에 맵핑 시킨다. Input -> String[] Output -> Object

정리된 함수를 가지고 클래스를 작성하면 단순하게 우리가 나타낼 수 있는 함수 형태가 된다.

class SplitFunction implements Function { @Override public String[] apply(String text) { if (text == null) return null; return text.split('\\t'); } } class MappingFunction implements Function { @Override public Object apply(String[] values) { return new Object(values); } }

이 두개의 인터페이스를 사용하는 클래스를 작성한다.

class Parser { private SplitFunction splitFunction; private MappingFunction mappingFunction; // 생성자로 각 함수 주입 public Object createObject(String text) { return mappingFunction.apply(splitFunction.apply(text)); } }

Parser 라는 클래스는 2개의 함수를 이용하여 1줄의 텍스트 데이터를 받아 tab으로 구분하여 나누고, 나눠진 택스트를 내가 원하는 객체에 맵핑 시킬 수 있다.

이런 상황에서 객체 안의 데이터들 중 다음과 같이 추가적인 계산을 하는 식이 추가되었다고 하면 어떻게 될까?

3. 생성된 객체의 가격 정보를 가져와서 계산식으로 값을 계산한다. Input -> Object Output -> Object (or void) 환율 계산식 Input -> Float Output -> Integer

Parser Class에 추가적으로 계산하는 공식을 추가하여 합성하면 문제는 해결된다.

// 환율 계산 적용 식 class CalculateFunction, Object> implements Function, Object> { @Override public Object apply(Object object, Function exchangeFunction) { object.setPrice(fnc.apply(object.getPrice())); return object; } } // 환율 계산 식 class ExchangeFunction implements Function { @Override public Integer apply(Float float) { return (int) float * 1174; // 당일 환율 계산 } }

(CalculateFunction은 인자가 3개를 받는 TriFuntion 이다. 가운데 들어오는 함수는 계산 하는 식에 대한 확장성을 생각하여 추가한 것이다.)

위와 같이 CalculateFunction을 만들어졌다. 이것을 가지고 기존에 있던 계산식에 넣어보자.

class Parser { private SplitFunction splitFunction; private MappingFunction mappingFunction; private CalculateFunction calculateFunction; private ExchangeFunction exchangeFunction; // 생성자로 각 함수 주입 public Object createObject(String text) { return calculateFunction.apply(mappingFunction.apply(splitFunction.apply(text)), exchangeFunction); } }

(apply 외에도 compose 사용할 수 있다.)

Parser class에 1개의 펑션이 더 추가되었고, 추가된 함수는 기존 함수에 합성하여 수정된 결과를 얻어온다.

작성된 코드를 확인 했을 때 변화가 크지 않다.

그리고 함수 계산식들은 상황에 따라 변경할 수 있다.

위에서 이야기 했던 1,2,3에 해당되는 내용대로 코드가 작성이 가능해졌고, 앞에서 설명한 내용 처럼 일정한 순서대로 작성되는 코드로 만들었다.

특정 복잡한 로직에 변화가 많이 발생되는 곳이 있다면, 이러한 장점을 이용하여 코드를 작성하면 변경에도 효율적일 것 같다.

This article is licensed under CC BY 4.0 by the author.