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
メソッドのジェネリクスでGoの夢は広がるか? / Kyoto.go #65
utgwkk
3
880
Claspは野良GASの夢をみるか
takter00
0
200
キャリア迷子上等 ─ "ない道"は自分で作ればいい
16bitidol
3
2.2k
AI 輔助遺留系統現代化的經驗分享
jame2408
1
930
AI時代のUIはどこへ行く?その2!
yusukebe
22
7.4k
PHPで使える日時の表現と、その知り方 #frontend_phpcon_do
o0h
PRO
0
260
JJUG CCC 2026 Spring: JSpecify で実現する Kotlin フレンドリーな Java API 設計
ternbusty
1
180
Even G2とAWSで推しのエージェントを召喚しよう!
har1101
1
120
ECSアプリログをFireLensでコスト削減しようとしたけど諦めた話 in Fargate×Node.js
akihisaikeda
2
4.2k
そのテスト、説明できますか?~LWテスト戦略FW~のご紹介
nakahara
0
160
Spec Driven Development | AI Summit Lisbon
danielsogl
PRO
0
200
「なぜそう決めたのか」を残し続ける仕組み ― Notion AI カスタムエージェント × Slack連携による設計判断の自動記録 - NIKKEI Tech Talk #47
niftycorp
PRO
0
220
Featured
See All Featured
Rails Girls Zürich Keynote
gr2m
96
14k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.5k
Product Roadmaps are Hard
iamctodd
PRO
55
12k
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
310
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
62
44k
The Cost Of JavaScript in 2023
addyosmani
55
10k
[SF Ruby Conf 2025] Rails X
palkan
2
1.1k
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.5k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
260
The Limits of Empathy - UXLibs8
cassininazir
1
370
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.4k
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 •
可読性の向上 • メンテナンス性の向上 • 再利⽤性の向上 • テストやバグ修正の効率化 コンポーネント化はメリットいっぱい