Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
JavaDo勉強会での学び実践
Search
sai-lens
October 24, 2025
Technology
110
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
JavaDo勉強会での学び実践
sai-lens
October 24, 2025
More Decks by sai-lens
See All by sai-lens
非エンジニアが院内での業務のために個人開発をした(続編)
sailen2
0
30
非エンジニアが院内での業務のために個人開発をした
sailen2
1
58
論文検索を日本語でできるアプリを作ってみた
sailen2
0
450
Ruby の統計ツールと Ruby on Rails で分析をしてみた
sailen2
3
130
React Tokyoのハンズオンに飛び込んでみた話
sailen2
0
87
Other Decks in Technology
See All in Technology
研究開発部の紹介 / Sansan R&D Profile
sansan33
PRO
4
25k
Oracle Cloud Infrastructure IaaS 新機能アップデート 2026/6 - 2026/8
oracle4engineer
PRO
0
140
AIで仕事のやり方を変える
matsu7874
3
1k
【視聴者参加型!】AWSセキュリティアンチパターンクイズ
syoshie
1
490
Podは生きているのにGoだけが落ちる:GOGCとGOMEMLIMITで追うInvisible OOM Killの謎
tkc66buzz
1
500
Code4Lib JAPANカンファレンス2026 開会挨拶 / Code4Lib JAPAN Conference 2026: Opening Remarks
ykiyota
0
330
Claude Code本って、 読む必要あるの?
oikon48
2
380
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
3
450
AIに丸投げしないトイル削減 / Eliminating Toil Without Leaving It All to AI
kohbis
4
1.1k
2026/09/10 Spring Bootから Jakarta EE/MicroProfileへの移行
megascus
0
300
なぜSRE・セキュリティは評価されないのか?守りの組織を事業成長エンジンに変えた実践
cscengineer
PRO
3
2.4k
Amazon Quick on DesktopがIAM Identity Centerで動かない理由
yukiogawa
0
150
Featured
See All Featured
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
490
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
How to Think Like a Performance Engineer
csswizardry
28
2.8k
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Code Review Best Practice
trishagee
74
20k
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
2
420
The Pragmatic Product Professional
lauravandoore
37
7.4k
Documentation Writing (for coders)
carmenintech
77
5.5k
Designing for humans not robots
tammielis
254
26k
HDC tutorial
michielstock
2
860
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
370
Faster Mobile Websites
deanohume
310
32k
Transcript
JavaDo勉強会での学びの実践 2025.10.23/はじめてのIT勉強会 in 札幌(2025) さい/sai-lens
⾃⼰紹介 • さい/sai-lens • 現在は病院で臨床検査技師として勤務 • プログラミング学習3ヶ⽉⽬ • 現在学習中の技術 ◦
フロントエンド:JavaScript, React ◦ バックエンド:Ruby, Ruby on Rails 1 @GTposiwill @sye-lens
本⽇のLTのきっかけ • 勉強会に参加 ◦ JavaDo「増田 亨さんと設計の実践的な考え方 を学ぼう!」 ◦ ⽇時:10/4(⼟) ◦
場所:クオリサイトテクノロジーズ株式会社 (⽇本⽣命ビル) • 勉強会での学びをアウトプットして⾝につけたい 2
ソフトウェアを取り巻く「現実」 なぜソフトウェア設計が難しいのか? ソフトウェアはそもそも複雑 ソフトウェアの利⽤環境、技術も、ビジネス要求も変化し、変わり続ける 未知の課題に、不確実な状況で取り組まなければならない 設計に使える時間は限られている @さい/sai-lens 3
では「良い設計」とは? 勉強会で学んだ、設計の本質 良い設計は悪い設計よりも変更しやすい — 『達⼈プログラマー』より 4
どう実現するか? → 「関⼼の分離」 モデル駆動設計(MDD)の考え⽅:役割ごとにコードを分ける UI (表⽰‧操作) ユーザーが⾒る画⾯や、 操作を受け付ける部分 インフラ (DBなど)
データを保存したり、 外部と通信したりする部分 Domain (ロジック) 「アプリの核となるルール」 を決め、考える部分 5
学びの実践(モデル駆動設計) JavaDoのワークショップで 「⽇程調整アプリ」の設計に挑戦 お題: ⽇程調整アプリ (「調整さん」のイメージ) ⼿法: モデル駆動設計(MDD) 焦点: 「最適⽇を決定するルール」
(=ドメイン)に焦点を当てる 6 sye-lens/nitteichousei
最適⽇を決定するルール • 参加者と必須参加者がいる。 • 全員の回答をもとに候補⽇を評価する。 • もし「必須参加者が全員◯」かつ「他の参加者も全員◯」の候補⽇があれ ば、⽇程をその⽇に確定する。それ以外は再調整。 • 「すべての参加者が◯」の候補⽇が複数ある場合は、もっとも早い⽇付を
選んで確定する。 7
ディレクトリ構成 domains/attendance_decision.rb はcontrollers, models, viewから独⽴ / ├─ app │ └─
assets │ ├─ controllers │ ├─ domains │ │ └─ attendance_decision.rb │ ├─ models │ └─ views ├─ db 8
domains/attendance_decision.rb class AttendanceDecision AttendanceDecisionResult = Struct.new(:decision_status, :most_suitable_date, keyword_init: true) def
initialize(members:, required_members:, proposed_dates:, responses:) @members = members @required_members = required_members @proposed_dates = proposed_dates @responses = responses end def decide if (d = decided_date) return AttendanceDecisionResult.new(decision_status: :decided,most_suitable_date: d) end AttendanceDecisionResult.new(decision_status: :reschedule_required, most_suitable_date: best_date) end private def decided_date @proposed_dates.find { |d| all_yes?(d) && required_all_yes?(d) } end . 9
「分離」がもたらす変化 ロジック(ドメイン)を分離すると、コード構造はどう変わるか 従来(混在したコード) 画⾯処理、DB操作、⽇程決定ロジックが すべて⼀箇所に固まっている ルールの変更が画⾯やDBの修正に影響し そうで怖い MDD(分離したコード) 「⽇程決定ロジック」だけが独⽴した 「ドメイン」として存在
UIやDBとは疎結合(お互い依存しな い) 10
メリット①:機能拡張が「楽」 もし「新しい⽇程決定ルール」を追加したくなったら? 例:最適⽇を選ぶとき、必須は全員◯の候補の中で、同点トップが複数なら最早⽇で確定 (多数決で決定) 変更するのは「ドメイン(ロジック)」の部分だけ。 UIやDBのコードを触る必要がないため、変更が楽 11
メリット②:UIなどのI/O周りの変更が「安全」 もし「画⾯デザインを刷新」したくなったら? 例:画⾯のデザインやスタイルを⼤幅に変更 変更するのは「UI」の部分だけ。 「ドメイン(ロジック)」は分離されているため、⽇程決定ルールを壊す⼼配 がない(安全) 12
メリット③:コードが「わかりやすい」 どこに、なにが書いてあるのかをわかりやすく書くことができる I/Oと独⽴していることで、メインロジックが理解しやすくなる 加えて、ロジック部分を「ビジネスの⾔葉」で記述する 例: `decided` (確定), `most_suitable_date` (最適⽇) エンジニアも⾮エンジニアも、ロジックの意図が理解しやすくなる
13
良い設計:attendance_decision.rbを修正するだけ class AttendanceDecision AttendanceDecisionResult = Struct.new(:decision_status,:most_suitable_date) . . def decide
if (d = decided_date) return AttendanceDecisionResult.new( decision_status: :decided, most_suitable_date: d, . end private def decided_date @proposed_dates.find { |d| all_yes?(d) && required_all_yes?(d) } end . . 14 if (d = decided_by_required_all_yes_tiebreak) return AttendanceDecisionResult.new( decision_status: :decided, most_suitable_date: d, ) end # 必須参加者が全員◯の候補のみを対象に、 # 「total_yes」が最大のスコアで同点の候補が複 数ある場合は最も早い日を返す # そうでなければ nil def decided_by_required_all_yes_tiebreak candidates = @proposed_dates.select { |d| required_all_yes?(d) } return nil if candidates.empty?
悪い設計:controllersでI/Oとロジックが混在 15 class AttendancesController < ApplicationController def update attendance =
Attendance.find(params[:id]) meeting = attendance.participant.meeting if attendance.update(attendance_params) decision, scores = meeting.decide_and_score respond_to do |format| format.turbo_stream do render turbo_stream: [ ] end else . . end private def attendance_params params.require(:attendance).permit(:status) end end # ①「全員◯ & 必須◯」なら即 decided decided_pd = date_rows.find do |pd_id, _d| all_yes_for.call(pd_id) && required_all_yes_for.call(pd_id) end if decided_pd decided_date = decided_pd[1] decision = OpenStruct.new(decision_status: :decided, most_suitable_date: decided_date) else # ② 機能拡張:必須は全員◯の候補のみ抽出 required_yes_candidates = date_rows.select { |pd_id, _d| required_all_yes_for.call(pd_id) } if required_yes_candidates.any? # total_yes の最大値を算出 with_total = required_yes_candidates.map { |pd_id, d| [pd_id, d, total_yes_count_for.call(pd_id)] } max_total = with_total.map { |(_id, _d, tot)| tot }.max . . viewへの出力 DBから入力データを取得
まとめ - 「良い設計」は「悪い設計」よりも変更しやすい - 「変更に強い設計」を実践、メインロジックをその他のI/Oから分離した - その結果 - メインロジックの機能拡張、変更が「楽」 -
メインロジックに⼲渉しないのでその他の変更が「安全」 - どこに何が書いてあるのかが理解しやすく、誰にでも意図が伝わる コードになる 16