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
百科事典の責務分割 PIXIV SPRING BOOT CAMP 2022 技術基盤(Webフ...
Search
usuyuki
March 17, 2022
Technology
0
3.1k
百科事典の責務分割 PIXIV SPRING BOOT CAMP 2022 技術基盤(Webフレームワーク)
PIXIV SPRING BOOT CAMP 2022での技術基盤(Webフレームワーク)コースに参加しました。
この資料は8日間のインターンを終えて最終発表で用いた資料です!
※公開許可取得済
usuyuki
March 17, 2022
Tweet
Share
More Decks by usuyuki
See All by usuyuki
(予告版)令和でもブログを自宅サーバで @大吉祥寺.pm 2025 前夜祭
usuyuki
1
500
令和でもブログを自宅サーバで@大吉祥寺.pm 2025
usuyuki
1
1.5k
味噌汁作り あるいは仕事の学び
usuyuki
0
1.5k
毎年殺されるPHPとは何か
usuyuki
0
550
新卒1ヶ月半の邁進と変化
usuyuki
1
990
5分で理解するWebAssemblyのWebの外の話 PHPはマイコンの夢を見るか?
usuyuki
3
1.1k
Git -研究室ミーティング2023/12/1資料-
usuyuki
0
880
非公式内定者懇親会 LT たのしい企業理念クイズ!
usuyuki
0
1.1k
技育展2023 ブロック予選関東① かどで日記
usuyuki
0
990
Other Decks in Technology
See All in Technology
AWSで始める実践Dagster入門
kitagawaz
1
750
slog.Handlerのよくある実装ミス
sakiengineer
4
480
LLMを搭載したプロダクトの品質保証の模索と学び
qa
1
1.1k
下手な強制、ダメ!絶対! 「ガードレール」を「檻」にさせない"ガバナンス"の取り方とは?
tsukaman
2
460
測りにくい成果を測る — BtoB SaaSにおける効果検証への挑戦 / Shirokane Kougyou vol 20
sansan_randd
1
110
Django's GeneratedField by example - DjangoCon US 2025
pauloxnet
0
160
プラットフォーム転換期におけるGitHub Copilot活用〜Coding agentがそれを加速するか〜 / Leveraging GitHub Copilot During Platform Transition Periods
aeonpeople
1
240
TS-S205_昨年対比2倍以上の機能追加を実現するデータ基盤プロジェクトでのAI活用について
kaz3284
1
230
Rustから学ぶ 非同期処理の仕組み
skanehira
1
150
使いやすいプラットフォームの作り方 ー LINEヤフーのKubernetes基盤に学ぶ理論と実践
lycorptech_jp
PRO
1
170
いま注目のAIエージェントを作ってみよう
supermarimobros
0
370
要件定義・デザインフェーズでもAIを活用して、コミュニケーションの密度を高める
kazukihayase
0
120
Featured
See All Featured
Product Roadmaps are Hard
iamctodd
PRO
54
11k
The Cost Of JavaScript in 2023
addyosmani
53
8.9k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
9
820
Into the Great Unknown - MozCon
thekraken
40
2k
Practical Orchestrator
shlominoach
190
11k
Fireside Chat
paigeccino
39
3.6k
Typedesign – Prime Four
hannesfritz
42
2.8k
Code Review Best Practice
trishagee
71
19k
Side Projects
sachag
455
43k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
61k
[RailsConf 2023] Rails as a piece of cake
palkan
57
5.8k
Transcript
百科事典の責務分割 PIXIV SPRING BOOT CAMP 2022 技術基盤(Webフレームワーク) pixiv Inc. usuyuki
2022.3.17
2 自己紹介 • アイコンの背景色とpixivのカラーが似ている • 鳥取県米子市生、島根県浜田市育ち • コーヒーが好き • しぐれうい先生を推しています
(イラストレーターとしても、VTuberとしても) • なんちゃってPHPer ◦ Laravelをよく使います • 心ばかりの ◦ 自然言語処理 ◦ インフラ環境構築 ◦ JSやPythonなど usuyuki 宇都宮大学
3 ピクシブ百科事典の 改善 メンターの tadsan インターンの usuyuki usuyukiの力上昇 メンターのtadsan
‘ピクシブ百科事典はアニメやマンガ、ゲームからデザイン・アートまで あらゆる言葉・現象・文化・作品を解説するみんなでつくる百科事典です。 ’ 4 ピクシブ百科事典 記事数 42万 ※日本語版 月間PV 1億
※日本語版
2009年来からのPHP製 独自フレームワーク 5 ピクシブ百科事典
6 8日間で行ったこと 大きく分けると2つ
7 8日間で行ったこと ※イメージ PHP フレームワーク アプリケーション
8 8日間で行ったこと ※イメージ PHP フレームワーク アプリケーション ルーティングを middlewareへ
9 8日間で行ったこと ※イメージ PHP フレームワーク アプリケーション /mypageのADR化
10 フレームワークのお話 ※イメージ PHP フレームワーク アプリケーション
11 やったこと ルーティングをmiddlewareへ
12 全体の流れ ページの閲覧 index.php 種々のミドルウェア Dispatcher ControllerまたはAction Model tplファイル •
田代砲やNGワードを弾く • HTTPSへのリダイレクト • セッションの初期化
13 全体の流れ ページの閲覧 index.php 種々のミドルウェア Dispatcher ControllerまたはAction Model tplファイル URLを元に対応するクラスやメ
ソッドを引っ張り出す
14 全体の流れ ページの閲覧 index.php 種々のミドルウェア Dispatcher ControllerまたはAction Model tplファイル 実際の処理
(記事の登録や呼び出し )
15 全体の流れ ページの閲覧 index.php 種々のミドルウェア Dispatcher ControllerまたはAction Model tplファイル
16 何が嬉しいの? 外部依存削減 & 責務分割
17 外部依存削減 外部依存削減
18 外部依存削減 その前に
19 PSR PSR
20 PSR PHP Standard Recommendationd PSR
21 PSR ピクシブ百科事典はPSR準拠に
22 PSR-7 HTTP Message Interface リクエストやレスポンスの インターフェイスなどが定義されている!
23 PSR-7 HTTP Message Interface そしてイミュータブル(不変)!
//どこかのファイル $_POST[‘title’] = ”任意の値”; PHPのスーパーグローバル変数 24 //どこかのファイル $title = $_POST[‘title’];//何が来るか分からない...
値の代入(任意の場所で任意の回数) 値の取り出し(グローバル変数)
$request = $request->withAttribute(RouteDispatchHandler::class, $new_handler); PSR-7準拠 25 public function handle(ServerRequestInterface $request)
{ $request->getAttribute(RouteDispatchHandler::class, $new_handler); 値の代入(1回限り) 値の取り出し(引数より頂戴できる)
26 こうすることで... これまで これから session_user()//関数内で$_SESSION['user']が呼ばれる public function hanlde(ServerRequestInterface $request) {
//中略 $request->getAttribute(‘user’)
27 外部依存削減 外部依存削減
28 責務分割 責務分割
29 Dispatcher これまで • httpならリダイレクト、セッションの初期化、 • urlから対応づくControllerやActionのクラスとメソッドを見つける • 問題のあるタイトルや意図しないものを弾く •
該当するクラスのメソッドを呼び出す • 該当するクラスのメソッドを呼び出す これから
30 PSR-15 HTTP Handlers middlewareやhandlerに関しての インターフェイス
class RoutingMiddleware implements MiddlewareInterface { インターフェイスを具象化したものを実装 31 class IndexAction implements
RequestHandlerInterface { Mypage/IndexAction RoutingMiddleware
32 PSR-15 middleware middleware HTTPリクエスト HTTPレスポンス
33 PSR-15 middleware middleware HTTPリクエスト HTTPレスポンス
34 責務分割 middlewareへ切り出した
35 従来 https://dic.pixiv.net/a/%E3%81%97%E3%81%90%E3%82%8C%E3%81%86%E3%81%84 dispatcher RouteConfigPC URLに対してどれを 呼び出すかが列挙されている 実際の処理(Controller,Action) を呼び出す! 種々のmiddleware
36 今回の実装 https://dic.pixiv.net/a/%E3%81%97%E3%81%90%E3%82%8C%E3%81%86%E3%81%84 dispatcher RouteConfigPC URLに対してどれを 呼び出すかが列挙されている RoutingMiddleware 実際の処理を呼び出す RouteDispatchHandler
該当する処理を見つけ出し、 RouteDispatchHandlerを$request に包む 実際の処理を準備する 種々のmiddleware 種々のmiddleware
//色々な処理... $new_handler = new RouteDispatchHandler($route, $controller, $this->response_factory, $this->stream_factory, $this->system_clock, $this->views_dir);
$request = $request->withAttribute(RouteDispatchHandler::class, $new_handler); return $handler->handle($request); RoutingMiddleware 37
//色々な処理... $handler = $request->getAttribute(RouteDispatchHandler::class); assert($handler instanceof RouteDispatchHandler); return $handler->handle($request); Dispatcher
38
//色々な処理... $handler = $request->getAttribute(RouteDispatchHandler::class); assert($handler instanceof RouteDispatchHandler); return $handler->handle($request); Dispatcher
39
Dispatcherの責務を減らす 40 237行 80行
41 PSR middleware HTTPリクエスト HTTPレスポンス PSR-7 ServerRequestInterface PSR-7 ResponseInterface PSR-15
RequestHandlerInterface PSR-15 MiddlewareInterface
42 テストが書ける • 途中に謎の要素を取り込まない! • 責務が分割されている 単体で完結してるので テストが書ける!
43 アプリケーションのお話 ※イメージ PHP フレームワーク アプリケーション
44 やったこと /mypageのADR(風味)化
45 MVC Model View Controller レスポンス リクエスト
46 ADR Domain Responder Action レスポンス リクエスト HTTPレスポンス作成 メソッド1つのみ (今回はDomain風味)
if (!is_login()) { return $this->createRedirectResponse('/login', ['return_to' => (string)$this->request->getUri()]); } $user
= session_user(); $this->set('user', $user); [$checklist, $checklist_count] = ChecklistModel::findByUserIDWithArticle($user->user_id, 0, 5); //続く... 47 旧:UserController mypageメソッド
public function handle(ServerRequestInterface $request): ResponseInterface { $user = $request->getAttribute('user'); if
($user instanceof NotLoggedIn) { return $this->responder->redirectForLogin((string)$request->getUri()); } //中略 return $this->responder->emitHtml($checklist, $created_articles, $activity, $access, $related_articles); 新:Mypage/IndexAction handleメソッド 48
public function emitHtml(array $checklist, array $created_articles, array $activity, array $access,
array $related_articles): ResponseInterface { $html = $this->html_factory->render($this->views_dir . '/user/mypage', [ 'checklist' => $checklist, //略 ]); return $this->response_factory->createResponse(200) ->withBody($this->stream_factory->createStream($html)); } 新:Mypage/IndexResponder 49
50 DI Mypage/IndexActionでResponderをDI! 返し方をActionは知らなくて良い ※抽象に依存という点では厳密には不十分
/** @var IndexResponder */ private $responder; public function __construct(IndexResponder $responder)
{ $this->responder = $responder; } Mypage/IndexAction のコンストラクタ 51
public function emitHtml(array $checklist, array $created_articles, array $activity, array $access,
array $related_articles): ResponseInterface { $html = $this->html_factory->render($this->views_dir . '/user/mypage', [ 'checklist' => $checklist, //略 ]); return $this->response_factory->createResponse(200) ->withBody($this->stream_factory->createStream($html)); } 新:Mypage/IndexResponder 52
public function handle(ServerRequestInterface $request): ResponseInterface { $user = $request->getAttribute('user'); if
($user instanceof NotLoggedIn) { return $this->responder->redirectForLogin((string)$request->getUri()); } //中略 return $this->responder->emitHtml($checklist, $created_articles, $activity, $access, $related_articles); Mypage/IndexAction handleメソッド 53
54 まとめ • ルーティング周りのmiddleware移行(PSR準拠) • /mypageのADR(風味)化 • これらのテストを作成
55 書ききれなかったけど学んだこと…… • PHPStanでの静的解析 • PHPDocの威力 ◦ ジェネリックス • テストの疎結合
• staticMock • autowire • git周りの知見 • PSRの仕様に関して • 名前空間 • オートロード • PHPの関数呼び出し順による最適化 • クリーンとイージーに関して • interface,trait,abstract • 安定度抽象度等価原則に関して • デプロイ環境に関して などなど...
56 まとめ この春 ピクシブで 圧倒的猛者になりました。
57 謝辞 tadsanさん、kamikoさん pixiv事業本部webエンジニアリングチームの皆様、 障害対応してくださった皆様、 インターンの手筈整えてくださった皆様、 充実した8日間をありがとうございました。
58 ピクシブ百科事典の 改善 メンターの tadsan インターンの usuyuki usuyukiの力上昇 全体を通して
59 ピクシブ百科事典の 改善 メンターの tadsan インターンの usuyuki usuyukiの力上昇 全体を通して
60 おわり ご清聴ありがとうございました!