javaで最強のfizz buzz

46
Javaで最強のFizzBuzz 16 渋谷じゃば 2016/07/23 @yy_yank

Upload: yy-yank

Post on 20-Mar-2017

2.464 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Javaで最強のfizz buzz

Javaで最強のFizzBuzz

第16回 渋谷じゃば 2016/07/23

@yy_yank

Page 2: Javaで最強のfizz buzz

          こいつです

          ・小物SIer          ・viキーバインド好き

          ・サクラエディタicon          ・JavaとKotlinが好き

ヤンク(@yy_yank)

自己紹介

Page 3: Javaで最強のfizz buzz
Page 4: Javaで最強のfizz buzz

FizzBuzzとは

Page 5: Javaで最強のfizz buzz

3の倍数ではFizzを出力して、5の倍数ではBuzzを出力して、 両方の倍数(15の倍数)の場合はFizzBuzzと出力して、それ以外は数字をそのまま出力する処理のことを言います

FizzBuzzとは

Page 6: Javaで最強のfizz buzz

なるほど

Page 7: Javaで最強のfizz buzz

public void fizzBuzz() throws Exception { IntStream.rangeClosed(0, 10000).mapToObj(FizzBuzz::make).forEach(System.out::println);}private static String make(int i) { return i != 0 && i % 15 == 0 ? "fizzbuzz" : i != 0 && i % 3 == 0 ? "fizz" : i != 0 && i % 5 == 0 ? "buzz" : String.valueOf(i);}

適当にやるならこんな感じ

Page 8: Javaで最強のfizz buzz

特に説明は不要ですよね

Page 9: Javaで最強のfizz buzz

設計を考える

Page 10: Javaで最強のfizz buzz

・言語規約を守る

・適切なインターフェースを実装する

Javaの設計で大事なこと

Page 11: Javaで最強のfizz buzz

3の倍数ではFizzを出力して、5の倍数ではBuzzを出力して、 両方の倍数(15の倍数)の場合はFizzBuzzと出力して、それ以外は数字をそのまま出力する処理のことを言います

要件を改めて見る

Page 12: Javaで最強のfizz buzz

3の倍数ではFizzを出力して、

5の倍数ではBuzzを出力して、 両方の倍数(15の倍数)の場合はFizzBuzzと出力して、それ以外は数字をそのまま出力する処理のことを言います

要件を改めて見る

Page 13: Javaで最強のfizz buzz

FizzBuzzFizzBuzzSonomama

クラス構成

Page 14: Javaで最強のfizz buzz

Fizz・・・fizzと出力

Buzz・・・buzzと出力

FizzBuzz・・・fizzbuzzと出力

Sonomama・・・そのまま数字を出力

なにをするか

Page 15: Javaで最強のfizz buzz

Fizz・・・3で割り切れたら

Buzz・・・5で割り切れたら

FizzBuzz・・・15で割り切れたら

Sonomama・・・3でも5でも15でも割り切れない

どのタイミングか

Page 16: Javaで最強のfizz buzz

よし、いけそう

Page 17: Javaで最強のfizz buzz

じゃあ、どうやって処理伝播をしよう

Page 18: Javaで最強のfizz buzz

投げよう

Page 19: Javaで最強のfizz buzz

これが最強のクラス構成だ

FizzBuzzPitcherFizzExceptionBuzzExceptionFizzBuzzExceptionSonomamaException

Page 20: Javaで最強のfizz buzz

FizzBuzzPitcherFizzExceptionBuzzExceptionFizzBuzzExceptionSonomamaException

これが最強のクラス構成だ

投げる

Page 21: Javaで最強のfizz buzz

FizzBuzzPitcherFizzExceptionBuzzExceptionFizzBuzzExceptionSonomamaException

これが最強のクラス構成だ

投げられる

Page 22: Javaで最強のfizz buzz

FizzBuzzPitcherFizzExceptionBuzzExceptionFizzBuzzExceptionSonomamaException

これが最強のクラス構成だ

持ちつ

Page 23: Javaで最強のfizz buzz

FizzBuzzPitcherFizzExceptionBuzzExceptionFizzBuzzExceptionSonomamaException

これが最強のクラス構成だ

持たれつ

Page 24: Javaで最強のfizz buzz

public class FizzBuzzPitcher { private FizzBuzzPitcher(){} public static void overThrow(int i) { boolean fizz = i != 0 && i % 3 == 0; boolean buzz = i != 0 && i % 5 == 0; boolean fizzBuzz = i != 0 && i % 15 == 0; if(fizzBuzz) { throw new FizzBuzzException(); } else if(fizz) { throw new FizzException(); } else if(buzz) { throw new BuzzException(); } else { throw new SonomamaException(i); }}

これが最強のピッチャーだ

Page 25: Javaで最強のfizz buzz

for (int i = 0; i < 10000; i++) try { FizzBuzzPitcher.overThrow(i); } catch (FizzException fizz) { System.out.println("fizz"); } catch (BuzzException buzz) { System.out.println("buzz"); } catch (FizzBuzzException fizzbuzz) { System.out.println("fizzbuzz"); } catch (SonomamaException not) { System.out.println(i); }

これが最強の処理実行だ

Page 26: Javaで最強のfizz buzz

完璧ですね

Page 27: Javaで最強のfizz buzz

いやチョット待て

Page 28: Javaで最強のfizz buzz

おかしいおかしい

Page 29: Javaで最強のfizz buzz

for (int i = 0; i < 10000; i++) try { FizzBuzzPitcher.overThrow(i); } catch (FizzException fizz) { System.out.println("fizz"); } catch (BuzzException buzz) { System.out.println("buzz"); } catch (FizzBuzzException fizzbuzz) { System.out.println("fizzbuzz"); } catch (SonomamaException not) { System.out.println(i); }

これが最強の処理実行だ

このあたりが冗長!!!

#そこかよ

Page 30: Javaで最強のfizz buzz

じゃあ、どうやって冗長さをなくそう

Page 31: Javaで最強のfizz buzz

AutoClosableを使おう

Page 32: Javaで最強のfizz buzz

FizzException implements AutoClosableBuzzException implements AutoClosableFizzBuzzException implements AutoClosableSonomamaException implements AutoClosableFizzBuzzCatcher

これが最強のクラス構成だ

Page 33: Javaで最強のfizz buzz

public class BuzzException extends RuntimeException implements AutoCloseable{ @Override public void close() { System.out.println(“buzz”); }}

これが最強のclose処理だ

Page 34: Javaで最強のfizz buzz

これが最強のキャッチャーだpublic class FizzBuzzCatcher { private FizzBuzzCatcher(){} public static AutoCloseable make(int i) { try { FizzBuzzPitcher.overThrow(i); } catch(FizzException | BuzzException | FizzBuzzException | SonomamaException e){ return (AutoCloseable) e; } // 投げられないのはおかしいから投げる

throw new IllegalStateException(); } public static void receive(int i) throws Exception { try(AutoCloseable ex = make(i)){} }}

Page 35: Javaで最強のfizz buzz

public class FizzBuzzCatcher { private FizzBuzzCatcher(){} public static AutoCloseable make(int i) { try { FizzBuzzPitcher.overThrow(i); } catch(FizzException | BuzzException | FizzBuzzException | SonomamaException e){ return (AutoCloseable) e; } // 投げられないのはおかしいから投げる

throw new IllegalStateException(); } public static void receive(int i) throws Exception { try(AutoCloseable ex = make(i)){} }}

これが最強のキャッチャーだ

try-with-resourecesで処理が呼び出される

Page 36: Javaで最強のfizz buzz

これでインスタンス生成するだけで標準出力されるぞ!!

Page 37: Javaで最強のfizz buzz

これが最強の処理実行だ

// なんと呼び出し側は1行!!!

for (int i = 0; i < 10000; i++) FizzBuzzCatcher.receive(i);

Page 38: Javaで最強のfizz buzz

・時として、人類は間違いをおかす

・誰かが止めなければならない

・例外は異常を伝えるために使いましょう

・例外をgoto文のように使ってはいけません

・AutoClosableインターフェースはクローズ処理を行うために使いましょう

※ちなみにjava.util.stream.Streamも

AutoCloseableです

まとめ

Page 39: Javaで最強のfizz buzz

・言語規約を守る

・適切なインターフェースを実装する

Javaの設計で大事なこと

Page 40: Javaで最強のfizz buzz

動けば良い、は良くない!!

Page 41: Javaで最強のfizz buzz

時間が余ったらおまけ

Page 42: Javaで最強のfizz buzz

これが最強のキャッチャーだpublic class FizzBuzzCatcher { private FizzBuzzCatcher(){} public static AutoCloseable make(int i) { try { FizzBuzzPitcher.overThrow(i); } catch(FizzException | BuzzException | FizzBuzzException | SonomamaException e){ return (AutoCloseable) e; } // 投げられないのはおかしいから投げる

throw new IllegalStateException(); } public static void receive(int i) throws Exception { try(AutoCloseable ex = make(i)){} }}

こういうふざけたコードを書いてたら Javaコンパイラのバグを踏みました※1.8.0_25のバグで、1.8.0_72で直ってます

Page 43: Javaで最強のfizz buzz

14:39:40: Executing external task 'build'...コンパイラで例外が発生しました(1.8.0_25)。Bug Paradeで重複がないかをご確認のうえ、Java Developer Connection (http://java.sun.com/webapps/bugreport)でbugの登録をお願いいたします。レポートには、そのプログラムと

下記の診断内容を含めてください。ご協力ありがとうございます。java.lang.ClassCastException: com.sun.tools.javac.code.Type$UnionClassType cannot be cast to com.sun.tools.javac.code.Type$IntersectionClassType

at com.sun.tools.javac.code.Types$8.visitClassType(Types.java:1540)at com.sun.tools.javac.code.Types$8.visitClassType(Types.java:1497)at com.sun.tools.javac.code.Type$ClassType.accept(Type.java:778)at com.sun.tools.javac.code.Types$DefaultTypeVisitor.visit(Types.java:4451)at com.sun.tools.javac.code.Types.isCastable(Types.java:1488)at com.sun.tools.javac.comp.Check.checkCastable(Check.java:568)at com.sun.tools.javac.comp.Check.checkCastable(Check.java:565)

Page 44: Javaで最強のfizz buzz
Page 45: Javaで最強のfizz buzz
Page 46: Javaで最強のfizz buzz

[JDK-8071291]Compiler crashes trying to cast UnionType to IntersectionClassTypehttps://bugs.openjdk.java.net/browse/JDK-8071291

バグレポートの書き方http://yyyank.blogspot.jp/2016/07/javajdk.html