BASEプロダクトチームブログ

ネットショップ作成サービス「BASE ( https://thebase.in )」、ショッピングアプリ「BASE ( https://thebase.in/sp )」のプロダクトチームによるブログです。

PHPerKaigi2021 参加レポート - 1 名のメンバーが登壇・ゴールドスポンサーとして協賛しました

この度は、3/26 (金) 〜 3/28 (日) にオンラインで開催された PHPerKaigi2021 にゴールドポンサーとして協賛し、また 1 名のメンバーが登壇しました。 今回は上記メンバーの他に一般聴講者として参加した 2 名のメンバーからの参加レポートをお届けします!

発表内容と補足(東口)

BASE BANK 株式会社の東口 (@hgsgtk)です。PHPerKaigi 2021 では次の 2 つのトークをしておりました。

  1. 実践ATDD 〜TDDから更に歩みを進めたソフトウェア開発へ〜(40 分)
  2. PHPUnit 9 時代のTest Doubleの作り方(5 分)

1. 実践ATDD 〜TDDから更に歩みを進めたソフトウェア開発へ〜

発表に用いた資料はこちらです。

発表の際には、ニコニコ生放送・Discord・Twitter での実況が行われていました。Twitter でのリアクションは以下の Togetter にまとめています。

https://togetter.com/li/1688539

資料公開後土日にも関わらずたくさん反応いただき、2021 年 3 月 28 日(日)のお昼ごろには100以上ブックマークいただきホットエントリー入りする反響でびっくりしました。

翌週以降も『テスト駆動開発』を翻訳されている和田卓人さんに直接感想をしていただいたりと、多くの方の目に触れる資料となり「頑張ってよかったな」と感慨深くなりました。

以降、収録された発表を見ながら補足情報として入れていた話・Ask the speaker でご質問・意見交換させていただいた内容を抜粋してまとめます。

イテレーション分の受け入れテストをまとめるアイデア

テストが増えた場合のテスト速度とフィードバックループについてどういうアイデアがあるかな〜という話を Ask the Speaker でしていました。その中で取り上げさせていただいたのが、「イテレーション分の受け入れテストをまとめる」アイデアです。

これは『Specification by Example』のChapter 10. Validating frequentlyで紹介されているアイデアです。

A common special case of breaking long tests into smaller packs is creating the current iteration pack. This pack contains the executable specifications that are affected by the current development phase.

ATDD を実践するために用いられるツールには、概ねディレクトリ分けや Tag 等で受け入れテストを分類する機能が備わっています。テスト量が増えた際には、当該イテレーションで関心を持つ受け入れテストのみを絞れるようにすると、開発中のフィードバックループの周りを維持できるかもしれません。

手動テストの扱い

手動テストも Specification に記載するという話を現場での試行錯誤の 1 つのアイデアとして紹介していました。

f:id:khigashigashi:20210401222004p:plain
発表資料から引用

これについて Ask the speaker でいろいろ意見交換させていただきました。

  • 手動テストの Specification には何を書いている?
    • 手動でテストしたいテスト項目について記載している、自動テストでは実行がスキップされるようなイメージ
    • スプリントレビューでデモするような動かし方を書いていたりもする
  • 手動テスト分を毎イテレーションテスター向けのキュー追加するとかできるとよさそう
  • 手動テストの実行結果はどうする?
    • 現状実行結果を記録する仕組みを用意してるわけではないが、イテレーションごとの実行結果としては記録したいモチベーションはたしかに。手動テストをイテレーションごとに Issue 作るなどするアイデアがありそう

おすすめの一冊『Specification by Example』

ATDD について知っている方であれば『実践テスト駆動開発 (Object Oriented SELECTION)』(通称 GOOS 本)の外側のフィードバックループを想起される方が多いかと思います。

個人的なおすすめとしては、GOOS 本は技術的要素へのフォーカスがメインなので、ATDD 自体の前提となるコラボレーションを重視する考え方などを知るには違う書籍で補完したほうがいいかもしれません。逆に言うと、ある程度 INPUT した上で実践書として GOOS 本を読むと、とても効果が高いと思います。

GOOS 本は原著が 2009 年出版ですが、ATDD や BDD のような考え方はそれよりももっと前から実践されているものです。具体的には Ward Cunningham 氏がFITを作った 2002 年にはそれらの考え方は確認されています。その後にも、2007 年に『Test Driven - Practical TDD and Acceptance TDD for Java Developers』が出版されており、そこでも ATDD の考え方と実践方法について触れられています。

様々書籍がある中で個人的に「現場で実践する上で一番良かったな」と思ったのは、『Specification by Example』です。

www.manning.com

著者のGojko Adzic氏はこれ以前に『Bridging the Communication Gap』にて、自身の実践方法について解説しています。しかし、『Specification by Example』は数十の企業へのインタビューを通じた実践事例集となっており、インタビューを通じてGojko Adzic氏自身の考え方がアップデートされた点なども解説に含んでおり面白いです。

実際に現場で実践するにあたって困ること・気になることについて網羅的に解説されていて、大変参考になりました。

おすすめをもう一冊『Agile Testing Condensed Japanese Edition』

『Specification by Example』は翻訳版が現在無いのですが英語に抵抗のある方であれば、全体像としてアジャイルテスト自体を抑えてから本腰を上げていただくのが良いのかなと思います。初めての一冊としてのおすすめは『Agile Testing Condensed Japanese Edition』です。

leanpub.com

Janet GregoryとLisa Crispinによる2019年9月発行の書籍『Agile Testing Condensed』の日本語翻訳版です。アジャイルにおいてどのような考えでテストを行うべきなのか簡潔に書かれています!

ソフトウェアテストを実践するに当たり、アジャイルテストという観点から現場を見直してみると、大局観をもって挑めるのでおすすめです。

2. PHPUnit 9 時代のTest Doubleの作り方

発表に用いた資料はこちらです。

PHP 発表資料中に引用したいテストコード付近で若干修正点があったので PR を出したりしておりました(当日発表 1 時間前)。

github.com

Lightning Talk で Ask the Speaker の時間があるのは新鮮な体験でした。「PHPUnit のバージョンどのくらい頻繁にあげてる?」みたいな雑談を@goodooさんとさせていただいてたり、"カンファレンスの廊下感"がありました。

スピーカーとして参加した感想

事前収録を見ながら補足する体験がよかった

事前収録良かった。収録したものを見ながら様々自分でここはこういうのが関連して〜的な補足が入れれたのが自分としては良かったのと、参加した方の感想でもそれがあって、濃密度の高い時間になったという声をいただけておりました。

オンライン + 事前収録の組み合わせならではでした。5 回くらいリテイクしてるので誰もいない部屋で一人ただ喋り続ける時間は大変だったのですが、その分当日に濃密度が上がる点がいいなと想いました。

Ask the speakerに人がたくさん

オンラインになってから Ask the speaker の時間は「はてどうしたらいいかな」と困る時間を過ごすことが多かったのですが、PHPerKaigi 2021 では Discord でのボイスチャットでたくさん人がいらっしゃっていて Ask the speaker が過ごしやすかったです。

その中で得られた新たなアイデアや言語化・分析の突破口みたいなのもたくさん会話の中から出て感謝です。

トラックごとにスタッフの方々がファシリテーターとしていらっしゃるのも時間の安心感としてありがたかったです。Track A ではスタッフの@akki_meganeさんやueshiyさんが、トーク前・トーク後に会話を回してくださりとても感謝です。たまたまマイクがオンになってる気配を見て唐突に@koyhogeさんに無茶振りさせていただいたり、オフラインで休憩室でわいわい雑談する感じがあってよかったですね。

質問する身としても、「とりあえずボイスチャット入っとこ」くらいのノリで Ask the Speaker に入れたのもハードルがひくくてよかった気がします。

運営の皆様ありがとうございました

発表資料内では題材システムとして fortee を例に取らせていただきましたが、例に取るくらいめちゃめちゃ作り込まれていて、トークの自動収録システムが用意されていたりと、小並感ある感想ですが「すごいな!」と驚嘆しておりました。

ノベルティのボックスやパンフレットのクオリティも高く、自宅から参加していましたが、「カンファレンスに来た」という感覚が強い時間でした。

コミュニケーションを促進する場の設計・運営をしていただいた PHPerKaigi 2021 運営スタッフの皆様ありがとうございました!

参加レポート(小笠原)

BASE に 2021 年 2 月に入社した小笠原奈々(@cureseven)です。土日ほとんどずっと聞いていたので全体を通しての感想を先にお話しします。

学生の頃からちょっとずつ各方面のカンファレンスに参加しているんですが、学生の頃は「エンジニアってどんな感じの人たちで、どんなことしてるんだろう?」の興味で行っていたので内容がさっぱりわかってなかったのですが、社会人になって、業務をしていく中で実体験を元に話が聴けるようになってきたことを実感しました。

反面、新しく聞く話も多く、まだまだ知らないことたくさんあるなあと感じました。

PHPで学ぶ、セッションの基本と応用

fortee.jp

あまり体系的に学ぶ機会のない Session の概要がきちんと整理された、初心者にも優しい内容でした。

そもそも Session という言葉の使い方が曖昧で、正しくは「Cookie を使った Session 管理」。元々ステートレス(状態を持たない)なプロトコル World Wide Web を、ビジネス利用しだし、状態を持ちたくなったため生まれたのが Cookie という技術です。

Cookie は 4KB の制限があるので、Session ID というキーを引き回し、それを元にセッションストアにアクセスしデータを取得することによって状態を表現します。

最低限の知識として

  • Cookie に属性が設定されている。
  • Session 管理を狙った攻撃がある。WAF ではそれを考慮しているので安全に $_SESSION を扱える。
  • 保持された情報によってバグが起こりやすいので、Session 管理の設計は大事。本当に Session 管理すべきなのか設計を見直すことも必要かもしれない。
  • セッションはファイルなので、サーバの台数を増やしてスケールアウトすると参照するセッションが別れてしまうので共通のセッションストアを見るなどする

ということが紹介されていました。

Cookie を使った Session の知識はかなり曖昧でした。この発表を通して用途と注意すべき事項がわかったので、今後の開発に生かすことができそうです。

PHP8になった今の時代に、PHPの「エラー」「例外」そして「Error」をおさらいしておこう

fortee.jp

エラーと例外とは何かを比較すると以下です。

  • エラー
    • 正常な処理ができない。難しそうな状況
    • プログラミング的に間違っている
    • PHP が発生させるもの
  • 例外
    • 事前条件、事後条件が満たされない状態になる時吐くもの
    • 契約プログラミングにおける契約的に間違っている
    • プログラム自体が発生させ、自身でコントロールしたいもの

改めて日本語にするのは難しいですが、感覚的にエラーと例外は自分の中では区分できているかなと思います。 このセッションでは、「エラーも例外もまとめて投げる \Throwable を闇雲に使うべきではない。」「例外を投げるにしても、捕捉してそれをどう扱いたいか明確なものを投げよ」ということを主張されていたと思います。

曖昧な throw を残すことは、何が起こるか不安な状態のままにしておくことと理解しました。

\Throwable\Error \LogicException \RuntimeException をキャッチします。 \Error \LogicException は本番では起こりえない状況なので throw せず、本番環境に乗せる前に修正すべきです。対して、\RuntimeException は本番ではどうしても起こるものなので、捕捉して回復する余地のある場合は回復する処理を書き、どうしようもない場合は諦めるのが良いと主張されていました。

今まで正しい理解がないまま \Throwable を書いていたのでこちらのセッションを聞いて理解が進みました。想定されるエラーと例外を考えるようにします。

自前の Exception を定義し、どういうコンテキストのエラーかをエラー名を見ることによって把握できる、という話もありました。

今私が参加しているプロジェクトではちょうど自前の Exception を作っていたのでよかったです。 レイヤーに合わせた抽象度の Error にして渡すのが良い、という話があったので、DDD の考え方は例外にも当てはめるべきということが新たな発見です。意識して書くようにしたいと思いました。

そのコード、フレームワークの外でも動きますか?

fortee.jp

tech.quartetcom.co.jp

このセッションでは、フレームワークに依存しない書き方を実践を通して紹介されました。40 分のセッションのうちに Laravel から Symfony にフレームワーク移行するデモンストレーションが入っていて驚きでした。

フレームワークから業務ドメインのコードを独立させておくことで、後方互換性を高くすると、リプレイス・リニューアルの時にまる写ししなくて済みます。

今私が参加しているプロジェクトでは保守性を高めるために DDD で開発しているので、参考になりました。

デモンストレーションの中でほとんど変更点がなく、名前空間や view の表記方法をちょっと修正したくらいのものを別のフレームワークに持ってきており、フレームワークに依存した書き方をしなければこんなに簡単に移行できるんだと改めて DDD で開発するありがたさがわかりました。

独立パッケージにするのも賢いと思い、検討したいです。

参加レポート(炭田)

Service Dev Section に所属しています炭田高輝(@tac_tanden)です。自分は 2021 年 3 月 27 日(土)〜3 月 28 日(日)の 2 日間参加しました。

PHPerKaigi は去年初めて参加して今年で 2 回目の参加です。今年は新型コロナウイルス感染症の影響でニコニコ生放送でのオンライン開催でしたが、どのセッションも熱いトークばかりでオフラインに負けず劣らずとても楽しいカンファレンスでした。この場をお借りして運営スタッフ/スピーカーの方々にお礼申し上げます。ありがとうございました!

各セッションでは、日頃開発をしているだけでは出会うことが中々難しい様々な知見にふれることができ、とても勉強になりました。自分が聴講したセッションの中から特に気になったセッション 3 つのレポートをしたいと思います。

PHPでCSVを安心して扱うために

fortee.jp

github.com

CSV への認識が 180 度変わったセッションでした。恥ずかしながらこのセッションを聞くまでは、CSV は正規化されたお手軽なデータ形式という認識でいました。

なぜこのような認識を持っていたかというと、今まで自分が携わった開発だとサービスの管理画面からデータ入稿をするのに便利だから使う程度の事しかしてこなかったからだと思います。

そのような場面で自分が扱っていた CSV データは「信頼している人が作成した信頼性の高い」という但し書きがついた CSV データだったんだなということを痛感させられました。

CSV データを処理するエンドポイントを、悪意があるユーザを含む様々なユーザが利用する場合、入力される CSV は文字コードや改行コード 1 つとっても様々なものが想定されます。また、クラッキングしようとするような悪意があるデータも含まれる可能性もあり、それらに対して全て考慮した実装にする必要があります。

セッションでは、PHP で CSV を扱う複数の手段とともに、それらの長所/短所やベストプラクティス、様々な文字コードへの対応を解説しながらどう PHP で CSV を扱うのか知ることができともて勉強になりました。次回 CSV を使った機能を開発するときに、ライブラリの利用やその内部実装を参考にさせていただきたいなと思いました。

モックの泥沼から脱却するために、あえてDBにつないでテストしている話

fortee.jp

データソースから取得したデータを整形したり何らかのロジックを適用したあとにデータを保存するといった処理のテストを行う場合、データに関連する部分以外の実装を細かなメソッドに切り出して、データに依存しないようにしてテストすることで、データ入出力まわりのテストの複雑さをさけてユニットテストを記述できると思います。

しかしこの場合、細かく切り出した複数のメソッドを協調させて使うようなメソッドのテストが最後にどうしても残ってしまいます。これらのメソッドをテストする場合、どうしても実装が複雑になってしまい、またデータへも依存するのでテスト用のデータの生成するのにもコストがかかります。

場合によっては、このようなメソッドを組み合わせたメソッドのテストは行わない戦略を取る場合もあると思いますが、自分個人としてはそのような Large サイズのテストもできるだけ実装したいと思っています。

このセッションでは、上記のようなデータにも依存し、かつ処理も複雑なテストをする場合、モックを使ったテストではなく DB につないでテストする選択をした場合のメリット/デメリットについて解説されていました。

テスト時にモックはたしかに便利ではあるのですが、どうしても自作自演のテストになってしまい「作成したモックが正しいことをどう担保するのか」がすごく難しくなってしまうと実感しています。なので、発表にあったように「実データ」を実際に用意して、特にユースケースやシナリオといった役割のクラスのメソッドに対してはテストしていくことが良いのかなと改めて考えさせられました。

ちなみに、BASE では実装者がテストで所望のデータを生成できるよう、Fabricate というライブラリを利用しています。

Fabricateの記事

devblog.thebase.in

devblog.thebase.in

改めて、テストの意味と役割について考えさせられたセッションでした。

作って理解するDIコンテナ

fortee.jp

tadsan.fanbox.cc

PHPerKaigi 最終日の trackA は DI(Dependency Injection)祭りでした。

その中でも自分がすごく勉強になったのがこちらのセッションでした。依存とは何かの初歩の部分から依存にどう立ち向かうのか、最後には DI コンテナを実装するところまで詳細に解説されていました。特に、依存とはなんなのか、なぜ DI という考え方を取り入れるべきなのかを今一度自分の中で整理することができました。

自分は DI をという概念を利用して実装はしています。ですが、DI コンテナのようなライブラリは利用しておらず、発表中は恥ずかしながら理解が追いつかない部分がありましたが、セッションの後に資料を見返してなんとか理解したつもりです。また、この発表を通じて初めて PHP-DI を知ることができました。

最後に

今回弊社は登壇者含めて計 3 名のメンバーで参加させていただき、たくさんの参加者の方々や発表にふれることができ、とても充実した時間を過ごさせていただきました。

それも実行委員長である長谷川さんをはじめ、実行委員会の皆様のおかげです。心より感謝申し上げます。

それでは、来年もまた皆様にお会いできることを楽しみにしております。最後までお読みいただきありがとうございました。