業務でJava8を使うようになってから、ラムダ式を使ってもう少し流暢なコードは書けないかと模索してきました。
最近やっと良さげなコードが書けたので、是非Java技術者の皆さんに共有したく、初めてQiitaで記事を書いています。
今回はサンプルのみ記載して、裏側の仕組みなどは別途紹介できたらなと思います。
サンプルはコーヒーを淹れる手順を模したプログラムになっています。
public void easygoing() {
WholeCoffeeBeans wholeBeans = WholeCoffeeBeans.inGrams(50);
GroundCoffeeBeans groundBeans = Mill.grind(wholeBeans);
Water water = Water.inMilliliters(500);
HotWater hotWater = Kettle.boil(water);
Coffee coffee = Dripper.drip(groundBeans, hotWater);
CoffeeAddict saya = new CoffeeAddict();
saya.drink(coffee);
}
日本語で書くと、ミルでコーヒー豆を挽いて、ヤカンでお湯を沸かして、ドリッパーで抽出したコーヒーをサヤさんが飲むと、となります。わざと入れ子無しで丁寧に書いているのですが、型をいちいち書かないといけないのでかなり面倒です。
同様の処理を以下のようにも書けます
public void impatient() {
new CoffeeAddict().drink(Dripper.drip(
Mill.grind(WholeCoffeeBeans.inGrams(50)), Kettle.boil(Water.inMilliliters(500))));
}
だいぶ短くなりましたが、2重の入れ子構造になっていて、中から外の順に解釈しないといけないため、人間の脳には若干厳しい感じです。
nagareで追加した8クラスを使うと以下のような記述が可能になります。
public void nagare_prepositive() {
CoffeeAddict saya = new CoffeeAddict();
Do.when(WholeCoffeeBeans.inGrams(50), Water.inMilliliters(500))
.then(Do.first(Mill::grind).and(Kettle::boil))
.then(Dripper::drip)
.done(saya::drink);
}
public void nagare_postpositive() {
CoffeeAddict saya = new CoffeeAddict();
Do.first(Mill::grind).and(Kettle::boil)
.then(Dripper::drip)
.done(saya::drink)
.by(WholeCoffeeBeans.inGrams(50), Water.inMilliliters(500));
}
public void nagare_logic_and_exec() {
Saver<Coffee> brewCoffee = Do.when(WholeCoffeeBeans.inGrams(50), Water.inMilliliters(500))
.then(Do.first(Mill::grind).and(Kettle::boil))
.then(Dripper::drip);
CoffeeAddict saya = new CoffeeAddict();
saya.drink(brewCoffee.let());
}
基本的な考え方はJava8で追加されたStreamに近い感じです。1番上は最初に引数を与える書き方、2番目は最後に引数を与える書き方、3番目はロジックと実行を分離した書き方です。
左から右(上から下)の順に一連の処理が書けるので、慣れてくると思考とコードが一致してなかなか楽しいです。
是非、趣味で書くコード等で試してみて下さい。(趣味でJavaを書く人がいるのか分かりませんが)
サンプルも単体テストとして入れてますので、裏側の仕組みと合わせて興味のある方は覗いてみてください。
https://github.com/mt-village/nagare