phpunitの`@runInSeparateProcess`,`@preserveGlobalState`利用時の注意点
概要
phpでアプリケーションを書いていて、当然unit testも書いています。
unit testを書いている中でmockが必要なパターンが出てくると思います。
その際にとても有名なmockery
を使っています
んで、mockery
を色々と使ってると@runInSeparateProcess
,@preserveGlobalState
が必要になることが多くあります
@runInSeparateProcess
@preserveGlobalState
正確な情報は上記のリンク先にお任せして、要は別のプロセスにしてグローバル参照させない設定という感じですね。
ぶち当たった課題
別プロセスで稼働するということはtestの中でsetUpBeforeClass
,tearDownAfterClass
を設定していた時に予期せぬタイミングで実行されるという...
具体的に
echo
を仕込んで実際に動かしながら見てみる
テスト対象のクラス
a.php
<?php namespace StaticMethods; class StaticMethods { public static function func() { return "this is static method. \n"; } }
テストコード test.php
<?php namespace Tests; use Mockery as m; use PHPUnit\Framework\TestCase; use StaticMethods\StaticMethods; /** * @group Test */ class Test extends TestCase { public static function setUpBeforeClass() { parent::setUpBeforeClass(); echo 'setUpBeforeClass'."\n"; } public static function tearDownAfterClass() { parent::tearDownAfterClass(); echo 'tearDownAfterClass'."\n"; } /** * @runInSeparateProcess * @preserveGlobalState disabled */ public function test_a() { $mock = m::mock('overload:' . StaticMethods::class); $mock->shouldReceive('func')->andReturn('is this static method ?'); echo(StaticMethods::func()."\n"); } public function test_b() { echo(StaticMethods::func()."\n"); } }
本体予想していたechoの期待値は
- setUpBeforeClass ->
- is this static method ? -> test_aのecho
- this is static method. -> test_bのecho
- tearDownAfterClass ->
実際のechoの期待値は
- setUpBeforeClass -> test_aの設定の別プロセス or もともとの setUpBeforeClass
- setUpBeforeClass -> test_aの設定の別プロセス or もともとの setUpBeforeClass
- is this static method ? -> test_aのecho
- tearDownAfterClass -> test_aの設定の別プロセス or もともとの tearDownAfterClass
- this is static method. -> test_bのecho
- tearDownAfterClass -> test_aの設定の別プロセス or もともとの tearDownAfterClass
この結果何が問題になるか
tearDownAfterClass
とはテストケースの最後に実行されるメソッドです。それが、まだテストが実行中にも関わらず実行されてしまう...😨
この現象でちょっとハマりました
回避方法
何通りかあると思う
- そもそも影響しないように
runInSeparateProcess
の設定があるテストは別に切り出す tearDownAfterClass
を諦めてtearDown
を使う- テストケースが多い場合は遅くなる可能性あるけど致し方なし
- 順番を考慮する
@runInSeparateProcess
の付いているテストを最後に持ってくる。そーすると下記のようになる- setUpBeforeClass -> もともとのプロセスのsetUpBeforeClass
- this is static method. -> test_bのecho
- setUpBeforeClass -> test_aの設定の別プロセスのsetUpBeforeClass
- is this static method ? -> test_aのecho
- tearDownAfterClass -> test_aの設定の別プロセス or もともとの tearDownAfterClass
- tearDownAfterClass -> test_aの設定の別プロセス or もともとの tearDownAfterClass
最後
微妙にハマり、半日は浪費してしまった気がする...😰
プロセスが並列に動いて処理をしているので(プロセス同士は互いに考慮せずに稼働する)、タイミングというか、ケースによっては必ずこの上記のような順序になるとは限らない...😓
副作用は色々あるなぁーと実感しました
フロントエンドのコードベースの改善話(1st step)
はじめに
抱えていた課題感
- フロントエンドのモダン化は結構前からの課題だった
- 今までのコード達はjQuery + pluginをダウンロードして、サーバに配置して、読み込んで、自分で直接書いたjavascriptも読み込んで頑張ってた
- DOMをガリガリ書き換えて頑張ってた。そろそろツライ
- ただ書き換えるにしてもフロントエンドの移り変わりが早くてコレというのが無いなぁ
改善方針
- いきなり全て書き換えることなど無理だし、ビッグバン・アプローチは怖すぎなので当然避ける
- 何に書き換えるか問題は別途考慮が必要なのでちょっとおいておく
- 自分たちの利用用途にあるFWだったりを検討するのに時間が必要なので
- とりあえずは各所に散らばったjQuery + pluginを読み込んで、そのままjavascriptを書いているやり方を止めよう!!
- この方法はバージョン管理もバラバラになりがちだし、ちゃんと動くのかというテスト的なもの不安がありすぎる...
- なのでjQuery + pluginはnpm管理して、es6で書くようにしてwebpackでビルドしてってするようにした
- ついでにwebpackでoptimizeもしとけば少しはパフォーマンスも良いだろう
- まぁちゃんとパッケージ管理するところからスタートする!!
- これ以上傷口を広げない作戦
いざ改善
ハマった点
- jQueryはもはや全画面で使ってるのでglobal用にnpm管理のところから出力したいなぁ
import 'jquery';
上記だけのファイルでwebpackでdestするようにしたが、グローバル参照ができなかった😱
解決方法
webpackの
ProvidePlugin
,loader
とnpmのexpose-loader
を使ったグローバル変数に代入してしまう
window.$ = $; window.jQuery = jQuery;
結局はProvidePlugin
とloader
を使っておいた方が無難な気がしたのでこれにしました。
最後
- とりあえずはこれ以上負債を出し続けなければいけない状況は防げたかなと -> 傷口を広げない作戦
- サービスを運用している以上、一旦止めることもできないし、日々の不具合対応やビジネス的にやらなければいけない新規施策とかはあってというツラさがある
- そんな中でも直ぐに負債になってしまう前のコードの書き方でやらなければいけないのは精神的、モチベーション的にツライのでこの作戦は良いと思ってる💪🏽
iosアプリからのwebviewはレンダリングは通常のブラウザに比べたら遅いよねという話
はじめに
- あるプロダクトでIOSのネイティブアプリからwebviewで既存のページを参照した時のレンダリングのメトリックスの話
- そもそも半分わかっていた事ではあるが、普通のブラウザでのレンダリングとネイティブアプリからwebviewのレンダリングを比べたら普通のブラウザのが早いに決まってるがそれを目の当たりにした話
計測したツール
- New Relicのブラウザ版
- 下記のグラフはネイティブアプリのwebviewから既存ページを参照をはじめた時を境にしたNew RelicのApdexのグラフの図です
- アプリケーションサーバのパフォーマンスは変わらず
- フロントエンドのパフォーマンスだけが悪化
- このグラフの波があった時期になんの変更をしているかと言えばネイティブアプリからwebviewで既存ページにアクセスをはじめたぐらい
少し考慮をすべき点
- ネイティブアプリではよく画面の遷移をよりスムーズにする為に一画面を描画するのにあえて複数ページ or 複数画像を事前に読み込んでたりするのでクライアント(モバイル端末)の仕事が多い点がある
- でも数値的に顕著に悪化してしまってるのでこれはこれで考えどころ
まとめ的に言いたい事
- フロントエンド周りの数値をKPIに据えて頑張っているチームはネイティブアプリのwebviewの部分はノイズになる可能性があるので外して計測すべし
- だいぶ今更だけど、ほぼwebviewだけの側アプリはユーザ体験としてはむしろマイナスんじゃなかろうか
- ネイティブアプリを出す理由は色々とあるけど、より快適にサクサク使えるという意味においてはwebviewはなるべく無くすべき
phanを使ってPHP7化に向かって効率的にリファクタした話
はじめに
そろそろphp7化に向かって動きたいなぁーと感じてて互換性チェックとテストの手間のカットをするためにまずは利用していないコードを効率的に抽出して消したいなぁーと思ったのがキッカケです
コードの見通しもよくなるし、リファクタして不要コード、ファイル削除は皆嬉しいはず
phan
互換性チェックなら下記も使える
GitHub - sstalle/php7cc: PHP 7 Compatibility Checker
メインの話
php7との互換性チェックは別の時に書くこととして効率的なリファクタの話をしようと思います リファクタと言ってもどこからも参照されていないメソッドやファイルなどをガシガシ削減していく事をメインにした
phpmdで感じてた不満
- publicメソッドでunuseメソッドの抽出ができない...privateはできる
- ざっと眺めてるだけで使ってないpublicメソッドが結構あるなーと感じてたので効率的にあぶり出したい...
- https://github.com/phpmd/phpmd
環境設定
- 対象のPHPファイル群はmacのvagrant上でphp5系が動いている
macにphp7環境をphpenvで作りphanとastをinstallして環境を作った
.phan/config.php
の設定
<?php return [ 'directory_list' => [ '/php/app/' ], 'exclude_analysis_directory_list' => [ /php/app/tmp/', '/php/app/tmp_sp/', '/php/app/tests', '/php/app/migrations/', ] ];
実行
./vendor/bin/phan --progress-bar -x -o phan.log
オプションの説明
-x, --dead-code-detection Emit issues for classes, methods, functions, constants and properties that are probably never referenced and can possibly be removed.
phan.logを眺める
結果
- phpmdの時に感じてたpublicのメソッドのunuseを検出できないという不満があった(privateメソッドならできる)。けど100点とは行かないけどpublicなunuse メソッドの検出に成功した
- FW部分とかで本当は参照しているけど検出してしまう部分は致し方ない
zero references to method
で指摘が出た部分がpublicでunuse methodという感じでcat phan.log | grep "zero references to method"
でさらに絞ってみた- 結局上記のgrepで抽出したmethodをide(intellij)から検索して不要だったことを確認してからdeleteした😰
- まぁでも効率的にリファクタはできたと思ってる💪🏽
気づき
Can run in the background (daemon mode)
とあるので定期的にlocalの開発環境でも実行しようかなと思った- smartyから呼び出しているobjectのメソッドも解析対象として動いた
<html> <head>~~~ <body> {$user->get_fullname()} </body> </html>
ちょっとしたオチ
- function名を変数に入れて、その変数からfunctionを実行しているところは考慮されず、使ってないなーと感じて消してしまった。
- bugを出してしまった😰
- エラーログ監視で見つけてソッコー修正しましたけど...すまん
最後
- まぁでも良かったんじゃなかろうか。効率的にリファクタできて
グループ内の合同勉強会でLTした
合同勉強会の概要
- 同じサイバーエージェントグループの
タップル誕生
のアプリを運営しているマッチングエージェントと急成長スタートアップ x 技術的負債
というテーマで勉強会に参加した時のメモ - 各プレゼンは上記のCyberAgentのdeveloperブログを読めばまとまっています
- このブログでは自分がLTした時の話の内容を残しておこうと思います
LT:古株のValueの出し方
主に伝えたい事
少し前提:これまでの経緯とか
- サービス立ち上げからやっているエンジニアって本当に苦労の連続でろくなエンジニアリングなんてしていなくて、ただただ目の前のキャッシュが切れるまでになんとかしなきゃの連続だった。
- 技術の積み上げなんてしている時間などなく、貯金の切り崩しの生活をする
- なので当然、早期に技術的負債を作りやすい傾向にある。ごめん😓
- サービスも成長し、新しいメンバーが入った時、新メンバーは現状のコードや運用の惨劇を目の当たりにする
- 特に
git blame
でだいたいは自分のアカウントが出てきて、なんでこんないけてない感じになってるの?的な質問攻撃連続(質問者には悪気はない) 人を憎まず、コードを憎む
とは言うものの、やはり自分はそこまでデキた人間ではないからdisられているかのうような感覚に陥る。。。反省- あの時はこーだった的に少しは言い返したくなる。
- でも総じて雰囲気が悪くなっていく
ここからが本題で言いたい事
- 初期からいる古株の人はすべてを飲み込む覚悟で臨まないとプロダクトの成長には寄与しない。それが出来なければただの老害となる
- 結局ドロ臭い作業を全て受け持ってるとか、成果の見辛い部分を担ってるとか色々と不満がある。
- 新しく入ってくれたメンバーからは色々と問題点をあげられ言われ放題。
- まぁ色々言いたい事はあるけど、ダメな所はダメでどんな背景があったとしても言い訳しててもしょうがない。そんな時間あったら1日でも早く改善する事を考えるべき
- とにかく立ち止まっている時間などないし、過去を振り返って反省は重要だけど前に進むことのがもっと重要。
- やるべき事はプロダクトを1mmでも良くする事だけで集中すべし
- その人のキャラにもよるけど、古株の振る舞いってとても重要
- 周囲に対する影響度合いで言うと古株の振る舞いは重要。ただのいち社員の発言ではない事を覚えておく
- 自分が抱える不満・本当はこうしたいけど出来ない歯がゆさ・立ち止まる事が出来ないストレスとか挙げたらキリないほどクソいっぱいあるけど全てを飲み込んで、プロダクトの為の発言行動、前向きな姿勢を見せる事で成長のギアが上がる
- 逆に全てを飲み込めず、愚痴っぽくなると全体的に停滞し、プロダクトは良くならない
- 経営者のみなさん、エンジニア古株の苦しみを少しでも理解してもらって🍻しましょう
- お酒の力を少々かりながら本音トークしましょう!
- プロダクトを良くしていきたいという強い思いは同じです
- 経営者の辛さも当然あるとは思いますが、お互いに腹割って🍻しましょう!語りましょう!
最後
- 正直自分も最初は愚痴っぽくなってたし、理解してくれる人がいなくてツライ日々を過ごした。偉そうに書いておきながら全然出来ていなかった。ゴメンなさい🙇
- 過去を振り返るならゴメンなさいという以外何もないです🙇
- 自分はデキた人間ではないので今でも口から出そうな時もあるが、少し立ち止まってプロダクトを良くするには今何が必要かだけを考えるようにしている
Redashへのリプレイスから活用方法までの話
はじめに
最近ウチはAuroraに切り替えをしました。🎉🎉🎉
当然良かった点はいくつもありますが、一つにリーダーエンドポイントが気軽に増やせることがあります
なので一つAurora Readerを作成してAnalytics用途として活用しています。このコトを契機に分析用の仕組みを色々と改善できるなーと感じていて
Aurora切り替えが無事に完了してRedash導入後、1ヶ月経過したので少しまとめて見ようと思います
Redashに移行する前の分析
- バッチで必要なデータを取得・加工してElasticSearchに入れる
- Kibanaからグラフ化してダッシュボード化して見ていた
ここでの課題感
- 分析するデータが増えた場合、バッチ修正して、既存Indexも作り直してってとても面倒だった😰
- 定期バッチで取り込んでいたので多少なりともタイムラグが存在していた😰
- キャンセルなどで過去のデータ=過去のIndexに修正が入った場合に修正するのがとても手間だった😰
- Elasticsearchの運用も日に日にかさんでいった…😰
- Google Analyticsのデータは別で分析してた。一元管理できなかった😰
そこでRedashに乗り換えたわけですが
最終的な構成イメージ
利用者はまず社内の認証システム(Single Sign-On)で認証してからRedashの閲覧できます
Redashのデータ・ソースとしては下記を設定
- AuroraのAnalytics用途のReader
- Google Analytics
- Google Spreadsheet
- Python
Redashを選んだ理由
簡単に書くと下記の点でうちにはマッチすると思った
- 元々データ分析のソースとしてはDBのデータ、Google Analyticsを使っていてこの2つを一元的に扱いたいなーと思ってた
- Redash1系からGoogle Analyticsのデータを直接参照できるようになった
- 元々Google Spreadsheetをフル活用してて、それらの資産を取り込めてダッシュボード化できた点
- Shell Script経由でDBからデータを抽出してSpreadsheetに反映させたりと色々動いていた
- Google App Scriptを活用してSpreadsheetに反映させてたりと色々動いていた
- Elasticsearch+kibanaの時の課題感も当然解消できると思った
他のツールとの比較した
Amazon QuickSight
- Google Analyticsのデータをデータソースとして活用できない… キビシイ😅
- あくまでもAWS内のマネージメントサービス内にあるデータを効率的に分析できるツールのようです
Google Data Studio
- データソースには当然Google Analyticsを扱えた
- Aurora Readerの設定もできそうだったけどセキュリティ的な部分で少々不安を覚えた😅
- 表示している期間と前の期間との比較させて見せるグラフとか気に入ってたりしたんだけど…
- 検討していた当時は無料枠では5つしか作ることが出来ず、また有料枠も明確な価格設定を出してなくて、んーとなった😅
Tableau
ビジネスインテリジェンスとデータ分析 | Tableau Software
- 一番評判の良いツールなので当然、セキュアにDBにつながるし、Google Anayticsにも繋げられる
- ただ、価格がうちにとっては高かった…😅
- ツールの位置づけもバリバリのデータサイエンティストがフル活用してやっとペイするような話を他部署で聞いたし…
そしてRedashをどのように業務に活用しているか
ダッシュボードを複数に分けて使っている
色々一つのダッシュボードにまとめたくなるけど、表示重くなるし、目移りしちゃうので一つにまとめることはやめた。
それぞれの立場の人によって一番みたいデータが異なる。なので見る人が誰で何のデータを一番見たいかを基準にまとめてる
- ビジネスサイド人向けのダッシュボード
- 開発者向けの〇〇機能のチーム向けのダッシュボード といった感じ
あとは期間としては30日間を目安に集計したデータを表示している
- 時と場合によるけど目先追いかけるデータとしては直近30日間が妥当だと思っている
他のツールの計測数値をiframeでRedashのダッシュボードに表示している
うちで言うとNewrelic、SpeedCurveのデータは関連するKPIと一緒に見たいときがある。大体のサービスはiframeでの表示機能を提供しているのでそのURLをコピペしてダッシュボードに一緒に表示している
最近の新たな活用方法
- メルマガ用のアドレス抽出に活用してたり、経理の締め作業に活用してたりしている様子
- そのうちSQLを覚える人が増える事を期待している🙂
こうできると良いなと思う点
まとめ
今のところうまく運用できていると思っている😀
朝会の時に昨日のデータをRedashのダッシュボードから見てから朝会しても良いなーとか思ってたりする💪🏽
`Inspired: 顧客の心を捉える製品の創り方` を読んだ
読んだ本
- 作者: マーティケイガン
- 出版社/メーカー: 株式会社 マーレアッズーロ
- 発売日: 2015/02/07
- メディア: Kindle版
- この商品を含むブログ (1件) を見る
気になった部分をピックアップ
第6章:プロダクトマネージャの条件
技術の進歩は急速なので、プロダクトマネージャーは、新しい技術を短期間で身につけることや、新しい分野で問題の解決に取り組むことが得意でなければならない。私がプロダクトマネージャーの候補者をインタビューするときは、すでに身につけているものは何かを見るのではなく、今までやってきた製品開発で、何を学ばなければならなかったか、学ぶのにどのぐらいの時間がかかったか、そして、身につけた知識をどのように活用したかを見るようにしている。
Engineer出身であると必然的にクリアしなければならない課題なのでEngineer的思考が十分に生かせるなーと感じた
第7章:プロダクトマネージャを管理する
ネットプロモータースコア(NPS)
普段ネットサービスを使っててよく出てくるアレである。この指標がプロダクトマネージャの評価基準になりえるのは初めて知った。コレ系はSaasとして取り入れたいなぁーと感じた。でもあまり世の中に無い気がする。
すべてのユーザが直感的に回答できるし、回答内容も全社的に共有して問題無いし、やるべきだなーと思った次第。
第11章:製品の市場性評価
顧客を理解するという点からは、財務部門が持っている情報はものすごく役に立つのだ。 財務部門の人間というのは、だいたいはかなりもの静かであり、プロダクトマネージャーのデスクまでやって来て製品機会について説いたりするようなタイプではない。だいたいは、プロダクトマネージャーのほうが、彼らのところに出向かなければならない。
この本を読まなければ気づかなかった視点でした。財務部門で扱うデータは提供しているWEBサービスでは出てこないが、とても情報の信頼度が高いものが集まっている(支払状況・今までの取引の記録・信用度等々)。顧客を理解する上ではとても有効な情報だなーと思った。
何に活かすという明確な形にはなりづらいけど、頭に入れておくという意味で良いと思った。
また、人のタイプ的にプロダクトマネージャーからアクションすべしという所も納得感あった。
第13章:製品理念
プロダクトマネージャーは、意思決定のプロセスと理由付けをみんなに完全に見えるようにしておくことだと思う。プロダクトマネージャーは、直感だけに頼っているとチームのみんなから思われるようではダメだ。プロダクトマネージャーの設定した目標と目的、それらの優先順位、プロダクトマネージャーがそれぞれの選択肢をどう評価したか、といったことについては、チームのメンバー全員にわかるようにしておかなければならない。
議論が紛争している時こそ、決断しなければいけなし、決断したら100%その決断にコミットをみんながしなければいけないし、でもそこにはある程度の納得感が必要。その一役に見える化しておく事。
普段からわかりきった事でもなるべく丁寧にプルリクに説明やら背景やらを書くことにしてレビューしてもらっているが、同じことだなぁーと感じた。
第15章:ユーザモニター制度
プロダクトマネージャーは、ユーザーとの面談、ユーザビリティテスト、ユーザーモニター制度での打合せなど、自分が担当する製品に直接関係のあるものなら何であっても出席するべきだ、と私は思っている。
当たり前だけど専任でやる前提での話。ユーザに直接ヒアリングできる機会ほど有効な時間はなし、関連するMTGに参加して洞察力を磨く事も重要だなと思った。結局参加するMTGに意味があったが無かったなどは臨む心構えで変わったりする時ある。
第18章:製品仕様はどうあるべきかを考える
製品仕様の大半は、ハイファイプロトタイプとするべきだ。
Sprintを区切ってやるべきだし、何度も作り直し前提だし、デザイナーを含めた実際に手を動かせる開発者をいかに早く巻き込めるかが重要かもしれない。
早く巻き込む事で生じる人件費等のコストは必要経費だし、そうしないと良い製品開発はできないという事なんだと思った。最近だとハイファイプロトタイプを支援するツール類も充実してきているし、前よりも低コストで実現可能だと思うのでやるべきですね。
第21章:製品仕様の検証
フィージビリティ(実現可能性)の検証
ユーザビリティ(使いやすいかどうか)の検証
価値(買いたいと思ってもらえるかどうか)の検証
特に目新しい内容では無いけど、やっぱり基本的な部分なので改めて大切だなと思いながら読んだ
第29章:大きい会社でもイノベーションは不可能ではない
私が知る限りでイノベーションを起こすいちばん手っ取り早い方法の1つは、実際のユーザーが自社の製品やライバルの製品を使ってみようとするところを、じっくり観察する(そしてユーザーの話に耳を傾ける)ことである。こういう観察を何回かやれば、ユーザーの不満や期待のパターンが見えてくるだろう。
自分たちのプロダクトではなく競合他社のプロダクトを使ってるところを観察するの事の重要性はこの本で初めて知ったし、低コストで実現できるなーと思った。
ひたすら自分たちのプロダクトについて色々と考えていたけど、競合他社のプロダクトをうまく使うことは考えつかなかったなぁ
第32章:特別仕様には要注意
特別仕様の何が悪いのだろうか?製品を作る会社は、顧客の要求をあるべき製品要求と取り違えることで、まず間違いなく道を踏み外す。
この言葉の理由には下記3つ簡単に記されていた
- 顧客にとっては、実際にそのものを目にするまでは、自分が何を必要としているのかを理解するのはとても難しい
- 顧客はどんな技術が可能であるかを知らない
- 顧客は共通のテーマを確認するために顧客同士が交流することはめったにない
特別仕様を飲み込めば大口の契約という目の前のメリットに惑わされることなく、常に本質を求めて行かなけれいけないなぁーと感じたけど、実際の経営者の立場からすると会社の経済状況が思わしくないと色々と考えが存在するだろうなと感じた。
CEOレベルの明確な意思表示が必要とも書いてあったけど、会社としての意思決定レベルの話ですね。
個人向けインターネットサービス製品で大切なこと
でも、顧客サポートの費用を抑えることが大事なのではなく、サービスを利用する顧客にすばらしい体験をしてもらうことが目的なのだ。
最近はカスタマーサービスに力を入れる企業も当たり前に増えて来たし、また改めてZappos.comの本を読みたくなった。日本の企業でも従業員の7割がカスタマーサポートの企業もあるし、サポートエンジニアの重要性も高まってきていると個人的に感じているし、そーいう流れなんだろうなと。
最後に
読みやすい本でした。いろいろな人が読める本だと思った。