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
イージーからシンプルへ 〜プロダクトの成長に合わせたアーキテクチャの変更〜
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
ham
February 22, 2023
Technology
5k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
イージーからシンプルへ 〜プロダクトの成長に合わせたアーキテクチャの変更〜
ham
February 22, 2023
More Decks by ham
See All by ham
その投資は、資本になっていますか?AI時代の開発投資を、ROIだけで判断しない「開発資本」という考え方
ham0215
0
110
プロダクト開発から業務改善コンサルまで。事業全体へ「染み出す」ことで広がるエンジニアの可能性
ham0215
0
230
AI時代に「チーム開発」を見直す ~個人アサインへのシフトと、AI駆動開発の実践例~
ham0215
0
69
機能開発を止めないために!運用と開発のバランスを可視化するために使っている指標をご紹介
ham0215
0
68
未来のAI駆動開発をイメージしながらAI開発基盤を整備する
ham0215
1
220
AIと過ごす1日〜全業務フローにAIを組み込む実践ガイド〜
ham0215
0
160
生成AIによる生産性向上〜テック企業やファインディの活用事例〜
ham0215
1
160
生成AI導入の効果を最大化する データ活用戦略
ham0215
0
670
データ駆動経営の道しるべ:プロダクト開発指標の戦略的活用法
ham0215
2
570
Other Decks in Technology
See All in Technology
Lambda MicroVMsは常駐サーバーの代わりに なるか? Kiro Crew を動かして検証してみた / Kiro Crew on Lambda MicroVMs
k_adachi_01
2
340
カンファレンスに参加した後の浮遊感とセルフケア
pauli
0
270
AIに書かせて、プラットフォームで縛る ― EKSプラットフォームで実践した責任境界と権限設計
elmodev09
1
1.1k
可視化から始めたAI駆動開発_ochi_ver1.01 / AI-Driven Development Starting with Visualization_ver1.01
yayoi_dd
0
110
いちAWSエンジニアのAI活用を振り返る #devio2026 / devio osaka 2026 kawahara
masahirokawahara
1
290
【ゲームメーカーズスクランブル2026】『Shadowverse: Worlds Beyond』UIとアニメーションで実現する最高のユーザー体験を叶えるプロトタイピング
cygames
PRO
1
710
VS Code × GitHub Copilot での Fabric 開発
ryomaru0825
1
210
営業オントロジーの作り方と、エージェントからの辿り方 ── ナレッジワークの現場から
kworkdev
PRO
1
220
【データ横丁主催】AI Agentがコンテキストを使って仕事をした後、何が残るのか― 組織の経験を次の判断に引き継ぐ「Agent Memory」
shisyu_gaku
2
300
Apache Iceberg が拓く AI 時代のオープンレイクハウス
tomtanaka
0
200
TiDBファミリーにDWHが新登場!! TiDB最新情報 / TiDB update 202609
yoshiakiyamasaki
0
180
AI Native Platform Engineering 〜PlatformとAgileで“作る速さ”を“価値”へ〜
uya116
0
570
Featured
See All Featured
Rebuilding a faster, lazier Slack
samanthasiow
85
9.7k
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
390
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.9k
Why Our Code Smells
bkeepers
PRO
340
58k
HDC tutorial
michielstock
2
930
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.6k
Paper Plane (Part 1)
katiecoart
PRO
2
11k
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
68
58k
Designing for Performance
lara
611
70k
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
520
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
VelocityConf: Rendering Performance Case Studies
addyosmani
331
25k
Transcript
イージーからシンプルへ 〜プロダクトの成長に合わせたアーキテクチャの変更〜 SaaSにおけるフロントエンドの技術戦略 | SaaS.tech #6 2023/02/22 ham
自己紹介 【略歴】 新卒でSIerとして就職 その後、Web系企業やスタートアップを経てファインディに参画 ファインディではFindy Team+のフロント&バックエンド開発を担当 React+Rails+GraphQL+AWSを使って開発しています 浜田 直人 (ham)
ファインディ株式会社 @hamchance0215
Findy Team+とは? https://findy-team.io GitHubやGitLab、Jiraなどエ ンジニア向けツールを解析す ることで、エンジニアリング組 織の生産性を可視化する サービスです。
プロダクトの歴史 2021/10 正式にローンチ 2022/10 Team+へ進化 生産性の可視化・向上に加え、エンジニ ア組織の「開発者体験」「改善文化」「採 用」を一貫してサポート 2020年 α版リリース
プロダクトの歴史 2021/10 正式にローンチ 2022/10 Team+へ進化 生産性の可視化・向上に加え、エンジニ ア組織の「開発者体験」「改善文化」「採 用」を一貫してサポート 2020年 α版リリース
プロダクトの成長と共にエンジニアが増加 チーム開発の効率を上げるためアーキテクチャを変更中
ローンチ当時の状況 2021/10 正式にローンチ • 不足している機能を新規開発し、顧客 価値を高めることに注力 ◦ 少人数でガンガン新規開発!
ローンチ当時の状況 2021/10 正式にローンチ • 不足している機能を新規開発し、顧客 価値を高めることに注力 ◦ 少人数でガンガン新規開発! • 簡単に使えることを重視
イージーなアーキテクチャ
現在の状況 2022/10 Team+へ進化 生産性の可視化・向上に加え、エンジニ ア組織の「開発者体験」「改善文化」「採 用」を一貫してサポート • 新規開発に加えて、既存機能をブラッ シュアップ ◦
既存機能を触る機会が増える • エンジニア増加。効率よくチーム開発 できることが重要 ◦ コードリーディングしやすく、誰で も触れるコードが良い
現在の状況 2022/10 Team+へ進化 生産性の可視化・向上に加え、エンジニ ア組織の「開発者体験」「改善文化」「採 用」を一貫してサポート • 新規開発に加えて、既存機能をブラッ シュアップ ◦
既存機能を触る機会が増える • エンジニア増加。効率よくチーム開発 できることが重要 ◦ コードリーディングしやすく、誰で も触れるコードが良い 簡単に理解できることを重視 シンプルなアーキテクチャ
イージーからシンプルへ
イージーからシンプルへ
イージーなアーキテクチャ ・Filterに指定した条件のデータを表示す る画面 ・画面ごとにFilterの種類や数、表示する データが違う
イージーなアーキテクチャ const [filters, setFilters] = useState(); return ( <Layout> <h1>Hoge画面</h1>
<Filters setFilters={setFilters} /> <div> Hogeなデータが表示されます </div> <DataTable type={hoge} filters={filters} /> </Layout> ); 各画面にFilterがあるのでまとめて <Filters />を作ろう
イージーなアーキテクチャ const [filters, setFilters] = useState(); return ( <Layout> <h1>Hoge画面</h1>
<Filters setFilters={setFilters} /> <div> Hogeなデータが表示されます </div> <DataTable type={hoge} filters={filters} /> </Layout> ); データ表示は<DataTable />を作ろう データ取得処理も内部に隠蔽すれば楽だな
イージーなアーキテクチャ const [filters, setFilters] = useState(); return ( <Layout> <h1>Fuge画面</h1>
<Filters setFilters={setFilters} disabledFilter3={true} /> <div> Fugeなデータが表示されます </div> <DataTable type={fuga} filters={filters} /> </Layout> );
イージーなアーキテクチャ const [filters, setFilters] = useState(); return ( <Layout> <h1>Fuge画面</h1>
<Filters setFilters={setFilters} disabledFilter3={true} /> <div> Fugeなデータが表示されます </div> <DataTable type={fuga} filters={filters} /> </Layout> ); 簡単に使えることを重視 共通コンポーネントをぽんぽん置いていく だけで類似画面が量産できる!
イージーなアーキテクチャ const Filters = ({ setFilters, disableFilter1, disableFilter2, disableFilter3, …
}) => { // いろいろなしょり … }); [props] 利用元の仕様を吸収する ため増加していく [処理] データ取得やレイアウトなど様々な責務を持ってい たり、利用元の様々なパターンに対応するため処理 が複雑に 一方、共通コンポーネント内は肥大化&複雑化していく... [テスト] コンポーネント内に外部 APIやGlobal Store への接続が混在しているため、テストが大変 大量のMockが必要となる
• 簡単に使えることを重視 ◦ 共通コンポーネントをぽんぽん置いていくだけで類似 画面が量産できる! ◦ 共通コンポーネント内が複雑になり、一定水準を超え ると簡単に使うことも難しくなる • 責務が複数あり、処理が複雑になりやすい
◦ キャッチアップが難しく、属人化が進む ◦ テストが書きづらい イージーなアーキテクチャ
イージーからシンプルへ
シンプルなアーキテクチャ // 外部APIやGlobal Stateへの接続を集約 const {data, options1, …, } =
useFacade(); return ( <Layout> <h1>Hoge画面</h1> // Filterは1つずつ配置 // 内部でデータ取得などはせずoptionsやeventは外から渡す <Filter options={options1} onChange={onChange1}/> <Filter options={options2} onChange={onChange2}/> <Filter options={options3} onChange={onChange3}/> <div> Hogeなデータが表示されます </div> // 取得したデータを渡し、DataTableは表示に専念 <DataTable data={data} /> </Layout> );
シンプルなアーキテクチャ // 外部APIやGlobal Stateへの接続を集約 const {data, options1, …, } =
useFacade(); return ( <Layout> <h1>Hoge画面</h1> // Filterは1つずつ配置 // 内部でデータ取得はせずoptionsやeventはpropsで渡す <Filter options={options1} onChange={onChange1}/> <Filter options={options2} onChange={onChange2}/> <Filter options={options3} onChange={onChange3}/> <div> Hogeなデータが表示されます </div> // 取得したデータを渡し、DataTableは表示に専念 <DataTable data={data} /> </Layout> ); 関数の責務を明確にする 名前を見るだけでやっていることが想像できる のでコードリーディングが簡単 新しいメンバーがキャッチアップしやすい データ取得などを呼び出し元で行うため、イー ジーと比べて一手間必要になる (やることは明確)
シンプルなアーキテクチャ // 外部APIやGlobal Stateへの接続を集約 const {data, options1, …, } =
useFacade(); return ( <Layout> <h1>Hoge画面</h1> // Filterは1つずつ配置 // 内部でデータ取得はせずoptionsやeventは外から渡す <Filter options={options1} onChange={onChange1}/> <Filter options={options2} onChange={onChange2}/> <Filter options={options3} onChange={onChange3}/> <div> Hogeなデータが表示されます </div> // 取得したデータを渡し、DataTableは表示に専念 <DataTable data={data} /> </Layout> ); 過度な共通化は行わない イージーよりコード量が増えるが、コン ポーネントが疎結合になり影響範囲が局 所化できて変更に強い
シンプルなアーキテクチャ const Filter = ({ selectedValue, options, onChange }) =>
{ const {state, handleHoge} = useFilter(); return ( <Select options={options} value={selectedValue} onChange={onChange} onHoge={handleHoge} /> ); }); [props] 表示に必要なデータは内部で取得せ ず、propsで受け取る componentは表示に専念 component内部でstateや callbackなどが必要な場合、専 用の関数で管理 共通コンポーネント内も責務を分離してシンプルに! [テスト] componentは外部接続などを行わないた め、テストやStrorybookが実装しやすい モック地獄からの解放
• 簡単に使えることより、簡単に理解できる(=シンプルな 実装)ことを重視 • 責務を明確にすることで可読性UP ◦ テストが書きやすい • 過度な共通化をしない ◦
コード量は増えるが変更に強い • キャッチアップしやすく、新しいメンバーに優しい ◦ チーム開発に向いている シンプルなアーキテクチャ
途中経過
アーキテクチャ変更の途中経過 12月から開始して現時点で半分ほど完了 一人当たりのプルリク作成数が増加中!! 一人当たりの プルリク作成数 約1.5倍に!! ※Findyではプルリク作成数 を開発生産性の1つの指標と して見ることが多い
イージーからシンプルへ 〜プロダクトの成長に合わせたアーキテクチャの変更〜 ご清聴ありがとうございました