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

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

Avatar for tockri tockri
April 09, 2026

 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)); } この部分だけ