Java 동작 파라미터화란?

컴업·2024년 3월 12일
0
post-thumbnail
post-custom-banner

동작 파라미터화(Behavior Parameterization)란?

동작 파라미터화란 말 그대로 메소드의 동작을 파라미터로 전달하는 것을 의미한다.
즉, 객체를 메서드의 파라미터로 전달하는 것 처럼 코드 블록을 파라미터로 전달하여, 메서드의 동작을 동적으로 변경할 수 있다.

아래 someMethod 메서드와 같이 코드 블록을 파라미터로 받아 해당 코드 블록을 실행 함으로서 동작을 동적으로 변경가능한 것이다.

public List<Apple> someMethod(_코드블록_ ) {
	
    초기화/준비코드
    
		_코드블록_ 
	
	정리/마무리코드
    
}

한가지 예시를 통해 좀 더 자세하게 알아보자

🤔 동작 파라미터화 적용 전

사과농장에서 상품성 좋은 사과를 출고하기 위해 무게가 150g이상인 사과와 초록색 사과를 분류할 수 있는 프로그램 개발을 요청했다.

만약 동작 파라미터화를 공부하지 않은 개발자라면 아래와 같이 코드를 작성할 것이다.

Apple 클래스

public class Apple {
    private int weight;
    private String color;

    public Apple(int weight, String color) {
        this.weight = weight;
        this.color = color;
    }

    public int getWeight() {
        return weight;
    }

    public String getColor() {
        return color;
    }

    @Override
    public String toString() {
        return "Apple{" +
               "weight=" + weight +
               ", color='" + color + '\'' +
               '}';
    }
}

핵심 비즈니스 메서드

public static List<Apple> filterHeavyApples(List<Apple> inventory) {
    List<Apple> result = new ArrayList<>();
    for (Apple apple : inventory) {
        if (apple.getWeight() > 150) { // 직접 조건을 메소드 내에 코딩
            result.add(apple);
        }
    }
    return result;
}

public static List<Apple> filterGreenApples(List<Apple> inventory) {
    List<Apple> result = new ArrayList<>();
    for (Apple apple : inventory) {
        if ("green".equals(apple.getColor())) { // 직접 조건을 메소드 내에 코딩
            result.add(apple);
        }
    }
    return result;
}

비즈니스 로직 실행

List<Apple> heavyApples = filterHeavyApples(inventory); // 무거운 사과 필터링
List<Apple> greenApples = filterGreenApples(inventory); // 녹색 사과 필터링

위 코드에서는 150g이상인 사과를 필터링하는 메서드, 색이 초록색인 사과를 필터링하는 메서드를 각각 생성하였다.

나쁘지 않은 코드이지만, 사과를 필터링하는 if 조건문을 제외한 나머지 코드들은 모두 중복된 코드들이다.
만약 새로운 필터링 조건이 필요해 유사한 메소드를 계속 추가하게 된다면 마찬가지로 if 조건문만 다른 중복코드가 계속해서 증가할 것이다.

이러한 방식은 유지보수 비용을 증가시켜 다양한 요구조건 변경에 유연하게 대처하기 어렵게 만든다.

😀 동작 파라미터화 적용 후

다음으로 동작 파라미터화를 적용해보자.
아래와 같이 if의 조건문에 들어갈 코드블록을 파라미터로 받아 실행하는 filter 메서드를 만들 예정이다.

public List<Apple> filter(List<Apple> inventory, _코드블록_ ) {
	List<Apple> result = new ArrayList();
	for(Apple apple: inventory) {
		if(_코드블록_){
        	result.add(apple)
        }
	}
	return  result;
}

그러나 당연하게도 자바에서는 코드 블록을 파라미터로 전달할 수 없음으로, 인터페이스를 정의후 그 구현체를 전달하는 패턴을 사용한다.

아래 코드를 천천히 읽어보며 어떤식으로 동작을 전달하는지 이해해보자.

사과 분류 인터페이스 생성

interface ApplePredicate {
    boolean test(Apple apple);
}

필터링 조건 구현체 작성

class AppleHeavyWeightPredicate implements ApplePredicate {
    public boolean test(Apple apple) {
        return apple.getWeight() > 150;
    }
}

class AppleGreenColorPredicate implements ApplePredicate {
    public boolean test(Apple apple) {
        return "green".equals(apple.getColor());
    }
}

핵심 비즈니스 메서드

public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p) {
    List<Apple> result = new ArrayList<>();
    for (Apple apple : inventory) {
        if (p.test(apple)) {
            result.add(apple);
        }
    }
    return result;
}

비즈니스 로직 실행

List<Apple> heavyApples = filterApples(inventory, new AppleHeavyWeightPredicate());
List<Apple> greenApples = filterApples(inventory, new AppleGreenColorPredicate());

위 패턴에서는 동작에 대한 인터페이스를 정의하고, 그에 대한 구현체를 파라미터로 전달함으로서 동작을 파라미터화 하였다.

이전 코드와 비교해보자.

핵심 비즈니스 메서드가 하나로 통합되어 중복코드가 줄었으며, 새로운 요구 조건이 추가되는 경우 ApplePredicate 인터페이스의 구현체를 통해 유연하게 대처할 수 있게되었다.

익명 클래스 사용

익명 클래스를 사용하면 직접 구현체 클래스를 생성해서 사용하는 것보다 좀 더 간단하게 동작을 전달할 수 있다.

// 비즈니스 로직 실행
List<Apple> heavyApples = filterApples(inventory, new ApplePredicate() {
    public boolean test(Apple apple) {
        return apple.getWeight() > 150;
    }
});

List<Apple> greenApples = filterApples(inventory, new ApplePredicate() {
    public boolean test(Apple apple) {
        return "green".equals(apple.getColor());
    }
});

람다 표현식 사용

람다 표현식을 사용하면 보다 간결하게 코딩할 수 있다

List<Apple> heavyApples = filterApples(inventory, (a) -> a.getWeight() > 150);
List<Apple> heavyApples = filterApples(inventory, (a) -> "green".equals(apple.getColor()));

참고

  • 모던 자바 인 액션 (Raoul-Gabriel Urma, Mario Fusco, Alan Mycroft)
profile
좋은 사람, 좋은 개발자 (되는중.. :D)
post-custom-banner

0개의 댓글