/////
Search
Duplicate
1️⃣

변화하는 요구사항에 대응하기

: 변화에 대응하는 코드를 구현하는 것은 쉽지 않은 일이다.
: 기존의 농장 재고목록 애플리케이션에 리스트에서 녹색 사과만 필터링하는 기능을 추가한다고 가정하자, 비교적 간단한 작업이라는 생각이 들 것이다.

1. 첫 번째 시도 : 녹색 사과 필터링

enum Color { RED, GREEN } public static List<Apple> filterGreenApples(List<Apple> inventory) { List<Apple> result = new ArrayList<>(); for (Apple apple: inventory) { if (GREEN.eqauls(apple.getColor()) { result.add(apple); } } return result; }
Java
복사
: 만약 이 상황에서 빨간 사과도 따로 필터링하는 기능을 만들어야 한다면? 단순히 filterRedApples라는 함수를 만들어서 if문의 조건을 빨간 사과로 바꾸는 방법을 채택할 것이다.
: 이와 같은 방법으로 빨간 사과를 필터링하 수는 있겠지만 나중에 농부가 좀 더 다양한 색에 대한 필터링을 원한다면 이런 경우마다 메소드가 하나씩 늘어나게 될 것이다.
: 이런 상황에서는 다음과 같은 규칙을 적용하는 것이 적합하다.
거의 비슷한 코드가 반복 존재한다면 그 코드를 추상화한다.

2. 두 번째 시도 : 색을 파라미터화

: 어떻게 해야 filterGreenApples의 코드를 반복사용하지 않고 filterRedApples를 구현할 수 있을까?
: 색을 파라미터화할 수 있도록 메서드에 파라미터를 추가하면 변화하는 요구사항에 좀더 유연하게 대응하는 코드를 만들 수 있을 것이다.
enum Color { RED, GREEN } public static List<Apple> filterApplesByColor(List<Apple> inventory, Color color) { List<Apple> result = new ArrayList<>(); for (Apple apple: inventory) { if (apple.getColor().eqauls(color)) { result.add(apple); } } return result; } List<Apple> greenApples = filterApplesByColor(inventory, GREEN); List<Apple> redApples = filterApplesByColor(inventory, RED);
Java
복사
: 그런데 갑자기 무거운 사과와 가벼운 사과를 필터링해주는 함수를 만들어달라는 요구사항이 발생했다.
: 그럼 아마 다음과 같이 구현할 것이다.
enum Color { RED, GREEN } public static List<Apple> filterApplesByWeight(List<Apple> inventory, int weight) { List<Apple> result = new ArrayList<>(); for (Apple apple: inventory) { if (apple.getWeight() > weight) { result.add(apple); } } return result; }
Java
복사
: 위 코드도 좋은 해결책이라 할 수 있다. 하지만 구현 코드를 자세히 보면 대부분의 코드가 색 필터링 코드와 중복된다.
: 이는 소프트웨어 공학의 DRY 원칙을 어기는 것이다. 탐색 과정을 고쳐서 성능을 개선하려면 무슨 일이 일어날까, 한 줄이 아니라 메서드 전체 구현을 고쳐야 한다.
: 색과 무게를 filter라는 메서드로 합치는 방법도 있다. 그러면 어떤 기준으로 사과를 필터링할지 구분하는 또 다른 방법이 필요하다.
: 따라서 색이나 무게 중 어떤 것을 기준으로 필터링할지 가리키는 플래그를 추가할 수 있다. (하지만 절대 이 방법을 사용하지 말아야 한다..!)

3. 세 번째 시도 : 가능한 모든 속성으로 필터링

: 다음은 만류에도 불구하고 모든 속성을 메서드 파라미터로 추가한 모습이다.
public static List<Apple> filterApples(List<Apple> inventory, Color color, int weight, boolean flag) { List<Apple> result = new ArrayList<>(); for(Apple apple : inventory) { if((flag && apple.getColor().equals(color)) || (!flag && apple.getWeight() > weight)) { result.add(apple); } } return result; } List<Apple> greenApples = filterApples(inventory, GREEN, 0, true); List<Apple> heavyApples = filterApples(inventory, null, 150, false);
Java
복사
: 형편없는 코드다. 대체 true와 false는 뭘 의미하는 걸까. 게다가 앞으로 요구사항이 바뀌었을때 유연하게 대응할 수 도 없다.
: 예를 들어 사과의 크기, 모양, 출하지 등으로 사과를 필터링하고 싶다면? 만약 녹색 사과중 무거운 사과를 골라내고 싶다면? 결국 여러 중복된 필터 메서드를 만들거나 아니면 하나의 거대한 메서드를 만들 수 밖에 없다.
: 만약 filterApples라는 함수를 정의해놓고 여기에 어떤 기준으로 사과를 필터링할 것인지 효과적으로 전달할 수 있다면 더 좋을 것이다.
: 동작 파라미터화에 대해 알아보자