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
COVESA VSSによる車両データモデルの標準化とAWS IoT FleetWiseの活用
osawa
1
370
[ JAWS-UG 東京 CommunityBuilders Night #2 ]SlackとAmazon Q Developerで 運用効率化を模索する
sh_fk2
3
450
Agile PBL at New Grads Trainings
kawaguti
PRO
1
450
これでもう迷わない!Jetpack Composeの書き方実践ガイド
zozotech
PRO
0
1k
研究開発と製品開発、両利きのロボティクス
youtalk
1
530
DroidKaigi 2025 Androidエンジニアとしてのキャリア
mhidaka
2
380
サラリーマンの小遣いで作るtoCサービス - Cloudflare Workersでスケールする開発戦略
shinaps
2
470
Modern Linux
oracle4engineer
PRO
0
150
LLM時代のパフォーマンスチューニング:MongoDB運用で試したコンテキスト活用の工夫
ishikawa_pro
0
170
スクラムガイドに載っていないスクラムのはじめかた - チームでスクラムをはじめるときに知っておきたい勘所を集めてみました! - / How to start Scrum that is not written in the Scrum Guide 2nd
takaking22
1
120
バイブスに「型」を!Kent Beckに学ぶ、AI時代のテスト駆動開発
amixedcolor
2
580
企業の生成AIガバナンスにおけるエージェントとセキュリティ
lycorptech_jp
PRO
2
190
Featured
See All Featured
Site-Speed That Sticks
csswizardry
10
820
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
358
30k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
139
34k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Building a Scalable Design System with Sketch
lauravandoore
462
33k
GitHub's CSS Performance
jonrohan
1032
460k
Become a Pro
speakerdeck
PRO
29
5.5k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.5k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.1k
Navigating Team Friction
lara
189
15k
Embracing the Ebb and Flow
colly
87
4.8k
Designing for Performance
lara
610
69k
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 おわり ご清聴ありがとうございました!