TECH PLAY

BASE株式会社

BASE株式会社 の技術ブログ

574

みなさん、こんにちは!めもりー ( @m3m0r7 ) です。 8/29 (木) から 8/31 (土) にかけて行われた builderscon tokyo 2019 に PHP で JVM を実装して Hello World を出力するまで というセッションタイトルで登壇させていただきました。 PHP で JVM を実装するとは? Java というファイルは class ファイル、つまり 中間コードにコンパイルされ、 それを VM, つまり Java Virtual Machine 上で理解をして動かします。 この VM の部分を PHP で実装するということです。 トーク自体は 60 分枠でしたが、内容を濃くしすぎてしまうと、60分ではおさまらない内容となってしまい、どこを削るかという葛藤の中でスライド資料を作成していました。 セッションについて 本セッションでは Hello World の出力に的を絞ってトークさせていただいておりました。 出現する命令セットも少なく、バイナリを読むということを楽しんでもらい、かつ Java Virtual Machine に興味を持ってくださる方が多くなることを祈っておりましたが、セッション終了後に「Scala で実装してみようと思いました!」でしたり、「PHP で書いてみようと思いました!」というお声がけを懇親会の場で頂いて、とても嬉しく思いました。 また、私自身も他の言語で本当にできるのか?という証明として、本イベント終了後に JavaScript で実装をしてみて、それについての解説も書かせていただきました。 セッションで使用したスライド Speaker Deck にスライドをアップロードしております。 speakerdeck.com JavaScript で実装した例 Qiita に書かせていただいています。 qiita.com さいごに 次は、 PHP カンファレンス北海道 2019 、 PHP カンファレンス沖縄 2019 で登壇させていただきます。 セッションの内容は本件のような何かを実装するわけではなく、少し話の趣旨を変えた PHPer のための PHPUnit と Selenium を使ったブラウザテストのすゝめ というタイトルで、どちらかというと実務向けの内容になるかなと思います。 それでは、今後もよろしくお願いいたします!
アバター
BASE株式会社 Product Dev Division ソフトウェアエンジニアの田中( @tenkoma )です。主にPHPアプリ開発を担当しています。 BASEでは、PHPアプリ開発で使うエディタに制限はありませんが、希望する人はPhpStormを使えます。 PhpStormは設定を全くしなくてもかなり快適に使えると思いますが、多少設定するとより快適になります。 この記事では主に、開発環境とIDEを連携させアプリケーション開発をスムーズに始めるため、以下の設定について紹介します。 Xdebugと連携してリモートデバッグを可能にする PHPUnitと連携してテストをIDEから実行可能にする PHP_CodeSnifferを使ってコーディングスタイルを適用する EditorConfigを追加してコーディングスタイルを開発者で共有可能にする Xdebugと連携してリモートデバッグを可能にする BASEでは開発環境を Docker (docker-compose) を使って構築していて、環境構築に必要な手順を極力コードにしています。 PhpStormにはDocker環境と連携してリモートデバッグしたり、テストする機能があり、日々活用しています。 今回は以下のようなDockerの設定があり、対象のアプリケーションへWebアクセスが可能になっている状態である前提のもと、ブラウザからWebアクセスしたときに自動的にデバッグモードが起動し、IDE上で設定したブレークポイントで処理を止められるようにしてみます。 (実際のプロジェクトの開発環境を簡素化しています) docker-compose.yml # docker-compose.yml version : '3' services : php-cli : build : ./docker volumes : - ./:/var/www/html - ./docker/php.ini:/usr/local/etc/php/php.ini working_dir : /var/www/html ports : - "8080:80" expose : - "8080" composer : image : composer volumes : - ./:/app - ./docker/php.ini:/usr/local/etc/php/php.ini working_dir : /app docker/php.ini ; docker/php.ini ; timezone date.timezone = Asia/Tokyo ; error reporting log_errors = On error_log = /dev/stderr ; Xdebug xdebug.remote_enable = On xdebug.remote_autostart = On xdebug.remote_connect_back = Off ; デバッグ接続先をホストOS( host.docker.internal )に向ける xdebug.remote_host = host.docker.internal docker/Dockerfile # docker/Dockerfile FROM php:7-apache # Xdebug のインストールと有効化 RUN pecl install xdebug \ && docker-php-ext-enable xdebug ENV APACHE_DOCUMENT_ROOT /var/www/html/public RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf このファイルがリポジトリに含まれているとして、PhpStormでデバッグしてみましょう。 まずコンテナ群を起動します。(PhpStormで docker-compose.yml を開き、緑矢印ボタンを押してもOK) $ docker-compose up -d デバッグするスクリプトを用意します。 <?php // public/index.php phpinfo () ; 3行目の phpinfo(); にブレークポイントを作成したらIDE右上の Start Listening for PHP Debug Connections をクリックして、 http://localhost:8080/ にアクセスします。 Start Listening for PHP Debug Connectionsボタン すると、「Incoming Connection from Xdebug」というダイアログが表示されますので、 Accept ボタンをクリックします。すると、以下のように index.php の3行目で処理がブレークします。 (ブレークしない場合、ファイアーウォールの設定を見直したり、一時的にオフにして問題の切り分けが必要になります。) index.php の3行目でブレークしているところ PHPアプリリポジトリに docker-compose.yml を用意しておけば、Preferences を開いて設定しなくても、PhpStormでデバッグできました。 PhpStorm のデバッグツールでは条件付きブレークや、ブレークする代わりにPHPコード実行結果をデバッグコンソールにログをとる機能もあるので、 デバッグ連携できると開発が非常に楽になります。 BASEのプロジェクトでは、複数のリポジトリから共通のローカル環境を使うため、Docker環境を独立したリポジトリで管理しています。そのような場合は、ホストOS-コンテナ間のPath Mapping設定を docker-compose.yml から読み取ってくれないので別途設定が必要です。 PHPUnitと連携してテストをIDEから実行可能にする IDEからテストを実行できると、ターミナルと行き来してテスト実行コマンドを入力しなくても良くなるため快適です。 前提として、以下の設定ファイルを用意します。 composer.json { " name ": " baseinc/sample-api-php ", " autoload ": { " psr-4 ": { " App\\ ": " src/ " } } , " autoload-dev ": { " psr-4 ": { " Tests\\ ": " tests/ " } } , " require-dev ": { " phpunit/phpunit ": " ^8.3 ", " squizlabs/php_codesniffer ": " 3.* " } } 保存したら、PHPUnitをインストールします。 $ docker-compose run composer composer install そして、テストファイルを追加してみます。 <?php // tests/SampleTest.php namespace Tests; class SampleTest extends \PHPUnit\Framework\TestCase { public function testSame () : void { $ this -> assertSame ( 0 , "0" ) ; } } エディタの左側に緑矢印が表示されますが、まだテストは実行できません。 PhpStormでPHPUnitを使ったテストを実行するための設定 PhpStormからDockerコンテナ上でPHPUnitを実行させるのはいきなりは出来ません。どこのPHPインタプリタを使用させるのか、どのテストフレームワークを使用させるかをPhpStormに設定しなければなりません。 CLI Interpreter とTest Frameworksの設定をします。 「Preferences」を開き、 Languages & Frameworks > PHP にアクセス 右パネルの CLI Interpreter: が <no interpreter> になっているかと思いますが、右側の ... ボタンをクリック 「CLI Interpreters」ダイアログが開いたら、左上の + ボタンから、 From Docker, Vagrant, VM, Remote... 」を選択 「Configure Remote PHP Interpreter」ダイアログが開いたら、 Docker Compose 選択し、 Service: を php-cli に変更して OK をクリックして閉じる 「CLI Interpreters」ダイアログが以下のような表示に変わったらOK 「CLI Interpreters」ダイアログ 次に Languages & Frameworks > PHP > Test Frameworks を選択 右パネルで、 + ボタンをクリックし、 PHPUnit by Remote Interpreter を選択 ポップアップダイアログでは php-cli (7.x.x) に切り替えて OK ボタンを選択 詳細な設定が入力できるようになるので、 Path to Script: に /var/www/html/vendor/autoload.php と入力し、 OK を押し、「Preferences」を閉じる Languages & Frameworks > PHP > Test Frameworks これで設定完了です。もし、 phpunit.xml.dist が用意されている場合は、 Default configuration file: をチェックし /var/www/html/phpunit.xml.dist を入力します。 緑矢印をクリックしてテストを実行すると、次のように結果が表示されます。 (前節でオンにした、IDE右上の Start Listening for PHP Debug Connections はオフにしたほうがいいみたいです。) PHPUnitテスト結果が表示されたRunパネル これでPHPUnit連携ができ、IDEから実行可能になりました。ショートカットキーから一発で実行することも出来ますし、デバッグ実行すれば設定したブレークポイントでブレークすることも可能です。 var_dump() によるプリントデバッグも手軽なのですが、実行途中の変数情報を一覧できたほうがもっと効率よくテストを書くことが出来るのでとてもおすすめです。 PHP_CodeSnifferを使ってコーディングスタイルを適用する コーディングスタイル違反はCIで指摘するよう設定されていますが、コミット前に修正できると指摘されなくなり、開発しやすくなります。 (本当はコミット時に自動適用される設定を紹介したかったのですが、やってみると、コミット 後 のソースに反映されてしまったので、IDEとの連携設定だけ紹介します) 1. phpcs , phpcbf のパスを設定する 「Preferences」を開き、 Languages & Frameworks > PHP > Test Frameworks > Quality Tools を開く Configuration: 右側の ... ボタンをクリック PHP Code Sniffer path: で /path/to/your/project/vendor/bin/phpcs を入力 PHP Code beautifier and Fixer Settings - Path to phpcbf: で /path/to/your/project/vendor/bin/phpcbf を入力 OK ボタンを押して、「Preferences」を閉じる Code Snifferダイアログ 2. コーディングスタイルルールを選択する 「Preferences」を開き、 Editor > Inspections を選択 PHP Code Sniffer validation にチェックを付ける Coding standard: の右側の更新ボタンをクリックすると、リストが更新されるので、 PSR2 を選択 Editor > Inspections 以上で設定完了です。この状態で以下のコードのコーディングスタイルを修正してみます。 <?php // src/Sample.php class Sample { public function test () : void { if ( $ _SERVER [ 'HTTPS' ] === 'on' ) { header ( "Location: https:// { $ _SERVER [ 'HTTP_HOST' ]} " ) ; } } } メニューバーから Code > Code Cleanup... を選ぶと、以下のように変更されます。 <?php // src/Sample.php class Sample { public function test () : void { if ( $ _SERVER [ 'HTTPS' ] === 'on' ) { header ( "Location: https:// { $ _SERVER [ 'HTTP_HOST' ]} " ) ; } } } EditorConfig設定を追加してインデントを自動調整する .editorconfig ファイルを用意しておくと、エディタのインデント設定を無視してそれに従ってくれます。 .editorconfig ; .editorconfig root = true [*] end_of_line = lf insert_final_newline = true [*.php] charset = utf- 8 indent_style = space indent_size = 4 trim_trailing_whitespace = true PHPファイルを保存すると、行末尾のスペースを削除したり、最終行末尾に改行が挿入されるのがわかります。 自動化されていないとバラバラになりがちなので便利です。 以前のバージョンでは、プラグインをインストールする必要がありましたが、2019.2でバンドルされるようになったので、手間が減りました。 設定ドキュメントを書く 上記で紹介したように、PhpStormに限定されないようなDocker環境/PHPUnit/PHP_CodeSniffer などの設定ファイルはリポジトリで共有していますが、PhpStormの設定については管理してないので、社内情報共有ツール(Kibela)にドキュメントを書いて共有しています。例えば以下のようなドキュメントがあります。 PHPプロジェクト向けIDE PhpStorm 推奨設定 PHPUnit と IDE(PhpStorm) を連携させて、PHPアプリ開発を楽にしよう PhpStorm おすすめプラグイン PhpStorm + Xdebug (Remote Debug) CLI編 プロジェクトの .idea ディレクトリの特定のファイルをリポジトリに含めれば、もっと環境構築をスムーズにできそうですが、PhpStormにロックインさせすぎるのもどうかな、という気持ちがあり、やっていません。スクリーンショット付きで説明したような手順についてはドキュメントで共有しています。 まとめ PhpStorm で開発がしやすくなるようDocker環境、デバッグ、テストの設定を用意したり、情報共有ツールで、PhpStormの設定ドキュメントを共有する話を紹介しました。
アバター
こんにちは! BASE BANK株式会社 Dev Divisionでソフトウェアエンジニアをやっている東口( @hgsgtk )です。先日、7月24日〜7月27日にアメリカ・サンディエゴで開催された GopherCon 2019 に参加してきました。初めてのアメリカ、初めての国際カンファレンスで、初めての英語でのLightning Talkをしてきました。当日の会場の様子も含めてGopherCon 2019の参加レポートをします!参加した結果、やっておいてよかったこと・やっておいたほうが良かったことといった反省点などもまとめます。 GopherCon 2019とは GopherCon 2019とは、プログラミング言語Go関連で世界最大級の国際カンファレンスです。今年は6年目となり、世界中から1800名弱のGopherが参加したようです。7月24日から27日にかけて4日間開催されました。 BASEでは、カンファレンスへの登壇や参加といったメンバーのコミュニティ貢献活動を積極的に支援しており、今回のGopherConにも業務として参加してきました。 www.gophercon.com 会場は、 Marriott Marquis San Diego Marina というアメリカ・サンディエゴにあるリゾートホテルでした。サンディエゴ国際空港から車で15分ほどの距離にあり立地的にも便利な場所にあります。 サンディエゴ国際空港より 会場のホテルはGopherCon一色に染まっていて、エントランスに入ると Welcome Gophers! とGopherCon参加者を迎えてくれます。 Welcome Gophers! 会場のホテルに泊まったのですがホテルのルームキーもGopher君が描かれています。 Gopherなホテルルームキー ホテルを出るとすぐ海岸なので、すこし散歩するだけで西海岸のきれいな夕焼けを見ることができます。 会場ホテルから見える西海岸の夕焼け 1800名弱が参加しているということで、世界中から集ったGoエンジニアがメイン会場を埋め尽くします。 メイン会場の様子 スケールが大きいカンファレンスで25日のWelcome Partyでは、 USS Midway Museum という実際に使われていた空母ミッドウェイという航空母艦を博物館にした観光名所を貸し切ってパーティが開催されました。 船上でのWelcome Party Lightning Talkでの発表 今回のGopherConでは、募集されていたCFPにうち、25分のKeynote style・7分のLightning Talkの2種類にプロポーザルを提出して、 Building API Server-side architecture for beginners というタイトルのプロポーザルが採択され発表しました。プロポーザルの内容自体については以下のブログで詳細について書いたので興味ありましたらそちらもご覧ください。 basebook.binc.jp GopherConは最終日(7/27)に10時から16時まで一日かけて約30名のスピーカーがLightning Talkに登壇しました。私は朝一の2番目の順番で発表しました。 LT登壇中 発表した内容は次のスライドでSpeakerDeckに公開しています。Goプロジェクトのサーバーサイドアーキテクチャを構築する考え方についてまとめたものです。特にGoを業務で採用し始めることを決断した"Beginners"な開発チームがどういうアプローチで取り組むかという視点で話を構成しています。 今回が私にとっては、初めての海外でのカンファレンス登壇で、初めての母国語ではない英語での発表でした。準備したこと・当日の発表について良かったこと・改善ポイントをまとめることは、きっと次同じようなチャレンジをされたい方に有益かなと思うので、ここで整理してみます。 CFPへのプロポーザルを振り返る 今回、Lightning Talkに提出したプロポーザルは以下の3つでした。 Building API Server-side architecture for beginner <- 発表 Design considerations for container-based Go applications Implementation example of OAuth 2.0 request handler with ensuring testability この3つのプロポーザルのうち最初3つとも採択いただきました。ただし、1人1トークということで運営の方より選んでいただき今回の発表内容になりました。 今回のプロポーザル提出を振り返って「良かったこと」・「やっておいたほうがよかったこと」は次のようなことです。 良かったこと Keynote(25min)にもプロポーザルを提出したこと 初めての国際カンファレンスで参加すること自体初めてな私にとって、KeynoteのCFPにプロポーザルを提出して英語で25分話すなど正気の沙汰ではないえげつない一歩でした。それができるほどのレベルの内容じゃないなとも思いました。 ただ、普段のカンファレンスでもそうですが、トークするに足る内容かどうかは採択していただく方々が決めることです。そう考えると、とにかく出してみることにしました。結果的にはKeynoteのCFPでは採択されなかったのですが、よりハードルが高いCFPに対してすでにプロポーザルを出していたので、Lightning Talkには大胆な心でプロポーザルを出せました。 国内で話した実績のある内容 国内カンファレンスのCFPに対しては、今まで話したことがない新規の内容について話すように心に決めているのですが、英語でトークすること自体がチャレンジなので、GopherCon 2019に限っては国内で話した内容を翻訳する形でプロポーザルを作成しました。 これにより、すでに話したことがある分、トークの内容の概要・詳細・構成についてプロポーザルの本文に込めることができました。また、いくつかやってきた過去のトークがあるので、何本か数を出すことができました。 やっておいたほうがよかったこと 締切に余裕を持った早期のプロポーザル提出 今回のプロポーザル提出は、いろいろ他のカンファレンスの発表準備をしているうちにギリギリの提出になってしまいました。ただ、GopherCon2019では早い段階で提出されたプロポーザルに対しては運営からのフィードバックをもらえたようです。たとえば、今回Tutorial style(45min)でスピーカーをされた、 @monochromegane さんは、早期にプロポーザルを提出したことから、運営からのフィードバックをもらいよりプロポーザルの内容・形式をブラッシュアップできたとおっしゃっていました。運営からのフィードバックをもらえるカンファレンスではしっかり早期に出したいなと思います(実際、 Go Conference'19 Summer in Fukuoka では、運営の方からのフィードバックでプロポーザルを見直すことができ非常によい体験でした)。 発表を振り返る これまで、色々なカンファレンス・イベントで発表してきたのですが、正直な話今回が過去最高に練習しました。実際に次のようなステップで練習を進めました。 発表資料作成 社内発表練習 現地発表練習 発表資料作成 発表資料作成にあたり工夫したことは「話す言葉をスライドに含める」という点です。一方で反省点としては、「スピード感を入れようとしない方がいい」という点です。 話す言葉をスライドに含める 発表資料の作成にあたっては、なるべく話すことをスライドに含めるようにしました。たとえば、母国語でのトークでは流れの中で口頭で補足するような言葉もスライドに入れました。 実際、現地の他の方の発表では、スライドは少なめで1枚のスライドで口頭補足を多く行う発表資料の方が多いです。英語での説明に苦がない方であればこのような工夫はいらないかもしれませんが、英語でのスピーチに不安がある場合には個人的には安心感がありました(いずれこういう工夫をしなくてよくなるように頑張りたい・・・!)。 スピード感を入れようとしない方がいい 一方で反省点として、Lightning Talkだしなとおもいスライド多めな構成にしたことが裏目に出ました。国内カンファレンスでLightning Talkする際はぎゅっと5分で詰め込んでスピードで駆け抜けるタイプの構成でやってしまうのですが、それは母国語だから(ぎりぎり)許されることだと感じました。 母国語じゃない不慣れな英語でやるのは今回の経験上、私はあまりおすすめできません(そもそもそういうスタイルがどうなんだみたいなツッコミもありますよね、過去の聴講者の方々すいません・・・!)。 不慣れな言語を早口で話すと聞き取りづらいですよね。普段、ネイティブの方が話してるのを聞いたときに感じる「話すの早いなぁ」と感じているあの速度で話そうとすると、聞き取りづらくなってしまいます。外国の方が片言の日本語でめっちゃ早口で話してきたらどうだろうかと想像していただくとガッテン行くかもしれません。 実際、一つ現地の方から頂いた感想で「日本人は英語を話すのが早い」というフィードバックでした。自分の想像している速度の0.75倍速くらいで話して、文節の区切りで話も区切るくらいがちょうどいいんだなと実感しました。 言い訳をすると、ゆっくり話すことは意識していました。しかし、意識していても緊張したら早口になってしまうのが人間というもの。その上で資料のスタイルがスピードトーク型だと、緊張との相乗効果が生まれて早くなってしまいます。 ゆっくり話す前提でトーク内容のボリューム・資料構成を考えると丁度いいスピードになるだろうと思います。 社内発表練習 資料が作成できたら発表練習を社内でやりました。普段のカンファレンス発表から練習に付き合っていただいている @nazonohito51 さんと、英語が得意なインターンでいらっしゃっていた 顧さん に2回ほど時間をもらい練習しました。 不自然な英語や発音・話すスピードなどについてフィードバックをいただき改善しました。 現地発表練習 現地サンディエゴに到着してから、日本人で発表する @monochromegane さん・ @hajimehoshi さん・私の3人と、 @go_sagawa さん・ @tenntenn さんでホテルの一室で発表練習をしました。現地で一回Gopherたちの前で発表しておいたことは「当日もなんとかなりそうだ」という安心感になりすごくよかったです(お付き合いいただいたみなさんありがとうございました!)。 のちに発表者全員の発表を終えたあとに記念撮影しました。 左: @hajimehoshiさん 中: @monochromeganeさん 右: @hgsgtk 初めての海外カンファレンス参加を振り返る 良かったこと Gophers slackのGopherCon参加者チャネル そもそもGopherCon 2019に参加してみたい・登壇してみたいと思ったときに、これまで参加したことがある人・登壇したことがある人が物理的に身近にはいませんでした。そんな迷いを雑にtwitterでつぶやいたところ、 @tenntenn さんがGopherCon 2019に参加しようか検討している人が集まるslackチャネルを作っていただきました。 Gophers Slackに gophercon-san-19-ja というチャンネルを作りました! — tenntennʕ ◔ϖ◔ʔ ==Go (@tenntenn) January 10, 2019 このチャネルで参考になる過去採択された方のプロポーザルの内容を共有いただいたり、非常に参考になりました。また、会社の中では一人で参加するわけで不安があったのですが、同じ日本から参加される方とこのチャネルを通じて事前につながっておけるのに非常に心理的な安心感がありました。 海外で登壇する経験 国際カンファレンスで登壇することは、単純に憧れていた一つの目標だったので良かったです。 現地で良かったことしては、会場のエンジニアと話すときに「Lightning Talkでこういうこと話す予定なの」みたいな切り口で会話のネタとして使えました。 また、Lightning Talkをしたことがある方ならイメージ付きやすいと思うのですが 、Lightning Talkの始まる直前ってスピーカー同士で待ってる間待機場所で話したりすることがありますよね。GopherConでも同様に自分の前後のスピーカーたちと話す時間になり結構楽しい時間になりました。 毎日参加ブログを公開して振り返る カンファレンスで現地にいる間、毎日その日の内容について参加ブログを書いていました。 GopherCon2019 参戦記 DAY1 (7/24) GopherCon2019 参戦記 DAY2 (7/25) GopherCon2019 参戦記 DAY3 (7/26) GopherCon2019 参戦記 DAY FINAL (7/27) これは、その日を振り返ってわからないことをまとめたりとか、その日の反省点を言語化して翌日以降の振る舞い方を考えるいい時間になりました。たとえば、2日目に英語力で躊躇してコミュニケーションが取れなかったことを反省して、3日目はとにかくメチャクチャな英語でいいから話すことを心がけるようにしました。 やっておいたほうがいいこと 時差ボケを矯正する一日をおいたほうが良い 今回の会場であるサンディエゴと日本は時差にして16時間あります。私は、カンファレンス中時差ボケで睡眠時間が非常に少なくなり、早朝に前日の参加速報ブログを書くといった生活になってしまいました。一方で、国際カンファレンス遠征に慣れてらっしゃる方々は前々日入りして一日時差を矯正する時間をとっていました。一日英語漬けで技術トークを聞いて会場のエンジニアと交流するのはそれなりに体力を要するので、時差ボケ問題は早めに解消しておくのがカンファレンスでしっかり学びを得るためによいでしょう。 話のきっかけを用意しておく 日本のカンファレンスと大きく異なる点として、参加者同士のコミュニケーションが多いです。 参加者は、日本のカンファレンスのようにTwitter実況するといったことはほとんど無く、直接現地のエンジニア同士のコミュニケーション・ネットワーキングに時間を使っていました。これは、普段のカンファレンスで人見知りでコミュニケーションが苦手な私にとっては、結構衝撃をうけたことでした。 コミュニケーションしていくことにしっかり向き合おうとすると、英語力が云々はとりあえずなんでもいいから話しかければいいとして、その「なんでもいいから」の話のきっかけが思いつかないのが、人見知りが人見知りしている所以のところですよね。 「どのトークが面白かった?」とか「普段はどういうサービスでGo使ってるの?」とか話のきっかけになるような質問を英文セットで考えておくと良いと思います。 最後に 今回、GopherCon 2019に参加して、特にLightning Talkをした経験の振り返りをしました。自分が繋がりを持てると感じられる世界が広がった、そんな感覚を今回のカンファレンスで持てました。行くまでは不安がとても大きかったのですが、終わってみたら「また行きたい!」とそう思える経験になっています。 海外のカンファレンスに参加してみたい・何かしら発表したいと目論んでる方々にとって、少しでも後押しになる情報になることを願います。 また、きっと開催されるであろう GopherCon 2020 にプロポーザルを超自信を持って出せる知見を積み重ねられるように、これからも精進します。では、また、次のGopherConでお会いしましょう!
アバター
こんにちは。UIデザイナーの野村( @nomjic )です。 世のUIデザイナーの皆様は、デザインツールには何を使ってますか?私はSketchとFigmaを行き来して使ってますが、割とFigma推しです。ノンデザイナーでも割とすんなり使える優れものです。 先日Figmaのプラグイン機能がリリースされましたね。この記事書いてる時点でプラグイン数は100近くあり、この先便利機能がガンガン増えてくものと思われます。 いろいろ触って知っておきたいぞ!ということでBDI(※)でチームの数名とプラグイン触ってみることにしました。 ※ BASEのデザインチームでは、第2第4金曜にBDI Night (BASE Design Inspiration Night) を開催しています。洒落た名前つけてますけどいわゆる社内勉強会です。 (集まってくれたチームの皆さん) 30分ばかりで各々プラグインを触ってみて、用意していたスプレッドシートに簡単なレポートを書いていきます。 (こんな感じでキャプチャと2〜3行の解説を載っけていきます) 17個のプラグインを試せました。以下、特に便利そうだと感じた5個をピックアップしてご紹介します。 特選「これ便利」5件 [その1:Autoflow] site link 1クリックで2つのFrameを線で結んでくれます。シンプルゆえにとても便利。ノンデザイナーがFigma使う時などに便利そうですね。 その2:Charts site link 5種のグラフを生成できます。 色変更、フォントサイズ変更可能です。 生成するグラフのサイズの指定ができないのがちょっと不満... グラフは作ると手間だしサンプルも見つけづらいので、これはとても便利ですね。 その3:Color Contrast Checker site link 背景とテキストのコントラストチェックしてくれます。 それだけなら目新しくないのですが、「コントラストがNGかOKか」を確認しながら色調整が行えるようになってるのが、痒いところに手が届いてる感あっていいですね。 その4:Figmotion site link モーションアニメを作成できます。 レイヤー単位でのkeyframeを打てて、カスタムでイージングを設定できるので、簡単にアニメーションを書けます。json/cssへの書き出しもできます。 gifやmp4にもできますね。(が、書き出せたことが少々わかりづらい...。) その5:Nisa Text Splitter site link テキストボックスで入力した文章を、1行のテキストにばらしてくれます。 テキストボックス内の文章を、A→Zに並び替えしてくれます。 我々的にはベストヒットなプラグインでした。 すごい地味だけどすごく良い。スプレッドシートから文字列を持ってきた時とか、リストUIの文字を一つの大きなテキストボックスで組んだ時とか、とても便利ですね。素晴らしい一品。 その他、触ってみたプラグインたち せっかくなので触ったプラグインのキャプチャと一言説明を以下に全部掲載します。 ざっと流し見しとくと今後のFigma作業が捗るのではないでしょうか。 Color Palettes site link 画像から5つ色を抜き出します。 Color Blind site link 色覚障害者からの見え方をシミュレートします。 写真に対しては無効です。 Chroma site link 選択したオブジェクトのfill色とオブジェクト名からカラースタイルを生成します。 Content Reel site link Sketchの「Data」機能と同じで、用意されたAssetから要素を挿入できます。 テキスト 顔写真 アイコン など。 Border site link Frameに線をつけます。 オブジェクトには無効なのでご注意。 Find & Focus site link 文字列の検索と置換です。 以前はChrome拡張として提供されていた機能がプラグインとして実装されたようです。 テキストオブジェクトだけでなくレイヤー名にも有効ですね。 Google sheets sync site link Google sheets上のテキストデータとFigmaファイル上のテキストオブジェクトを同期させます。 文言管理に便利なのですが、Google sheetsがWeb公開されていないと使えないので業務ではちょっと扱いづらくもあります。 Iconify site link アイコンのライブラリを開いてアイコンを挿入します。 Super Tidy site link 選択したFrameを、 等間隔に配置できます。 グリッド状に1クリックで配置できます。 名前を一括で連番にできます。 Table Generator site link 表組みを生成します。cols/columnsとdataを入れるだけでサクッと作れる便利プラグインです。 Unsplash site link フォトライブラリから画像をもってきます。 カテゴリ内の画像をランダムに選ばせるか、キーワード検索で抽出した任意の画像を選んで挿入することができます。 Viewports site link デバイスに沿ったviewportサイズでFrameを切り替えてくれます。デバイスのシェア率が書いてあったりもするのですが... 使い道がイマイチ思い浮かばず、でした。 以上、「Figmaのプラグインを色々触ってみようの会」のご報告でした。 世のUIデザイナーのお役に立てたなら幸いです。
アバター
UIデザイナーの野村( @nomjic )と申します。 今回はフレームワークの話をしたいと思います。と言ってもRailsとかVueとかの開発フレームワークでなくて思考フレームワークです。 そうですデザイン思考です。 デザイン思考フレームワークを体験する2時間ワークショップを社内で行ったのでその様子をお伝えします。 まず、デザイン思考とは何なのか Wikipedia上では以下のように書かれています。 デザイン思考(でざいんしこう、英: Design thinking)とは、デザイナーがデザインを行う過程で用いる特有の認知的活動を指す言葉である よくわからないですね。 本読んだりWeb記事読んだりすると色々と書かれているのですが、コンテクストによって解釈は様々で、調べれば調べるほど混乱してしまいます。 私個人としては、 デザイナーの思考・行動パターンの中の、汎用的に適用しやすい部分を切り出したもの をデザイン思考と呼んでるのだと解釈してます。 デザイン思考はビジネスに限らず日常生活やレジャーの中でも役立つものなので、万人が知ってて損はないものだと思ってます。かといって万能って訳でもないですが。 そんなデザイン思考を体験してみませんか?と社内Slackで声かけたところ、そこそこ人が集まったので、ワークショップを実施した次第です。 ワークショップ風景 ワークショッププラン 参考にしたワークショップ 2018年夏に某所で開催された コペンハーゲン式デザイン思考を学ぶ!1dayワークショップ で実践されていたプロセス(図参照)を下敷きにして、2時間程度の尺に収まるようプランしました。 図: 参考にさせていただいた1dayワークショップでのプロセス このプロセスの後半あたりの、 CO-CREATION まで体験できることを目標にプランを立てました。 全体の流れ タイムスケジュールは以下の通り。 アサンプションマッピング(連想ワード書き出し):8分 模擬ユーザインタビュー Round1:8分 模擬ユーザインタビュー Round2:8分 インタビュー分析(課題抽出):16分 問い(仮説と"How Might We 〜 ?")の作成:10分   --- 休憩5分 --- アイディエーションRound1:10分 アイディエーションRound2:10分 ソリューション検討:10分 シェアと振り返り:5分 てんこもりですね。 テーマ 「旅行の計画立ての体験を向上するプロダクトを作る」 をテーマに掲げました。 シンプルに「旅行」でも良かったのですが、短い時間のワークショップなのでテーマは狭めた方が良さそうと考え、このようなテーマに相成りました。 人数とか場所とか 12名のメンバーに集まってもらえたので、4人ずつの3チームに分けました。 社内の打ち合わせスペースで、大きいテーブル1つと小さい卓を1つ、それとホワイトボード3枚を使って実施しました。 ワークショップ内容(実施したこと・様子) 連想ワード書き出し まずは頭の体操がてら、「旅行計画」から連想する言葉をひたすら書き出してみます。 各々の頭の中の情報の可視化と共有をざっくり行うことを意図してます。 模擬ユーザインタビュー 各チーム内で、各々の「旅行計画にまつわる体験」を掘り下げるインタビューを行ってもらいます。 以下のような質問例を挙げはしましたが、基本自由に聞きたいことを聞いてもらいました。 過去に、どんな風に旅行を計画しました? その中で、好ましく感じた体験は? 良くなかった体験は? インタビューに不慣れなためか最初はスムーズにコミュニケーションが進まなかったチームも見受けられましたが、一定程度は体験と価値観の共有ができたようです。 このあたりは、チームビルディングの観点でも組織の活動に貢献できると考えています。 ここで得た共通認識を踏まえて、以降の課題発見&ソリューションのフェーズへと進んでいきます。 仮説立て(課題発見) インタビューで引き出した種々の体験を踏まえ、「良い旅行計画とは何か?」「悪い旅行計画とは何か?」についての仮説を立ててもらいます。この段階では複数の仮説を立てて、付箋に書いていきます。 うん、お腹減らさない、大事ですね。大事大事。 問いを作る 仮説をもとに、「いかにしてXXXを排除し、YYYをより良くするか」という問いを作ります。 (XXXには「悪い体験」、YYYには「良い体験」が入ります。) 作成された問いの一例 「いかにして、計画を固く定めず、旅行中のライブ感を大切にしてアクシデントを楽しむか」 いわゆるHMW(How Might We... ?)というやつなのですが、ここがなかなか慣れないと難しいところで、「問い」とは少し違う形になってしまったチームもありました。 とはいえ、次ステップでアイデア出しするための情報は出揃ったので、進めます。 アイデア出し 作成した「問い」に回答する形で、アイデア出しをします。 クレイジー8方式 で実施しました。 もう少しグラフィカルにアイデアを出してくれることを期待したのですが、付箋が小さすぎて描きづらかったかな、と反省。 「デザイナーはビジュアライズ必須」とか縛りを与えても良かったのかもしれないです。 ATI(圧倒的当事者意識) に強烈な思い入れを持つチームがあったりもしました。 こういうキャッチーなワードが取り上げられ、不思議な一体感が生じるのもワークショップの醍醐味かもしれません。 ソリューション提案作成 アイデアの取捨選択・統合をして1つのソリューションに整理します。 整理のためのヒントとして、以下のようなフォーマットを提示しました。 提案名・提案概要 想定ユーザ ユーザにもたらす価値 他サービスに対しての位置付け マネタイズ そして、複数のソリューション提案が作成されました。以下、一例。 提案名:いきなりトリップ 予算感とNG項目(アレルギー等)だけ伝えて、あとのプランは全て任せられるサービス。プランは当日、現地についてから伝えられるので、バラエティ番組の企画のような無茶振りを楽しめる。 割とどのチームもまとまった提案になりました。アイデア出しの途中で 「過酷な試練を与えて、それに耐え抜かないと旅行に参加できないシステムを...」 とか聞こえて、どんなソリューションに昇華するのか楽しみにしてたのですが、提案には採用されなかったようです。 プレゼンテーション 各チームよりアイデアのプレゼン&シェアをしてもらいました。 そして片付け・解散と相成りました。お疲れ様でした。 今後の予定 単発で終わらせず、継続していきたいと思っています。 部活的なものにするとか、新人研修プログラムに組み込むとか... 個人的には、社外の人や「BASE」のユーザーも参加できるオープンな場にして、ユーザーリサーチを兼ねたりできたら良いなあ、なんていう野望もあります。 他の会社さんでもやってみたいなと思っていますので、ご興味のある方がいらっしゃいましたら @nomjic にDMいただけると嬉しいです。 以上、お読みいただきありがとうございました!参加してくれた12名はホントホントありがとうございました!
アバター
Product Dev Divisionの川島( @nazonohito51 )です。 BASEでは創業当時よりCakePHPによるWebアプリケーション開発を行っており、同時にそのテストも充実させてきました。ですがその過程で気づくのは、CakePHP標準の仕組みだけではテストを増やせば増やすほどテストデータの管理が難しくなり、テストをメンテナンスするのが困難になる問題でした。きちんと長期的にサービスを良くしてくれる資産価値の高いテストが書けるように、今回はその問題と向き合い、解決するために @sizuhiko さんの開発された Fabricate というライブラリを導入したお話を書かせていただこうかと思います。 BASEの直面した課題 CakePHP2のFixtureという仕組み 詳細は 公式ページ を参照していただきたいのですが、CakePHP2にはテストデータを作るためのFixtureという仕組みがあります。おおよそのWebフレームワークにもあるとは思いますが、事前にデータベースに対してテストに必要なテストデータを入れておくための仕組みです。 このFixture、テストの数が少ないうちは良いのですが、テストの数が増えてくると扱いが難しくなる面が出てきます。BASE内部で発生した問題を挙げますと、まずテストメソッド毎に個別のテストデータを用意することがFixtureだと大変なので、複数のテストメソッドで同じFixtureを共有していましたが、後の改修案件の際にテストデータを更新するとたくさんテストが失敗していました。どこがいじって良くて、どこがいじっちゃだめなのか、テストからそれを読み解こうと思っても各テストメソッドにとって本当に必要なカラムがどれなのかを理解することが困難でもはや手を出せません。ちょっとした改修でも本来なら全然関係ない箇所のテストの修正まで派生し、テストのメンテナンスに大きなコストがかかっていました。 もちろんFixtureという仕組みの問題というより、BASEの運用の問題もあったりしますが、本質的にFixtureはテストのスケールに耐えられる仕組みではないと捉えています。正確性には欠けますが、社内にFixtureの問題を理解していただくために簡易的に用意した図が以下となります。 CakePHP初期 CakePHP中期 CakePHP後期 xUTPから見る現状の問題整理 これらは具体的にどんな問題なのか、そして解決するにはどの方向へ向かうべきなのかを理解するにあたり、 xUnit Test Patterns の掲げるテスト原則を参考にしますと、 Keep Tests Independent(テストを独立させよ) と Communicate Intent(意図を明確にせよ) に違反している状況と捉えています。 Keep Tests Independent 原則の意味 テストが相互依存的あるいは順序依存的である場合に、テストが我々に提供するフィードバックが信用できなくなってしまうため独立させるべき、という原則 若干の読み替えはありますが、テストデータを含めてテストメソッド間の依存を取り払うべきとも解釈できます BASEにおける原則違反 複数のテストメソッドで同じFixtureを共有しているため、テストデータを介してテストメソッド同士が相互依存的になってしまっている 後にテストデータを更新すると多くのテストが壊れてしまい、変更しづらい・メンテナンスしづらいテストになってしまっている ※テストデータを共有すること自体が悪いことではないのだが、BASEではメンテナンスに支障をきたすほどの共有が行われている Communicate Intent 原則の意味 意図が明確なテストは理解することとメンテナンスすることが容易である、という目的で掲げられている原則 BASEにおける原則違反 そのテストメソッドが本当に必要としているテストデータをFixtureから読み解きづらいため、何故テストが成功/失敗しているのかその因果関係を読み解くことが出来ない 理解することが出来ないため、後から改修することも難しい 以上の原則から照らし合わせて、現状のBASEはテストを作ったは良いものの、後から理解し修正することが容易ではない、資産価値の低いテストコードを量産してしまっている状況であると言えます。(資産価値の低いテストコードとは、テストを通して開発コストを下げたかったはずが、逆にメンテナンスするコストが大きいようなテストコードを指しています)これらの問題を解決するには、各テストが独立しやすく、かつ可読性が高くできる新しい仕組みが必要であると考えました。そしてそれは後述のFabricateというライブラリが最適であると考えました。 Fabricateによる解決 Fabricateとはなにかを身も蓋もなく言ってしまえば「Railsの FactoryBot みたいなやつ」と言ってしまったほうが多くの人に伝わりやすいかもしれません。概要を書くなら「テストメソッドごとの差分をオーバーライドしながら実テストデータを生成する」ライブラリです。 Laravelにも同様の仕組み があります。 Usage まずはFabricateの1テーブル辺りの定義を書きます。これは実テストデータを作るためのテンプレートのようなものであり、コレ自体は実テストデータではありません。あらかじめ属性のセットないしはその生成方法を定義しておくと、これをベースにFabricateはテストデータを作成してくれます。この作業は必須ではありませんが、なるべくリアルなテストデータを使いたいという理由からBASEでは全テーブル分の定義を書いています。 <?php class FabricateUserFixture extends CakeTestFixture { public $ import = 'User' ; public function init () { parent :: init () ; Fabricate :: define ([ 'User' , 'class' => 'User' ] , function ( $ data , $ world ) { $ now = new DateTimeImmutable () ; return [ 'id' => $ world -> sequence ( 'user_id' ) , 'login_id' => $ world -> sequence ( 'login_id' , function ( $ i ) { return 'loginid' . $ i ; }) , 'last_name' => $ world -> faker () -> lastName, 'first_name' => $ world -> faker () -> firstName, 'state' => 0 , 'created' => $ now -> format ( 'Y-m-d H:i:s' ) , 'modified' => $ now -> format ( 'Y-m-d H:i:s' ) ] ; }) ; } } そしてテストメソッド内では以下のようにしてテストデータを作成します。 <?php class SomeClassTest extends CakeTestCase { public $ fixtures = [ 'app.Fabricate/fabricate_user' , ] ; public function testMethod1 () { Fabricate :: create ( 'User' ) ; $ this -> assertSame ( 1 , ClassRegistry :: init ( 'User' ) -> find ( 'count' ) ; ) ; } } 上記のうち Fabricate::create('user'); がFabricateによるテストデータ生成を行っている箇所となります。このステートメントでFabricateが事前に定義したテンプレートを元にテストデータを作成してデータベースに保存してくれています。これはサンプルなので特に意味のないテストではありますが、その後のアサーションでデータが1件保存されていることを確認しています。ちなみに実際のデータベースを覗くと以下のようなデータが保存されており、テンプレートの定義に沿ったデータが保存されていることが分かります。 mysql> select * from users; +----+---------------+-----------+------------+-------+---------------------+---------------------+ | id | login_id | last_name | first_name | state | created | modified | +----+---------------+-----------+------------+-------+---------------------+---------------------+ | 1 | loginid1 | 鈴木 | 裕太 | 0 | 2019-07-23 11:43:55 | 2019-07-23 11:43:55 | +----+---------------+-----------+------------+-------+---------------------+---------------------+ 1 row in set (0.00 sec) Fabricateで独立したデータを作成する さて前述の課題のうち、テストが密結合してしまっている課題をテストメソッド個別のテストデータを作ることで解消してみます。もちろんFixtureでもやろうと思えば出来なくもないのですが、Fabricateだととてもかんたんに実現できるという例になります。 <?php class SomeClassTest extends CakeTestCase { public $ fixtures = [ 'app.Fabricate/fabricate_user' , ] ; public function testMethod1 () { Fabricate :: create ( 'User' , [ 'state' => '0' ]) ; $ this -> assertSame ( '0' , ClassRegistry :: init ( 'User' ) -> find ( 'first' )[ 'User' ][ 'state' ]) ; } public function testMethod2 () { Fabricate :: create ( 'User' , [ 'state' => '1' ]) ; $ this -> assertSame ( '1' , ClassRegistry :: init ( 'User' ) -> find ( 'first' )[ 'User' ][ 'state' ]) ; } } 上記の例の場合、2つのテストメソッドで Fabricate::create() が呼ばれていますが、その第2引数に違いがあります。Fabricateは生成したいテストデータのうち、特定のカラムの値をオーバーライドすることでテストメソッド上から明示的に指定することが出来ます。上記の例の場合はtestMethod1では 'state' カラムの値を0として生成しており、testMethod2では1として生成しています。指定していないカラムの値はテンプレートの定義に従って作成されます。 このようにFabricateではテストメソッド個別に必要なテストデータを柔軟に用意することが出来ます。Fixtureで用意するテストデータは(多くの場合)固定値であるため柔軟に用意することは難しかったのですが、実際のところ各テストメソッドがそのテスト要件として本当に必要なデータはそれぞれ 微妙に 違うことがほとんどです。テストメソッドの数を増やせば増やすほどテスト全体として必要とするテストデータのバリエーションは膨大な数になりますが、Fabricateはそのようなバリエーションの違いをテストメソッド上のオーバーライドによって実現し、柔軟なテストデータの供給を実現しています。 また「必要なカラムだけオーバーライドする」というこの作成方法は後述の可読性にも寄与していると捉えています。 Fabricateで可読性の高いテストメソッドを書く <?php class SomeClassTest extends CakeTestCase { public $ fixtures = [ 'app.Fabricate/fabricate_user' , ] ; public function testMethod3 () { Fabricate :: create ( 'User' , [ 'login_id' => 'testuser' , 'state' => '1' ]) ; $ user = ClassRegistry :: init ( 'User' ) -> find ( 'first' )[ 'User' ] ; $ this -> assertSame ( 'testuser' , $ user [ 'login_id' ]) ; $ this -> assertSame ( '1' , $ user [ 'state' ]) ; } } 上記の例では 'login_id' と 'state' の2つのカラムをオーバーライドしてテストデータを作成しています。そしてこのステートメントは「このテストメソッドではlogin_idとstateが必要であり、その他のカラムの値に関心はない」と読むことが出来ます。仮にこのテストが他のカラムも実は必要としている場合でも(テンプレートの作り方にもよりますが)Fakerによるランダムな値生成により安定したテストとはならないでしょう。 このようにテストデータをオーバーライドで柔軟に用意する仕組みは、同時にそのテストに本当に必要なカラムをすべて明示的に指定することをある程度強制する力があると思っています。(色々な要素が絡むのでこの辺りをハッキリ断言することはとてもとても気後れがあります・・・・・・・・・こういう使い方もある程度に捉えていただけましたら幸いです)そしてそれはテストの可読性を上げ、メンテナンスしやすいテストにする効果があると考えています。 FactoryBotをご存知のかたは「traitで属性の集合に名前つければいちいちテストメソッドで全部指定しなくて良い」といった指摘もきっとあるかと思いますが、もちろんそういったこともBASEでは行っています。ですが今回はFabricateの詳細な機能まで触れる記事ではないので割愛させていただきます。 弊社内の工夫 Fabricate v1はCakePHP2での利用を想定されたライブラリでした。しかしFabricate v2ではフレームワーク非依存を目指し、アダプタを書けばどのフレームワークでも動くことを目指されています。(ただしアダプタはCakePHP3用のもののみが用意されているので、それ以外で動かす場合はアダプタを自作する必要があります)弊社ではこのうちあえてv2を使用しています。 というのも以下の標語が頭をかすめたためです。 テストコードのライフサイクルはフレームワークのライフサイクルよりも長い 要するにフレームワークのバージョンアップ時にアプリケーションの振る舞いが変わっていないことを確認できるようにテストを書いているのに、バージョンアップと同時に動かなくなるようなテストでは本末転倒だという話です。なのでテストコードはフレームワークとは関係なく動かなくてはなりません。そのためにもわざわざCakePHP2用のアダプタを自作して、フレームワーク非依存のFabricate v2を選択しました。 まとめ テスト原則と照らし合わせながら現状の課題を整理し、目指す方向を見据えて弊社ではFabricateを導入しました。Fabricateはまだまだ機能があり、実テストを書く上ではそれらも使いこなさないと実際の運用に耐えるテストは書けないのですが、今回はBASEにおいて導入して感じたメリットを端的にまとめる形でこのぐらいで記事は締めさせていただこうかと思います。 BASEではサービスを成長させながら同時にテストを充実させてきました。そして今度はテストをスケールさせる過程で発生する問題をどう解決するかを考えるフェーズに既にあります。今回はテストデータを供給する部分の問題をFabricateというライブラリの導入によって乗りこえようと試みました。まだ導入したてで効果の程は測りかねますが概ねうまく行っている感触です。
アバター
こんにちは! BASE BANK株式会社 Dev Divisionでソフトウェアエンジニアをやっている東口( @hgsgtk )です!7月13日(土)に福岡で開催された Go Conference'19 Summer in Fukuoka で登壇してきました。登壇内容や当日についてざっとレポートします。 Go Conference'19 Summer in Fukuoka - Go Conference'19 Summer in Fukuoka 登壇内容 Cost-effective Go unit test thinking and practices というタイトルで発表させていただきました。 個人的な観測では、Go界隈はユニットテストを書くことやテスタビリティの良いコードへの意識は強く、すでにユニットテストの技法に関する良資料はたくさんあるのですが、今回は WHY に着目した観点でプロポーザルを出して採択いただきました。 PHP界隈のカンファレンスでも ユニットテストの現場の問題を原則に立ち返って考える など、「ユニットテストを作る設計指針」なるものを考えてきました。しかし、Goでは"Proper error handling, reporting"や"table-driven testing"など公式的に提案しているような基礎的な考え方・技法があるといった特殊な点があったので、ユニットテストの目的自体に立ち返って「 Goのこの考え方・技法にはどのようなメリットが有るか 」というところから抑えた内容としました。 また、現場でGoコードのテストを実践していく中で基礎を忘れてしまうと、 Goが狙っている方向性からずれてしまったり、費用対効果の低い"資産価値の低いテストコード"が生まれてしまう 事があるなと感じていました。なので、実践例を示した上で「ユニットテストの目的」までつながる背景論理を発表内容に投写することを試みました。現場での実践に参考になれば良いなという願いを込めつつ。 業務で使用している方なら一度は触っているであろうものについての解説なので、期待感に答えられたか不安でしたが、twitterや懇親会などでいい反応をいただけました、安堵...。 テストの話よく整理されてて良かった #gocon — songmu (@songmu) July 13, 2019 Go の Unit Test の話を聞いてる。 @hgsgtk さんの理論から積み上げて最適を追求していく姿勢はすごいなぁといつも思ってる #gocon — po3rin 📖 技術書典7 golang.tokyo (@po3rin) July 13, 2019 参加して 今回、福岡でのGo Conferenceは初めての試みのようでしたが、初めてと全く思えない運営の方々のきめ細やかで大変満足感を持ってカンファレンスを終えました。 また、去年からPHPのカンファレンスに出ていくことが多かった私にとっては、お世話になっているPHPerの方々がちらほらいらっしゃる安心感がありました。 PHPerの @hgsgtk さんじゃん #gocon pic.twitter.com/vk0N55GkIz — せいけしろー (@seike460) July 13, 2019 PHPerの @cakephper さんじゃん #gocon pic.twitter.com/oVggjZWe84 — せいけしろー (@seike460) July 13, 2019 スピーカーディナー終了後は、同じく登壇されていて普段から交流のあった @budougumi0617 さん・ @po3rin さんと天神の屋台に繰り出すなど福岡を堪能できた一日になりました! 次は さて、次回繰り出すのは7月24日〜7月27日にアメリカ・サンディエゴで開催される GopherCon です。 Building API Server-side architecture for beginners というタイトルでLTしに行きます。 www.gophercon.com 帰国したら現地レポートブログを公開するのでお楽しみに!
アバター
こんにちは。BASE株式会社 Design Groupに所属しているイシグロです。 普段は主にマークアップを担当しています。 今回、ブログ初投稿ということで、ネットショップ作成サービス「BASE」でショップを運営するにあたり、ショップのデザインに大きく関わる「HTML編集App」と「デザインテーマ」についてお伝えできればと思います。 主に下記の方にお役に立てる情報かと思います。 「BASE」でネットショップ開設を検討していて、ショップのデザイン部分が気になる方 すでに「BASE」でネットショップを開設していて、ショップのデザインをもっと工夫したいという方 「BASE」で開設されたネットショップのページを、HTMLやCSSを用いてオリジナルのデザインを作成される方 オリジナルデザインのネットショップが作りたい!そんなショップオーナーのための「HTML編集App」 せっかくネットショップを作るなら素敵なデザインがいい。そう思ってらっしゃるショップオーナー様は大勢いらっしゃると思います。 でも「BASE」をはじめとするネットショップ作成サービスだと予め用意されたデザインを選ぶだけだったり、 パーツを組み合わせるだけであまり自由にデザインを変更できない。そういうイメージありませんか? まずはこちらのショップ様を御覧ください。 TAWARA HONEY SELECTION ( http://www.honey-selection.com/ )様 こちらは実際に「BASE」をご利用頂いているショップ様で、デザインは完全オリジナルとなっています。 冒頭のアニメーションが可愛いので是非リンクをクリックして実際のショップを御覧いただきたいです。 ※こちらのデザインはBASEオフィシャルパートナーのLANDMARK様が制作されたものです。( https://thebase.in/andbase ) 「BASE」ではネットショップの基本的な運営をするための基本機能とは別に、「 BASE Apps 」という形で様々な追加機能を提供しています。 初心者の方でも簡単に運営できるよう手助けをするようなAppsが多い中、「HTML編集App」はちょっと初心者の方には手を出しづらいAppかもしれません。 HTML編集画面 こちらはショップページのHTML編集をする画面です。Web制作のご経験がある方はお分かりになるかと思いますが、その名の通り「HTML編集App」は独自のHTML、CSS、Javascriptなどを用いてショップ毎にオリジナルデザインのネットショップを作成することを可能にするAppです。 上記のキャプチャ画像は「BASE」の管理画面の「デザイン編集」から「HTML編集」の画面に切り替わった状態のものです。 ここで直接編集することもできますし、お好みのエディタで記述したソースを貼り付けることで反映することも可能です。 「BASE Template」という仕組みでショップの様々な情報を表示 HTML編集エリアには {PageTitle} などの見慣れない記述があるかと思いますが、こちらが「BASE」独自の「 BASE Template 」という仕組みです。 基本的にはHTMLの中にこのBASE Templateのタグを組み込み、ショップや商品の情報などを含むページを構成するパーツをページの必要な箇所で出力します。 タグのには2種類あり、タグ単体で情報を出力する 変数 と、エリアを指定する ブロック があります。 変数 には商品名やショップ名などのいわゆるテキストを単純に表示する小さなものから、お問い合わせフォーム一式をHTMLとしてまとめて出力する大きいものまで様々です。 タグ 説明 {ItemId} 商品のID {ItemTitle} 商品の名前 {ItemPrice} 商品の価格 {ItemProperPrice} 商品のセール価格に対する通常価格 {ItemDiscountRate} 商品の割引率 {ItemStock} 商品の在庫数 {ItemDetail} 商品の説明 ※一部抜粋 ブロック は「ここからここまでは商品詳細ページ」といったエリアを限定する if文 に相当するものと、「登録されてる商品の数だけ繰り返す」といった繰り返しの for文 に相当するものがあります。 タグ 説明 {block:Items} 商品一覧における商品のループ {block:HasItems} 商品がある {block:NoItems} 商品がない {block:HasItemProperPrice} 通常価格がある {block:NoItemProperPrice} 通常価格がない {block:HasItemStock} 商品の在庫がある {block:NoItemStock} 商品の在庫がない ※一部抜粋 これらを駆使し、1ソースの中にショップのすべてのページの構造を記述します。 6~13ページ分(※)のソースを1ソースに記述するのですが、短いテーマで500行、長いテーマで2500行ぐらいになります。 (※BlogAppやカテゴリAppを使うとショップのページ数が増えます) 1ソースで!? とお思いになられるかもしれませんが、AboutページやContactページに表示するコンテンツ部分は、予め用意されたタグ一つで表示できるのでそれ自体は1行で完結します。 ヘッダーやフッターなどのショップ全体で共通なものは1箇所に記述すれば使い回せるので、あとは該当ページをどういうページレイアウトにしたいのかによって、レイアウト用のHTMLタグが必要になるだけです。 (※ 1ソースの全体構成の例 ) CSS、JavaScript、画像ファイルなどはファイルアップローダーを使って外部読み込み HTMLとBASE Templateタグについてご説明してきましたが、Webサイトの構成に欠かせないのがCSS、JavaScriptや様々な画像ファイルです。 CSSやJavaScriptまで1ソースで記述してしまうと更に行数も増え管理が大変です。 そのため「BASE」では外部ファイルとして読み込むファイルはファイルアップローダーをご用意しています。 BASE Developers ファイルアップローダー (※ファイルアップローダーはBASE Developersからショップアカウントでログインすることで使えます) アップローダーでサーバーにアップロードされたファイルは上記 https://example.com/sample.css のように独自のURLが発行されますので、それをソース内でファルパスとして記述することで読み込むことが可能です。 (※例としてexample.comとして改変しているので、本来はもっと長いURLになります。) ここまで分かればテーマが作れる!? 先はまだまだ長く険しいテーマ作成 Web制作のスキルがある方にとっては、ここまで分かればテーマ作れそうと思われるかもしれません。 しかし大変なのはここからで、対応しなければならないAppsの数だけ様々なケースを想定してチェックしなければなりません。 テーマ チェックリスト チェックリストにあるとおり、在庫がある場合、在庫がない場合、商品名が長い場合、短い場合、商品画像が少ない場合、多い場合など様々なケースの組み合わせの表示チェックが必要になります。 また、「英語・外貨対応App」や「販売期間設定App」などもご利用になる場合はさらに大変です。 英語表示になると文字数が増えるので往々にしてデザインが崩れたり、販売期間設定の場合、販売開始前、販売期間中、販売終了後の表示確認もあります。 他にも「BlogApp」、「セールApp」、「カテゴリApp」など、ショップの表示に関わるAppsが多くあり、 大規模ショップで高機能になればなるほどあらゆる想定をしたチェックが必要になります。 また1ソースが故に、必然的にモバイル表示も考慮に入れたレスポンシブデザインにする必要があります。 (※デザイン編集の設定で、モバイル表示のときはBASEのデフォルトテーマを表示するという設定もあります。) BASE Templateを使いこなし作り上げられた「デザインテーマ」 この「HTML編集App」は誰でもご利用いただくことが可能ですが、さすがにHTMLやCSSの知識がないと使いこなすことはすこし難しいかもしれません。 さらに前述の通り何通りものチェックが必要になります。 しかし、ご自身で「HTML編集App」でカスタマイズをせずとも、実は同じBASE Templateの仕組みで制作されたテーマを購入することができます。 BASEデザインマーケット( https://design.thebase.in/ ) ここで販売されているテーマは外部のデザイナーの方々が独自にテーマを作成し、前述のあらゆるケースを想定したBASE社内の審査を経ている完成されたデザインテーマです。 販売金額はテーマ制作者が自由に設定することができ、5,000円から上は1万円を超えるものまで様々。 テーマがショップオーナー様に購入されると、規約に則った配分でテーマ制作者の方に報酬として支払われます。 現在販売されているテーマは40種類以上あり、テーマによっては特定の利用ケースを想定したユニークなものもあります。 例えばこちらの LPshoot はランディングページのようなデザインになっており、商品数がごく少数の場合に適したデザインとなっています。 BASE デザインテーマ購入ページ( https://design.thebase.in/detail/34 ) その他にも大量の商品を扱うことに適しているテーマや、柔らかいデザインで和の雰囲気の商品を扱うことに向いているテーマなど、単純にレイアウトが違うというよりも、様々なジャンルのショップに適したテイストのテーマが作られています。 また、各テーマには「デザインオプション」と呼ばれるテーマ独自の設定項目が用意されていて、直接HTMLを編集しなくても、バナーの表示、特定のエリアのレイアウト変更、独自に作成したページコンテンツの表示なども可能となっています。 このデザインオプションでショップ独自の設定を適応することで、高機能なテーマだと、同じテーマでも全く違うテーマのような魅せ方をすることも可能です。 実際各テーマの購入ページには、そのテーマを利用しているショップ様のページへのリンクがありますので、ぜひいろいろなテーマ、およびショップ様をご覧になってください。 各テーマ、各ショップ様ともに創意工夫にあふれていて、見ていて飽きないかと思います。 デザインテーマのソースをHTML編集Appでカスタマイズして独自テーマに拡張 私が個人的にショップオーナー様にオススメしたいのは、「好みのテーマを購入」し「HTML編集Appでちょっとだけカスタマイズ」です。 あくまでHTMLなどWeb制作に関するスキルをある程度持ち合わせていることが条件ですが、前述の様々なチェックやBASEの審査をクリアしているデザインテーマを元にすれば、ある程度は安心してご自分の好みにカスタマイズすることができるのではないでしょうか? (※一度HTMLを編集すると新機能追加などテーマの自動更新がされなくなります。カスタマイズはあくまで自己責任でお願いします。) 購入したデザインテーマは「HTML編集App」で修正することが可能です。ここの色だけ変えたい、画像サイズを修正したい、このエリアにバナー画像を挿入したい、などちょっとした修正ならば、不具合を起こす可能性もゼロからつくるよりもかなり低くなります。 素敵なデザインのショップがたくさん増えることを願って 「HTML編集App」および「デザインテーマ」にご興味をお持ち頂けましたでしょうか? ご興味のあるショップオーナー様はぜひ「HTML編集App」を触ってみてください。 失敗しても元々のテーマを再度選択すればもとに戻りますのでご安心を。 また、デザインテーマは購入する前にご自分のショップに適用した状態を確認できます。 「BASE」にログインした状態でテーマ購入ボタンの横にある「プレビュー」ボタンを押してください。 プレビュー状態でも様々なデザインオプションを変更したりすることで購入後のイメージができるかと思います。 お気に召しましたら是非ご購入を。 Web制作のご経験のあるクリエイターの方は是非テーマを作成して販売してみませんか? テーマ作成にはショップ開設が必要ですが、ショップ開設は無料ですし、ご心配でしたら「 シークレットECApp 」を使えば作成中のテーマを見られる心配もありません。 ご自分のデザインスキルを活かして副収入を得たいという方、是非どうぞ!
アバター
こんにちは!この度、6/29(土)に開催された PHPカンファレンス福岡2019 にて、BASEがスポンサーとして協賛&2名のメンバーが登壇いたしました!今回は川島( @nazonohito51 )・めもりー( @m3m0r7 )・東口( @hgsgtk )・田中( @tenkoma )の4名より参加レポートをお届けします! 会場レポート みなさん、こんにちは!基盤チームのめもりー ( @m3m0r7 ) です!今回、私は参加者として、PHP カンファレンス福岡に参加してきました! BASE では、カンファレンスへ登壇や参加といったメンバーのコミュニティ貢献活動を積極的に支援しており、今回PHPカンファレンス福岡も業務として参加してきました これが決まったのは、実は先週だったこともあり、ホテルや飛行機などの予約が大変でしたがそれでも無事参加することができました。 ということで会場レポをお送りしたいと思います。 会場レポ 今回弊社はブロンズスポンサーとしてスポンサードさせていただいており、かわいい旗がずらりとしている中に弊社が! 弊社デザイナーがめちゃめちゃかわいく仕上げてくれました!ありがとうございます。 まだ、PHPカンファレンス福岡でしか配布していない BASE BANK のステッカーです! 弊社はブロンズスポンサーとはまた別に、2名のエンジニアが登壇させていただいておりました。 下記に詳しく記載します! 一方、セッションの裏では… セッションの裏では、GMOペパボさんが開催していた、「マネクラからの挑戦状」があり、これは参加しなくては…!ということで参加してきました。 〜 が ? に文字化けしてる! 具体的には2つに分かれて、一つが脆弱性を見つけていくもの、もう一つが既存のコードを短くしていくもので、通称「コードゴルフ」と呼ばれているものです。 私はコードゴルフの方をやっていました。 もともとのコードは下記でした。 詳しくは ペパボさんの GitHub リポジトリ を御覧ください。 それを下記のようにしていきました… 追い打ちをかけるようにスコアを更新しまくっていました。 時間が限られていたのでコードがだいぶ雑ですが、最初の4,855,534 スコアから 75,371 スコアまで減らして、無事優勝しました! そして 10 万円分のクーポンをもらってしまいました。本当にいいんですか?ありがとうございます。 コードゴルフ一位は めもりーさんで、10万円クーポンをお渡ししました。 おめでとうございます!  #hall_lo #phpcofuk #mclolipop pic.twitter.com/ARuYGO4n8k — すねこすり (@sunecosuri) June 29, 2019 ということで、セッションの内容も楽しかったですが、合間の時間も楽しく、とても有意義な1日でした。 ありがとうございました! 余談ですが、アフターハックとしてもっと短くできないかと思い、また桁数を1つ減らす形でスコアを更新して最終的に 7,159 となりました。 @tenkoma さんのコードと組み合わせるともう少し短くなりそうです。 <?php array_multisort ( $ v =$ _GET , $ a = SORT_DESC, $ b = SORT_STRING, array_keys ( $ v ) , $ a , $ b , $ v )?> <!DOCTYPE html> < style > body , html { height : 100 vh; margin : 0 ; background-color : #fff ; color : #465560 ; font-family : Arial , Verdana , Meiryo , sans-serif ; font-feature-settings : "pkna" ; letter-spacing :. 04em ; font-size : 1rem ; text-rendering : optimizeLegibility ; -webkit- font -smoothing: antialiased } body { font-size : 1rem } * { box-sizing : border-box ; background-repeat : no-repeat ; padding : 0 ; margin : 0 } table { width : 100 %; height : 100 % } html { box-sizing : border-box ; -webkit- text-size-adjust : 100 % } td { text-align : center ; height : 50 %; width : 5 % } h1 { font-weight : 400 ; margin : 0 }</ style >< table border = "0" cellspacing = "0" >< tr >< td bgcolor = "#147ecc" >   < td >   < td style = "width:80%" >< table >< tr >< td style = "height:10%;" >   < tr >< td style = "height:80%" >< img src = "https://raw.githubusercontent.com/pepabo/lolipop-mc-codegolf-challenge/master/mc.png" width = "100%" />< br >< h1 > <? = strrev ( array_values ( $ v )[ 2 ] ?? '' )?> </ h1 >< tr >< td style = "height:10%" >   </ table >< td >   < td bgcolor = "#147ecc" >   マネクラからの挑戦状参加レポート by 田中( @tenkoma ) BASE Product Dev Division 基盤グループの田中です。午前中セッションを聴講して、午後はマネクラからの挑戦状(PHPアプリケーション脆弱性修正チャレンジ)に参加していました。 ルールについては pepabo/lolipop-mc-vuln-challenge をご覧ください。 用意されたWebページに脆弱性があるのでそれを直す、という問題が5つ用意されていました。時間内に5問解けたので11,000円分のクーポンをいただきました!(最速で解けた場合豪華なクーポンがあったのですが、残念ながら2位でした) めもりーさんが優勝された コードゴルフ も面白そうだったので、翌日 株式会社Fusic で開催された (非公式)PHP Conference Fukuoka 2019 After Hack!! のネタにしたいな、と思いました。楽しむためにはオンラインで動いているチェッカーが必要なので、イベントを開催された GMOペパボ株式会社 の方にお願いしたところ、翌日も動作してもらえることになりました。 マネクラからの挑戦状で使われたチェックサービスを明日も動かしてもらえることになったので、アフターハックでハックしていきましょう!! #phpconfuk #hall_lo https://t.co/kkkEKB9yY1 — Koji Tanaka (@tenkoma) 2019年6月29日 会場で書き換えて、東京に戻ってからも書き換えた結果、PNG画像ファイルを含めて60315というスコアになりました。コードゴルフなのでかなりダーティなコードですが以下のようになります。 <!DOCTYPEhtml> < table cellspacing = 0 >< tr >< td bgcolor = #147ecc >< td >< td style = width:80% >< table >< tr >< td style = height:10% >< tr >< td style = height:80% >< img src = m width = 100% >< h1 > <?php foreach ( $ _GET as$ k =>$ v ){ $ t [] = [ $ k , $ v ] ; } usort ( $ t , function ( $ a , $ b ){ $ i =$ a [ 1 ] !=$ b [ 1 ] ? 1 : 0 ; return strcmp ( $ b [ $ i ] , $ a [ $ i ]) ; }) ; echo $ t [ 2 ] ? strrev ( $ t [ 2 ][ 1 ]) : '' ?> < tr >< td style = height:10% ></ table >< td >< td bgcolor = #147ecc >< style > body{height:100vh;font-family:Helvetica;letter-spacing:.04em}table{height:100%}*{border:none;padding:0;margin:0;font-weight:400;color:#465560;text-align:center}td{height:50%;width:5%} 見やすくフォーマットされたコードはこちら https://gist.github.com/tenkoma/416cdf36a51c9610e0a7d353102a43ce 実はチェッカーは、リダイレクトをチェックしてなかったため、「コンテナ内の /var/www/html 内にWebサイトを表示するのに必要な全てのコード、およびファイルを設置してください」というレギュレーションを無視すれば以下のコードもチェッカーをパスします。(スコア: 80) <? = header ( 'Location://phpconfuk-codegolf-php.lolipop.io?' . getenv ( QUERY_STRING )) ; 「マネクラからの挑戦状」、ゲームを楽しみながらマネージドクラウドの使い方を覚えるというナイスな企画で、楽しく参加できました。 登壇スライド 今回登壇した、東口( @hgsgtk )・川島( @nazonohito51 )の発表内容について発表者自身より紹介します。 ユニットテストの現場の問題を原則に立ち返って考える by 東口和暉 BASE BANK株式会社 Dev Divisionでソフトウェアエンジニアをやっている東口( @hgsgtk )です。 これまでのPHP系のカンファレンスにて、いろいろユニットテストについて話してきたのですが、今回もユニットテストの話です。 今回の内容は、ユニットテストについて現場で起きる問題や悩みがちな意思決定について、問題を整理した上で取りうる戦略とその戦略の良し悪しを様々な文献をもとに説明するものです。各々の現場で異なりうる意思決定の判断材料を提供することを試みました。 駆け足で話してしまったのですが、Ask the Speakerにて、現場でテストを書いてる聴講者の方々に「参考になった」と言っていただけたので、ある程度この発表が目指したいものは実現できたかなと思います。 今年は、今後も CakeFest や Go Conference Summer in Fukuoka 、 PyCon JP 2019 等で、ユニットテストについて話す機会を頂いているので、引き続きユニットテストをはじめとしたソフトウェア開発に関する造形を深めるべく精進していきます。 PHPStanでCustomRuleを作る by 川島慧 BASE Product Dev Division 基盤グループの川島( @nazonohito51 )です。今回はPHPStanを使って独自の静的検査を行うことが出来るというお話をさせていただきました。 PHPStanにはCustomRuleという独自の検査を作るための機能が備わっているのですが、READMEにほぼ記述はなく、かなり手探りの作業を要求されます。今回は私が dependency-analyzer という静的解析ライブラリを作った経験から、そのあたりの知見をコミュニティに還元すれば喜ぶ人がいるんじゃないかな?という思いで発表させていただきました。なるべく「こんなに簡単にCustomRule書けるんだよ」と簡単さを押して資料を作りましたが、ありがたいことに意外と簡単にかけそうだぞという感想もいただいて、発表の目指したいところは達成できたかと思います。 同時に気になったのが「静的解析って何ですか?」という質問でした。色々お話させていただいた感触としては、おそらく「PHPStan/Phanというツールの存在はなんとなく知っているが、具体的にそれらがどういうものなのかはみんなハッキリとは認識していない」ぐらいなのがコミュニティの実情なのかなという感触を得ました。 @tadsan さんとも懇親会の場でお話しましたが、やはりみんなあまり知らなそうだという認識とのことです。 https://twitter.com/suzuki/status/1144873913790259201 PHPstan + CustomRule によるコードクオリティの維持については、既にアプリケーションエンジニアの範疇を超えて来ている気もするなー。 これができるなら、そういう役割のおちんぎんがプラスされても良い世界な気がする。 #phpconfuk — suzuki (@suzuki) June 29, 2019 なるほど。たしかにコードクオリティを維持する仕組みづくりは、事業へのコミットしながら同時に手を出すのは難しい領域かもしれません。これらを踏まえて、大多数の人が興味を持ちづらい領域の話だったかな〜と思いました。次回はより多くの人が興味を持ってくれそうな話をしたいと思います! まとめ 台風が直前に出現するなど困難が現れる中、トラブルなく素晴らしいカンファレンスを運営していただいた、実行委員長の松村様( @tsubakimoto_s )をはじめ実行スタッフの皆様、本当にありがとうございます。 また、登壇者の皆様、スポンサー企業各位、聴講者の皆様方にこの場を借りて御礼申し上げます。 引き続き、PHPコミュニティに積極的な貢献を続けていきたいと思います。
アバター
はじめに BASEでは、開発者様向け機能として BASE Template と BASE API を提供しています。 BASE TemplateではBASEショップが使えるHTMLテンプレートの開発を、BASE APIではショップの商品情報や注文などをWEB API経由でアクセスしアプリケーション開発を行うことができます。 今回はその2つの機能のドキュメントサイトをリニューアルしましたのでお知らせ致します。 なぜリニューアルする必要があったのか 以前のドキュメントサイトは、以下のようにGitHub上にドキュメントとしてMarkdownファイルを配置しているだけでした。 template-docs baseinc/api-docs 機能としては最低限満たしてはおりましたが、デザイン性は乏しく必要な情報へのアクセスも難しいという問題がありました。 加えて、ドキュメントに新しいAPIレスポンスについての情報を加えようとするとGitHubのPull Requestを経由せざるを得ず弊社エンジニアやデザイナー同士の仕様定義についてのやりとりも見えてしまうという問題も存在しておりました。 これらの問題を解決しつつ開発者の皆様に使いやすいドキュメントにリニューアルしていく運びとなりました。 どのようなツールを利用するか 社外向け開発ドキュメントをホストするサービスやツールは数多くあります。 弊社で選定する際に重要視したのは下記です。 既にあるMarkdown ドキュメントを大幅に変更する必要がない ある程度デザインを自由に変更することができる 独自ドメインを割り当てることができる なるべく新しいSaaSなどを利用したくない 検索機能を開発せずに利用できる もともとドキュメントはmarkdownで書かれていますので、例えばSphinxなどをドキュメントツールとして選定してしまうとrst形式に書き直す必要があります。 今回のリニューアルではドキュメント自体を変更することまでは考えておりませんでしたので作業工数的な考えからも現在のドキュメント資産自体はなるべくそのまま利用できることが重要な条件でした。 検索機能についても同様で、検索機能は必要ではありますが一から開発していくことは望ましくありません。 デザインに関してははBASEのブランドガイドラインに沿ったサイトを構築するのが望ましく、一定のカスタマイズが可能である必要があります。 独自ドメインは大抵のドキュメントツールや静的サイトのホスティングでサポートしています。 ですが、別途SaaSなどを契約することでアカウント管理の煩雑さを増やすことは避けたいという考えもありました。ドキュメントをメンテナンスする社内メンバーは多くいるためそれらの人に改めてアカウント権限を付与する作業が必要となってしまうためです。 Docusaurus + GitHub Pages 上項のような条件のもと、GitBookやHugo、Swagger-UI、API Blueprintなどを試していたところ Docusaurusというツールに出会いました。 https://docusaurus.io/ DocusaurusはFacebook社が公開しているOSS向けReact製のドキュメント作成ツールです。 React NativeやRedux、textlintのような OSSドキュメント に利用されています。 Docusaurusはmarkdown形式のドキュメントを扱うため、一部の変更は加える必要はありましたがBASEの既存ドキュメントからの移行は問題なくできるようでした。 デザインは柔軟に変更でき、ローカルでの開発も容易でしたのでデザイナー自らがデザイン修正を行うことができました。 Docusaurusでドキュメントを作ることができたのでそれをホストする環境についての選定をしましたが、ここは順当にGitHub Pagesを選定しました。 独自ドメインを扱うことも可能ですし、弊社ではGitHubを元々利用しているため公開フローのために特別なアカウントを必要としないことが選定理由です。 現状問題はほとんどありませんが、ステージング環境のような物が存在しないのでローカルで検証したサイトを複数人で確認し辛い事に少し不安があるなと感じています。 既存ドキュメントの移行作業 ツールの選定が終わったので、あとは既存ドキュメントを移行していきます。 docusaurus のセットアップ docusaurus-init というツールを利用すると最低限必要な初期ファイルを用意してくれます。 基本的なドキュメント部分は設定ファイルとmarkdownの変更で対応できますが、例えばトップページを変更したい、となった場合はある程度 React の知識が必要になってきます。 リニューアルタイミングで新しい機能が追加される予定だったこともあり、今回はエンジニアがデザインの組み込み込みで構築を担当し、デザイナーを中心にドキュメントの追加、修正、構成の見直しを行いました。 移行作業 既存の markdown のドキュメントからの移行は、ヘッダー情報を付加するのみで行うことができました。 いままではコンテンツのみが書かれていた markdown にこのようなヘッダーを追加します。 --- id: add title: items/add --- # POST /1/items/add 商品情報を登録 id は、ドキュメント上で自身が存在するディレクトリを含めたユニークキーとなります。例えばこのファイルは docs/api/items/add.md に配置されているので、実際の id は api/items/add となります。 あとはこれをすべて markdown に追加していき、sidebar.json へ構成を記述すれば完成です。 "docs": { "BASE API": [ "api/index", { "type": "subcategory", "label": "OAuth", "ids": [ "api/oauth/authorize", "api/oauth/access_token", "api/oauth/refresh_token" ] }, { "type": "subcategory", "label": "Item", "ids": [ "api/items/index", "api/items/search", "api/items/detail", "api/items/add", ... 検索 Docusaurusはそのままでは検索を利用する事ができません。 ですが、 Docsearch と連携させることで検索機能を使うことができます。 Docsearchはalgolia製の検索を提供してくれているサービスで、OSS向けでは無料で利用することができます。 利用する際はDocsearchのサイトから、利用申請を送る必要があります。 送った後数日で、このサイトの管理者かどうか?といった質問がメールで送られてくるので管理者である旨を返信するとAPI keyなどが送られてきます。 下記のようにconfigが配置されていれば検索が可能になっているのでDocusaurusのsiteconfig.jsonに設定を書き加えることで検索機能が有効になります。 https://github.com/algolia/docsearch-configs/blob/master/configs/thebase.json 検索のレスポンスが驚くほど速いのでDocusaurusを利用しなくとも、Docsearch(algolia)を利用する価値はあると感じました。 GitHub Pageへのデプロイ GitHub PagesへのデプロイはCircleCI 経由でやっています master branchへのcommitを検知すると、デプロイ jobを実行しGitHub Pagesへのデプロイを行っています。 これらの 手順 もDocsaurusのドキュメントに詳細に書いてあるので手厚いなと感じました。 これによりエンジニアでなくともGitHubのアカウントさえあれば手軽にドキュメントのメンテナンスが行えるようになっています。 ドキュメント上で一部機能の確認が行えるようになりました。 ここからは新機能のお知らせとなりますが、昨今のBASE TemplateはBASE Appの拡充に伴い様々な条件を想定し開発をしていただく必要があります。 しかし、現状のエディタ機能では色々パターンを想定し開発していただくのには不便であることは開発チームとしても課題として受け止めておりました。 そこで、今後のシステムの拡張の先駆けとして、テンプレートのサンドボックス機能を一部実装いたしました。 サンドボックスは BASE Template に関するドキュメントの 対応ページ で確認することができます。 この機能はテンプレートを作成するにあたって、複雑化するタグの動作イメージをつかんでもらおう、という目的で実装されました。 タグによっては BASE Apps (拡張機能) の有無や、商品に設定されている項目や時間によって動作が異なることがあるため、 動作を確認するためには実際に Apps をインストール、設定、アンインストールしてまたインストールというような労力をかけていただく必要がありました。 サンドボックスではこれを解決するため、Apps の設定を簡略化したものをその場で設定できる機能を搭載しています。 この機能は現在一部のタグのみをサポートしていますが、徐々に対応範囲を広げていく予定です。 最後に 今回はBASE TemplateとBASE APIのドキュメントサイトの更新とドキュメントへの機能追加についてお知らせさせていただきました。 開発者の皆様がBASEを使ってHTMLテンプレートやアプリケーション開発をして頂く際の一助としてお使い頂ければと思います。 ご不便な点や間違いなどを見つけられた際には開発チームに メール にてお知らせ頂ければ幸いです。
アバター
こんにちは、BASE株式会社 ランニング部部長の元木です。 日々、社員に運動不足解消を促す傍ら、Owners Marketingというチームでバックエンドエンジニアをしています。 さて、弊社ではソースコードを変更した際に必ずメンバー間でコードレビューを行ない、OKが出たコードだけをデプロイすることになっております。 今ではほとんどの開発現場でコードレビューを取り入れていると思いますが、読者の中には 「レビューのコメントって、どう書いたらいいのか分からない」 「こんな事を言って嫌な顔をされたり、喧嘩にならないか心配」 などと、苦手意識を持っている人もいるのではないでしょうか? そこで、今回は私がコードレビューの際に気をつけているコメントの書き方をご紹介したいと思います。 気を付けているポイントとレビューコメントの書き方の例 私は、レビューで指摘事項をコメントする際のポイントは 「いかに分かりやすく、納得感のあるコメントを書けるか」 だと考えております。 そのために、コメントは以下の順に書くようにしています。 どのように修正してほしいか なぜ、そのように修正してほしいのか エビデンス それでは、以下仮のPHPコードを例に順を追ってご説明します。 <?php /** * 引数 $phone_number が電話番号であることをチェックする。 * ただし、厳密なチェックはせず、'-'を除いた後の桁数と数字だけの文字列であることのみチェックする。 * * @param string $phone_number 電話番号 * @return bool 引数 $phone_number が電話番号ならば true。 */ function is_phone_number ( string $ phone_number ) : bool { $ phone_number = str_replace ( '-' , '' , $ phone_number ) ; $ length = strlen ( $ phone_number ) ; if ( $ length < 10 || $ length > 11 ) { return false ; } return is_numeric ( $ phone_number ) ; } このコードは実装者の意図通りに動くでしょうか? 結論を言うと、このコードにはバグがあります。それをコメントで指摘してあげましょう。 まずは悪い例から。 こんなコメントをする人はまずいないと思いますが、下手をすれば喧嘩になるかもしれません。 では、次はどうでしょうか? 間違ったことは書いていません。 なぜか、を同時に書くと親切かなとおもいます。 分かりやすくなりました。 エビデンスを示すのは、親切心のためだけではありません。勘違いなどにより、間違った指摘をしてしまうのを防ぐ目的もあります。 しかし、これを読んだレビュイーは 「じゃあ、どうすればいいの?」 と悩むかもしれません。 特にレビュイーが新人プログラマーだった場合は、そうなりやすいです。 そこで、「どのように修正してほしいか」も追記します。 これならレビュイーも悩む必要がなくなりますね。 最後に、修正方法を先頭に移動します。 最初の一文だけ読めば結論がわかるようになりました。 日本語の文章としてはちょっと違和感があるかもしれませんが、こちらの方が読み手に優しい文章だと思います。 それに、熟練のプログラマーなら結論だけで 「あ、そうか」 と気づいてくれるかもしれません。 もちろん、すべてのコメントをこのように書けるとは限りません。 問題があることは分かったけど修正方法が思いつかないこともありますし、エビデンスを示すのが難しい指摘事項などもあるからです。 そういった場合は無理せず、書けることだけをコメントするとよいと思いました。 他のレビュアーが補足してくれるかもしれませんし、大抵の場合、レビュイーはコメントをもらえるだけで十分にありがたいと思ってくれるはずです。 コードレビューはみんなの資産 コードレビューは、ぶっきらぼうなコメントですと殺伐としたり、そうなるのが嫌で億劫になりがちです。 HRTのマインドセットをお互いに持ち、コメントの書き方を工夫することで、レビューしやすい/されやすい文化が育まれ、良いコードと良いチームへ繋がっていくと思います。
アバター
こんにちは、Design Groupに所属している森( @ mrkzk )です! 年末に初めてアドベントカレンダーでテックブログデビューを果たしたのですが、新しく入社された方に「あのブログを通して、エンジニアと他部署の距離の近さ、社員同士の仲の良さが見えてよかったです」というお声をいただきまして嬉しい限りです! と、前置きはこのくらいにしておいて、実は最近 ブランドプロジェクト が始まり、ブランドポリスに就任しました! ブランドポリスって何?という部分と、ブランドポリスとして実際にやっていることのお話をしたいと思います。 ブランドプロジェクトの目的って?ブランドポリスって? ブランドプロジェクトの目的は、プロダクトを通じて実現したい未来のために、メンバーが共有すべき考え方を明確にし、それに対してメンバー全員の意識を合わせることです。 私たちが「BASE」というプロダクトによって伝えたいメッセージや体験をユーザーをはじめとするステークホルダーに届けるためには、まず情報のアウトラインを整え、そこから情報の信頼性を高めていくことが重要だと考えました。 例えば、メンバーのひとりひとりが認識しているBASEのミッションが同じであっても、アウトプットの方法が異なると、情報を受ける側のBASEに対する認識は変わってしまいます。 それはロゴの見せ方であったり、外部の方向けの資料のデザインからも伝わるものなので、体裁が整っていないと、その情報を受け取った方は「これって「BASE」の公式情報なのかな?」と不安になってしまうのではないでしょうか。。。 「これは「BASE」が発信しているオフィシャルの情報だから安心できる!」 そう思っていただくために、外部向けの資料やドキュメントはもちろん、オフィス内でしか利用しないものまで、その全てをプロダクトと捉え、メンバーみんなで自信を持って提供できるような体制とデザインを整えていきたい!そんな思いから始動しました。 そして、そのための施策を実行し、「BASE」のブランドを保持するため「ブランド毀損してませんか~~」とBASEが発信するクリエイティブを取り締まり、会社全体で自信を持って提供できるようデザインと意識を統一していこうね!と呼びかけることが私、ブランドポリスの役割です! それで具体的には何をするの?? BASEでは、営業資料など外部の方にお渡しするものはもちろん、社内利用のみであるオフィス販売のラベルも含んで全てをプロダクトとして扱う方針です。 こちらを考慮して施策を挙げてみると・・・ ブランドガイドラインの作成 カラーガイド フォントの統一 ロゴの調整、追加 スライド資料の作成 既存営業資料のクリーンナップ テンプレートの新規作成 ブランドガイドラインの社内研修 請求書、明細書、送付状デザインの統一 営業提案時のチラシや採用パンフレットのデザイン 「SHIBUYABASE」「OIOI BASE」などのポップアップのポスターやサイネージ、ポスターデータなどのテンプレ作成 ブランド毀損に該当していそうなSNSのカバーやアイコンの修正 社内クリエイティブのデザイン(オフィスコンビニのQRコードラベルなど社内販売のパネル、SNSの投稿写真に写り込んでもおかしくないものは全て) 名刺のリニューアル 管理画面のグラフィック刷新 などなど、ここにないものも含めとにかく大量・・! デザイナー3人がかりで徐々に倒していきましたが、この中で最も力を入れていた(つまり苦労した) ①ブランドガイドライン ②スライド資料 ③研修 の3つを簡単に取り上げていきたいと思います。 ①ブランドガイドライン BASEにはブランドガイドラインというものがほとんどない状態だったのでそこからのスタート・・・! ブランドガイドラインになくてはならない基本的な ⅰ.ロゴ ⅱ.カラー iii. フォントの3つガイドを作成しました。 ロゴ BASEのロゴはデザイナーが使用するにも難しいバランスで作られていました。今回、全体的にセーフティスペースを広げることで非デザイナーでも、置くだけで他の要素とのバランスも綺麗に取れるロゴに微調整してあります。 また、サービスのマルチカラーロゴは色が淡いので背景が複雑であったり写真の上に配置する際に視認性が低く、悩みのタネでしたが、これを機にステッカー風の白ふち付きロゴを新たに追加しました。可愛い! 他にも、デザイナーのみ使用OKとしたWebページフッター用の白抜きロゴなども用意しました。 カラー サービスのマルチカラーはBASEそのものを象徴する色であり、管理画面に使用されているカラーはテキストを強調するための色。これらの同じプロダクトに使用されているカラーでもそれぞれ用途が違うことなどもお話ししています。 フォント デザイナーのチームでは「BASE」のクリエイティブをつくる際にAXISという有料フォントを使用しているのですが、全社で使っていくには難しいので、よく似たニュートラルで「BASE」のイメージにぴったりな源の角ゴシックというフォントを採用しました。 ②スライド資料 BASEが社外に共有している資料は、サービス概要の紹介資料、会社紹介資料、その他「&BASE」などのプロジェクト紹介資料などがあるのですが、こちらカスタマーサクセスやMarket Developmentなどビジネス部門の方々が各自思い思いに作成してくださったものなので トンマナが揃っていない ロゴに枠線が付いているなどブランド毀損にあたる 使用PCがWindowsだったりMacだったり、使用ソフトがKeynoteだったりPowerPointだったりバラバラなので互換性が低く崩れている など改善点がいくつもありました。 使用PCがWindowsだったりMacだったり、使用ソフトがKeynoteだったりPowerPointだったりとバラバラなので互換性が低く崩れている 特に重たかったこちらの課題は、それぞれのソフトで同じ資料を作ることで解決するべく、クリーンナップを行いました。 資料の作成ツールは、下記の3つがあり Keynote(for Mac) PowerPoint(for Win)(稀にトリッキーなppt for Mac) Googleスライド 資料の種類は大きく3つ コーポレート サービス 登壇用スライド そしてスライドのサイズも標準、ワイドのそれぞれテンプレートを用意すると既存資料だけでも18個・・・!!!頑張るぞ!! と、こちらがクリーンナップした資料のビフォーアフターの一部です。(Keynoteバージョン) このようにサービスカラーのフッター・ヘッダー、 confidentialをマスターに追加して固定してあります。 そして、既存資料以外にも、誰でも新たに資料を作成、スライドを追加しやすいよう、それぞれサービスに合ったテンプレートを作ることにしました。 ここでご紹介したいのが Keynoteのテーマ作成 !!!!テンプレのテーマ作成がすごい! カスタムテーマと言って、ヘッダー、フッター、ページ番号、テキストプレースホルダー など、それぞれスライドを作成してテーマで保存すると、ローカルに落としてテンプレートを引き出せるので簡単に資料作成ができちゃうんです。 (この下に実際に動かしているGifがあります) ちょうどこのタイミングでカンファレンスなどで登壇の機会が多いエンジニアさんからこのようなご要望ありました。 このように社内でいただいたご要望に応えることもポリスの役割なので、エンジニアさん用の「BASE」感控えめの登壇資料テンプレも作成することに。 エンジニアさんの登壇資料ということで、プロフィールページを追加し、TwitterやGitHubアカウントを入れられるプレースホルダーを作成。 このようにプロフィール画像もダブルクリックでカンタンきれいに設定できちゃうんです。 (Keynoteのテーマ作成、本当に便利なのでぜひ使ってみてください!) 上記が良い例ですが、Slackに#brand_design_checkというチャンネルを設けており、いつでも「資料用のアイコンが欲しい」、「サービスカラーの可変グラフが欲しい」などのリクエストを受け付けるための環境も整えています。 ③研修 もちろん、デザインガイドラインを作り終えておしまい!ではなく、これらのガイドラインを会社の皆さんにも知っていただく必要があるので、研修を実施しました。 研修は、PRの田中(@yokotie)と一緒になって実施しました。田中には、PR視点でパブリックリレーションズとは何か?や、ブランドを保持することの意味などを話してもらい、デザイナー側では今後全社で使っていくフォントをインストールしてもらったり、今回作成したこれらのガイドラインや資料の周知、新しいロゴの使い方やスライドの追加方法、素材の紹介、質疑応答などを行いました。 チームごとに開催したので、1回60分の研修を計13回ほど行いました。BASEのメンバー全員が対象なので当然!CEOの鶴岡ら役員にも受けてもらいました! 研修と言っても終始和やかな雰囲気で、笑顔が絶えない会ばかりでした!正直はじめは照れるなあ、と思っていたのですが、でも、相談しやすいポジションでありたい!という思いから欠かさなかった「この度ブランドポリスに就任しました、森です!」の挨拶も、会を重ねるともはや照れる気持ちもどこかへいきました!さいなら! 途中雑談も交えつつ、最後までしっかりコミュニケーションを取りながらすべての研修を終えることができました。 無事、全研修が終了した日にはこれまで頑張ってきたメンバーと最高のお寿司ランチをきめました!!赤しゃりサイコー!(白目) 最後に 今回ガイドラインやテンプレートといったルールを決めたことで、メンバーから「フォントをわざわざインストールするのが面倒」、「何でもかんでもチェックしてもらわなきゃいけないのは苦痛」などマイナスの声をもらうこともあるかもしれないな、と懸念していましたが、 「確かにこれは「BASE」っぽい、これは「BASE」っぽくないがなんとなくわかるようになった」 「提案資料がすごく見やすくなった」 「迷わず簡単に資料を作れるようになるのは嬉しい!」 など本当にプラスのお声ばかりいただきました。研修中も、みなさんしっかり目を見て、表情や相槌でリアクションを取ってくれたり、受講者なのにウケを取りにいってくださる方もいらっしゃったりと、全体的にワイワイ賑やかな雰囲気で進んでいたので私も特に緊張することなく、とってもやりやすかったです。はぁ〜〜めっちゃいい会社じゃん、、と好きが溢れ落ちましたぁ。 そもそもこのブランドガイドラインはガチガチにルールで縛るものではなく、社員のみなさんが何かを作る際に”迷うことなく、サクッと時間をかけず簡単に、それなのに「BASE」らしさのあるものを制作して対外的にもアピールできちゃう!”ことが目的だったのでとても嬉しい感想でした。 今回の施策はロゴの簡単な改善や資料のクリーンナップなど、マイナスをゼロにするものが中心でしたが、今後は「BASE」への信頼を向上させるようなプラスを作る発信のサポートをしていきたいと思っていますのでどうぞよろしくお願いします!
アバター
こんにちは、CommerceDevというチームでエンジニアをやっています島田です。 このチームは、Eコマースプラットフォーム「BASE」のサービスの根幹を作る事をミッションとし、ショップオーナーの管理画面や決済機能の改善に取り組んでいます。チームができる前は決済チームのエンジニアリングマネージャー(以下EM)をやっていたのですが、いまはEMを移譲しエンジニアとして働いています。 今回はマネジャーを移譲した理由を含め僕がBASEに入社してからのチーム変化を書きたいと思います。 EMになるまで 僕が入社した当時、社内にエンジニアは10名程度でした。現在は約50名のエンジニア組織になりました。 エンジニア以外の社員も増え、それに伴ってかつて問題ではなかったことが問題になったり、これから問題になるだろう課題も抱えるようになっていきました。人が増えると組織としてやることが増えますが、エンジニアも例外ではありません。細かい事の積み重ねにより関心事が増えるとエンジニアが本当にやりたい事に集中してコミットできなくなり、結果としてパフォーマンスを十分に発揮できないという悪循環に陥ってしまいます。 それを解決するためにエンジニアとしてどういった振る舞いをするのが良いのか考えた時、今はマネージャーになりエンジニアがエンジニアとしてちゃんと力を発揮できる環境を作ったほうが良いのではないかと思いました。 EMとして考え実施してきたこと どういった制度や環境があればエンジニアが事業に一番コミットできるかを考えていました。 自分の背景がエンジニアなので、エンジニアとしてここはこうしたほうが良いと思うことを検討し、関係各所と連携して進めました。実現するためにはエンジニアだけでなく人事や労務など別の部署にも協力をお願いすることが多いので、関係各所との関係性を構築しておくのも大事だと感じました。 ここからは、EMとして考えて実施してきたことをいくつか挙げてみたいと思います。 採用 ビジネスとプロダクトと開発の課題調整 エンジニアの提供価値に対しての適切な評価 エンジニアの生産性向上・スキル向上に寄り添う 採用 組織の規模が小さかったときは各エンジニアが全体を見ることもできたのですが、組織が大きくなるにしたがって並行で進行するプロジェクトが増えたためそれが難しくなっていきました。 当初は1人のエンジニアが開発を複数かけ持ちすることもあったのですが、やはり関心事が増えると一つのことに集中しにくくなり結果的にあまり生産性がよくありませんでした。また、エンジニアが他社との折衝やテストの段取り、カスタマーサポートチームへの共有といった開発自体以外にも工数が取らていることは課題だなと思いました。 そこで、開発時の役割を細分化しエンジニアは開発に専念できるよう、工程管理などは開発ディレクターを立てることにしました。すでに社内にもいましたがエンジニアの数とのバランスが取れていなかったのと、今後さらにエンジニアが増えたときにもっと必要になると思い、組織や会社の状況を考察しながら、どういった人材が必要か検討し人事などと協力し採用を進めました。 開発現場の意見やプロダクトの成長から、今後どういった組織にすべきか、どういった人材が何人必要なのか、人事と協力しながら解決していきました。 ビジネスとプロダクトと開発の課題調整 BASEの機能開発の基点とには、プロダクトマネージャーやBusiness部門(事業開発、カスタマーサクセス、カスタマーサポート、マーケティングなど)の企画・依頼以外に、エンジニアからの課題発見や機能提案があります。 この時に、「この機能を開発してもらいたい」「こっちのほうが優先順位が高いのでは?」とグループの目標や視点の違いによって、組織の課題認識にズレが生じる場合があります。 そこでEMは全体を理解し、その時・その後も最適になるようにうまく調整する必要があると思います。 あるときにはプロダクトマネージャーやBusiness部門からの開発案件を優先し、またあるときには開発側として重要だと思うことの優先度を上げる。そのためにEMがそれぞれが納得感を得られるように調整し目標咀嚼して伝え協力的な職場をつくることに取り組みました。 時々、開発現場からの意見や課題はプロダクトマネージャーやBusiness部門とは別の観点を優先していることもあります。ですが、その課題の解決を疎かにしてしまうとふとした時に事業やプロダクトの成長の足かせになってしまいます。事業とプロダクトの長期的なビジョンをEM自身が理解納得したうえで、エンジニア個人の短期・中期・長期的な成長・変化を想像しつつ、実現するためにどういった環境にすべきか考えていきました。 エンジニアの提供価値に対しての適切な評価 EMの役割として一番重要だと思います。どんな成果物を作ったかという点に偏りがちですが、それ以外にもたくさん評価すべき点があります。例えば次のようなことも評価対象にしていました。 テックブログの投稿、カンファレンスへの登壇 技術力の向上は良いプロダクト作りへつながり、良いサービスを提供できるようなると考えています。私たちが使っているOSSやコミュニティへの貢献もできます。また、社内の別のエンジニアに対しても良い刺激になります。 レビュー時の指摘が的確、コメントが優しい 的確なレビューはそのままコードのクオリティ向上に繋がりますし、優しいコメントはレビューを依頼しやすい空気感がうまれ、心理的安全性に繋がります。また、レビューは教育的要素があるので技術の底上げにも繋がります。 自分以外の人でも分かるようにドキュメントをまとめた ドキュメントは大事な資産だと思います。開発の経緯や使い方などをきちんとドキュメントに落とし込んでおいてもらえると誰かに作業を依頼するときにも調査などの時間を削れますしミスも少なくなります。また、自分でも半年くらいすると記憶が曖昧になるので、そういったときにも役立ちます。 メンバーの普段の活動を通じてどういった価値を提供しているかをしっかり見続けて、適切に伝えていくことが大切だと思います。メンバーとの1on1や上長とのミーティング時の他、普段からピアボーナスのUniposを使ってメンバーの良かったことを伝えていました。 エンジニアの生産性向上・スキル向上に寄り添う 性能の良いPCや自分にあった椅子を推奨 技術書の購入補助 カンファレンスやテックイベントへの出席・登壇を推奨 このあたりの制度や文化はすでにベースがあったので僕の方では大きなことはしていません。もしこれから検討する場合は総務や労務の方と一緒に進めていったと思います。 組織がどう変わっていったか 組織構築の一環として採用を強化しことによりメンバーが増えました。メンバーが増えたことによってノウハウも増えましたし、メンバーが自主的に行っていた勉強会やイベント登壇などに賛同する人も増えました。 各メンバーが会社や社外に提供してくれた価値をきちんとポジティブ評価することによって流れが加速し、新しいことへ挑戦するモチベーションと技術の向上のにつながりました。 EMはメンバーが活躍できるフィールドを作り、そしてメンバーを集め、活躍できるようにフォローし、適切に評価することが大事だと思いました。 EMとエンジニア文化 EMはメンバーの評価や組織作りを通じて会社のエンジニア文化を作ることができます。良い文化ができると良いエンジニアが集まってきます。 エンジニア文化は一夜ではできないし1人で作ることは難しいです。メンバーの協力がなくては実現できないので、メンバーやEM仲間にも協力してもらいながら少しづつ積み重ねていくと良いと思いました。 一方でエンジニア文化は定期的に見直すと良いと思いました。時間がたつとその時の最適解が今の最適解ではないことが多いです。また、グループごとに培った良い文化を交換留学のように取り入れあうのも良いです。そのためにはEMはローテションさせ、定期的に客観的な視点で見直しを行うのが良いと思いました。 EMの先のキャリア 社内にはEMの先の事例がないことにも気づきました。 「プログラムを書くのは好きだけどマネージャーになってからコードを書く時間が減ってしまった。」という言葉も良く聞きます。 エンジニアからEMになった後に再びエンジニアになるというのは、正直なところネガティブな印象があるかもしれません。ただその印象を少しでも変えられたら、エンジニアのキャリアパスを広げられるのではと思っていたので、自ら実行することにしました。あわせてEMが居なくなってしまうと組織のバランスが崩れてしまうので権限委譲も合わせて行いました。 エンジニアに戻ってみて感じたこと プロダクトは日々成長していたので、再びエンジニアとして途中から開発に合流することは不安でした。 それを救ってくれたのが意外にも自分でやってきたことで、たとえばドキュメントやログをちゃんと残すことや、他の社員へのノウハウの共有を評価項目としていたおかげで調べたり聞けばなんとかなる環境ができていました。 エンジニアのためにやってきたことが正しいことだったのか、自分がその立場になることで結果検証できたのがよかったです。 おわりに 当時はEMになろうとは思っていませんでした。ただ結果的に自分のやってきたことを振り返ってみると、CTO藤川の記事にもある、 「事業、プロダクトに貢献しながら、チームのエンジニアの活躍にコミットすることで、メンバーの評価を上げる仕事」 になっていたなと思います。 (参考: エンジニアとしてワクワクし続けるためのエンジニアリングマネージャという役割分担 ) エンジニアの働きやすさというのは組織の変化や個人のライフスタイルの変化によっても変わってきますので、その時々で課題を感じた人がEMの役割を担い自分が働きやすい環境に改善していける文化があると良いのではないかと思います。 BASEではEMによるエンジニアのためのエンジニア組織の改善を日々行っています。エンジニア、EMの仲間を募集中です!もしこの記事を読んでご興味を持った方はぜひご連絡下さい。 open.talentio.com
アバター
こんにちは。 BASE BANK株式会社 でバックエンドエンジニアをやっている東口( @hgsgtk )です。 先日開催された Go Conference Tokyo 2019 Spring にて、「 Design considerations for container-based Go applications 」というタイトルで20分トークのお時間をいただきました。このエントリでは、 発表内容をどう作ったか ということについて紹介してみようと思います。 発表内容 実際に発表したスライドはこちらです。私が去年から取り組んできたサービス開発で得た実践知見を、なるべく忠実に投影した発表内容にしました。 Go・コンテナの組み合わせで開発・運用している・したい方が多いのか、当日は立ち見の方が出るくらい多くの方に参加していただき、大変感謝です。 今回は、トーク準備にあたって、どのように発表内容・構成を作っていったかについてご紹介します。 発表構成を考えるにあたって トークするにあたって、至極当たり前のことなので恐縮ですが、「トークを聞きに来る人の期待に応える時間にしたい」という風に思います。この発想を重視して、次のような流れで発表内容・構成を考えました。 「誰に役立ってほしいか」というありたい姿を整理する 期待チェックリストを作る 期待に応えるための構成・ストーリーを作る 1. 「誰にどう役立ってほしいか」というありたい姿を整理する 「自分が共有する内容はこういう人に役立つはず」というトークのありたい姿を考えます。実際、このトークでは次のように定義していました。 誰に:Go、コンテナでのアプリケーションを本番導入しようとしている方 どう役立つ:「これでいいのか?」という不安を少しでも解消して一歩進める内容にしたい 2. 期待チェックリストを作る 実際に話を聞きにきてもらう「 聴講者の期待 」・場を与えてくれる「 カンファレンスの期待 」の2点について考えて整理しました。 聴講者の期待 自分がトークする20分の時間、聞いてくださる方々の時間をお借りすることになります。全ての人の期待にしっかり応えられるかわかりませんが、なるべく多くの方にとって有意義な時間にしたいです。そのため、「 プロポーザル概要を読んで何を思うか 」について新鮮な目で見直しました。 今回のプロポーザル概要はこちらです。この概要を読んで「どんな事を話してくれそう」と期待するかをリストアップしてみます。 Go言語でのアプリケーション開発で、特にコンテナを前提とする場合の設計考慮点について話します。 例えば、Go言語でAPIを開発する場合、コンテナとして動かすことを前提とするケースが多いと感じます。コンテナベースで動かすことを前提とした場合、コンテナイメージ作成・アプリケーション監視において、考慮すべき点が出てくるでしょう。このトークでは、Go言語での実装にまで踏み込んだ上で、コンテナベースアプリケーションにおける設計の考慮点について話します。 カンファレンスの期待 トーク時間をいただくにあたって、プロポーザル審査の時間をかけていただき採択いただいています。そのため、「カンファレンスとしてどういうことが期待されているのか」について改めて見直しました。実際、公開されてる Call For Proposal のSelection Criteriaを読み直しました。 結果的に、ありたいトークの姿・聴講者の期待・カンファレンスの期待を総合的に見て、次の期待チェックリストになりました。 Goの話が聞ける 知識ではなく実践の話が聞ける 業務導入の参考にしたい方のために業務での実践の話が聞ける コンテナ使う場合に抑えておくと良い設計ポイントがつかめる その設計ポイントを実現するためのGoの実装例が聞ける 3. 期待に応えるための構成・ストーリーを作る ここまで期待を定義した上で、構成・ストーリーを考えていきます。特に今回のトークタイトルだと、「抽象的な概念の話」なのか「具体的な実践の話」なのかどちらなのかわかりずらいだろうと感じたので、 トークの課題・背景共有 を入れる方式にしました。 トークの課題・背景共有 前述したようなこのトークで伝えたい内容を定義します。「こういう話するんだな」という認識の統一を図る意図です。例を挙げると、「このトークで持ち帰ってほしいこと」とか「このトークで話すこと」といったタイトルのスライドのことですね。 また、実例系の話の場合、誰がどのような現場で実践したのかという前提があると参考にしやすいと思っています。そのため、Goへの習熟度・アプリケーション規模などの背景を抑えるための自己紹介・会社紹介を入れました。 プレゼンの準備 事前の練習 恥ずかしながらこれまで何度かカンファレンスで話させていただいていますが、脳内シミュレーションのみを行っていて、事前の社内プレゼン練習はしていませんでした(社内で話すほうが緊張するといった理由で避けていたり・・・)。今回は、1週間前に同僚に練習を見てもらってフィードバックをもらい、内容をブラッシュアップしました。 練習することで、よりわかりやすい構成や見えにくいスライドの改善など、より伝わりやすい表現を模索するきっかけに繋がりました。 道具の導入 プレゼン自体に向き合ってみようということで、ずっと二の足を踏んでいたlogicoolの Spotlight を導入しました。 www.logicool.co.jp 遠隔でスライドを操作したり、ポインタで画面を拡大したりするものです。Spotlight自身がタイマー機能を持っていて適宜バイブレーションで残り時間を伝えてくれたり便利です。一番、大きい点としてPC操作から離れられる点でした。PCから離れて壇上中央寄りに立つことで、聴講者の方々の視線・顔が見えるので、 伝える ことに意識を向けようとする効果がありました。 発表を終えて 実際、全員の参加者の方の期待に添えた内容を伝えられたかは分かりませんが、Twitter上では次のような反応をいただけてひとまず安心しています。 コンテナアプリケーション設計方針、具体的なノウハウが詰まっててとてもためになった #gocon #gocon_a — nosukeru (@ey_nosukeru) May 18, 2019 基本が忠実に押さえられてて、最初の一歩にちょうどいい感じのトークでした。 #gocon_a #gocon — チェシャ猫 (@y_taka_23) May 18, 2019 なかなか個人でここまで気にした開発運用はできないのでこういう場か業務でしか得られない知識だ #gocon #gocon_a — むさしん (@musaprg) May 18, 2019 Design considerations for container-based Go applicationsを聞いてる。 @hgsgtk さんの発表慣れがすごい #gocon #gocon_a — po3rin (@po3rin) May 18, 2019 昨年の Go Conference 2018 Spring に聴講者として参加してから、セッション登壇する(できるくらいGo力を上げる)ことがひとつの目標だったので、今回その目標を達成できてよかったです。 また、スピーカー特典でGopherくんの人形もらえて嬉しかったです。社内のデスクに飾ってます。 Gopher君かわいい ただし、Go力はまだまだ足りないので、レベルアップしてまた次のカンファレンスでお会いできるように精進します。 Next Go Conference 2019年7月13日(土)に Go Conference'19 in Fukuoka が開催されます。 fukuoka.gocon.jp 私も 「 Cost-effective Go unit test thinking and practices 」というタイトルで同じく20分お時間頂いています。ユニットテストの基礎的な考え方・Go特有のアプローチ・実践例について紹介します。ぜひ、福岡でお会いしましょう!
アバター
こんにちは、BASEの次世代管理画面プロジェクトでデザインを担当している小山です。 ネットショップ作成サービス「BASE」は2019年2月に、商品管理ページをリニューアルしました。 今回は商品管理ページをリニューアルして、再検討が必要になってしまった機能にどう向き合ってきたかをお伝えできればと思います。 「次世代管理画面プロジェクト」がどのようなコンセプトのプロジェクトであるかは、過去のアドベントカレンダーで早川が書いた記事がありますので、そちらをご覧ください。 devblog.thebase.in 次世代商品管理ページリリース まずは2月にリニューアルされた商品管理ページの Before / After を紹介します。 リニューアルのポイント 今回のリニューアルでは、主に以下の点を変更しました。 スマートフォンファーストなデザイン 新機能(商品の複製、一括削除、一括公開/非公開設定)を追加 検索・絞り込みの強化 商品登録の整理 コンポーネント刷新 リリース後の反応 今回の商品管理ページのリニューアルはインパクトの大きいリリースとなり、リリース後は良い反応から悪い反応まで様々なフィードバックをいただきました。 5年以上続いているサービスのUIをリニューアルしたので、「使いにくくなった」「前の方がよかった」という声はある程度覚悟していましたが、今回のリニューアルで最も多くフィードバックを頂いたのは、ページャーと並び替え機能でした。 リニューアルでページャーと並び替え機能に加えた変更 BASEのサービスが成長するにつれショップの規模も大きくなり、登録商品数は増加傾向にあります。 リニューアル前は登録商品数が多くても100件程度を想定して無限スクロールを採用していました。しかし、登録商品数が100件を超えるショップが多くなり、無限スクロールでは、全体数の把握のしにくさや該当商品へのたどり着きにくさ、商品編集後のページ保持が困難であることなど、不便な状況が多くなってきました。この問題を解決するため、今回のリニューアルではページャーを採用しました。 次に、商品の並び替えについてです。 リニューアル前は、リストの一番上にある商品を一番下に移動する場合、ドラッグで並び替える方法しかなく、商品数が多いショップの場合、複数回のドラッグ操作が必要でした。そのため、数値を入力して並び替えができる機能を追加し、移動距離の多い並び替えを簡単にできるようにしました。 フィードバックの例 ページャーと並び替え機能をリニューアルしたことで、実際にユーザーから頂いたフィードバックの例としては下記のようなものがありました。 「並び替えを終了する」ボタンがページの一番下まで行かないと押せないのがめんどくさい 20個区切りでページが分かれてるのが大変、せめて100個とか選べるようにしてほしい ドラッグで並び替えたいのに移動先が次のページになってしまって移動できなくなった 数値で並び替えができるけど、毎回移動先の順番を確認するためにページを行ったり来たりするのが大変 ページごとに区切られたせいで全体の並びが確認できず使いにくい 前の管理画面に戻してほしい(せめてページ分けではなく無限スクロールにしてほしい) フィードバックを元にどう改善していくか これらのフィードバックを受けて、旧デザインの商品管理に戻すという判断はしませんでした。次世代管理画面プロジェクトは「これからの5年を支える」という目的で進めてきたので、ユーザーの声から新デザインの問題点を整理して、旧デザインのよかったところを新デザインに追加していくことで、前に進みながらUI/UXを改善していく方針をとりました。 まず、並び替え機能に関しては、小さな改善を段階的にリリースをすることで、すばやく改善をすることにしました。はじめに、1ページあたりの商品数を増やし、「並び替えを終了する」ボタンを見直しました。 また、特に要望の多かった「ドラッグで並び替えたいのに移動先が次のページになってしまって移動できない」という問題は、並び替え機能とページャーの両方に関係しています。そのため、プロダクトマネージャーやエンジニアと一緒に議論し、まずはPC側の開発を優先して素早いリリースを目指しました。 PC並び替え機能リニューアルリリース ユーザーさんから頂いたフィードバックを元に以下の改善を加えました。 並び替え専用ページを作成 商品管理ページはページャーのまま、並び替え専用ページは無限スクロールを採用 並び替え終了ボタンを下の方に配置しセンター表示にすることで見慣れたレイアウトに変更 また、画面下部に固定配置させることでボタンのコンポーネントを変更させずに目立たせた 1ページあたりの表示商品数を増やせるグリッド表示の切り替えを追加 表示切り替えを追加したのでドラッグで並び替えと数値で並び替えを1画面内でできるように変更 並び替え専用のページを作成しページ遷移をさせることで不要な情報はすべて非表示に まとめ 長年使われてきたデザインをリニューアルすると、使い慣れたユーザーからはネガティブなフィードバックがくることがあります。その際に、旧デザインに戻すのではなく、フィードバックと旧デザインを元に、新デザインをより使いやすく改善していくことが重要です。 その場合、新デザインの改善は細かくリリースして、なるべく早くユーザーに価値を届けていくことが大切だと感じました。 「次世代管理画面プロジェクト」では、これからもユーザーの声を聞きながら「これからの5年を支える管理画面」を目指して開発を進めて行きます。今後はユーザーインタビューやユーザーテストの実施なども予定しています。 最後に、BASEではUXデザイナーを募集しています。 この記事を読んで興味が出たという方は以下よりご連絡ください。 open.talentio.com
アバター
こんにちは。SREチームの山根( @fumikony )です。 このブログでも東口( @hgsgtk )が何度か紹介している即時資金調達できる金融サービス「 YELL BANK(エールバンク) 」のインフラまわりに関わっています。 今回は、YELL BANKのデプロイメントパイプラインを構築したときの工夫などを紹介します。 インフラ構成 インフラ構成図 まず大まかなインフラ構成について説明します。上の図は構成図です。 YELL BANKではGo言語でAPIサーバを開発しており、ビルドしたコンテナをECSのFargateモードを使って動かしています。 コンテナレジストリにはAWSのECRを使っています。 また複数AWSアカウント構成をとっていて、本番・ステージング・開発の各環境ごとに個別のAWSアカウントを用意しています。 今回のデプロイ機構ではこれらの環境のうち本番環境(prd)およびステージング環境(stg)を対象としました。 GitリポジトリにはGitHub、CIにはCircleCIを使っています。 デプロイ ECSデプロイツールには kayac/ecspresso を採用しました。 GitHub上のmasterブランチへのマージをトリガーとして、CircleCI内からecspressoを実行することでECSへのデプロイを実現しています。 以下、このデプロイ機構について説明していきます。 ecspressoについて ecspressoはGo言語製のECSデプロイツールです。 今回ecspressoを採用した理由は主に2つあります。 1つは、 aws ecs describe-task-definition で出力されるjsonを、そのままecspressoで使うことができるという点です。これによって、まずECSのマネジメントコンソール上で試行錯誤してタスク定義を作り、それをそのままecspressoで使うという事ができます。これはECSの経験が浅い身としてはとても便利でした。 もう1つはテンプレート機能の存在です。これは、タスク定義のjson内に {{ env `FOO` `bar` }} という記述があると、その部分を環境変数 FOO で置き換えるというものです。 bar は FOO がなかった場合のデフォルト値です。また、 {{ must_env `FOO` }} という記述の場合は FOO が無いとエラーになります。 この機能を使って、タスク定義内部で以下のように記述しました。 taskdef.json { " taskDefinition ": { " containerDefinitions ": [ { " name ": " example ", " image ": " {{must_env `AWS_ACCOUNT_ID`}}.dkr.ecr.ap-northeast-1.amazonaws.com/basebank/example:{{env `D_TAG` `latest`}} ", これによって2つのことが実現できました。 環境変数 D_TAG によって、dockerイメージのタグをデプロイ実行時に指定します(省略時は latest )。 環境変数 AWS_ACCOUNT_ID によって環境ごとの差を吸収します。こうすることで、prdとstgのタスク定義を一括で管理できます。 なお、これらの機能はecspressoの README で説明されているので、あわせて参照いただければと思います。 CircleCI設定 いきなりですが、今回作成した .circleci/config.yml です。縦に長いですがご容赦ください。 .circleci/config.yml # https://circleci.com/orbs/registry/orb/circleci/slack # https://circleci.com/docs/2.0/env-vars/#using-bash_env-to-set-environment-variables version : 2.1 orbs : slack : circleci/slack@2.0.0 commands : install_awscli : steps : - run : | sudo apt-get install python-pip sudo pip install awscli setenv_docker_tag : steps : - run : echo "export DOCKER_TAG=${CIRCLE_SHA1:0:8}" >> $BASH_ENV setenv_stg : steps : - run : echo "export AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXXXXXXXX" >> $BASH_ENV - run : echo "export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY_STG" >> $BASH_ENV - run : echo "export ECR_ENDPOINT='yyyyyyyyyyyy.dkr.ecr.ap-northeast-1.amazonaws.com'" >> $BASH_ENV setenv_prd : steps : - run : echo "export AWS_ACCESS_KEY_ID=YYYYYYYYYYYYYYYYYYYY" >> $BASH_ENV - run : echo "export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY_PRD" >> $BASH_ENV - run : echo "export ECR_ENDPOINT='zzzzzzzzzzzz.dkr.ecr.ap-northeast-1.amazonaws.com'" >> $BASH_ENV jobs : test : docker : - image : circleci/golang steps : - checkout # (略) build : ## (B) docker : - image : circleci/golang steps : - slack/notify : message : "begin build" - checkout - setup_remote_docker - install_awscli - run : name : docker build command : | make build - setenv_docker_tag - setenv_stg - run : name : stg docker tag & docker push command : | $(aws ecr get-login --no-include-email --region ap-northeast-1) docker tag "basebank/example" "${ECR_ENDPOINT}/basebank/example:latest" docker push "${ECR_ENDPOINT}/basebank/example:latest" docker tag "basebank/example" "${ECR_ENDPOINT}/basebank/example:${DOCKER_TAG}" docker push "${ECR_ENDPOINT}/basebank/example:${DOCKER_TAG}" - setenv_prd - run : name : prd docker tag & docker push command : | $(aws ecr get-login --no-include-email --region ap-northeast-1) docker tag "basebank/example" "${ECR_ENDPOINT}/basebank/example:latest" docker push "${ECR_ENDPOINT}/basebank/example:latest" docker tag "basebank/example" "${ECR_ENDPOINT}/basebank/example:${DOCKER_TAG}" docker push "${ECR_ENDPOINT}/basebank/example:${DOCKER_TAG}" deploy-stg : ## (C) docker : - image : circleci/golang steps : - slack/notify : message : "begin deploy-stg" - checkout - setup_remote_docker - install_awscli - setenv_docker_tag - setenv_stg - deploy : name : deploy-stg command : | make deploy-stg D_TAG=$DOCKER_TAG - slack/status deploy-prd : ## (C) docker : - image : circleci/golang steps : - slack/notify : message : "begin deploy-prd" - checkout - setup_remote_docker - install_awscli - setenv_docker_tag - setenv_prd - deploy : name : deploy-prd command : | make deploy-prd D_TAG=$DOCKER_TAG - slack/status workflows : ## (A) version : 2 test-build-deploy : jobs : - test - build : requires : - test filters : branches : only : master - deploy-stg : requires : - build filters : branches : only : master - slack/approval-notification : message : 'prdにデプロイするにはApproveが必要です' mentions : '<!here>' requires : - deploy-stg filters : branches : only : master - approve-deploy-prd : type : approval requires : - deploy-stg filters : branches : only : master - deploy-prd : requires : - approve-deploy-prd filters : branches : only : master 以下、工夫したポイントを解説していきます。 (A): workflows デプロイの流れが test-build-deploy というワークフローに定義されています。 GitHubのmasterブランチにfeatureブランチがマージされると、以下のような流れでデプロイが進んでいきます。 テスト ビルド stgへのデプロイ Manual Approval prdへのデプロイ Manual Approvalというのは CircleCIの機能 で、ワークフローの次のjobに行く前に手動による承認を要求するというものです。 これをワークフローに挟み込んでおくことで、stgでの確認を終えるまでprdへのデプロイを待たせることができます。 また、ワークフロー内に slack/approval-notification というものがありますが、これは CircleCIのSlack Orb を利用したもので、以下のようなSlack通知を簡単に出すことができます。( @ が重なっているのは、Orbが @here に対応していないところに強引に入れたため) Slack Orbによる通知 (B): build このjobでは、docker build、docker tag、docker pushを行っています。 この際、stgで動作確認したイメージそのものをprdにもデプロイしたいので、同一job内でstgとprd両方のECRに対してdocker pushしています。 また、dockerのtagとしては、gitのコミットハッシュの先頭8桁を使うようにしました。こうしておくことで、どのコミットからビルドされたイメージなのかわかります。 (C): deploy-stg, deploy-prd 各環境へのデプロイを実行するjobです。 具体的なデプロイコマンドはMakefileにラップして、例えばstgであれば make deploy-stg D_TAG=$DOCKER_TAG のようにしています。この D_TAG というのはecspressoに渡すための環境変数です。 Makefileのターゲットとしては以下のようになっています。 deploy-stg: bin/ecspresso AWS_ACCOUNT_ID=yyyyyyyyyyyy \ ./bin/ecspresso deploy --config=config/stg.yml deploy-prd: bin/ecspresso AWS_ACCOUNT_ID=zzzzzzzzzzzz \ ./bin/ecspresso deploy --config=config/prd.yml Makefileにラップしておくことで、いざというときには手元からもデプロイしやすくなっています。 おわりに CircleCIとecspressoを用いて、ECSへのデプロイメントパイプラインを構築しました。 しばらく使ってみるうちにいくつか気になるところも出てきたので、引き続き改良していこうと思っています。 また、今回ひととおりのECSデプロイを組んでみて、ECS自体にも慣れることができました。 次の機会があればCodePipelineによるBlueGreenデプロイメントを使うパターンなども試してみて、今回作ったものとの比較できればと考えています。そのときにはまた本ブログで紹介しますので、お楽しみに。
アバター
こんにちは! この度、3/29(金)から3/31(日)に開催された PHPer Kaigi 2019 にて、BASEがゴールドスポンサーとして協賛&3名のメンバーが登壇いたしましたので、今回のそのレポートを書いていきたいと思います! 会場レポート 今年の会場も去年と同じく 練馬区立区民・産業プラザ Coconeriホール にて開催されました。入り口ではロールアップバナーが出迎えてくれます。 アイキャッチ画像にもありますとおり、本当にたくさんPHPerたちが集まっていました。「同窓会のようなカンファレンスにしたい」という実行委員長の言葉もあって、PHPerたちが楽しみながら互いに交流を深める仕掛けがたくさんあり、あちこちで盛んな交流が行われていました! トークの採択を通して選ばれた登壇者による発表ももちろん、アンカンファレンスによる突発的な発表、IRT(Interactive Round Table)による相談会(こちらも突発的なものがありました!)など、「主催者側がコントロールしてない突発的なイベントが発生してしまう」ほど練度の高いエンジニアが集まり、思う存分技術談義が楽しめるような圧倒的空間でした!(もちろん楽しいですよ!)同時にすごいエンジニアたちがこれだけ集まるのだからと、PHP界隈の盛り上がりを感じずにはいられません。 そんなPHPer Kaigiに、今回弊社はゴールドスポンサーとして協賛させていただき、3名のエンジニアが登壇いたしました! 登壇スライド 「質」の良いユニットテストを書くためのプラクティス by 東口和暉 BASE BANK株式会社 Dev Divisionでソフトウェアエンジニアをやっている東口( @hgsgtk )です。 私は、ユニットテストに関心が強く、最近のカンファレンスではユニットテスト関連の話をしているのですが、今回もユニットテストの話です。 以前、 PHPカンファレンス2018 にて、 PHPバージョンアップと決済リプレイスを支えたユニットテスト というトークで、 テストの量 を増やしていった過程を話しました。今回のトークは、 テストの質 に焦点を当てたものになります。 仕事の現場で発せられる「テストの質」という言葉について「その本質・意味はなんなんだ」というなにやら壮大なテーマをモヤモヤ考えていました。途中のいくつかのカンファレンス・勉強会・ブログでのアウトプットを通じて少しずつ考えを整理していって、30分で話せる内容にまとめました。 それなりに壮大なテーマを発表したので少し反響が不安だったのですが、聴講者の方から「わかりやすかった」などの良い反応を頂いたり、はてぶやTwitterでもたくさん拡散していただいて、トーク採択から3ヶ月間、考え抜いてまとめたものが多くの人に役立つものになったことに安堵しています。また、会場で公開収録されていた PHPの現場 28. ファミコンで理解する DI(ytake) でもトークを紹介していただいてとてもありがたい限りでした。 特にアウトプットしてよかったと感じているもう一つの要素として、会場内での質問やAsk the Speakerによって多くの議論ができたことが挙げられます。せっかくなのでその際の内容を共有します。 質問・Ask the Speakerでの議論 質問:それでもprivateメソッドに対してテストしたいと思った時どうするか 「privateメソッドに対してもテストしたい時があり、テストしないということにもやもやを感じる」という疑問がありました。これについてその後のAsk the speakerにて議論なども踏まえて、3つの観点でまとめます。 1. private methodを切り出す選択肢 「privateメソッドをテストしたい」と思った時点で、そのメソッドは責務を持っていることが考えられます。そのため、「privateメソッドをテストしたい」と思った時点で別クラスへ切り出すなど設計の検討をする必要があるかもしれません。 2. どの視点を前提とするか 「privateメソッドをテストしない」という主張の根底には、オブジェクト指向という視点が前提にあり、手続き型的に考えると可視性はprivate修飾子で明示した上で、privateメソッド内の手続きはテストしたいという考え方もあるというフィードバックをいただきました。 たしかに、プログラム開発をどういう視点でみるかによってここの考え方は変わるポイントだなと感じたと共に、「プロジェクトとして何を大事にするか」によって判断が変わる可能性がありますね。 3. 変更の頻度をどこまで気にするか 「privateメソッドをテストしない」という主張の根拠として、privateメソッド自体の不安定さをあげました。しかし、テストを書いている以上、「しっかり落ちてほしい変更」もありますよね。この点に関して、落ちてほしい変更というものがある中で、どういう変更を「変更の頻度が高い」と捉えるかについての質問がありました。 オブジェクト思考の考え方の延長線上として、テスト対象をブラックボックスと捉えた上で、外部への振る舞いをテストで保証し、その振る舞いの内部で行われている処理詳細についてはテストでは検証しないという考え方が前提にあると解釈しています。 その解釈を前提とした場合、変更には「外部に対する振る舞いを変えるもの」と、「そうではないもの」という2種類が存在します。前者の変更はシステム全体の欠陥になりうるため「しっかり落ちてほしい」反面、後者の変更は「内部の処理詳細」の変更に対して落ちることになるので、「落ちてほしくない」ものと捉えられると思います。 つまり、privateメソッドの実装は、「内部の処理詳細」を担っているケースが多いため、「privateメソッドは極力テストしない」というふうに説明させていただきました。 どこまでモックするか 「不安を軽減するためのテスト」と考えると、AWS S3など外部サービスをモックせずに直接テスト対象に含めて不安を軽減したいという気持ちがあるという考え方をフィードバックとしてもらいました。これは、 PHPの現場 28. ファミコンで理解する DI(ytake) でも話題に上がっていましたが、「どこまでをテスト対象とみなすのか」・「何をテストしたいのか」といったテストに対する要件から、テストの不安定さ・速度の低下といったデメリットなど様々な考慮事項を踏まえて、総合的に判断しないといけない部分で難しいポイントですね。 まだまだ、言語化できていない領域がたくさんあるので、これからも精進して継続してアウトプットしていこうと思います。 PhpStormでコードを理解する技術 by 田中孝治 BASE Product Division で技術基盤の整備を担当している田中 ( @tenkoma ) です。 今年初めくらいにアプリケーション開発をより容易にするため、ユニットテストをPhpStormから実行できるようにしましたが、PhpStormを使ってコードを理解するために様々な機能を使ってきたと思い、そのノウハウをまとめて発表しました。 今回の発表ではIDEでコードを理解するための技法を4つに分類したのが成果かな、と思っています。 単方向依存を実現する静的解析ライブラリのご紹介 by 川島慧 田中と同じくBASE Product Divisionで技術基盤を担当している川島( @nazonohito51 )と申します。 今回は自作していた静的解析ライブラリのご紹介をさせていただきました(BASEのプロダクトではまだ使ってませんが、機会を見て導入していきたいと考えています)。元々15分相当の内容を5分に凝縮しているため「マシンガントーク」とか「いつ息継ぎしてるんだ」とか色々言われました(笑) シンタックスの強化やPhpStormの影響で近年のPHPソフトウェアは静的構造を持つようになってきた時代であることを背景に、どうすれば設計に意識を持ってもらえるか、どうすれば設計者の意図を表明できるか、ということを考え続けた結果生まれたライブラリです。PHPという言語がサポートしてくれない領域を静的解析による力技でカバーしようとしているのですが「そうだよこれこれ、これが欲しかったんだよ」と、ありがたいことに会場内の沢山の人に興味を持ってもらえて、何人かの方の参加レポートでも取り上げていただけました。引き続き機能を拡張して、開発チーム全員が同じ設計指針を共有して開発できる環境づくりを支えるライブラリにしていきたい所存ですのでよろしくお願いいたします。 まとめ 3日間開催というおそらく開催期間という意味で国内最大のPHP系カンファレンスにもかかわらず、トラブルもなく大変実りある時間を過ごすことができました。大量のCFPへのトーク応募が殺到する中、3名もの登壇者を送り出すことのできた弊社としましても、今回のカンファレンスを大変意義深く感じております。実行委員長の長谷川様( @tomzoh )をはじめ実行スタッフの皆様方、登壇者の皆様、スポンサー企業各位、もちろん聴講者の皆様方にこの場を借りて御礼申し上げます。
アバター
こんにちは、 BASE BANK株式会社 でソフトウェアエンジニアをやっている東口( @hgsgtk )です。 さて、Eコマースプラットフォーム「BASE」は、2019年3月29日(金)から3/31(日)に開催される「 PHPer Kaigi 2019 」にゴールドスポンサーとして協賛します。 PHPer Kaigiへは昨年に引き続き今年もスポンサーをします。昨年のようすは こちら をぜひご覧ください。 今年のPHPer Kaigiは、 PHPerチャレンジ という企画など盛りだくさんの内容で、参加するエンジニア一同とても楽しみにしています。 また、BASEから3名のメンバーが登壇予定です。 3/29(金)17:55~ Track A レギュラートーク 30分「 「質」の良いユニットテストを書くためのプラクティス 」  スピーカー:東口 和暉( @hgsgtk ) 3/31(日)11:25~ Track B レギュラートーク 15分「 PhpStormでコードを理解する技術 」  スピーカー:田中 孝治( @tenkoma ) 3/31(日)16:05~ Track A LT「 単方向依存を実現する静的解析ライブラリのご紹介 」  スピーカー:川島 慧( @nazonohito51 ) 当日ご参加される方は、ぜひ登壇を聞きにいらしてください! #BASE_PHP_Yatteiki
アバター
出典: https://unsplash.com/photos/36Vbwo1OiZU BASEでData Strategyチームのマネージャーをしている鈴木僚です。 Data Strategyチームのミッションは、データを使ってプロダクトを成長させ、戦略的に事業を推進させることです。 EC事業では、オーナーズ(ショップオーナー)・購入者・社内メンバーの3者からなる膨大なデータが日々蓄積されています。Data Strategyチーム(以下、DSチーム)では、その3者に対して、より良い意思決定ができるよう機械学習を活用したソリューションを提供しています。例えば、直近ではオーナーズがより簡単にショップ運営ができたり、ショップと購入者のマッチングをより適切なものにしていくことに取り組んでおります。また、安心して購入者の方々にショッピングを楽しんでいただけるように商品の品質の自動チェックも始めております。 中長期的には、プロダクトだけでなく経営戦略、事業戦略など会社全体でデータを使った意思決定ができるようにすることを目指しています。 チーム設立から1年が過ぎ、組織としてのアウトプットも安定してきたため、今回はチームビルディングをどう進めてきたか、時系列順に共有したいと思います。 目次: Phase 0 チームを作る前にすべき事 Phase 1 チーム発足、ミニマムスタートを最速で Phase 2 レコメンドモデル(ショップ教えるくん)リリース Phase 3 学習モデル作成とパーソナライズ Phase 4 マイクロサービスアーキテクチャと本格稼働 Phase 5 属性情報を取得 Phase 6 BASE BANK Phase 0:チームを作る前にすべき事 まだ、自分一人しかいない状態。 周りのチームはもりもりビジネスを進めているので、焦りを感じます。この焦りをうち消すためにも、事業のゴールに対して現状・課題・理想をなるべく早く掌握する事がキーとなります。 *1 *2 Phase 0 チーム発足前 このフェーズで実施したのは以下の通りです。事業規模にもよりますが、心理的に2週間位で終わらせたいです。 このフェーズでやるべきこと: 現状のシステムを把握する(何がどこにあって、何をしている?) 組織のビジョンと、ゆるいロードマップを作る ビジョンに賛同してくれる人材の募集 チームメンバーの募集 チーム方針を決定したら、その方針に賛同してもらえそうなエンジニアを社内外から集めることになるかと思います。 データ戦略を司るチームを立ち上げるポイントとしては、以下の経験者がなるべく初期の段階で揃うことかと思ってます。 ビジネスプランナー 機械学習エンジニア データアナリスト また、マネージャーに求められる役割としては、このあたりが重要かと考えてます。 ビジネスモデルとコストマネジメントはマネージャーが受け持つ 集中出来る環境:外部からの突発タスクはなるべくマネージャーが拾う 相談を自由にできる雰囲気づくり(メンバーからの相談を求めるだけではなく、相談しやすいチームメンバーの環境構築にもマネージャーの力量がかかってます。) 良い道具、良い開発環境、実力の発揮できる時間の提供 前処理がされた、質の良いデータの準備 得意なことは得意な人に任せる、任せられる雰囲気づくり 成長の機会の提供:論文・資料・勉強会・学会、input出来る機会は全力で応援する・すべき Phase 1 : DSチーム発足、速度優先でミニマムスタート 社内のBI環境を構築したメンバーが加わり、過去の施策内容にグッと迫る事ができるようになりました。 Phase 1 チーム発足時の状態 準備運動なしに全力疾走すると足がつるのと同じように、ビジネス案件を実施する前に、必要最低限の環境を揃えます。とはいえ、組織として社内的信用は無なので、組織イメージが社内で固まる前にアピアランスを上げる努力が必要となります。すなわち、 本番にデプロイできる何かを作る 。どのような業務であっても過去に頓挫したタスクが存在するので、これらの中から優先して探します。なぜなら、以下のような事が事前に分かっているからです。 既にニーズの検証は行なっている 期待される効果もわかる なぜ止まったかもわかる 検討した結果、DSチームの最初のタスクは、アプリ内における おすすめショップのリコメンド に決定しました。前提の共有ですが、アプリとは、ネットショップ作成サービス「BASE」で開設された70万のショップがすべて集まるショッピングアプリです。それまでアプリ内の「おすすめショップ」は、ショップのキュレーションを担当する社内のメンバーがマンパワーでピックアップしていました。 ニーズ キュレーターによるレコメンドはキュレーターのセンスに左右される 担当キュレーターが休むと、レコメンドが止まる 期待される効果 CTRが上がる→CVRも上がる→GMVに繋がる なぜ止まったか 分析まで行ったが、実装する機械学習エンジニアがいなかった このフェーズでやるべきこと: ミニマムスタート 必須の環境作り 前処理とログ取得がきちんとできる環境を作る 効果測定ができる環境を構築する 基本的な開発環境が整う チームのアピアランスを上げる 本番にデプロイできる何かを復活させる これで、アウトプットを生み出す状況が整いました。 Phase 2:レコメンドモデル(ショップ教えるくん)リリース 既存の仕組みが存在する場合、担当チームとの意識合わせと共感が成功に結びつきます。 キュレーターが所属しているチームとレコメンドの目的や背景、そしてチームが持つ価値観の共有と共感した上で、既存のオペレーション内容と効果測定基準をヒアリングし、数値目標を定義しました。 Phase 2 レコメンドモデルのリリース この段階から徐々にキュレーターの業務内容に影響してきます。具体的には、冒頭に触れた3者向けのコンテンツ育成やブランディング等、より人と人とのコミュニケーションが重要となる業務が中心となっていき、全体を俯瞰する業務になってきます。一方、機械学習が活躍する分野の一つとしてパーソナライズがあり、その部分についてはDSチームが担当することとなりました。言うなればセンスと数字の分業と考えています。 実際、今後このような形で人間と機械(ロジック)がそれぞれ得意なタスクに分かれて業務が進行していくかと思います。とはいえ、一方で今まで人が担当していた部分なのでロジックを擬人化してみました。 擬人化したレコメンドモデル その時の紹介文がこちら: ショッピングアプリBASEのおすすめのショップ枠で修行させていただくことになった、『ショップ教えるくん』です!全アプリユーザーのお気に入り、フォロー、購入データから、あなたが好きそうなショップを考えて選びます! まだ選んだショップをフォローしてくれて嬉しい!というポジティブな感情しかないので、選んだのに無視された、、などのネガティブな感情には対応できてませんし、24時間に1回しか勤務できませんが頑張るのでこれからよろしくお願いします。 結局、 ショップおすすめ君 とか おすすめショップ君 とか名前をちゃんと覚えてもらえませんでしたが、ひとまず社内で何をやっているのかは周知できました。 このフェーズでやるべきこと: 本番環境の環境構築 最初は計算結果をバッチでDBに格納する DB・サーバーサイド・アプリケーションチームとの連携をしっかりと取る 実装と効果検証 導入した結果、タップ率は従来に比べ4倍以上に向上しました。 Phase 3:学習モデル作成とパーソナライズ 成功事案ができると、チーム的には、組織の仕組み チョットワカル の段階に入ったともいえます。ですが、急に前が開ける段階が来るまでは、類似手法で改善できる箇所を探しつつ、バッチ処理とサバイバルコードからの脱却を目指します。 また、それまでサービスドメインに適応した基礎データ、例えば単語辞書を作成していなかったので、このタイミングで整備するようにしました。 devblog.thebase.in 伸ばすとどこか歪むので見つける、治す この頃からBatch処理におけるデータ転送量やDBへの負荷が高すぎて本番系に悪影響が出始めるようになってしまいました。また、似たような処理を行うインスタンスも増えてきました。 ここでメンバーが増えたので、バッチ処理を学習済モデルを用いてAPIで必要な時に都度計算する方式に置き換えてDBへの負荷を減らし、あわせておすすめ商品、関連商品など、複数のサジェストの実施できる環境を構築し始めました。 Phase 3 学習モデル作成とパーソナライズ パーソナライズの開始 学習モデルの特性として、よりセグメント化されたデータの方が精度が良くなります。セグメントも含めて最初から推定する方法もありますがあまり精度は良くありません。それよりは一人一人におすすめ出来るパーソナライズという目的があるのであれば、各ユーザー様に直接確認するのが一番早い、ということで、アプリユーザーに対してチュートリアルの際に性別と興味のあるジャンルを伺うように変更しました。ありがたいことに、相当数の方に答えていただいているため、パーソナライズの基礎を構築することができました。 このフェーズでやるべき事: コードが本番に出た時に、問題が起こりそう、もしくは発生している時に、成果物自体が何を目指していたかを復習する 成果物は会社の利益になるか、数字で説明しようと思ったらできるようにしておく。即座に数字にする必要はない。逆に数字目標だけおうと、必ずサバイバルコードができて、後で倍苦労する サバイバルコードを廃止し、学習済モデルを使用する形に変更する レコメンドのロジック改善(学習モデルもパーソナライズ化) 効果測定結果の理論的な説明 このあたりで改めて機械学習チームにおける環境構築の経験と測定結果の正当性がきちんと把握できるメンバーが不足している事が改めて感じられたので、募集内容の変更を行いました。このように特にチームの規模が小さい段階ではチームの状況に応じて募集要項をこまめに変更することは重要だと考えていますし、実際に募集要項をこまめに変更している会社も多いように感じます。 Phase 4:マイクロサービスアーキテクチャ化と安定稼働 さらに新しいメンバーが増え、AWSのサーバレス環境へ完全移行しました。 Phase 4 マイクロサービスアーキテクチャと本格稼働 また、Terraformを用いてインフラの構築、変更管理を安全にかつ効率的に行える仕組みを導入しました。Terraformは比較的最近リリースされたAWSコンポーネントにも対応しているため、新しい機能を追加する際もほぼほぼ問題ない状態です。 *3 また完全移行したことによって、DS AWSと呼んでいる独自環境が誕生し、本番系環境とは基本APIを介してデータをやりとりするようになりました。このあたりはチームメンバーの氏原の記事が詳しいです。 devblog.thebase.in それに伴い、データ周りも分析やモデル作成用途のものはDS AWSに保管するように変更し、大量データがあっても自分たちで負荷コントロールできるようになりました。 そこで、本番系では躊躇していた画像データの分析を開始し、関連商品のサジェストに画像とテキストの組み合わせたモデルを使用するようになりました。こちらによる回遊性は非常に効果が高かったです。 自分たちの責任で環境を何度も再構成できるということの恩恵に、発表されたばかりの論文やロジックの検証も手軽にできるようになりました。実際の例として、こちらの記事にあるようなモジュールをいち早く本番運用に適用することができました。 devblog.thebase.in このフェーズでやる事: サーバレスへの完全移行 インフラの整備 本番環境と分離I αやβのモジュールを採用する勇気 Phase 5:テキストや画像の属性の取得 パーソナライズが進んでくると、改めてクラスタリングを行いたくなってきます。そのためには属性情報が重要になってくるため、再び社内外からヒアリングを行います。 そして、いくつか肝となる属性が見えてきました。ハンドメイドと量産品の違い、商品の品質など、従来の画像やテキスト分析だけでは難しい属性です。そう行った情報を元に、ロードマップの先を伸ばす施策を考えるようになりました。企画と未来は尽きてしまってからでは事業的にもモチベーション的にもリカバリーが難しいので、随時更新・修正するフェーズを設けることによってハンドリングしています。 このフェーズでやる事: 属性用の学習モデルの作成 信用モデルに必要なパラメータの収集開始 企画と未来は尽きる前に補充する Phase 6:BASE BANKと機械学習 属性情報を作成している段階で、ショップ単位で、月次決算を試算したいという話が出てきました。また、このタイミングで、データ分析を得意とするメンバーがチームに加わり、それにあわせて100%子会社のBASE BANK株式会社が本格的にサービスを立ち上げるという話が進行し、即効薬を求められるようになりました。 Phase 6 BASE BANK 例えば定番?のDCF法(割引キャッシュフロー法)などを試してみました。 shikakutorunara.tokyo 他にも試した手法の一つをチームメンバーの岡が記事にしています。 devblog.thebase.in ここで作られたロジックは、BASE BANKが提供している、即時に資金調達ができる金融サービス 「YELL BANK(エールバンク)」 の調達可能金額の算出に現在用いています。 まとめ 今回は、駆け足でDSチームの1年間を振り返ってみました。チームが大きくなるにつれ、より多くのメンバーやビジネスシーンが関わり、スケール感が増してくるのを感じることができました。今現在も新たなPhaseが進行中です。 BASEでは一緒にネットショップ作成サービスを開発・改善するエンジニアを募集してます。 機械学習チームでは、様々なデータや技術を使ってECならではの開発を続けています。 ご興味のある方はぜひ遊びにきてください!! binc.jp *1 : この段階でチーム方針の資料を作成することになるかと思うのですが、その資料にバズワードや図を取り込むと読み手・書き手共に不幸の始まりになるので、なるべく具体的にかつ自分の言葉で説明できる事が望ましいです。(例えば人工知能・AI、光り輝く脳の図とか) *2 : 以前の職場では、うっかり資料にバズワードが蔓延してしまい、エンジニアを含めチームが何を作ったら成果と言えるのか理解できなくて、頭を抱える状況が生まれてしまいました。 *3 : 実際に待ったのはFargate導入の際、実装されるのを少し待った位です。
アバター
出典: https://unsplash.com/photos/JKUTrJ4vK00 BASE BANK株式会社 でソフトウェアエンジニアをやっている東口( @hgsgtk )です。即時に資金調達ができる金融サービス「 YELL BANK(エールバンク) 」というプロダクトを開発・運用しています。 さて、日々、ユーザーに使っていただくサービスを運営していく中で、「サービスを安定的に提供できているか」という観点において、 監視する技法 について関心があります。 そんな折、『 入門 監視――モダンなモニタリングのためのデザインパターン 』という書籍が最近発売され、世間的にも監視について、関心が高まっているかと思います。 今回は、この書籍の中から、実際に業務で実践していた「 Health エンドポイントパターン 」について、 実践例 と 書籍の内容の深掘り を含めて紹介しようと思います。 また、 Mackerel Meetup #13 Tokyo というイベントでも今回の内容を発表いたしましたので、こちらも合わせてご参照ください。 Health エンドポイントパターンとは アプリケーションの健全性を伝えるアプリケーション内のHTTPエンドポイントを作る パターンです。 カナリアエンドポイント(canary endpoint)・ステータスエンドポイント(status endpoint)とも呼ばれ、特に名前がついていることを知らずに使っている方も多いのではないでしょうか。(筆者もその一人でした。) このエンドポイントでは、最低限「HTTPリクエストを受けてレスポンスを返せるか」という情報のみを返すこともできれば、デプロイされたバージョンや依存関係のあるDBなどのサブコンポーネントのステータスといった情報までをレスポンスに含めることもできます。 使用用途としては、次のようなケースがあげられます。 Mackerel など監視SaaSからの 外形監視 ALBなど ロードバランサのヘルスチェック アプリケーション 起動確認のデバッグ 実際に、実践する場合、アプリケーションの状態を伝えるHTTPエンドポイントを作成します。例えば、 /healthcheck や /ping などと言った名前になるでしょうか。 そのエンドポイントは、 ヘルスチェックに成功すればHTTPステータスコード200 を、 失敗した場合は200以外(特に503) を返すという実装になります。 BASE BANKでの実践例 BASE BANKでは、2つのエンドポイントを用途別に用意する方法をとっていて、それぞれ外形監視の対象としています。 ひとつが、 コンテナ単体の生存確認 を主目的とした、 /health 、もう一つが、 依存しているDB・Redisなどへの接続までを確認対象に含める 、 /health/deep です。 なお、この実践例は、 「 Mackerel Meetup #13 Tokyo 」で 山根 ( @fumikony ) より発表した、『 BASEにおけるMackerel利用上の工夫と困りごとのご紹介 』内でも事例として言及しております。 Mackerel 等の監視SaaSとの組み合わせという点では、合わせてこちらを一読いただけるとより良いかなと思います。 単体の生存確認: /health Go言語で実際に実装する場合は、例えば次のようなHTTP Handlerになります。 // HTTPステータスをフィールドに含むレスポンスフォーマット type SimpleResponse struct { Status int `json:"status"` Message string `json:"message,omitempty"` Detail string `json:"string,omitempty"` } // 200レスポンスが返却される func SimpleHealthCheck(w http.ResponseWriter, r *http.Request) { rs := SimpleResponse{ Status: http.StatusOK, } respondJson(w, rs, http.StatusOK) } // JSON形式でレスポンスを返却する func respondJson(w http.ResponseWriter, body interface {}, status int ) { w.Header().Set( "Content-Type" , "application/json; charset=utf-8" ) w.WriteHeader(status) if err := json.NewEncoder(w).Encode(body); err != nil { fmt.Fprintf(os.Stderr, "failed to encode response by error '%#v'" , err) w.WriteHeader(http.StatusInternalServerError) return } } これを、 /simple/.health_check に対してルーティング設定した場合は次のようなレスポンスとなります。 -> % curl -i http://localhost:8080/simple/.health_check HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Mon, 04 Mar 2019 13:24:23 GMT Content-Length: 15 {"status":200} これは、ロードバランサからの外形監視などの際に利用しています。 依存サービス込みの動作確認: /health/deep 次に、DBやRedisなど依存している外部サービスに接続できているかどうかを確認対象に含めるエンドポイントです。 func SimpleDeepHealthCheck(w http.ResponseWriter, r *http.Request) { _, err := NewMySQL(config.DB) if err != nil { // DBへのコネクションにてエラーが発生した場合は503レスポンス rs := SimpleResponse{ Status: http.StatusServiceUnavailable, Message: "failed to get connection database" , Detail: err.Error(), } respondJson(w, rs, rs.Status) return } rs := SimpleResponse{ Status: http.StatusOK, Message: "success to connect server" , } respondJson(w, rs, rs.Status) } これを、 /simple/.health_check/deep に対してルーティング設定した場合次のようなレスポンスが返却されます。 -> % curl -i http://localhost:8080/simple/.health_check/deep HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 Date: Mon, 04 Mar 2019 13:33:22 GMT Content-Length: 53 {"status":200,"message":"success to connect server"} 例えば、データベースに対する接続が失敗した場合は、次のような503レスポンスが返却され、アプリケーションの健康状態について知ることができます。 -> % curl -i http://localhost:8080/simple/.health_check/deep HTTP/1.1 503 Service Unavailable Content-Type: application/json; charset=utf-8 Date: Mon, 04 Mar 2019 13:35:38 GMT Content-Length: 106 {"status":503,"message":"failed to get connection database","string":"sql: connection is already closed"} このパターンのエンドポイントは、 Mackerel からの外形監視で主に利用しています。 利点 外形監視に利用できる APIの通信ができるかといった外形監視は特にアプリケーションを運用していると最低限関心をもつところだと思います。このパターンでは、ステータスコードで状態を判別できるため、外形監視に使いやすいかと思います。 デバッグに有効 起動したアプリケーションが正しくHTTPリクエストを処理する事ができるかを知る上で、重宝しています。 さらに、依存関係のあるDBなどのサービスへのコネクションが取れるかについても最低限確認できるため、起動確認に有用です。 余談:コンテナベースアプリケーションとの親和性 運用している YELL BANK というサービスは、以前公開した『 ECS(Fargate)でコンテナアプリケーションを動かすための設定情報の扱い方 』という記事でも紹介した通り、コンテナ上で動作することを前提としたアプリケーションとして機能提供しています。 コンテナ内で動かすアプリケーションにおいても、外形監視は重要と感じていますが、実際このパターンはコンテナベースアプリケーションにおいてはどのように考えられるでしょうか。 コンテナベースアプリケーション設計として、「Health エンドポイントパターン」をどう評価できるかを考えるにあたり、 redhat が公開している『 Principles of container-based application design 』 から参考になる原則を一つ見てみましょう。 それが、「 HIGH OBSERVABILITY PRINCIPLE (HOP) 高観測可能性の原則 」 という設計原則です。 これは、コンテナ内部をブラックボックスのように扱う設計前提を持った上で、自身のアプリケーションの活動状況や準備状況など、様々な状態チェックについてAPIを提供するという設計について言及しています。 自身の健康状態を伝える「Health エンドポイントパターン」も、観測度を上げる上で有用なパターンと言えそうですね。 ドラフト段階の共通レスポンスフォーマットについて さて、「Health エンドポイントパターン」について、パターンと実践について見たところで、少し話を深掘りして『 Health Check Response Format for HTTP APIs 』という議論中の共通レスポンスフォーマットについて見ていきたいと思います。 これは、『 入門 監視――モダンなモニタリングのためのデザインパターン 』の「付録C」という章で言及されているものです。 どういったレスポンスを返すべきか、議論中のこのフォーマットについて少し深掘りしてみます。 Health Check Response Format for HTTP APIs このフォーマットは、大きく以下の3つの特徴を持ちます。 JSONフォーマット を利用する media-typeは、 application/health+json とする 必須フィールドである status と いくつかのオプショナルなフィールドを含む 必須フィールド: status status には「次のどれかの値を設定する」とされています。 pass : healthy status code: 2xx-3xx range (MUST) その他、下記の選択肢も可能 Node's Terminus をサポートするための ok JavaのSpringBootのための up fail : unhealthy status code: 4xx-5xx range (MUST) その他、下記の選択肢も可能 Node's Terminus をサポートするための error JavaのSpringBootのための down warn : healthy, with some concerns status code: 2xx-3xx range (MUST) warningレベルのタイプが設定できるのは一つ面白いところかなと思いました。 その他フォーマット一覧 必須とされている status 以外にも次のフィールドがオプショナルな項目として提示されています。 status version (optional) - サービスの公開バージョン releaseId (optional) notes (optional) - 健康状態に関する記述 output (optional) - 生のエラー出力、 statusが pass のときは省略すべき details (optional) - 依存しているサービスも含めた詳細情報、 The Details Object というオブジェクトで定義 links (optional) - より詳細情報を得るための外部URLなど serviceId (optional) - アプリケーションスコープなユニーク識別子 description (optional) - 人間に優しい説明 The Details Object 下流の依存関係やRedisなどのアプリケーションから見たサブコンポーネントの状態を伝えるためのオブジェクトとして提示されています。公式の例では、以下のようにcassandraやcpu・memory状態などアプリケーションが依存するものについての健康状態を伝える例を示しています。 " details ": { " cassandra:responseTime ": [ { " componentId ": " dfd6cf2b-1b6e-4412-a0b8-f6f7797a60d2 ", " componentType ": " datastore ", " observedValue ": 250 , " observedUnit ": " ms ", " status ": " pass ", " time ": " 2018-01-17T03:36:48Z ", " output ": "" } ] , " cassandra:connections ": [ { " componentId ": " dfd6cf2b-1b6e-4412-a0b8-f6f7797a60d2 ", " type ": " datastore ", " observedValue ": 75 , " status ": " warn ", " time ": " 2018-01-17T03:36:48Z ", " output ": "", " links ": { " self ": " http://api.example.com/dbnode/dfd6cf2b/health " } } ] , " uptime ": [ { " componentType ": " system ", " observedValue ": 1209600.245 , " observedUnit ": " s ", " status ": " pass ", " time ": " 2018-01-17T03:36:48Z " } ] , } , inadarei.github.io Health Check Response Format for HTTP APIs から学ぶこと これは、現時点では、ドラフト版なので正式に守るべき標準・制約というわけではありません。しかし、実際に「Health エンドパターン」を実践するにあたって、詳細な点について迷いが生まれた際にこのように議論している場所があると知ると、参考になるかと思います。 最後に 私は、PHPやGo言語でのアプリケーション開発がメインのサーバーサイドエンジニアですが、そのような視点でも、『 入門 監視――モダンなモニタリングのためのデザインパターン 』は非常に勉強になります。 迷われている方はぜひお手にとって見てはいかがでしょうか。 また、 BASE株式会社 は、サービスの継続的な提供を守り・発展させていきたいそんな方を募集中です。ご興味があればぜひお気軽に遊びにいらしてください。 binc.jp
アバター