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
120
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
40
非エンジニアが院内での業務のために個人開発をした
sailen2
1
79
論文検索を日本語でできるアプリを作ってみた
sailen2
0
480
Ruby の統計ツールと Ruby on Rails で分析をしてみた
sailen2
3
140
React Tokyoのハンズオンに飛び込んでみた話
sailen2
0
96
Other Decks in Technology
See All in Technology
お客様の「やりたい」の先を見通す合意形成プロセス ~裏にある課題と不安を解きほぐすコツ~
yukakoseki
0
110
複雑な業務システムを高速でつくるため、チーム全員をつくれる人へ
ayakurabuchi
0
140
Context Ontology Accelerator 入門 (業務データの意味を、AI エージェントに渡す)
inariku
PRO
3
510
基本から分かる!AWSセキュリティ運用の考え方と任せ方
cmusudakeisuke
1
450
AIがGISを代替する日:〜すべてをAIが創る時代に、私たちがFOSS4Gに関わる意味〜
lehupa
1
210
ゼロから作るWebアプリの新定番!?Amplify Gen 2 × AWS Blocksで実現する「開発速度とRDBの柔軟性のいいとこ取り」
amixedcolor
1
170
新卒エンジニア、 介護士になる
ryu1013
1
690
AWSを利用する上で知っておきたい名前解決の話 2026
nagisa53
5
3.2k
少ない人手 限られた予算 それでも守る 消せない・見つける・戻れる オールハザード型BCP on AWS / 20261107 Mitsutoshi Matsuo
shift_evolve
PRO
0
210
An Introduction to Context Ontology Accelerator (teaching AI agents what your data means)
inariku
PRO
1
110
生成AI時代のIAMのマニアックな話
takuros
6
2.7k
Lint の層を組み直した話
bengo4com
3
320
Featured
See All Featured
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
350
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
560
Into the Great Unknown - MozCon
thekraken
41
2.8k
[SF Ruby Conf 2025] Rails X
palkan
3
1.5k
Faster Mobile Websites
deanohume
310
32k
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
830
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
670
Fireside Chat
paigeccino
43
4.1k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.7k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.4k
WCS-LA-2024
lcolladotor
0
980
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