Because We Love Happy Coding

フリーライターからエンジニア × 講師。発信力だけあり余ってる感じ

PHPカンファレンス2019に行ってきた! #phpcon

今日もまたコーディング。だって僕らはHappy Codingが大好きだから。

PHPカンファレンス2019に行ってきました。蒲田まで。

私が参加した講演について、簡単にまとめましたので、アップロードしておきます。

今の自分の興味に沿って、テスト関連だったり、電気回路だったり、ツールだったりと面白い話をいろいろ聞くことができました。

Track3は機械トラブルがあって開始がちょっと遅れてしまったりしていたようです。後半は回復したようですが。

メモ書きですので、網羅的な内容ではありません。スライドを見る方が内容は追えると思います。

10:00〜 Track 1 (1F 大展示ホール) オープニング

11:00〜 Track 3 (4F コンベンションホール 鶯) Chatworkのシステムから学ぶレガシーなPHPの限界とレガシーからの脱却

村上 俊介 / Chatwork株式会社 (1) しゃか (@shaka0maru) / Twitter

Chatworkのシステムから学ぶレガシーなPHPの限界とレガシーからの脱却 by 村上 俊介 | トーク | PHP Conference Japan 2019 #phpcon - fortee.jp

speakerdeck.com

レガシーコードの定義

書籍や人によって定義が違う。「テストがないコード」「柔軟性のないコード、テストされていないコード、技術的負債を抱えているコード」

この発表では『レガシーコードからの脱却』の定義に合わせて「修正、拡張、作業が非常に難しいコード」とする。

Chatworkのバックエンド構成

現状、Chatworkでは四桁のリクエスト/secを受けて30〜200msくらいで返している。

サーバーサイドの構成

Scala採用を決めて3年半たった、CTOの振り返り。アーキテクチャ刷新を成し遂げるために必要なこと - Chatwork Creator's Note

scala採用を決めて3年半のCTOの振り返りが記事になっている。
PHPScalaでゼロベースでつくりなおす。
→ なんとかしないとレガシーなシステムは死ぬ

PHPアプリケーションのつらみ

ChatWorkとPHPと私 - Speaker Deck

  • メンテナンスがつらい状態。
    • 巨大なモノリスプロジェクト、1万行のUtilクラス
    • 古いオレオレフレームワーク モダンな静的解析ツールの適用が難しい
    • 暗黙知と歴史的経緯 + 粒度がまちまちなドキュメント
  • 責務が入り交じりすぎていて分割が困難

静的解析ツールで解決を試みる

  • PHPStan
  • Phan php-ast拡張(Php7)が必須。
  • SonarQube 大きいファイルで動かすとdockerコンテナが落ちる。
  • PhpMetrics →採用

PhpMetrics。
package、Objectレベルでのメトリクス。
パッケージ依存クラスを図示。

どうしてこうなった?

  • 速度優先で開発を続けてきた副作用
  • ビジネスが拡大したタイミングで使用を厳格かしなかった。Chatworkはもともと社内ツール。曖昧な仕様が曖昧な仕様を生む。
  • 過去にコードの改善に失敗した。Scala化が部分的であり、PHP仕様に引きずられている

レガシーなPHPの限界

修正・拡張作業が非常に難しい。

  • プロジェクトの規模が大きく、アーキテクチャの変更が困難
  • plain-phpによる同期処理前提の仕様。→ SwoleやAmpの導入が難しい

デカルトは「困難を分割せよ」と言うが、分割自体が難しい。

DB分割の困難さ。 クライアント1万台問題。
プロセス単位で動くPHPのスケールアップはできるけれど、DBはスケールアップしづらい。
「スケールアップするとサービスが赤字になる」状態にまでなっていく。

何が問題か

  • PHPは遅くないし悪くない
  • 自社製フレームワークもレガシーだが遅くない。重厚なフレームワークだとパフォーマンスが出なくてサービスが落ちる
  • サービス規模にPHPが適合しなくなった。
    • DBコネクションプールが欲しい。
    • nK/rpsを同期処理の言語で処理するのは難しい。JVM、Go、ErlangVMなどが適切

レガシーからの脱却

Todo

  • サービス互換性を保ちつつ開発を楽にする
  • 数倍のトランザクションを処理可能にする
  • 組織にスケーラビリティを持たせる。「開発者を増やして効率が上がる」組織。組織としてのスケーラビリティ

リアクティブシステム
新メッセージングシステムを支える技術。

スケールアウト

システムと組織をスケールアウトする仕組み。

メルヴィン・コンウェイ(英: Melvin Conway)は初期のコンピュータ科学者、プログラマーであり、コンウェイの法則として知られる法則「システムを設計する組織は、その構造をそっくりまねた構造の設計を生み出してしまう」 (原文: "Organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations.")を生み出したハッカーとしても知られる。
  • システムだけスケールアウトしてもメンテナンスできる体制が整っていないと持続できない。コンウェイの法則
  • 組織のスケールに併せて生産性を高められる構成
    • Microservices
    • Modular monolith

ヒエラルキー型組織からの脱却

  • チーム間のコミュニケーションが取りづらい。マネージャー経由になる。仕様を分かっている人間が
  • 意志決定の責務が曖昧

ラクラシー組織

  • ロールベースの自立したチーム
  • 権限、責務を分散

どう移行できるのか、会社に向いているかの判断、など。

これから

  • 移行計画、方針プランニングPoc
  • 要求分析、モデリング
  • RDRA DDD

ドメインモデリング

これからのTODO

  • モデリング
  • コンテキスト分割
  • 開発
  • データ移行
  • 開発組織の刷新

まとめ

関連ツールの限界がレガシーなPHPの限界になる
→ 困難を分割できる設計 を目指す

サービスの社会的責任が高まってからの大規模な刷新は大変
→ ビジネス規模に合わせて適切なタイミングでリファクタリングなどの手を打つ

13:00〜 Track 5 (1F AB会議室 - サテライト: 6F C/E会議室) PHPerのためのテストコード入門

大津 和槻 ウィルゲート 02 (@cocoeyes02) / Twitter

PHPerのためのテストコード入門 by 02 / 大津 和槻 | トーク | PHP Conference Japan 2019 #phpcon - fortee.jp

speakerdeck.com

  • そもそもなぜテストを書くのか
  • なぜテストコードを導入するべきなのか
  • それぞれのテストコードの特徴
  • それぞれのテストコードのメリットデメリット

言葉の定義

「テスト」 …… ソフトウェアが正しく動作するか

本講演のゴール

「なぜそのテストコードを書くのか」を話せるようになること

  • なぜ書くのか
  • なぜ導入するのか
  • 特徴と比較

テストの目的

ISTQB テスト技術者資格制度

テストの目的 = 品質を可視化する & ソフトウェアのどの品質を高めるかの判断材料を提供する

「品質」は見えづらい → テストを使って確認する

ただし、ソフトウェアテストだけでは品質を「高める」ことはできない。バグ修正が必要。
テストは品質の保証であって、品質の向上ではない。

品質向上のための様々な判断
「ソフトウェアの品質を高める判断の材料を提供する」のがテストである。

例題

テスト結果と上長判断

プログラマが知るべき97のこと』通称キノコ本

プログラマが知るべき97のこと

プログラマが知るべき97のこと

「ソフトウェア開発プロジェクトをすすめる時は目に見える証拠がたくさんあるという状態を維持すべきでしょう。」

テストコードの目的

テストコードの目的 = 「品質と開発スピードを両立すること」

ソフトウェアテストの7原則「3. 早期テストで時間とコストを節約」

「シフトレフト」 …… 「バグを見つけるのが早ければ早いほど修正工数が少なくて済む」という原則。

バグが見つかった時の対応は遅れれば遅れるほど工数が増える

  • リリース後だとお問い合わせ対応などもしなければならない。
  • テスト後だと再テストが必要になる。
  • 設計時なら定義書、設計書修正、レビューといった程度で済む。

手動テストとテストコード

  • 実行タイミング
    テストコードがあれば、テスト工程より先に気軽にテストが可能になる。自動化されているのでテスト時間も短い。早い段階でテストを実行するようになる。
  • 確実に実行できるか
    テストコードでは(手動テストに比べて)ヒューマンエラーを排除できる。何度実行しても同じ結果が得られる。

工数を減らして確実」というと無敵のようだがそうではない。

テストコードのコスト。
手動でなければできないテストもある。
テストコードにできるものはコードで、という棲み分けが必要。

様々なテストコードを知る

3つの分類。

ユニットテスト

一つの関数、メソッドについてI/Oを通じて仕様通りか確認する。PHPUnit

結合、統合テスト

featureテスト、APIテストなどがこれにあたる。特定のリクエストを投げてレスポンスを検証する。PHPUnit

UIテスト

SeleniumなどE2Eテスト。ユーザー目線に一番近いテスト。PHPUnitPHP-WebDriverを使ったE2Eテスト。classとIDを指定すれば自動操作ができるため、バックエンドを気にしないでテストできる。

比較

テスト範囲はテストのコストにつながる。

UIテストはテスト範囲が広い。その分、原因特定や、テスト条件のメンテナンスに工数がかかる。

実行時間が短く、テストの原因特定がしやすいユニットテストをたくさん書くのが理想とされる。

ユニットテストでチェックできないものを結合、UIでテストする。

テストピラミッド

3種類のテストの割合に関する目安。

  • UI
  • 統合
  • ユニット

上に行くほどコストが大きい。少なくするべき。つまり、UIテストは少なく、ユニットテストは多く書く方が効率よいとの示唆。

テストピラミッドの例

手動のUIテストを自動化する。そこから次第に結合テストユニットテストに分割していく → 逆三角形のテストピラミッドになる
これを少し調整して、統合テストが多くなるように持っていく、など。

ただし、ピラミッドの最適解はサービスの性質による。必ずしもユニットテストが一番たくさん必要、というわけではない。チーム内で摺り合わせること。

ゴール

「なぜそのテストコードを書くのか」を話せること。

品質を担保できれば開発スピードも上がる。両立を目指すためのテストコード。

13:35〜 Track 3 (4F コンベンションホール 鶯) 改善失敗から学ぶ、レガシープロダクトに立ち向かうチーム作り。

杉山 祐一 / サイボウズ株式会社 すぎやま@MASH弦楽団 (@oogFranz) / Twitter

改善失敗から学ぶ、レガシープロダクトに立ち向かうチーム作り。 by 杉山 祐一 | トーク | PHP Conference Japan 2019 #phpcon - fortee.jp

speakerdeck.com

Garoon …… 大規模向けのグループウエア

PHPMySQL。17年目のサービス。

  • チームの広げ方
  • 強くする方法

5年前のチーム構成

やりとりはプログラマ3人。
タスクがリーダーを通してPMからくる。
テストはQAリーダーが海外にふる

エンジニアはソースコードに集中できる環境。

エンジニア「この部分をリファクタしていい?」
PM「テストが必要だからQAに確認。」「技術負債箱に入れておいて」

  • 技術的負債 = 開発速度の低下を引き起こす、設計やコードの問題。
  • 技術的負債箱 = 技術的負債を可視化し、貯めておく場所

見てみると、100件以上の負債が残っている。
登録 → 次のバージョンでどれを修正するか決める。半年後になる。

なぜただのリファクタに半年かかっていたのか。ウォーターフォール開発のため。

開発期間、影響範囲とテスト。

スクラム開発

スクラム開発が始まる。スプリントを設定。

しかし失敗。タスク数のバーンダウンチャート。理想的には0に近づくはずだが、二週間後スプリントが終わる頃には減らずに増えている。

スクラム開発。二週間の中で計画、実施、ふりかえりをする。

「失敗したところを振り返る」が大事。失敗する前提で仕組みが設計されている。

  • 実装する内容の認識差。
  • テストのために必要な情報の認識差
  • お互いの作業内容の認識差

そこで、改善を入れた。

  • 実装範囲とテスト範囲の確認
  • 仕様の穴を実装前にQAから教えてもらえる。
  • QAがテストで困っていることがすぐにわかる
  • テスト設計にプログラマの知識を活かせる
  • 不具合を一緒に、リアルタイムに確認・改修

共同作業でコミュニケーションロスが減る。

PMとの摺り合わせ

  • 最低限の必要な機能についての認識差
  • 機能によって実現したい価値の認識差

組織変更したら部長がいなくなりました - Cybozu Inside Out | サイボウズエンジニアのブログ

チームをもっと多様にする

PMとうまくいったので、他の職能をまきこむともっとよくなるかも。

  • 文言(TC)チームからの文言変更依頼
  • タスクチケットを切る
  • 実装
  • テスト

「文言の改修を文言チームで完結させてはどうか」と提案。 → 長文で怒られた。

もともと文言チームのもやもやがあった。自分の提案は開発チームのもやもやしか改善されないものだった。 → 技術的なことを文言チームに丸投げしない。

非エンジニアへの学習コストを最小限に。

  • 開発環境をシンプルに。
  • Githubのドキュメントを整備
  • 開発モードの作成
  • リソースとプロダクトコードの分離
  • 困った時にいつでも聞いてもらえる関係性

現状では文言チームが文言を改修している。

失敗して学ぶチームを強くする

コード品質との闘い

  • 不具合が大量発生
  • 手動テスト
  • リリース後もバッチ対応
  • 障害対応は日本側
  • デグレ発生リスクを下げたい
  • テストのないGaroonはレガシーコードだ。

人数が日本側3〜4人。海外(ベトナム・上海)10〜で圧倒的に多い。品質への意識が違う。

  • テストが根付かない
  • スキルとコード品質の意識が高いメンバーのみ
  • そもそもスキルが高くない
  • スピードを重視したいメンバーもいる

チームの意識が揃っていなかった。

「ルールではなく、目的意識を共有する」

チームの意識をルールで揃えようとすると破綻する

「CIを落としたら落とした人が直す」というルールを作っただけでは、同じ事がまた起きる。

チームには「目的を共有する」方がうまくいく。

  • 「CIをグリーンに保ちたい」
  • 「コードの品質を保ちたい」

グスタフ・マーラー(作曲家)「伝統とは火を守ることであり、灰を崇めることではない」

コードの品質という守りたい火

  • 拠点をまたいでのコードレビュー
  • 海外拠点含め全員でのReadableCodeの輪講
  • 海外拠点含め全員でのレガシーコード改善ガイドの輪講

共通言語でコード品質を語ることができるようになった。

「Readableコードの〜にあるとおり、ここは直した方がいい」

チームの共通言語を作ること。もっと強くするには? チームメンバー全員で同じ体験をすると、チームで議論する共通言語になる。

  • チームで勉強する
  • レーニングタスク
  • 重複しても良いので同じタスクを各拠点で解決してみる
  • 海外拠点に集まって勉強会
  • チームで勉強できる福利厚生

Garoonの闇は晴れたのか

  • つらいものはつらい
  • 17年積み重ねた夫妻はすべては改修できない
  • ソースコードにだけ向き合っていればいい状態でhないのでエンジニアとしてはツラい
  • まだ失敗はある。

ふりかえりのProblem登録件数推移。問題は増えている。まだまだ失敗できる余地がありそう。

  • 失敗して学ぶチーム文化が育ってきた。
  • 失敗しないことよりも失敗から学ぶ方法を学ぶ

14:45〜 Track 6 (3F 特別会議室 - サテライト: 6F D会議室) 「CPUとは何か」をPHPで考える

長谷川智希 / デジタルサーカス株式会社 Tomoki Hasegawa (@tomzoh) / Twitter

「CPUとは何か」をPHPで考える by 長谷川智希 | トーク | PHP Conference Japan 2019 #phpcon - fortee.jp

speakerdeck.com

休憩時間の前座トーク

  • 「0-1で表現する」ということの意味。デジタル回路では電圧の高低
  • NAND回路とLEDの例

自己紹介

PHPerKaigi 2020 トーク(2019-12-02まで)募集中

CPUを3つの視点から見てみる

  • 実行環境としてのCPU
  • エミュレート対象としてのCPU
  • 電気回路としてのCPU

題材となるCPU: TD4

『CPUの創り方』良書。

CPUの創りかた

CPUの創りかた

CPUを創りながら動作を理解しよう。

プログラム実行環境としてのCPU

実行環境としてのCPU = マシン語プログラムの実行環境である

/usr/bin/php
C言語→(コンパイル)→ニーモニック→(アセンブル)→マシン語

TD4のマシン語のルール。

4ビットの命令(オペコード)+4ビットの引数(オペランド)
1命令 = 1バイトになる。

$09(16進数) = 00001001(2進数)
前半0000が命令
後半1001が引数

命令セットは全12命令。

1Hzで駆動する。1秒に1命令を処理する。

自分の使う機能のみの理解でOK。
すべての命令・仕様を知る必要は無い。

エミュレート対象としてのCPU

CPUのふるまいをPHPでエミュレートする。

  • メモリの実装
  • 命令の実装
  • I/Oの実装

メモリの実装

1バイトのデータを保持するデバイス。CPUはアドレスを指定してデータを読み書きする。「配列」を使えば実現できる。

class Cpu
{ 
   private $ram 
}

「命令を実装する」

プログラムカウンタ $this->pc を設定しておく。

I/O実装

ここではPCレジスタを++して処理しているが、最後にクロックが来てリセットする際に問題が生じてしまっている……。

完成したものがGithubにある

GitHub - hasegawa-tomoki/php-terminal-td4-emulator: A TD4 emulator written in PHP

対象CPU用に書かれた全てのプログラムを動作させる存在。「CPU仕様の完全な理解」が必要。

電気回路としてのCPU

CPUをハードウェアとして考える。

すべての命令は「何かと何かを足してどこかに転送する」という形になっている。静的回路を処理装置化する存在。

PCレジスタからメモリに指示を出す。メモリは指示通りに出力する。

クロック信号が来るとPCレジスタ++される。
→ クロックに従って状態遷移する回路としてCPU命令を表現した存在

仕様と物理のパズルを解いてCPU仕様を創り上げる

質問 PCレジスタが最後にインクリメントすると困る、はどう解決している?

最終的には条件分岐のような形で処理している。

質問 CPUボードのクロックを創る部分は?

RC回路で発信する。マニュアルも用意されており、スイッチを一回押すとクロックが進む。

15:20〜 Track 3 (4F コンベンションホール 鶯) このPHP QAツールがすごい!2019

sasezaki sasezaki (@sasezaki) / Twitter

このPHP QAツールがすごい!2019 by sasezaki | トーク | PHP Conference Japan 2019 #phpcon - fortee.jp

www.slideshare.net

後半スピードがあがってついていけなくなったので(汗)上記スライドをご参照ください……。

まとめ

品質への不安を減らす。本来開発したい機能に集中できる。