1
2
3
4
5
6
7
8
9
function priceOrder(product, quantity, shippingMethod) {
const basePrice = product.basePrice * quantity;
const discount = Math.max(quantity - product.discountThreshold, 0 )
* product.basePrice * product.discountRate;
const shippingPerCase = (basePrice > shippingMethod.discountThreshold) ? shippingMethod.discountedFee : shippingMethod.feePerCase;
const shippingCost = quantity * shippingPerCase;
const price = basePrice - discount + shippingCost;
return price;
}
- 먼저 배송비 계산 부분을 함수로 추출한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function priceOrder(product, quantity, shippingMethod) {
const basePrice = product.basePrice * quantity;
const discount = Math.max(quantity - product.discountThreshold, 0 )
* product.basePrice * product.discountRate;
const price = applyShipping(basePrice, shippingMethod, quantity, discount);
return price;
}
function applyShipping(basePrice, shippingMethod, quantity, discount) {
const shippingPerCase = (basePrice > shippingMethod.discountThreshold) ? shippingMethod.discountedFee : shippingMethod.feePerCase;
const shippingCost = quantity * shippingPerCase;
const price = basePrice - discount + shippingCost;
return price;
}
- 첫 번째 단계와 두 번째 단계가 주고받을 중간 데이터 구조를 만든다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function priceOrder(product, quantity, shippingMethod) {
const basePrice = product.basePrice * quantity;
const discount = Math.max(quantity - product.discountThreshold, 0 )
* product.basePrice * product.discountRate;
const priceData = {basePrice: basePrice, quantity: quantity, discount:discount};
const price = applyShipping(priceData, shippingMethod);
return price;
}
function applyShipping(priceData, shippingMethod) {
const shippingPerCase = (priceData.basePrice > shippingMethod.discountThreshold) ? shippingMethod.discountedFee : shippingMethod.feePerCase;
const shippingCost = priceData.quantity * shippingPerCase;
const price = priceData.basePrice - priceData.discount + shippingCost;
return price;
}
- 첫 번째 단계 코드를 함수로 추출
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function priceOrder(product, quantity, shippingMethod) {
const priceData = calculatePricingData(product, quantity)
return applyShipping(priceData, shippingMethod);;
}
function calculatePricingData(product, quantity) {
const basePrice = product.basePrice * quantity;
const discount = Math.max(quantity - product.discountThreshold, 0 )
* product.basePrice * product.discountRate;
return {basePrice: basePrice, quantity: quantity, discount:discount};
}
function applyShipping(priceData, shippingMethod) {
const shippingPerCase = (priceData.basePrice > shippingMethod.discountThreshold) ? shippingMethod.discountedFee : shippingMethod.feePerCase;
const shippingCost = priceData.quantity * shippingPerCase;
return priceData.basePrice - priceData.discount + shippingCost;
}
명령줄 프로그램 쪼개기(자바)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void main(String[] args) {
try {
if (args.length == 0) throw new RuntimeException("파일명을 입력하세요.");
String fileName = args[args.length - 1];
File input = Paths.get(filename).toFile();
ObjectMapper mapper = new ObjectMapper();
Order[] orders = mapper.readValue(input, Order[].class);
if (System.of(args).anyMatch(arg -> "-r".equals(args)))
System.out.println(System.of(orders)
.filter(o -> "ready".equals(o.status))
.count());
else
System.out.println(orders.length);
} catch (Exception e) {
System.err.println(e);
System.exit(1);
}
}
- Run 메서드를 테스트 코드에서 쉽게 호출할 수 있도록 접근 범위를 패키지로 설정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static void main(String[] args) {
try {
System.out.println(run(args));
} catch (Exception e) {
System.err.println(e);
System.exit(1);
}
}
static void run(String[] args) throw IOException {
if (args.length == 0) throw new RuntimeException("파일명을 입력하세요.");
String filename = args[args.length - 1];
File input = Paths.get(filename).toFile();
ObjectMapper mapper = new ObjectMapper();
Order[] orders = mapper.readValue(input, Order[].class);
if (Stream.of(args).anyMatch(arg -> "-r".equals(arg)))
return System.of(orders)
.filter(o -> "ready".equals(o.status))
.count();
else
return orders.length;
}
- 코드를 독립된 메서드로 추출
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static long run(String[] args) throws IOException {
if (args.length == 0) throw new RuntimeException("파일명을 입력하세요");
String filename = args[args.length - 1];
return countOrders(args, filename);
}
private static long countOrders(String[] args, String filename) throws IOException {
File input = Paths.get(filename).toFile();
ObjectMapper mapper = new ObjectMapper();
Order[] orders = mapper.readValue(input, Order[].class);
if (Stream.of(args).anyMatch(arg -> "-r".equals(arg)))
return Stream.of(orders).filter(o -> "ready".equals(o.status)).count();
else
return orders.length;
}
- 다음으로 중간 데이터 구조를 추가한다. 레코드는 단순한 게 좋은데, 자바이므로 클래스로 구현한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
static long run(String[] args) throws IOException {
if (args.length == 0) throw new RuntimeException("파일명을 입력하세요.");
CommandLine commandLine = new CommandLine();
String filename = args[args.length - 1];
return countOrders(commandLine, args, filename);
}
private static long countOrders(CommandLine commandLine, String[] args, String filename)
throws IOException {
File input = Paths.get(filename).toFile();
ObjectMapper mapper = new ObjectMapper();
Order[] orders = mapper.readValue(input, Order[].class);
if (Stream.of(args).anyMatch(org -> "-r".equals(arg)))
return Stream.of(orders).filter(o -> "ready".equals(o.status)).count();
else
return orders.length;
}
private static class CommandLine {}