- Top
- JJUG CCC Spring 2025 に参加しました
JJUG CCC Spring 2025 に参加しました
2025/08/10目次
参加目的
普段、業務で Java を使っていることもあり、Java のトレンドや新しい技術を学ぶために参加しました。
Java の言語仕様やフレームワーク、テスト、組織の話など幅広いトピックに対して興味を持って参加しました。
そして参加した結果、普段の業務に何か生かせる情報を得られればと思っていました。
セッション別メモ
ユニットテスト基礎講座
ユニットテストの基礎が幅広く体系的に学べる内容でした。
また、良いユニットテストを書くためには設計が重要であることを再認識しました。
memo
ユニットテストの定義
- 1 単位の振る舞いを検証すること
- 実行時間が短いこと
- 他のテストケースから隔離された状態で実行されること
ユニットテストの目的
- 期待通りに正しく動作することを検証する
- リグレッションを防ぐ
- ドキュメンテーション (副次的)
テストコードはコード量が多くなるので、意識しないと膨大になる
→ テストコードの SOS (独自言語)を意識しよう
- Structured: 構造化されている
- Organized: 整理されている
- Self-documenting: 自己文書化されている
1 単位の振る舞いをどう見つけるか
トランザクションスクリプトではユニットテストが書きづらい
→ 分割して統治せよ
具体的には、
- 大きな振る舞いを小さな振る舞いに分割する
- 処理フローロジックと中核ロジックに分ける
- この処理フローロジックがつまりアプリケーションサービス
- 関心を分離して、小さな振る舞いの因子数を減らす
質の良いテストコードを書くために重要な観点
- 構造化されている
- パッケージ構造を業務観点での分割にする
→ テストスイートとしての対象範囲を絞れて、開発者の認知負荷が下がる - 内部クラスを用いてテストケースを階層化する
→ テストランナーで視覚的に構造を俯瞰でき、必要に応じてドリルダウンできる
- パッケージ構造を業務観点での分割にする
- 整理されている
- テストケースのグループ分け
→ 観点の抜け漏れや網羅性がチェックしやすくなる - テスト設計の根拠を表現できないので、JavaDoc コメントを残すのがおすすめ - パラメータ化テストの活用
→ 同じ内容の検証を行うテストメソッドが多数あると冗長で見通しが悪いのを解決する
- テストケースのグループ分け
- 自己文書化されている
自己文書化とは?
テストコードを一瞥しただけでテストの目的や条件がわかること - テストの名称から、テスト条件と期待する振る舞いがわかるようにする - AAA または Given - When - Then を整理 - Act は原則 1 文 - 可読性を考慮する - Arrange と Asert は記述が冗長になりがち。Arrange はヘルパーメソッドに切り出すなど
大きな振る舞いに対するテストはどうする?
アプリケーションサービスが処理フローの制御の責務のみを担っている前提であれば
網羅的に見る必要はなく、代表的なケースとエッジケースを見れば十分
テストダブルの利用指針
- まずはテストダブルを使わずに済むか考える
- スタブは目的を理解した上で適切に使えば OK
- モックの利用は極めて慎重に
ビズリーチにおけるリアーキテクティングの実践事例 ~ 大規模システムを継続的に変革するための組織 × アーキテクチャ戦略~
大規模な組織で大規模なプロダクトのリアーキテクトを進める上での重要な点が幅広く述べられているセッションでした。
特に、技術面とプロセス・組織の面が勉強になりました。
memo
リアーキテクティングの目的はアジリティを獲得すること
アジリティを獲得するために考えるべき要素
-
マインドセット
-
プロセス
-
技術
-
組織
-
技術
- モジュール分割を行う
その際の適切な境界面はどこ? - → うまく境界面を設定できている状態は、非同期で業務機能間が結合されている状態 - 「残」が業務分割の自然な切り口になりうる
残とイベント駆動でコンテキストを繋ぐ - ビジネス価値の高いものから開発をする。
ユーザーが毎日使う機能、各事業 KPI に影響が大きい機能から - 検索基盤の例
専用チームを作って、インタフェースを変えなければ何やってもいいよっていう状態にした
→ A/B テストとかをやって刷新できた - 専用チームを作ることで専門性の高いメンバーの獲得や育成の話が出てくる - 変更容易性とテスト容易性を高める設計パターンを採用しましょう
- 意識するのは、「関心事の分離」
- テストピラミッドを段階的に実現していく
- モジュール分割を行う
-
プロセスと組織
- プロダクト価値を可視化して、価値に基づく優先順位付けをしよう
- バリューストーミングで可視化をした
- QA エンジニアがテスト分析、テスト設計をファシリテートして、エンジニアへいねーブリング
- ナレッジマネジメントの実践
- 属人化を防ぐ
- チームで学習する文化が自律的に育まれている
- プロダクト価値を可視化して、価値に基づく優先順位付けをしよう
Java の関数型インタフェースの基礎と活用法
関数型インタフェースの基礎を改めて学びました。
また、関数型インタフェースを使うことで、コードの可読性や再利用性が向上することを実感しました。
使える場面では積極的に使用して、業務に活かしていきたいと思います。
memo
関数型インタフェースとは?
ラムダ式やメソッド参照の受け皿となるインタフェース
抽象メソッドを 1 つだけ持つ
- 関数型インタフェースを学ぶ意義
- 短く直感的にかける
- 構造と処理の分離がしやすい
→ 構造に対する共通操作を再利用しやすくなる - 命令型から宣言型への変換
→ どうやるか ではなく 何をやるか に視点が変わる - 他言語へも流用可能
- 最近では、非同期処理・リアクティブプログラミングでは必須の知識になってきてる
- 関数型インタフェースに苦手意識を感じる理由
- 宣言型の考え方に馴染めていない
→ 抽象的にイメージするのが大事 - 型宣言が複雑でとっつきにくい
- 慣れるのが一番
- 宣言型の考え方に馴染めていない
覚えておくべき関数型インタフェース
インターフェース | 引数 | 戻り値 | 代表メソッド | イメージ |
---|---|---|---|---|
Runnable | なし | なし | void run() | 処理の実行 |
Supplier<T> | なし | あり | T get() | 値の生成 |
Consumer<T> | あり | なし | void accept(T t) | 値の利用 |
Function<T, R> | あり | あり | R apply(T t) | 値の変換 |
Predicate<T> | あり | boolean | boolean test(T t) | 値の判定 |
関数型インタフェースの利用例
- 乱数生成を入れ替え可能に
- 独自の関数型インタフェースを作る
- 標準の関数型インタフェースは例外をスローできないので不便
Java で学ぶ代数的データ型
曖昧だった代数的データ型の理解が深まりました。
memo
関数の宣言を見て振る舞いが想像できる & 期待通りに振る舞うような関数を定義することに代数的データ型が役立つ
代数的データ型とは、直積型と直和型の概念を組み合わせたもの
直積型とは
AND を表現する型。要素の組み合わせの数だけ取りうる組がある
Java でいう Record や Bean Class
要はデータクラス
直和型とは
OR を表現する型。複数の型のうちどれか一つを表す型
Java でいう enum や sealed class
代数的データ型がないと、許容したくない状態のインスタンスの生成を許容してしまう
代数的データ型があると、データの意味が一目でわかるし、間違いも起こりにくくなる
Java ならば sealed Class を使うのが適切
- enum はだめ?
- enum で直積の性質を表現するのは無理がある。コードが綺麗じゃなくなる
- 継承はダメ?
- 継承を使うと理論上無限の集合ができる。直和の性質がない
代数的データ型を使うことによる実際のメリット
- データの不整合が起こり得ない
- 取りうる値の範囲が限定されることで、switch にデフォルトが生えない
- コンパイル時点での品質保証に寄与する
- 取りうる値が増えた時の修正漏れも起こりづらい
- 明示的なシグネチャを定義可能
シンプルは作れる! - 実験からも見えてきたイミュータブルデータモデルの効果
イミュータブルデータモデルとは何かの説明と、実際にイミュータブルデータモデルをテーブル設計に用いてみた結果の発表でした。
正直、イミュータブルデータモデルの理解はまだ浅い気がしているので、実践を通して理解を深める必要があるなと感じています。
memo
- 複雑さには本質的なものと偶有的なものがある
- 偶有的複雑さには銀の弾丸は存在するが、本質的複雑さには銀の弾丸は存在しない
- 本質的な複雑さはどう設計を工夫しても減らない
- この本質的複雑さは設計によって変わるものではないということを、「本質的複雑さ保存の法則」という
- 本質的な複雑さは Complex と Complicated の状態で存在する
- Complicated な状態にして「頑張れば理解可能」にしておく
- Complex
- 因果関係がはっきりしない状態
- 時間と労力をかけても理解できないものがあるかもしれない状態
- Complicated
- 分割され、数が多く、認知負荷が高い状態
- 時間と労力をかければ理解可能な状態
- イミュータブルデータモデル
- エンティティをイベントとリソースに分類する
- イベントエンティティ
- 日時属性をただ 1 つだけ保持する
- 業務のイベントはある時点で何が起こったのかの記録
- イベントは事業の記録なので、更新してはならない
- リソースエンティティ
- 日時属性を全く持たないようにする
- 更新の内容を保持したい場合、イベントエンティティを追加する
- イベントエンティティ
- ただ、テーブル設計の指針というわけではなく、要求の本質的な複雑さをデータモデリングを通じて明らかにすることが狙い
- エンティティをイベントとリソースに分類する
変化に強いテーブル設計の勘所
変化に弱いデータベースのなかで、いかにして変化に強いテーブル設計を行うかについてのセッションでした。
将来のシステムの変更に強いテーブル設計を行うための考え方や実践方法が幅広く述べられていました。
memo
- データベースは変更に弱い。ただ、ビジネスは常に変化し、仕様変更は常にある
- この時にマジカルな設計をテーブルに起こしてしまうと、将来的にビジネス側に不要な制約を生み出してしまう
- LINE ログインの例
- この時にマジカルな設計をテーブルに起こしてしまうと、将来的にビジネス側に不要な制約を生み出してしまう
- ビジネスロジックの複雑さはアプリケーションレイヤーで担保するべき
- テストコード書きやすい
- 振る舞いのテストもしやすい
- デプロイもデータベースと比較する問い簡単
- データベースには事実のみを保存し、状態をもたせないようにする
- そのために必要なのが「正規化」
- 正規化のコツ
- 以下の 4 つを満たしていたら大体正規化できている
- 事実だけを保存する
- 重複がない
- 不整合がない
- null がない
- 種別と状態を考えることも重要
- ライフサイクルが違うデータは往々にして状態や種別が異なる
- 4 つ以上の index が必要な場合はそのテーブルの責務を考える
- 以下の 4 つを満たしていたら大体正規化できている
- テーブルを Simple にしよう。そうすると変更に強くなる
- 単一責任だと変更時に他に影響を与えづらくなる
- Simple と Easy は違う
- Simple は一個のテーブルの要素数を必要最低限にして、責務を一つにした状態
- Easy は情報を 1 つのテーブルにまとめて、自分にとって馴染みがある状態
- Simple と Easy は違う
- 単一責任だと変更時に他に影響を与えづらくなる
まとめ
Java の仕様から、データベース設計、組織の話など、幅広いトピックが扱われており、非常に有意義な時間でした。
参加した後すぐに業務に活かせる内容も多く、特にテストやデータモデルの設計については、すぐに実践できると感じました。
また、自分も知見を深めて登壇する側になりたいと強く思いました。

ryounasso