Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
レガシープロダクトの画面部品をUIコンポーネント化 〜駆逐してやる!!このプロダクトから.....
Search
Kohei Y
March 21, 2025
Programming
60
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
レガシープロダクトの画面部品をUIコンポーネント化 〜駆逐してやる!!このプロダクトから... 一匹残らず!!〜
Kohei Y
March 21, 2025
More Decks by Kohei Y
See All by Kohei Y
レガシーコードに潜む奇妙なコメント 〜信じるか信じないかはあなた次第〜
yamamuuu
0
2.1k
不幸を呼び寄せる命名の数々 ~君はそもそも何をされてる方なの?~
yamamuuu
0
1.9k
Other Decks in Programming
See All in Programming
AI時代の仕事技芸論〜ソフトウェア開発で「遊ぶように働く」職人的熟達のすすめ(スクフェス仙台 2026バージョン)
kuranuki
0
630
Developing with AI Agents — Codex, Claude Code & Cowork Practical Guide
x5gtrn
PRO
0
1.4k
【やさしく解説 設計編 #1】「ドメイン駆動」と「実装駆動」ってなに? 〜設計の考え方を、たとえ話で学ぼう〜
panda728
PRO
1
120
Even G2とAWSで推しのエージェントを召喚しよう!
har1101
1
170
ビデオ通話が繋がる0.2秒で何が起きているのか
supurazako
2
150
1B+ /day規模のログを管理する技術
broadleaf
0
140
PHP Application における Kubernetes 内 gRPC 通信
ganchiku
0
410
任せる範囲はこう広がった / How the Scope of AI Delegation Has Expanded
nrslib
1
250
Honoでのサプライチェーン侵害対策 〜 3つのライブラリに学ぶ
yusukebe
7
1.9k
えっ!!コードを読まずに開発を!?
hananouchi
0
200
才能?センス?知らん、 続けたもん勝ちだ。-- 結婚・出産・癌を越えてなお、私がプロダクトを創り続ける理由
16bitidol
2
850
SREの積み重ねがAI駆動開発のガードレールになった ― 7つの実践/SRE Guardrails The 7
tomoyakitaura
8
4.2k
Featured
See All Featured
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
330
The Curious Case for Waylosing
cassininazir
1
430
The Cult of Friendly URLs
andyhume
79
6.9k
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
190
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
55k
From π to Pie charts
rasagy
0
230
Odyssey Design
rkendrick25
PRO
2
730
Navigating Weather and Climate Data
rabernat
0
350
WENDY [Excerpt]
tessaabrams
11
38k
The Cost Of JavaScript in 2023
addyosmani
55
10k
Scaling GitHub
holman
464
140k
Transcript
© RAKUS Co., Ltd. レガシープロダクトの画⾯部品をUIコンポーネント化 〜駆逐してやる!!このプロダクトから... ⼀匹残らず!!〜 PHPerKaigi 2025 株式会社ラクス
⼭村 光平 2025/03/28 1
⾃⼰紹介 2 • ⼭村光平 • ラクスの新卒3年⽬ • 2024年4⽉にメールディーラーから 楽楽販売へ担当プロダクトが変更 •
業務は実装とかテストとか • 趣味は旅⾏‧テニス‧映画鑑賞
© RAKUS Co., Ltd. 3 技術的負債を返してますか? #PHPerKaigi 2025
© RAKUS Co., Ltd. 4 真摯に向き合ってますか? #PHPerKaigi 2025
© RAKUS Co., Ltd. 5 ちゃんと理解してますか? #PHPerKaigi 2025
© RAKUS Co., Ltd. 6 技術的負債とは #PHPerKaigi 2025
技術的負債 • 将来的な⼿直しにかかる暗黙のコスト • ⾦銭的負債と同様に、返済されなければ「利⼦」が蓄積され 変更の実施が困難になる • プロジェクトを前進させるために必要な場合もある 7 Wikipediaより
Wikipediaより引用:https://ja.wikipedia.org/wiki/%E6%8A%80%E8%A1%93%E7%9A%84%E8%B2%A0%E5%82%B5
技術的負債 • 最初のコードを出荷することは、借⾦をするようなもの • 負債が返済されない場合、コードのために費やされた1分1秒が、 その負債の利息としてカウントされる • 実装の負債の負荷によって、エンジニアリング組織全体が停⽌してしまう 可能性がある -
ウォード・カニンガム、1992年 8 Wikipediaより Wikipediaより引用:https://ja.wikipedia.org/wiki/%E6%8A%80%E8%A1%93%E7%9A%84%E8%B2%A0%E5%82%B5
© RAKUS Co., Ltd. 9 負債である以上返済しなくてはならない #PHPerKaigi 2025
© RAKUS Co., Ltd. 10 バックエンドのロジックだけでなく フロントエンドも例外ではない! #PHPerKaigi 2025
© RAKUS Co., Ltd. 11 PHPで画⾯部品の UIコンポーネント化 #PHPerKaigi 2025
© RAKUS Co., Ltd. 12 なぜUIコンポーネント化? #PHPerKaigi 2025
プロダクトがレガシー 13 • 誕⽣から15年以上経つプロダクト • クラウド型の販売管理システム ◦ 複雑な⾦額計算や請求‧売上計上を⾃動化 楽楽販売について
プロダクトがレガシー 14 • ⾔語:もちろんPHP • フレームワーク:Zend Framework • フロントエンド:ネイティブのJavaScriptとjQuery、フレームワークなし 技術スタック
• 誕⽣から15年以上経つプロダクト • クラウド型の販売管理システム ◦ 複雑な⾦額計算や請求‧売上計上を⾃動化 楽楽販売について
コピペの蔓延、再利⽤性が低い • 15年以上に渡り、静的HTMLの画⾯部品コードがコピペされ続けている • ⾔わずもがな共通化は⾏われていない • 結果として、1画⾯あたりのコード量が巨⼤ • 新画⾯を作成するたび、PhpStormが親の仇の如く「Duplicated Code」を指摘
してくる 15 背景 • コードの可読性を改善し、容易にメンテナンス可能なコード構造を実現する 課題
© RAKUS Co., Ltd. 16 PHPで画⾯部品の UIコンポーネント化 #PHPerKaigi 2025
本セッションについて • UIコンポーネント化のメリット • PHPでコンポーネント化をどのように実装したか • コンポーネントを活⽤してもらうための施策 17 話すこと
本セッションについて • UIコンポーネント化のメリット • PHPでコンポーネント化をどのように実装したか • コンポーネントを活⽤してもらうための施策 18 話すこと •
技術的負債を解消したい⼈(多分全PHPer) • レガシープロダクトから脱却したい⼈(多分ほぼ全PHPer) • フロントエンドのフレームワークを利⽤していない⼈ • 画⾯部品のUIコンポーネント化に興味がある⼈ 対象者
© RAKUS Co., Ltd. 19 UIコンポーネント化とは? #PHPerKaigi 2025
UIコンポーネント化とは • 画⾯部品を独⽴したモジュールとして切り出す • 各部品の機能やスタイルをひとまとめにして共通化 • 他の画⾯でも簡単に利⽤できるように設計 20 ※画⾯部品:画⾯上に配置される具体的な要素(ボタン、ヘッダー、フッターなど)
• 可読性の向上 • メンテナンス性の向上 • 再利⽤性の向上 • テストやバグ修正の効率化 UIコンポーネント化のメリット 21
© RAKUS Co., Ltd. 22 ゴール #PHPerKaigi 2025
ゴール 23 • コピペ⽂化の脱却 ◦ 今後コピペによるコードを駆逐すること • 共通UIコンポーネントの整備 ◦ シンプルな記述で画⾯部品を表⽰でき、複数画⾯で再利⽤可能な
共通コンポーネントを作成する • UIコンポーネントの活⽤推進 ◦ コードの再利⽤を促進する施策を実施し、活⽤を定着させる
© RAKUS Co., Ltd. 24 前提 #PHPerKaigi 2025
前提 25 • フレームワークは使わない
前提 26 • フレームワークは使わない ◦ フレームワークは⽢え
前提 27 • フレームワークは使わない使えない ◦ フレームワークは⽢え
前提 28 • フレームワークは使わない使えない ◦ フレームワークは⽢え ▪ ReactとかVueはUIに変更を加える案件が控えているため無理......
前提 29 • フレームワークは使わない使えない ◦ フレームワークは⽢え ▪ ReactとかVueはUIに変更を加える案件が控えているため無理...... ▪ Laravelとかも検討してるけどすぐには無理......
前提 30 • フレームワークは使わない使えない ◦ フレームワークは⽢え ▪ ReactとかVueはUIに変更を加える案件が控えているため無理...... ▪ Laravelとかも検討してるけどすぐには無理......
• PHPで画⾯部品をコンポーネント化
© RAKUS Co., Ltd. 31 ⽅針 #PHPerKaigi 2025
⽅針 32 1. 画⾯を部品ごとに分解し、各部品のクラスを作成 2. 各画⾯のパーツをファイルに切り出してテンプレート化 3. JavaScriptの利⽤がある場合は汎⽤化して、個別ファイルに切り離す
© RAKUS Co., Ltd. 33 結果 #PHPerKaigi 2025
管理者設定画⾯のタブメニューをコンポーネント化 34 これ →
35 Before(735⾏) タブメニューを表⽰するためのコード
36 TabPanel::show(new Tabs($tabs), $tabMenuList, $this->form?->getTabCategory()); After(1⾏) 表⽰コードはたったの1⾏に!! 管理者設定画⾯のhtml全体の⾏数は805⾏ → 496⾏に削減!
タブメニューを表⽰するためのコード
© RAKUS Co., Ltd. 37 実装の詳細 #PHPerKaigi 2025
画⾯部品を分解し、各部品のクラスを作成 38
画⾯部品を分解し、各部品のクラスを作成 39 Tabsクラス
画⾯部品を分解し、各部品のクラスを作成 40 Tabsクラス Tabクラス
画⾯部品を分解し、各部品のクラスを作成 41 ListGroup クラス
画⾯部品を分解し、各部品のクラスを作成 42 ListGroup クラス LinkListItemクラス
画⾯部品を分解し、各部品のクラスを作成 43 TabPanel クラス
44 クラス設計 TabPanelオブジェクトにTabsとTabMenuList をプロパティで持たせる ※TabMenuListにしているのはListGroup以外 も注⼊されることもあるため TabPanelクラス /** * @param
Tabs $tabs * @param array<string, Component> $tabMenuList * @param string|null $defaultActiveId */ public function __construct( public Tabs $tabs, public array $tabMenuList, public ?string $defaultActiveId = null, ) { parent::__construct(); } TabPanelクラスのコンストラクタ Tabsクラス ListGroupクラス
45 クラス設計 表⽰するメソッド Tabsクラス /** * タブパネルを表示する * * @param
Tabs $tabs * @param array<string, Component> $tabMenuList * @param string|null $defaultActiveId */ public static function show( Tabs $tabs, array $tabMenuList, ?string $defaultActiveId = null ): void { echo ( new self($tabs, $tabMenuList, $defaultActiveId) )->render(); } TabPanelオブジェクトにTabsとTabMenuList をプロパティで持たせる ※TabMenuListにしているのはListGroup以外 も注⼊されることもあるため TabPanelクラス
クラス構成イメージ Tabs Tab Tab Tab Tab
クラス構成イメージ 47 ListGroup LinkListItem LinkListItem LinkListItem
クラス構成イメージ 48 Tabs Tab ListGroup LinkListItem Tab Tab Tab LinkListItem
LinkListItem TabPanel
各パーツをファイルに切り出して、テンプレート化 49 <section> <?php // タブを表示 ?> <?php echo $this->tabs->render()
?> <div> <div> <div> <?php foreach ($this->tabs->tabList as $tab) : ?> <div id="<?php $this->write($tab->id); ?>"> <?php // タブメニューを表示 ?> <?php echo $this->tabMenuList[$tab->id]->render(); ?> </div> <?php endforeach; ?> </div> </div> </div> </section> TabPanel.inc • HTMLをファイルに切り出し
各パーツをファイルに切り出して、テンプレート化 50 <section> <?php // タブを表示 ?> <?php echo $this->tabs->render()
?> <div> <div> <div> <?php foreach ($this->tabs->tabList as $tab) : ?> <div id="<?php $this->write($tab->id); ?>"> <?php // タブメニューを表示 ?> <?php echo $this->tabMenuList[$tab->id]->render(); ?> </div> <?php endforeach; ?> </div> </div> </div> </section> TabPanel.inc • HTMLをincファイルに切り出し • ⼦コンポーネントを利⽤できる 箇所は適宜置き換え Tabsクラス ListGroupクラス
JavaScriptを汎⽤化してファイルに切り出し 51 function tab_action(activeTabId) { $target = $("#" + activeTabId);
$targetTab = $("#t_" + activeTabId); $target.parent().children().hide(); $target.css('display','').show(); $targetTab.parent().children().not(this).removeCl ass('current'); $targetTab.addClass('current'); } tab-panel.js • TabPanelクラスで⽣成された タブパネルに適⽤される
© RAKUS Co., Ltd. 52 プロダクト全体ではどれぐらいの効果が期待できる? #PHPerKaigi 2025
© RAKUS Co., Ltd. 53 パンくずリストのコンポーネントで検証! #PHPerKaigi 2025
パンくずリストのコンポーネントで検証 • 楽楽販売で利⽤されているパンくずリスト数:351箇所 • 前提:表⽰されるパンくずリストは平均3とする • 元のパンくずリスト表⽰のためのコード⾏数:22⾏ • コンポーネント化したパンくずリストの表⽰のためのコード⾏数:わずか5⾏ 54
Breadcrumbs::show([ new Crumb(title: '管理者設定(サンプル) ', url: {url}), new Crumb(title: 'コンポーネント一覧の設定 ', url: {url}), new Crumb(title: 'コンポーネント一覧の設定の設定 '), ]);
結果 55 5967⾏の削減!! ※ 削減⾏数 * パンくずリスト数 htmlファイル全体の3%に相当
© RAKUS Co., Ltd. 56 あとは使うだけ #PHPerKaigi 2025
© RAKUS Co., Ltd. 57 そもそもなぜ⼈はコピペをしてしまうのか #PHPerKaigi 2025
• コンポーネントの存在を知らない なぜ⼈はコピペをしてしまうのか 58
• コンポーネントの存在を知らない • コンポーネントが探しにくい なぜ⼈はコピペをしてしまうのか 59
• コンポーネントの存在を知らない • コンポーネントが探しにくい • コンポーネントの使い⽅が分かりづらい なぜ⼈はコピペをしてしまうのか 60
• コンポーネントの存在を知らない • コンポーネントが探しにくい • コンポーネントの使い⽅が分かりづらい • ⽂化 なぜ⼈はコピペをしてしまうのか 61
• コンポーネントの存在を知らない • コンポーネントが探しにくい • コンポーネントの使い⽅が分かりづらい • ⽂化 なぜ⼈はコピペをしてしまうのか 62
© RAKUS Co., Ltd. 63 コンポーネントを⼀覧で確認できる画⾯を作ろう #PHPerKaigi 2025
コンポーネント⼀覧画⾯の設計 • コンポーネントに何があるか把握できる • イメージはBootstrap • サイドバーでより探しやすく 64 • 各コンポーネントのサンプルコード表⽰
使い⽅が分かりづらい 探しにくい Bootstrapより引用:https://getbootstrap.jp/docs/5.3/components/navs-tabs
完成した⼀覧画⾯ 65
完成した⼀覧画⾯ 66 いい感じ!!
• コンポーネントの存在を知らない ✅ コンポーネントが探しにくい ✅ コンポーネントの使い⽅が分かりづらい • ⽂化 なぜ⼈はコピペをしてしまうのか 67
• コンポーネントの存在を知らない ✅ コンポーネントが探しにくい ✅ コンポーネントの使い⽅が分かりづらい • ⽂化 なぜ⼈はコピペをしてしまうのか 68
⇒ ガイドラインに追加
✅ コンポーネントの存在を知らない ✅ コンポーネントが探しにくい ✅ コンポーネントの使い⽅が分かりづらい ✅ ⽂化 なぜ⼈はコピペをしてしまうのか 69
🎉
既存画⾯のHTMLを画⾯部品に置き換え 今後の展望 • 今後コピペコードが増えることはなくなる • 既存の画⾯は据え置きされている • 既存画⾯の画⾯部品をコンポーネント化 70 •
今回全ての画⾯部品をパーツ化できたわけではない • 随時コンポーネント化していく UIコンポーネントの拡充
PHPでもコンポーネントは作成できる まとめ • フレームワークはなくてもできる! • コードの削減、共通化が可能 • 親コンポーネントに⼦コンポーネントを⼊れ⼦構造で設計すると良き 71 •
可読性の向上 • メンテナンス性の向上 • 再利⽤性の向上 • テストやバグ修正の効率化 コンポーネント化はメリットいっぱい