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.2k
不幸を呼び寄せる命名の数々 ~君はそもそも何をされてる方なの?~
yamamuuu
0
2k
Other Decks in Programming
See All in Programming
壊れたパーサから始める関数型設計と構成的なパーサ #fp_matsuri
raiga0310
2
450
AI時代のPHPer生存戦略 ~「言語、もうなんでもよくない?」に本気で向き合う~
vivion
0
240
霧の中の代数的エフェクト
funnyycat
1
480
仕様駆動開発の消費期限
watany
14
6.8k
全PRの83%がAIレビューだけでマージできるようになった開発組織はその後どうなったか
athug
1
1.5k
GDG Korea Android: 2026 I/O Extended ~ What's new in Android development tools
pluu
0
210
生成AIで帳票OCRが「簡単に」作れる時代になった?
kon_shou
0
580
torikago - Ruby::Boxで照らすモジュラモノリスの実行境界
se4weed
1
340
PHP に部分適用が来るぞ!……ところで何それ?おいしいの? #phpcon / phpcon-2026
shogogg
0
580
ソフトウェア設計に溶けるインフラ ― AWS CDK のインフラ認識論
konokenj
3
760
自動化したのに回らないテスト運用の壁ーAI時代の品質責任と生産性
mfunaki
0
130
源内ハンズオン概要編
hideg
0
120
Featured
See All Featured
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.6k
Accessibility Awareness
sabderemane
1
170
Done Done
chrislema
186
16k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.5k
Building AI with AI
inesmontani
PRO
1
1.1k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
300
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
380
The Cult of Friendly URLs
andyhume
79
7k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
63
45k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.7k
Side Projects
sachag
455
43k
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.5k
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 •
可読性の向上 • メンテナンス性の向上 • 再利⽤性の向上 • テストやバグ修正の効率化 コンポーネント化はメリットいっぱい