学習・技術検証用デモ — 本システムは実際の銀行サービスではありません。

公開情報をもとに構築した教育目的のシステムです。実在する個人情報・口座情報・機密情報・認証情報等を入力しないでください。

ミニ銀行ACADEMY SYSTEM LEARNING
教材メニュー
学習進捗0 / 134
あと134項目
INTERMEDIATE · 中級COURSE 05 · JAVA / ENTERPRISE DEVELOPMENT

Service:ユースケースの順序を表す

Service層はControllerやDB通信の詳細から離れ、1つのユースケースで何をどの順番に行うかを表します。PaymentApplicationServiceが薄い理由を読み解きます。

04 / 11
JAVA / ENTERPRISE DEVELOPMENT · Java・エンタープライズ開発

Java / Spring Bootを入口に、金融システムのService・Repository・Transaction設計を読む。

先に学ぶ内容 — Prerequisite: ソフトウェア工学 / 銀行システム

学ぶこと — LEARNING GOALS

このページで学ぶこと

  • application serviceの責任
  • domain modelへの変換
  • 薄いServiceと貧弱なServiceの違い

体験36 · JAVA SERVICE(順序を表す)

Service層が薄いのは、手を抜いているからか確かめよう

まずは予想をひと言。本文を読んだ後、教材内の参照元で実際のServiceの実装を確認します。

体験学習 · STEP 1 / 5
  1. 01
    まず予想する — PREDICT

    まずここだけ:思ったことをひと言書く

    Service層が薄く実装されているのは、手を抜いているからだと思いますか?

    正解でなくて大丈夫です。「〜だと思う」から始めてみましょう。

    ヒント1を見る

    『薄い』ことは、常に手抜きを意味するでしょうか?

    ヒント2を見る

    残高やKYCの最終判断は、どこにあるべきでしょうか?

    もっと詳しく:この問いで使う専門用語
    • Application Serviceは、ユースケースの処理順序をまとめる層です。
    • Commandは、ユースケースへ渡す入力をまとめた型です。
    • 薄いServiceは、責任を別の正式な境界へ委ね、必要な順序だけを持つServiceです。
まずはひと言だけで大丈夫です。

この後の本文を最後まで読んでから、実際に操作して確かめるステップへ進みます。

日常語で理解する — PLAIN LANGUAGE

まず、ここだけつかむ

1

ServiceはHTTPやJSONの詳細から離れ、1つのユースケースで何を行うかを表します。

2

PaymentApplicationServiceは入力金額をMoneyへ変換し、RPC用の値を組み立ててGatewayを呼びます。

3

業務規則がDB RPCにあるため、Javaへ同じ判定をコピーせず意図的に薄く保っています。

順番に理解する — DIFFICULT PARTS, STEP BY STEP

難しいポイントを、順番にほどく

専門用語を覚えることより、「なぜ必要か」「このシステムのどこで使うか」を理解することが目標です。

01

Application Service

やさしく言うと

ユースケースの処理順序をまとめる層です。

なぜ必要?

HTTPとDB通信の詳細から業務の流れを切り離すためです。

Minibankでは

createPaymentとconfirmOtpを提供します。

02

Command

やさしく言うと

ユースケースへ渡す入力をまとめた型です。

なぜ必要?

HTTP DTOをそのまま内部へ広げないためです。

Minibankでは

CreatePaymentCommandが振込依頼の入力です。

03

薄いService

やさしく言うと

責任を別の正式な境界へ委ね、必要な順序だけを持つServiceです。

なぜ必要?

同じ業務規則の二重管理を避けるためです。

Minibankでは

KYCや残高はDB RPCが最終判断します。

発展 — ADVANCEDもっと詳しく確認する最初の学習では読まなくても問題ありません。仕組みをもっと深く理解したい場合に開いてください。

ServiceはHTTPを知らず、業務の入口になる

PaymentApplicationServiceはHTTPステータスやJSONを扱いません。入力をMoneyとRequestTransferParamsへ変換し、Gatewayを呼びます。

これによりControllerは通信契約、Serviceはユースケース、Gatewayは外部システム呼び出しへ集中できます。

public PendingPayment createPayment(
        String bearerToken,
        CreatePaymentCommand command,
        UUID idempotencyKey) {
    Money amount = Money.ofYen(command.amount());
    // RPC用パラメータへ変換してGatewayを呼ぶ
}

現在のServiceが意図的に薄い理由

KYC、口座状態、残高、冪等性、排他ロック、台帳記帳は既存PostgreSQL RPCが一貫して判断します。Javaへ同じ規則をコピーすると、片方だけ変更された時に結果が食い違います。

薄いこと自体が良いのではありません。正式な業務判断をDBへ残すというアーキテクチャ判断に沿って薄くしています。

Command・Domain・Responseを分ける

型信頼範囲役割
CreatePaymentRequest外部入力形式を検証する
CreatePaymentCommandControllerからServiceユースケース入力を表す
Money検証済みドメイン値整数円の不変条件を守る
PendingPaymentRPCの業務結果OTP待ち状態を表す
CreatePaymentResponse外部出力公開してよい形へ整える

Serviceを変更する時のレビュー観点

  • 同じ業務規則がJavaとDBへ二重定義されていないか
  • 途中失敗した時に何が残るか
  • 外部呼び出しの再試行で二重処理にならないか
  • tokenや秘密をログへ出していないか
  • ドメイン結果とHTTP表現が混ざっていないか

体験学習の続き · LEARNING LOOP

ここまで読めましたか?続けて確認してみましょう

Application ServiceとThin Serviceの考え方を読んだところで、教材内の参照元で実際のServiceの実装を確認し、自分の言葉で説明してみます。

STEP 2〜5 / 5
  1. 02
    仕組みを確かめる — CONCEPT CHECK

    画面操作なしで、仕組みを確かめる

    この仕組みは、Mini Bankの画面には現れません。次のEvidenceとCode Trail、教材本文だけで理解を進めます。

  2. 03
    証拠を確認する — EVIDENCE

    何を見たか、1つずつ確かめる

    Evidence(判断の根拠となる記録)を確認したらチェックします。各項目の「何を見るか」を手がかりにしてください。

    画面を開けない項目は、Source Trail(教材の参照元)と教材の説明で確認できます。失敗を実際に起こす必要はありません。

  3. 04
    コードの処理経路を追う — CODE TRAIL

    コードを書く必要はありません

    ここでは「説明されている仕組みが、実際のMini Bankのどこに実装されているか」を確認します。まずは日本語の役割説明を読み、入力した依頼がどこへ渡るかをつかみましょう。コードの全文を読む必要はありません。

    まずServiceが何を扱い何を扱わないかを見て、次にHTTPから切り離された入力の型を見ます。

    振込依頼とOTP確認のオーケストレーション。

    services/payment-service/src/main/java/com/minibank/payment/application/PaymentApplicationService.java

    HTTPから切り離したユースケース入力。

    services/payment-service/src/main/java/com/minibank/payment/application/CreatePaymentCommand.java
    教材の参照元を確認する — Source Trail ↓
  4. 05
    自分の言葉で説明する — EXPLAIN

    LEVEL 1 — やさしい説明(まずここだけ)

    なぜPaymentApplicationServiceは、残高やKYCの判定を自分で持たずDB RPCへ委ねているのでしょうか? 短い2文を目安に説明してください。

    日常語だけで完了できます。専門用語の数や正誤を自動採点するものではありません。

    ヒント1を見る

    「薄いService」という言葉を使って書いてみましょう。

    ヒント2を見る

    同じ業務規則を2箇所で持つと何が困るか考えてみましょう。

    もっと詳しく:LEVEL 2 — 専門用語を使った説明(任意)

    Application Service、Command、薄いServiceの3つを使って、Service層の責任を説明してみましょう。

    挑戦する場合は、上の説明欄に追記できます。追加しなくても完了できます。

    説明の確認ポイント — Checkpoint
    • 薄いServiceは手抜きではなく設計判断だと説明できる
    • 正式な業務判断の場所が1つに保たれていると説明できる
予想5文字以上・証拠2項目・説明20文字以上で完了できます。

証拠の確認:0 / 2。LEVEL 2(専門用語での説明)は任意です。

入力はこのブラウザに保存されます。Academy教材の進捗とは別の学習メモです。

理解を確かめる — CHECK YOUR UNDERSTANDING

3問で理解チェック

答えを頭の中で考えてから、各項目を開いて確認してください。

Q1Serviceが薄ければ常に良い設計ですか?
答え

いいえ。どこが正式な業務判断を持つかという設計理由が必要です。

Q2ServiceはHTTPステータスを決めますか?
答え

現在の構成ではControllerが決め、Serviceはドメイン結果を返します。

Q3Javaでも残高検査をすればDBの検査を削除できますか?
答え

できません。同時実行で値が変わるため、更新と同じDB transaction内の最終検査が必要です。

ここまで読めましたか?

完全に暗記する必要はありません。大切な考え方を説明できそうなら押してください。

教材の参照元 — SOURCE TRAIL

根拠と関連教材

CURRENT IMPLEMENTATIONは確認したrepository内の実装です。HISTORICAL IMPLEMENTATIONは導入・修正の履歴で、後続migrationによる再定義があり得ます。RELATED LESSONは教材への案内で、実装の一次Sourceではありません。ASSUMPTIONは仮定、UNKNOWNは未確認を表します。

確認基点: d02eae8914f39cbf06bfe422dc39c71886f82b3e / 2026-09-11。稼働環境への適用確認: UNKNOWN。パス実在の自動検査と、記述した技術的事実の確認は別です。

  • 現在の実装 — CURRENT IMPLEMENTATIONservices/payment-service/src/main/java/com/minibank/payment/application/PaymentApplicationService.java振込依頼とOTP確認のオーケストレーション
  • 現在の実装 — CURRENT IMPLEMENTATIONservices/payment-service/src/main/java/com/minibank/payment/application/CreatePaymentCommand.javaHTTPから切り離したユースケース入力
  • 現在の実装 — CURRENT IMPLEMENTATIONservices/payment-service/src/main/java/com/minibank/payment/domain/Money.javaServiceが生成する金額値