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
32
非エンジニアが院内での業務のために個人開発をした
sailen2
1
59
論文検索を日本語でできるアプリを作ってみた
sailen2
0
450
Ruby の統計ツールと Ruby on Rails で分析をしてみた
sailen2
3
130
React Tokyoのハンズオンに飛び込んでみた話
sailen2
0
89
Other Decks in Technology
See All in Technology
ソフトウェアDNAとクラウドエージェントのススメ
cloudace
0
120
30座EKS, 180次升級淬煉的EKS Upgrade Skill 的歷程
eric8230
0
200
SREへの勘違いに気づいた後の話
tomodakengo
0
110
AIに任せた品質は、誰が見立てるのか - AI時代のテストマネジメント
nakanao
3
2.5k
AIを活用するために決めた "やらないこと" - 価値に注目する / Not betting on AI
soudai
PRO
3
570
データ界隈LT祭 第1回LT登壇
taromatsui_cccmkhd
2
1.5k
Oracle Cloud Network Path Analyzerを試してみた/I Tried Out Oracle Cloud Network Path Analyzer
masakiokuda
1
110
Minecraft JavaのMODをSwiftで作る
1mash0
0
190
現場で役立つ技術負債の効果的な返済方法
masuda220
PRO
9
4.7k
今話題のAI「Jev」って何? 宇宙最速で学ぶ会
minorun365
PRO
30
17k
事業課題から技術的負債に向き合う
sansantech
PRO
2
2k
LLMに渡さなかった仕事
nanaism
0
1.2k
Featured
See All Featured
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
A Modern Web Designer's Workflow
chriscoyier
699
190k
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
2k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
How STYLIGHT went responsive
nonsquared
100
6.3k
[SF Ruby Conf 2025] Rails X
palkan
3
1.4k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
460
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
More Than Pixels: Becoming A User Experience Designer
marktimemedia
3
530
Making Projects Easy
brettharned
120
6.8k
Technical Leadership for Architectural Decision Making
baasie
3
570
Bootstrapping a Software Product
garrettdimon
PRO
306
120k
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