Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Javaでなんちゃって鉄道志向プログラミング

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

 Javaでなんちゃって鉄道志向プログラミング

Avatar for tockri

tockri

April 09, 2026

More Decks by tockri

Other Decks in Programming

Transcript

  1. ⾃⼰紹介 & 今⽇の発表内容 藤⽥正訓(ふじたま) • ふくおかフィナンシャルグループ(2年⽬) • だいたい何でも書けるプログラマー • 関数型プログラミングLOVE❤

    ◦ 「こわくない関数型プログラミング」⾒てね 最近のJavaの機能を使うと関数型プログラミング「みたいな感じで」鉄道志向プ ログラミングが気持ちよく書けたよ、という話をします
  2. 例外は読みにくい try { var some = doSomething(); var another =

    doSomethingElse(some); var result = doSomethingAnother(another); } catch (SomeException e) { log.warn("処理に失敗しました", e); : : } ⼤域脱出はgotoと似てる(Bobおじさん) catchしてるコードを⾒て、どこから来たかわからない
  3. こっちのほうが読みやすい 前の処理は前の⾏に書かれてる。 どこが失敗したのか⼀⽬瞭然 var some = doSomething(); var another =

    doSomethingElse(some); var result = doSomethingAnother(another); if (result instanceof Failure failure) { log.warn("処理に失敗しました: {}", failure.getMessage()); }
  4. ビジネスロジックは条件分岐で書くのがいいよね 2パターンの返り値を返せる必要がある 「他の⼈のIDとかぶってたらエラーメッセージをレスポンスする」 なら、こうだよね // SELECT FOR UPDATE Optional<User> anotherUser

    = repository.findByUserIdForUpdate(newUserId); if (anotherUser.isPresent()) { return (エラーメッセージを含むオブジェクト); } else { repository.save(user.updateUserId(newUserId)); return (成功したことを示すオブジェクト); }
  5. 鉄道指向(Railway Oriented)プログラミング Javaでもやりたいなあ。でも関数合成は(簡単には)できないんだよなあ Scott Wlaschin(2014) • F#を念頭 • モナドの理解の第⼀歩 •

    エラー処理という問題にフォーカス • 例外ではなく、返り値で「成功」と「失敗」を表現する • Success、Failureの2態を持つResult型
  6. (ちょっと違うけど)できた public sealed interface Result<T> permits Success, Failure { default

    <S> Result<S> then(Function<T, Result<S>> func) { return switch (this) { case Success<T>(var value) -> func.apply(value); case Failure<T>(var errors) -> new Failure<>(errors); }; } } public record Success<T>(T value) implements Result<T> {} public record Failure<T>(List<String> errors) implements Result<T> {} JavaScriptのPromise.then()をパクインスパイア <Java17> Sealed Class <Java21> Record Pattern Matching <Java8> Function <Java8> record この部分 <Java14> switch式 <Java8> default
  7. こんな感じにできる(1) 引数を受け取ってResultを返すメソッドをいくつも作る 要件を1つだけ満たす単純なメソッド  →単体テストも単純   →AIが⼀瞬で正解してくれる Result<ValidOrder> validate(OrderRequest request) { if

    (request.orderDateTime().isAfter(LocalDateTime.now(clock))) { return new Failure<>(List.of("注文日時が不正です ")); } return new Success<>(toValidOrder(request)); } この部分だけ