狠狠撸

狠狠撸Share a Scribd company logo
真っ当な技術を使ったふつうの
Webサービス開発
ログミー株式会社 / 野崎翔太
1 / 26
野崎翔太 / @emonkak
Vimmer / Haskeller
ログミー唯一のエンジニア
OSS
Feedpon - LDRライクなフィードリーダー
emonkak/php-di - 高速なDIフレームワーク
emonkak/php-orm - object-mapperスタイルの軽量ORM
emonkak/php-enumerable - LINQ to ObjectsのPHP移植
自己紹介
2 / 26
世界をログする書き起こしメディア
ログミー:IT、スタートアップ関係のイベントの書き起こし
ログミーTech:エンジニア勉強会の書き起こし
ログミーファイナンス:決算説明会の書き起こし
ログミーについて
3 / 26
WordPressで独自にテーマ、プラグインを開発して運用
開発?運用?デザインは社外に依頼
現在はログミーファインスについてのみこの旧システムで動作
リニューアル以前のシステム
4 / 26
極度にグローバル変数に依存した設計
テンプレート主体の設計でView以外のロジックを書くべき場所がない
とにかく遅い、キャッシュが必須
平均レスポンスタイムが約2000msだったことも(今は約400msまでは
改善)
WordPressのつらみ
5 / 26
開発者主導で仕様はほぼなし
WordPressから必要な機能だけを抽出してLaravelで再実装
技術的な課題の解決を優先、ビジネスサイドの要望は後回し
しかし新ためてヒアリングしてみると、同じシステムを再発明する意義
は薄かった
一度目のリニューアル
6 / 26
開発の内製化
ドメイン駆動設計の導入
ユビキタス言語定義してそこからドメインモデルを構築
開発体制の変更
7 / 26
基本的にシステム上での業務に関しては記事を作成して公開するという
単純なもの
しかしログミーには独自の概念「シリーズ」があった
「シリーズ」は日本語で言う「連載」という続きもの記事の集合、とい
うのは正確ではなかった
「シリーズ」は親子関係を持つことができる
親子関係は多いものでも3代まで
3代というのが理解の鍵に
ドメインモデルの構築
8 / 26
三代のそれぞれの「シリーズ」は役割が違っていた
異なる概念を同じ「シリーズ」という言葉でまとめて親子関係にしてい
た
親シリーズ:イベントの主催者(コミュニティ)
子シリーズ:コニュニティによって開催されたイベント(イベント)
孫シリーズ:イベントで行なわれたセッションを記録した記事の集
合(ログ)
ドメイン知識の蒸留
9 / 26
リニューアルするサービスは売り上げが立っている
売り上げが立っているサービスは継続可能性が高い
長期間の保守に耐えられる設計が必要
一方、売れるかわからない新規のサービスはスピードが重要
リニューアルのための技術設計
10 / 26
真っ当な技術?実装を選択する
標準化?規格化された技術
デファクトスタンダートの技術
捨てられる実装
真っ当な技術≠枯れた技術
有用な枯れた技術はあまりない
保守性を担保するための技術選択
11 / 26
バックエンドの構成
12 / 26
構成技術
PHP(FastCGI)
nginx
MySQL
memcached
crond
モノリシックシステム
今後はレコメンド処理をマイクロサービス化を予定
バックエンドの構成
13 / 26
PHP-FIG(PHP Framework Interop Group)という組織が出している
PSR(PHP Standard Recommendation)という標準勧告がある
Javaで言う所のJSR(Java Specification Request)
PSRはPHPコミュニティでかなりの影響力がある
HTTPサーバーのインターフェイスを定義したPSR-15(HTTP Server
Request Handlers)がある
PHPにおける標準化
14 / 26
interface RequestHandlerInterface {
public function handle(
ServerRequestInterface $request
): ResponseInterface;
}
interface MiddlewareInterface {
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface;
}
PSR-15のインターフェイス
15 / 26
Webフレームワークは使わずにPSR-15に準拠した形でアプリを実装
フルスタックのWebフレームワークは便利だが最新版に追従するのが
大変
ルーティングはTrie木を利用した独自の仕組みをPSR-15のミドルウェ
アとして実装
emonkak/routerを利用
パスを/区切リにして木を構築してキャッシュ
それに対してマッチングをかけることで高速なルーティングを実現
PSR-11(Container interface)のDIコンテナのインターフェイスも利用
実装としては依存グラフを丸ごとキャッシュすることでが高速なイ
ンスタンス化ができるemonkak/diを利用
Frameworkless PHP
16 / 26
JavaのPersistence API(JPA)のような永続化に関するPSRはない
Object-MapperスタイルのシンプルなORM emonkak/orm を独自開
発
Entityはプレーンなオブジェクトとして定義可能
このORMに依存するのはRepositoryの実装のみ
永続化とORM
17 / 26
public function articleOfId(ArticleId $articleId): ?Article {
return $this->grammer
->getSelect()
->with(Relations::oneToOne(
'eye_catch',
'images',
'eye_catch_id',
'image_id',
$this->pdo,
new ObjectFetcher(Image::class),
$this->grammer->getSelect()
))
->from('articles')
->where('articles.article_id', '=', $articleId->getId())
->getResult($this->pdo, new ObjectFetcher(Article::class))
->firstOrDefault();
}
Repositoryの実装
18 / 26
ユーザーにはドメインモデルで表現される形とは違う見せ方をしたい場
合がある
CQRS(Command Query Responsibility Segregation)の考え方を活
用してコマンドモデルとクエリモデルに分ける
データの更新を対応するコマンドモデルはドメイン知識を反映したドメ
インモデル
データの読取を対応するクエリモデルをプレゼンテーション用のモデル
として新たに実装
実装としてはアプリケーション層に FooData、FooQueryService と
いう名称で作成
これはドメイン層における Entity と Repository の関係と一緒
CQRSの活用
19 / 26
フロントエンドの構成
20 / 26
ビルドツール
Webpack
Babel
TypeScript
MPA(Multi Page Application)
フロントエンドの構成
21 / 26
jQueryの時代はこんなコードを各所に書いていました
$('#js-button').on('click', function() {
...
});
コンポーネント単位での再利用が難しい
要素とJSのコードが離れてしまっていて管理が難しい
Reactなら ReactDOM.render() をどこに書くべきかとう問題が生じ
る
JSのブートストラップをどこでやる
か問題
22 / 26
Web Componentsはカスタム要素(タグ)を作るためのAPI群
モダンブラウザはネイティブサポート
IE11はPolyfill必須
Custom Elementのみ使用
Shadow DOMは使わない
HTMLElementを継承したComponent実装のための基底クラス
StatefulComponentを作成
ReactライクコンポーネントAPI
テンプレートの描画にはlit-htmlを利用
コンポーネント間のメッセージングにはCustomEventを活用
全部で400行程度のコンパクトな実装
WebComponents + lit-html
23 / 26
インフラ構成
24 / 26
Pull
RDS(MySQL)
ECS Service(Fargate)
S3
Cloudflare
Application Load balancer
App Container
(PHP-FPM)
ElastiCache
(Memcached)
Proxy Container
(nginx)
Scheduler Container
(PHP+crond)
CodePipeline
Push
GitHub
CodeBuild
Deploy
Lambda
ECR
インフラ構成
25 / 26
リニューアルするサービスは継続可能性が高いので保守性を重視して開
発
サーバーサイドはPSRの標準化技術を使って、フルスタックのフレーム
ワークの利用を避けた
フロントエンドはブラウザの組込みの機能であるWebComponentsと
lit-htmlを使ってコンポーネントを実装
インフラはコンテナ技術とデプロイの自動化をすることで運用コストを
削減
長文を掲載するメディアなので読み易くなるようなUIデザイン
まとめ
26 / 26

More Related Content

真っ当な技术を使ったふつうの奥别产サービス开発