Ch06.08 Introduce Parameter Object 매개변수 객체 만들기
<java />//[Before] public class Station { ... public List<Temperature> readingsOutsideRange(int min, int max) { return readings.stream() .filter(t -> t.getTemperature() < min || t.getTemperature() > max) .toList(); } } //[After-Step01] public class Station { ... public List<Temperature> readingsOutsideRange(NumberRange range) { return readings.stream() .filter(t->t.getTemperature() < range.getMin() || t.getTemperature() > range.getMax()) .toList(); } //[After-Step02] public class Station { ... public List<Temperature> readingsOutsideRange(NumberRange range) { return readings.stream() .filter(t->!range.contains(t.getTemperature())) .toList(); } }

ch06.11 split phase 단계 쪼개기
<java />//[Before] public class ReadOrder { public static void main(String[] args) { try { if (args.length == 0) throw new RuntimeException("파일명을 입력하세요."); String filename = args[args.length - 1]; File input = new ClassPathResource(filename).getFile(); System.out.println(input.getAbsolutePath()); ObjectMapper mapper = new ObjectMapper(); Order[] orders = mapper.readValue(input, Order[].class); if (Stream.of(args).anyMatch(arg -> "-r".equals(arg))) System.out.println(Stream.of(orders) .filter(o -> "ready".equals(o.getStatus())) .count()); else System.out.println(orders.length); } catch (Exception e) { System.err.println(e); } } }
<java />//[After- 방법1] public class ReadOrder26 { public static long run(String[] args) throws IOException { return countOrders(new CommandLine(args)); } private static long countOrders(CommandLine commandLine) throws IOException { File input = new ClassPathResource(commandLine.filename()).getFile(); ObjectMapper mapper = new ObjectMapper(); Order[] orders = mapper.readValue(input, Order[].class); if (commandLine.onlyCountReady()) return Stream.of(orders) .filter(Order::isReady) //캡슐화 : 메서드 이동 .count(); else return orders.length; } private static class CommandLine { String[] args; public CommandLine(String[] args) { if (args.length == 0) throw new RuntimeException("파일명을 입력하세요."); this.args = args; } String filename() { return args[args.length - 1]; } boolean onlyCountReady() { return Stream.of(args).anyMatch(arg -> "-r".equals(arg)); } } }
<java />//[After-방법2] // Strategy & Factory 적용 public class ReadOrder31 { public static long run(String[] args) throws IOException { return countOrders(new CommandLine(args)); } private static long countOrders(CommandLine commandLine) throws IOException { // 팩토리 클랫 생성 CountOrders countOrders = CountOrderFactory.createCountOrders(commandLine.onlyCountReady()); return countOrders.count(getOrders(commandLine)); } private static Order[] getOrders(CommandLine commandLine) throws IOException { File input = new ClassPathResource(commandLine.filename()).getFile(); ObjectMapper mapper = new ObjectMapper(); Order[] orders = mapper.readValue(input, Order[].class); return orders; } private static class CommandLine { String[] args; public CommandLine(String[] args) { if (args.length == 0) throw new RuntimeException("파일명을 입력하세요."); this.args = args; } String filename() { return args[args.length - 1]; } public boolean onlyCountReady() { return Stream.of(args).anyMatch(arg -> "-r".equals(arg)); } } } public interface CountOrders { long count(Order[] orders); } public class CountOrdersAll implements CountOrders { @Override public long count(Order[] orders) { return orders.length; } } public class CountOrdersOnlyReady implements CountOrders { @Override public long count(Order[] orders) { return Arrays.stream(orders) .filter(Order::isReady) .count(); } } public class CountOrderFactory { public static CountOrders createCountOrders(Boolean onlyCountReady) { if (onlyCountReady) return new CountOrdersOnlyReady(); else return new CountOrdersAll(); } }

Ch07.03 Replace Primitive with Object 기본형을 객체로 바꾸기
<java />public class Order { private final Long id; private final String priority; public Order(Long id, String priority) { this.id = id; this.priority = priority; } public Long getId() { return id; } public String getPriority() { return priority; } } //[Before] public class Orders { private final Order[] orders; public Orders(Order[] orders) { this.orders = orders; } public Order[] getOrders() { return orders; } public long highPriorityCount() { return Arrays.stream(orders) .filter(o -> o.getPriority().equals("high") || o.getPriority().equals("rush")) .count(); } public long lowerPriorityCount() { return Arrays.stream(orders) .filter(o -> o.getPriority().equals("low") || o.getPriority().equals("medium")) .count(); } public long lowestPriorityCount() { return Arrays.stream(orders) .filter(o -> o.getPriority().equals("low")) .count(); } public Order getOrder(int index) { return orders[index]; } } class OrdersTest { @Test void testHighPriorityCount() { Order[] orders = { new Order(1L, "high"), new Order(2L, "low"), new Order(3L, "rush"), new Order(4L, "medium") }; Orders ordersObj = new Orders(orders); assertEquals(2, ordersObj.highPriorityCount()); } }
<java />//[After-방법1] // 배열 index의 순번을 우선순위 값으로 응용 public class Priority { private final String value; public Priority(String value) { if (!legalValues().contains(value)){ throw new IllegalArgumentException("Invalid Priority Value"); } this.value = value; } public static List<String> legalValues(){ return List.of("low", "normal", "high", "rush"); } public int index(){ return legalValues().indexOf(value); } public boolean higherThan(Priority other) { return this.index() > other.index(); } public boolean lowerThan(Priority other) { return this.index() < other.index(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Priority priority = (Priority)o; return Objects.equals(value, priority.value); } @Override public int hashCode() { return Objects.hash(value); } @Override public String toString() { return value; } }
<java />//[After-방법2] // Enum을 이용 public enum Priority { LOW, MEDIUM, HIGH, RUSH } public class Orders { private final Order[] orders; public Orders(Order[] orders) { this.orders = orders; } public Order[] getOrders() { return orders; } public long highPriorityCount() { return Arrays.stream(orders) .filter(o -> o.getPriority() == Priority.HIGH || o.getPriority() == Priority.RUSH) .count(); } public long lowerPriorityCount() { return Arrays.stream(orders) .filter(o -> o.getPriority() == Priority.MEDIUM || o.getPriority() == Priority.LOW) .count(); } public long lowestPriorityCount() { return Arrays.stream(orders) .filter(o -> o.getPriority() == Priority.LOW) .count(); } public Order getOrder(int index) { return orders[index]; } }
<java />//[After-방법3] // Enum에 필드값과 메서드를 이용 public enum Priority { LOW(1), MEDIUM(2), HIGH(3), RUSH(4); Priority(int priorityLevel) { this.priorityLevel = priorityLevel; } private final int priorityLevel; public boolean isHigherThen(Priority other) { return this.priorityLevel > other.priorityLevel; } public boolean isLowerThen(Priority other) { return this.priorityLevel < other.priorityLevel; } public boolean isLowest() { return this.priorityLevel == LOW.priorityLevel; } } public class Orders { private final Order[] orders; public Orders(Order[] orders) { this.orders = orders; } public Order[] getOrders() { return orders; } public long highPriorityCount(Priority priority) { return Arrays.stream(orders) .filter(o -> o.getPriority().isHigherThen(priority)) .count(); } public long lowerPriorityCount(Priority priority) { return Arrays.stream(orders) .filter(o -> o.getPriority().isLowerThen(priority)) .count(); } public long lowestPriorityCount( ) { return Arrays.stream(orders) .filter(o -> o.getPriority().isLowest()) .count(); } public long equalPriorityCount(Priority priority) { return Arrays.stream(orders) .filter(o -> o.getPriority().equals(priority)) .count(); } public Order getOrder(int index) { return orders[index]; } }

'프로그래밍 > 리팩터링' 카테고리의 다른 글
리팩터링 2nd 10.3 중첩 조건문을 보호 구문으로 바꾸기 (0) | 2025.04.09 |
---|---|
리팩터링 2nd 8.7 Split Loop (0) | 2025.04.07 |
리팩터링 2nd Chapter 01 실습 (0) | 2025.03.25 |
IntelliJ가 지원하는 자동 리팩터링 목록 (1) | 2025.02.10 |
Refactoring if-else 제거 (0) | 2025.01.15 |