π¦ chap10. λλ€λ₯Ό μ΄μ©ν λλ©μΈ μ μ© μΈμ΄
chap10. λλ€λ₯Ό μ΄μ©ν λλ©μΈ μ μ© μΈμ΄
10.1 λλ©μΈ μ μ© μΈμ΄
DSLμ νΉμ λΉμ¦λμ€ λλ©μΈμ λ¬Έμ λ₯Ό ν΄κ²°νλ €κ³ λ§λ μΈμ΄μ΄λ€.
DSLμ΄λ νΉμ λΉμ¦λμ€ λλ©μΈμ μΈν°νμ΄μ€λ‘ λ§λ APIλΌκ³ μκ°ν μ μλ€.
- μ½λμ μλκ° λͺ νν μ λ¬λμ΄μΌ νλ©° νλ‘κ·Έλλ¨Έκ° μλ μ¬λλ μ΄ν΄ν μ μμ΄μΌ νλ€.
- κ°λ μ±μ μ μ§λ³΄μμ ν΅μ¬μ΄λ€
10.1.1 DSLμ μ₯μ κ³Ό λ¨μ
- μ₯μ
- κ°κ²°ν¨: APIλ λΉμ¦λμ€ λ‘μ§μ μΊ‘μννμ¬ λ°λ³΅μ νΌνκ³ μ½λλ₯Ό κ°κ²°νκ² νλ€
- κ°λ μ±: λΉ λλ©μΈ μ λ¬Έκ°λ μ½λλ₯Ό μ½κ² μ΄ν΄ν μ μλ€
- μ μ§λ³΄μ: μ μ€κ³λ DSLλ‘ κ΅¬νν μ½λλ μ½κ² μ μ§λ³΄μνκ³ λ°κΏ μ μλ€
- λμ μμ€μ μΆμν: μΆμν μμ€μμ λμνλ―λ‘ λλ©μΈκ³Ό μ§μ μ μΌλ‘ κ΄λ ¨λμ§ μμ μΈλΆμ¬νμ μ¨κΈ΄λ€
- μ§μ€: νλ‘κ·Έλλ¨Έκ° νΉμ μ½λμ μ§μ€ν μ μκ³ κ²°κ³Όμ μΌλ‘ μμ°μ±μ΄ μ’μμ§λ€
- κ΄μ¬μ¬μ λΆλ¦¬: μ΄ν리μΌμ΄μ μ μΈνλΌ κ΅¬μ‘°μ κ΄λ ¨λ λ¬Έμ μ λ 립μ μΌλ‘ λΉμ¦λμ€ κ΄λ ¨λ μ½λμ μ§μ€νκΈ° μ©μ΄νλ€. κ²°κ³Όμ μΌλ‘ μ μ§λ³΄μκ° μ¬μ΄ μ½λλ₯Ό ꡬννλ€.
- λ¨μ
- μ€κ³μ μ΄λ €μ: κ°κ²°νκ² μ νμ μΈ μΈμ΄μ λλ©μΈ μ§μμ λ΄λ κ²μ μ½μ§ μλ€
- κ°λ° λΉμ©: μ΄κΈ° νλ‘μ νΈμ λ§μ λΉμ©κ³Ό μκ°μ΄ μλͺ¨λλ©° μ μ§λ³΄μμ λ³κ²½μ λΆλ΄μ μ£Όλ μμμ΄λ€
- μΆκ° μ°ν κ³μΈ΅: DSLμ μΆκ° κ³μΈ΅μΌλ‘ λλ©μΈ λͺ¨λΈμ κ°μΈλ©° κ³μΈ΅μ μ΅λν μκ² λ§λ€μ΄ μ±λ₯ λ¬Έμ λ₯Ό ννΌν΄μΌ νλ€.
- μλ‘ λ°°μμΌνλ μΈμ΄: νμ΄ λ°°μμΌνλ μΈμ΄κ° ν κ° λ λμ΄λλ€λ λΆλ΄μ΄ μλ€
- νΈμ€ν μΈμ΄ νκ³: μ₯ν©ν νλ‘κ·Έλλ° μΈμ΄λ₯Ό κΈ°λ°μΌλ‘ λ§λ DSLμ μ±κ°μ λ¬Έλ²μ μ μ½μ λ°κ³ μ½κΈ°κ° μ΄λ €μμ§λ€.
10.1.2 JVMμμ μ΄μ©ν μ μλ λ€λ₯Έ DSL ν΄κ²°μ±
λ΄λΆ DSL
μλ° κΈ°μ€μΌλ‘ μλ°λ‘ ꡬνν DSLμ μλ―Ένλ€.
μ₯μ
- κΈ°μ‘΄ μλ° μΈμ΄λ₯Ό μ΄μ©νλ©΄ μΈλΆ DSLμ λΉν΄ μλ‘μ΄ κΈ°μ μ λν λ Έλ ₯μ΄ νμ νκ² μ€μ΄λ λ€.
- λ€λ₯Έ μΈμ΄μ μ»΄νμΌλ¬λ₯Ό μ΄μ©νκ±°λ μΈλΆ DSL λꡬμ λν μΆκ° λΉμ©μ΄ λ€μ§ μλλ€
- μλ‘μ΄ μΈμ΄λ₯Ό λ°°μ°μ§ μμλ λλ€
- κΈ°μ‘΄ μλ° IDEμ μλ μμ±, μλ 리ν©ν°λ§ κ°μ κΈ°λ₯μ κ·Έλλ‘ μ¬μ©ν μ μλ€.
- μΆκ° DSLμ κ°λ°ν΄μΌ νλ μν©μ μ½κ² ν©μΉ μ μλ€.
λ€μ€ DSL
JVMμμ μ€νλλ μΈμ΄λ 100κ°κ° λλλ€.
λ¨μ
- μλ‘μ΄ νλ‘κ·Έλλ° μΈμ΄λ₯Ό λ°°μ°κ±°λ μ΄λ―Έ ν΄λΉ κΈ°μ μ κ°μ§κ³ μμ΄μΌ νλ€.
- μ¬λ¬ μ»΄νμΌλ¬λ‘ μμ€λ₯Ό λΉλνλλ‘ λΉλ κ³Όμ μ κ°μ ν΄μΌ νλ€.
- μλ°μ νΈνμ±μ΄ μλ²½νμ§ μμ μ±λ₯ μμ€μ΄ λ°μν μλ μλ€.
μΈλΆ DSL
μμ λ§μ λ¬Έλ²κ³Ό ꡬ문μΌλ‘ μ μΈμ΄λ₯Ό μ€κ³ν΄μΌ νλ€.
μ₯μ μ 무νν μ μ°μ±μ μ 곡νλ€λ κ²μ΄μ§λ§, λΉμ¦λμ€ μ½λμ λΆλ¦¬λ‘ μΈκ³΅ κ³μΈ΅μ΄ μκΈ°κΈ° λλ¬Έμ μλ μ κ²κ³Ό κ°λ€.
10.2 μ΅μ μλ° APIμ μμ DSL
- λ€μ΄ν°λΈ μλ° API
μλ° 8μμ λλ€μ λ©μλ μ°Έμ‘°λ₯Ό ν΅ν΄ μ¬μ¬μ©μ±κ³Ό λ©μλ κ²°ν©λκ° λμμ‘λ€.
10.2.1 μ€νΈλ¦Ό APIλ 컬λ μ μ μ‘°μνλ DSL
Stream μΈν°νμ΄μ€λ λ€μ΄ν°λΈ μλ° APIμ μμ λ΄λΆ DSLμ μ μ©ν μ’μ μμμ΄λ€.
1
2
3
4
5
6
7
8
9
10
11
12
List<String> errors = new ArrayList<>();
int errorCount = 0;
BufferedReader bufferedReader
= new BufferedReader(new FileReader(fileName));
String line = bufferedReader.readLine();
while (errorCount < 40 && line != null) {
if (line.startWith("ERROR")) {
errors.add(line);
errorCount++;
}
line = bufferedReader.readLine();
}
μ½λκ° μ₯ν©μ μλλ₯Ό νλμ νμ νκΈ° μ΄λ €μ΄ μ½λμ΄λ€.
μ΄λ₯Ό Stream μΈν°νμ΄μ€λ₯Ό μ΄μ©ν΄ ν¨μνμΌλ‘ ꡬννλ©΄ μ½κ³ κ°κ²°νκ² μ½λλ₯Ό ꡬνν μ μλ€.
1
2
3
4
List<String> errors = Files.lines(Paths.get(fileName)
.filter(line -> line.startsWith("ERROR"))
.limit(40)
.collect(toList());
μ€νΈλ¦Ό APIμ ν루μΈνΈ νμμ μ μ€κ³λ DSLμ νΉμ§μ΄λ€.
10.2.2 λ°μ΄ν°λ₯Ό μμ§νλ DSLμΈ Collectors
Collector μΈν°νμ΄μ€λ λ°μ΄ν° μμ§μ μννλ DSLλ‘ κ°μ£Όν μ μλ€.
κ·Έλ£Ήν νκ° μμκ° λ¬λΌμ§ μ μλλ° μ΄λ GroupingBuilder λ₯Ό λ§λ€μ΄ μμ μ μμνλ©΄ ν΄κ²°ν μ μλ€.
10.3 μλ°λ‘ DSLμ λ§λλ ν¨ν΄κ³Ό κΈ°λ²
10.3.1 λ©μλ 체μΈ
DSLμμ κ°μ₯ νν λ°©μμ΄λ€. μ΄λ₯Ό μ΄μ©νλ©΄ ν κ°μ λ©μλ νΈμΆ 체μΈμΌλ‘ κ±°λ μ£Όλ¬Έμ μ μν μ μλ€.
1
2
3
4
5
6
7
8
9
10
Order order = forCustomer("BigBank")
.buy(80)
.stock("IBM")
.on("NYSE")
.at(125.00)
.sell(50)
.stock("GOOGLE")
.on("NASDAQ")
.at(375.00)
.end();
μ΄λ₯Ό μν΄ ν루μΈνΈ APIλ‘ λλ©μΈ κ°μ²΄λ₯Ό λ§λλ λͺ κ°μ λΉλλ₯Ό ꡬνν΄μΌ νλ€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class MethodChainingOrderBuilder {
public final Order order = new Order();
private MethodChainingOrderBuilder(String customer) {
order.setCustomer(customer);
}
public static MethodChainingOrderBuilder forCustomer(String customer) {
return new MethodChainingOrderBuilder(customer);
}
public TradeBuilder buy(int quantity) {
return new TradeBuilder(this, Trade.Type.BUY, quantity);
}
public TradeBuilder sell(int quantity) {
return new TradeBuilder(this, Trade.Type.SELL, quantity);
}
public MethodChainingOrderBuilder addTrade(Trade trade) {
order.addTrade(trade);
return this;
}
public Order end() {
return order;
}
}
buy, sell λ©μλλ λ€λ₯Έ μ£Όλ¬Έμ λ§λ€μ΄ μΆκ°ν μ μλλ‘ μμ μ λ§λ€μ΄ λ°ννλ€
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class TradeBuilder {
private final MethodChainingOrderBuilder builder;
public final Trade trade = new Trade();
private TradeBuilder(MethodChainingOrderBuilder builder,
Trade.Type type, int quantity) {
this.builder = builder;
trade.setType(type);
trade.setQuantity(quantity);
}
public StockBuilder stock(String symbol) {
return new StockBuilder(builder, trade, symbol);
}
}
Stock ν΄λμ€μ μΈμ€ν΄μ€λ₯Ό λ§λλ TradeBuilder μ κ³΅κ° λ©μλλ₯Ό μ΄μ©ν΄μΌ νλ€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class StockBuilder {
private final MethodChainingOrderBuilder builder;
private final Trade trade;
private final Stock stock = new Stock();
private StockBuilder(MethodChainingOrderBuilder builder,
Trade trade, String symbol) {
this.builder = builder;
this.trade = trade;
stock.setSymbol(symbol);
}
public TradeBuilderWithStock on(String market) {
stock.setMarket(market);
trade.setStock(stock);
return new TradeBuilderWithStock(builder, trade);
}
}
μ£Όμ μμ₯μ μ§μ νκ³ κ±°λμ μ£Όμμ μΆκ°νκ³ μ΅μ’ λΉλλ₯Ό λ°ννλ on λ©μλ ν κ°λ₯Ό μ μνλ€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class TradeBuilderWithStock {
private final MethodChainingOrderBuilder builder;
private final Trade trade;
public TradeBuilderWithStock(MethodChainingOrderBuilder builder, Trade trade) {
this.builder = builder;
this.trade = trade;
}
public MethodChainingOrderBuilder at(double price) {
trade.setPrice(price);
return builder.addTrade(trade);
}
}
μ¬μ©μκ° λ―Έλ¦¬ μ§μ λ μ μ°¨μ λ°λΌ ν루μΈνΈ APIμ λ©μλλ₯Ό νΈμΆνλλ‘ κ°μ νμ¬ κΈ°μ‘΄ κ±°λλ₯Ό μ¬λ°λ‘ μ€μ νκ² λλ€.
λ€λ§ μμ μμ€μ λΉλλ₯Ό νμ μμ€μ λΉλμ μ°κ²°ν μ μ°© λ§μ μ½λκ° νμνλ€λ κ²μ΄ λ¨μ μ΄λ€.
10.3.2 μ€μ²©λ ν¨μ μ΄μ©
λ€λ¦ ν¨μ μμ ν¨μλ₯Ό μ΄μ©ν΄ λλ©μΈ λͺ¨λΈμ λ§λλ DSL ν¨ν΄μ΄λ€.
1
2
3
4
Order oder = order("BigBank",
buy(80, stock("IBM", on("NYSE")), at(125.00)),
sell(50, stock("GOOGLE", on("NASDAQ")), at(375.00))
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class NestedFunctionOrderBuilder {
public static Order order(String customer, Trade... trades) {
Order order = new Order()
order.setCustomer(customer);
Stream.of(trades).forEach(order::addTrade); // μ£Όλ¬Έμ λͺ¨λ κ±°λ μΆκ°
return order;
}
public static Trade buy(int quantity, Stock stock, double price) {
return buildTrade(quantity, stock, price, Trade.Type.BUY);
}
public static Trade sell(int quantity, Stock stock, double price) {
return buildTrade(quantity, stock, price, Trade.Type.SELL);
}
private static Trade buildTrade(int quantity, Stock stock, double price, Trade.Type buy) {
Trade trade = new Trade();
trade.setQuantity(quantity);
trade.setType(buy);
trade.setStock(stock);
trade.setPrice(price);
return trade;
}
public static double at(double price) {
return price;
}
public static Stock stock(String symbol, String market) {
Stock stock = new Stock();
stock.setSymbol(symbol);
stock.setMarket(market);
return stock;
}
public static String on(String market) {
return market;
}
}
λ©μλ 체μ΄λμ λΉν΄ ꡬνμ΄ κ°λ¨νλ€.
νμ§λ§ κ²°κ³Ό DSLμ λ λ§μ κ΄νΈλ₯Ό μ¬μ©ν΄μΌ νκ³ μΈμ λͺ©λ‘μ μ μ λ©μλμ λ겨μ€μΌ νλ€λ μ μ½μ΄ μλ€.
μΈμ μλ΅μ λν κ°λ₯μ±μ μ²λ¦¬ν μ μλλ‘ μ¬λ¬ λ©μλ μ€λ²λΌμ΄λλ₯Ό ꡬνν΄μΌ νλ€.
10.3.3 λλ€ ννμμ μ΄μ©ν ν¨μ μνμ±
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class LambdaOrderBuilder {
private Order order = new Order();
public static Order order(Consumer<LambdaOrderBuilder> consumer) {
LambdaOrderBuilder builder = new LambdaOrderBulider();
consumer.accept(builder)
return builder.order;
}
public void forCustomer(String customer) {
order.setCustomer(customer);
}
public void buy(Consumer<TradeBuilder> consumer) {
trade(consumer, Trade.Type.BUY);
}
public void sell(Consumer<TradeBuilder> consumer) {
trade(consumer, Trade.Type.SELL);
}
private void trade(Consumer<TradeBuilder> consumer, Trade.Type type) {
TradeBuilder builder = new TradeBulder();
builder.trade.setType(type);
consumer.accept(builder);
order.addTrade(builder.trade);
}
}
buy sell λ©μλλ λ κ°μ Consumer λλ€ ννμμ λ°κ³ , μ΄λ₯Ό μ€ννλ©΄ κ±°λκ° λ§λ€μ΄μ§λ€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class TradeBuilder {
private Trade trade = new Trade();
public void quantity(int quantity) {
trade.setQuantity(quantity);
}
public void price(double price) {
trade.setPrice(price);
}
public void stock(Consumer<StockBuilder> consumer) {
StockBuilder builder = new StockBuilder();
consumer.accept(builder);
trade.setStock(builder.stock);
}
}
1
2
3
4
5
6
7
8
9
10
11
public class StockBuilder {
private Stock stock = new Stock();
public void symbol(String symbol) {
stock.setSymbol(symbol);
}
public void market(String market) {
stock.setMarket(market);
}
}
λ©μλ μ²΄μΈ ν¨ν΄μ²λΌ ν루μΈνΈ λ°©μμΌλ‘ κ±°λ μ£Όλ¬Έμ μ μν μ μκ³ ,
μ€μ²© ν¨μ νμμ²λΌ λ€μν λλ€ ννμμ μ€μ²© μμ€κ³Ό λΉμ·νκ² λλ©μΈ κ°μ²΄μ κ³μΈ΅ ꡬ쑰λ₯Ό μ μ§νλ€.
λ€λ§ DSL μμ²΄κ° μλ° 8 λλ€ ννμ λ¬Έλ²μ μν μ‘μμ μν₯μ λ°κ² λλ€.
10.3.4 μ‘°ν©νκΈ°
1
2
3
4
5
6
7
8
9
10
Order order =
forCustomer("BigBank",
buy(t -> t.quantity(80
.stock("IBM") // κ±°λ κ°μ²΄λ₯Ό λ§λλ λλ€ ννμ λ°λμ λ©μλ 체μΈ
.on("NYSE")
.at(125.00)),
sell(t -> t.quantity(50)
.stock("GOOGLE")
.on("NASDAQ")
.at(125.00)) );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class MixedBuilder {
public static Order forCustomer(String customer, TradeBuilder... builders) {
Order order = new Order();
order.setCustomer(customer);
Stream.of(builders).forEach(b -> order.addTrade(b.trade));
return order;
}
public static TradeBuilder buy(Consumer<TradeBuilder> consumer) {
return buildTrade(consumer, Trade.Type.BUY);
}
public static TradeBuilder sell(Consumer<TradeBulder> consumer) {
return buildTrade(consumer, Trade.Type.SELL);
}
private static TradeBuilder buildTrade(Consumer<TradeBuilder> consumer, Trade.Type type) {
TradeBuilder builder = new TradeBuilder();
builder.trade.setType(buy);
consumer.accept(builder);
return builder;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class TradeBuilder {
private Trade trade = new Trade();
public TradeBuilder quantity(int quantity) {
trade.setQuantity(quantity);
return this;
}
public TradeBuilder at(double price) {
trade.setPrice(price);
return this;
}
public StockBuilder stock(String symbol) {
return StockBuilder(this, trade, symbol);
}
}
public class StockBuilder {
private final TradeBuilder builder;
private final Trade trade;
private final Stock stock = new Stock();
private StockBuilder(TradeBuilder builder, Trade trade, String symbol){
this.builder = builder;
this.trade = trade;
stock.setSymbol(symbol);
}
public TradeBuilder on(String market) {
stock.setMarket(market);
trade.setStock(stock);
return builder;
}
}
μΈ κ°μ§ DSL ν¨ν΄μ νΌμ©ν΄ κ°λ μ± μλ DSLμ λ§λλ λ°©λ²μ΄ μλ€.
μ¬λ¬ ν¨ν΄μ μ₯μ μ νμ©ν μ μμ§λ§ μ¬λ¬ κ°μ§ κΈ°λ²μ νΌμ©νκ³ μκΈ° λλ¬Έμ μ¬μ©μκ° DSLμ λ°°μ°λλ° μ€λ μκ°μ΄ κ±Έλ¦¬κ² λλ€.
10.3.5 DLSμ λ©μλ μ°Έμ‘° μ¬μ©νκΈ°
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class TaxCalculator {
private boolean useRegional;
private boolean useGeneral;
private boolean useSurcharge;
public TaxCalculator withTaxRegional() {
useRegoinal = true;
return this;
}
public TaxCalculator withTaxGeneral() {
useGeneral = true;
return this;
}
public TaxCalculator withTaxSurcharge() {
useSurcharge = true;
return this;
}
public double calculate(Order order) {
return calculate(order, useRegional, useGeneral, useSurcharge);
}
}
1
2
3
double value = new TaxCalculator().withTaxRegional()
.withTaxSurcharge()
.calculate(order)
TaxCalculator λ μ§μ μΈκΈκ³Ό μΆκ° μκΈμ μ£Όλ¬Έμ μΆκ°νκ³ μΆλ€λ μ μ λͺ ννκ² λ³΄μ¬μ£Όμ§λ§
μ½λκ° μ₯ν©νλ€λ κ²μ΄ λ¬Έμ μ΄λ€.
μλ°μ ν¨μν κΈ°λ₯μ μ΄μ©νλ©΄ λ κ°κ²°νκ³ μ μ°ν λ°©μμΌλ‘ κ°λ μ±μ λ¬μ±ν μ μλ€.
1
2
3
4
5
6
7
8
9
10
11
12
public class TaxCalculator {
public DoubleUnaryOperator taxFunction = d -> d;
public TaxCalculator with(DoubleUnaryOperator f) {
taxFunction = taxFunction.andThen(f);
return this;
}
public double calculate(Order order) {
return taxFunction.applyAsDouble(order.getValue());
}
}
1
2
3
double value = new TaxCalculator().with(Tax::regional)
.with(Tax::surcharge)
.calculate(order);
μ΄ κΈ°λ²μ μ£Όλ¬Έμ μ΄ ν©μ μ μ©ν ν¨μ ν κ°μ νλλ§ νμλ‘νλ©°, TaxCalculator ν΄λμ€λ₯Ό ν΅ν΄ λͺ¨λ μΈκΈ μ€μ μ΄ μ μ©λλ€.
10.4 μ€μνμ μλ° 8 DSL
10.4.1 jOOQ
SQLμ ꡬννλ λ΄λΆμ DSLλ‘ μλ°μ μ§μ λ΄μ₯λ νμ μμ μΈμ΄μ΄λ€.
λ°μ΄ν°λ² μ΄μ€ μ€ν€λ§λ₯Ό μ곡ννλ μμ€μ½λ μμ±κΈ° λλΆμ μλ° μ»΄νμΌλ¬κ° 볡μ‘ν SQL ꡬ문μ νμμ νμΈν μ μλ€.
1
2
3
create.selectFrom(BOOK)
.where(BOOK.PUBLISHED_IN.eq(2016))
.orderBy(BOOK.TITLE)
μ€νΈλ¦Ό APIμ μ‘°ν©ν΄ μ¬μ©ν μ μλ€λ κ²μ΄ λλ€λ₯Έ μ₯μ μ΄λ€.
10.4.2 νμ»΄λ²
BDD(λμ μ£Όλ κ°λ°)λ ν μ€νΈ μ£Όλ κ°λ°μ νμ₯μΌλ‘ λ€μν λΉμ¦λμ€ μλ리μ€λ₯Ό ꡬ쑰μ μΌλ‘ μμ νλ κ°λ¨ν λλ©μΈ μ μ© μ€ν¬λ¦½ν μΈμ΄λ₯Ό μ¬μ©νλ€.
νμ»΄λ² μ€ν¬λ¦½ν μΈμ΄λ‘ κ°λ¨ν λΉμ¦λμ€ μλ리μ€λ₯Ό μ μν μ μλ€.
1
2
3
4
5
Feature: Buy stock
Senario: Buy 10 IBM stocks
Given the price of a "IBM" stock is 125$
When I buy 10 "IBM"
Then the order value should be 1250$
μ μ 쑰건 μ μ Given
μννλ €λ λλ©μΈ κ°μ²΄μ μ€μ§ νΈμΆ When
ν μ€νΈ μΌμ΄μ€μ κ²°κ³Όλ₯Ό νμΈνλ Assertion Then
μΈ κ°μ§λ‘ ꡬλΆλλ κ°λ μ μ¬μ©νλ€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class BuyStocksSteps {
private Map<String, Integer> stockUnitPrices = new HashMap<>();
private Order order = new Order();
@Given("^the price of a \"(.*?)\" stock is (\\d+\\$$")
public void setUnitPrice(String stockName, int unitPrice) {
stockUnitValues.put(stockName, unitPrice);
}
@When("\I buy (\\d+) \"(.*?)\"$")
public void buyStocks(int quantity, String stockName) {
...
}
@Then("^the Order value should be (\\d+)\\$$")
public void checkOrderValue(int expectedValue) {
assertEqulas(expectedValue, order.getValue());
}
}
μλ° 8μ΄ λλ€ ννμμ μ§μνλ©΄μ λ κ°μ μΈμ λ©μλλ₯Ό μ΄μ©ν΄ μ΄λ Έν μ΄μ μ μ κ±°νλ λ€λ₯Έ λ¬Έλ²μ κ°λ°ν μλ μλ€.
1
2
3
4
5
6
7
8
9
10
11
public class BuyStocksSteps {
private Map<String, Integer> stockUnitPrices = new HashMap<>();
private Order order = new Order();
public BuyStocksSteps() {
Given("^the price of a \"(.*?)\" stock is (\\d+\\$$",
(String stockName, int unitPrice) -> {
stockUnitValues.put(stockName, unitPrice);
});
...
}
ν μ€νΈ λ©μλκ° λ¬΄λͺ λλ€λ‘ λ°λλ©΄μ μλ―Έλ₯Ό κ°μ§ λ©μλ μ΄λ¦μ μ°Ύλ λΆλ΄μ΄ μμ΄μ‘λ€.
10.4.3 μ€νλ§ ν΅ν©
μ λͺ ν μν°νλΌμ΄μ¦ ν΅ν© ν¨ν΄μ μ§μν μ μλλ‘ μμ‘΄μ± μ£Όμ μ κΈ°λ°ν μ€νλ§ νλ‘κ·Έλλ° λͺ¨λΈμ νμ₯νλ€.
μ€νλ§ κΈ°λ° μ΄ν리μΌμ΄μ λ΄μ κ²½λμ μ격, λ©μΈμ§, μ€μΌμ₯΄λ§μ μ§μνκ³ μ±λ, μλν¬μΈνΈ, ν΄λ¬, μ±λ μΈν°μ ν° λ± λ©μΈμ§ κΈ°λ°μ μ΄ν리μΌμ΄μ μμ νμν κ°μ₯ 곡ν΅μ ν¨ν΄μ λͺ¨λ ꡬννλ€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Configuration
@EnableIntegration
public class MyConfiguration {
@Bean
public MessageSource<?> integerMessageSource() {
MethodInvokingMessageSource source = new MethodInvokingMessageSource();
source.setObject(new AtomicInteger());
source.setMethodName("getAndIncrement");
return source;
}
@Bean
public DirectChannel inputChannel() {
return new DirectChannel();
}
@Bean
public IntegrationFlow myFlow() {
return IntegrationFlows
.from(this.integerMessageSource(), c -> c.poller(Pollers.fixedRate(10)))
.channel(this.inputChannel())
.filter((Integer p) -> p % 2 == 0)
.transform(Object::toString)
.channel(MessageChannels.queue("queueChannel"))
.get();
}
}
λ©μλ μ²΄μΈ ν¨ν΄μ ꡬννλ IntegrationFlows ν΄λμ€κ° μ 곡νλ μ μ°ν λΉλλ₯Ό μ¬μ©νλ€.
νλ‘μ°λ κ³ μ μλλ‘ MessageSource λ₯Ό ν΄λ§νλ©΄μ μΌλ ¨μ μ μλ₯Ό μ 곡νκ³ , νμλ₯Ό λ¬Έμμ΄λ‘ λ³νν΄ μ΅μ’ μ μΌλ‘ κ²°κ³Όλ₯Ό μΆλ ₯ μ±λμ μ λ¬νλ€.