Configure::readOrFail()っていうのがあって便利だからみんなで使おう

CakePHPorFailシリーズ

Configure に、定数ぽい値を持たせていたりしている。

※ イミュータブルじゃなくなるし、constとしたほうが良いのでない?という観点はあります。
※ 「いや、stageによって異なる値を上書きしたりしたいじゃん!」という声もありますが、それはdotenvや環境変数でどうにかなりそうな問題
※ まぁ色々あって、Configure::write() に寄せているよ!というお話をスタート地点とさせていただきます。

直接 ::write()メソッドを用いて書き込む〜というよりかは、 config/app.php のような「設定ファイル」を介在させて食わせて、という風な。

「絶対に設定しないと行けない」という制約

例えば、cakephp/appを見てみると、 App.encodingenv('APP_ENCODING', 'UTF-8') と書かれていたりするじゃないですか。 みたいな感じで、

  1. 環境変数として値を用意して
  2. Configureに食わせる

という利用シーンはあると思います*1
その中には、「どの環境においても、絶対に設定されていなければ困る」というものもあると思うのです。

Configure::read() とすると、「キーが存在しなかった場合はnull」を返します。
場合によっては、「nullのまま進んでは困る」と。
このときに役立つのがConfigure::readOrFail() です。 Class Cake\Core\Configure | CakePHP 3.5

keyが未設定、もしくはされているがnullいなっている 場合に、RuntimeExceptionを投げるようになります。
read()になっている箇所を置き換えるだけで、「ちょっと事故った、しかし事故が大きくなりすぎる前に気付く」ことがしやすくなります。

まだまだあるぞ! orFail()シリーズで堅牢なプログラミング

良きようにfail fastになるな、という利点です。 Configure::read() 以外にも、 orFail()なメソッドはちょこちょこあります。

f:id:o0h:20171124221702p:plain

  • SELECTを試みたレコードが1件もなかった場合に例外を投げる Query::firstOrFail()
  • saveを試みて(validation error/ domain rule violationで)保存ができなかった場合に例外を投げる Table::saveOrFail()
  • deleteを試みて、(entityにPKがない / entityが「isNew()」である / domain rule violationで)削除ができなかった場合に例外を投げる Table::deleteOrFail()

こういった顔ぶれです。 便利ですね😁

*1:最も、「読み出せなかったときのために初期値を用意して扱う」というのが良いのかもしれませんが・・

我々はcomposer scriptをもっとカジュアルに使っていってもいいかもねの話②

ふと気付いて実行してみたら便利っぽい使い方ができたので、 前回の続きみたいなエントリー。 daisuki.nichiyoubi.land

自分で使うプロジェクトに関しては、composer でどこからでも叩ける用にDockerfileなんかでパスを通している。

RUN wget http://getcomposer.org/composer.phar && \
    mv composer.phar /usr/bin/composer && \
    chmod 0755 /usr/bin/composer

みたいな。

で、composer.jsonスクリプトで例えば

    "scripts": {
        "test": "phpunit"
    },

なんて書いておいて。

こうすることで、ホスト上から

docker-compose run my_service composer test

みたいに、気軽にコマンドを叩くことができるようになる。 CodeSnifferや静的解析だったりとか、そこら辺をすぐに使えるようになるかも? あと内容によってはgit pre-push hookとかと合わせてもいいのかもしれないなぁ。

我々はcomposer scriptをもっとカジュアルに使っていってもいいかもねの話

composer script

というものがある。 Scripts - Composer

あまり「自分らが開発しているPJ」において拡張しまくっていたりはしないものの、 これを「当たり前に使う」ようなレベルまで持っていくと、まぁ便利ではあるんだろうな〜とは思う。 もちろん、各種イベントにフックして実行する手続きをドン!!というのはもちろんとして、 「そうじゃなくても!」だ。

例えば、CakePHPでは以下のようになっている。

    "scripts": {
        "check": [
            "@cs-check",
            "@test"
        ],
        "cs-check": "phpcs --colors -p ./src ./tests",
        "cs-fix": "phpcbf --colors ./src ./tests",
        "test": "phpunit",
        "test-coverage": "phpunit --coverage-clover=clover.xml"
    }

これがあるので、composer check などとするだけでCodeSnifferとtestが走り出すのだ。 個人でやっている内容については、例えるなら.bashrcなどに書くような「便利エイリアス」くらいの働きはしてくれそう。 チームでやっているのであれば「このくらいは、普段から(なるべく)意識しておこうな!」というスタンダードの表明的な役割はあるのではないか。

例えば「○○ツールで静的解析をやるときは、このphp.iniを食わせてからやるぜ!」とかいうのは、 いちいち覚えておくのが面倒くさそう。それが composer check くらいで済むのなら、嬉しくないですか? もしくは、よくありそうなのはCIに任せたい一連の処理をPHPで記述しておいて、composer経由で叩かせる・・とかか。

なんか使いみちあるかなー

今更ながらPHPStormの「Diagrams」に感動したのでメモ

コードリーディングの補助ツールとしてのIDE

「この機能がいいね」と君が言ったら・・・ 記念日である。

GuzzleHttpを用いてアプリケーションを書いていて、例外処理を行おうとしていて少し困った。 「ClientExceptionServerExceptionと、あとBadResponseExceptionが来る可能性があるなー」と。 サーバー例外!と変な応答例外!はなんとなく近い気がする(1つの共通クラスで丸っととってこれそうなイメージ)、ただクライアントが変!!のときは、何か違うかな・・・?と。名前から受ける印象。

で、「そういえば」と思ってクラス名を右クリックした結果。

f:id:o0h:20171114215522p:plain f:id:o0h:20171114215541p:plain な〜んだ、どちらも RequestException を取っているのね!であれば、それで拾ってしまって良さそうだな。 getRequest() getResponse()どちらも通る前提での実装ができる。

未知のコード・未知の知識として、「正直、細部まで丁寧に読んだり追ったりしている余裕はないぞ・・・」というときに、すごく助けられるな〜と思った次第。

Viewing Diagram - Help | PhpStorm

phpのマニュアル、意外と例外の使い分けについて丁寧にかかれている気がした

PHP: 例外 - Manual を見ていて。

例えば

UnexpectedValueException クラス ¶

(PHP 5 >= 5.1.0, PHP 7)
はじめに ¶

いくつかの値のセットに一致しない値であった際にスローされる例外です。 これが発生する例としては、ある関数が別の関数をコールしていて、 その関数の返り値が特定の型や値である (そして計算やバッファ関連のエラーがない) ことを想定している場合があります。

とか書かれている。

やっぱり「適切な例外を扱えると、気持ちいい」というのがあるので、こういうふうに「どう使うの」が記述されているのは嬉しい。

——

ついでながらPHP: 定義済みの例外 - Manual普段あまり「自分で使わない」ようなものが並んでいるな、と思う。 概ね LogincExceptionRuntimeExceptionを継承して利用する感じになると思うが、それらはSPLなのか・・・あまり意識していなかったな。(FWを使うと、その例外をそのまま継承することも多いですし。)

このあたりから、「PHPにとって例外とは」というのがなんとなく見えてくるような気がした。

どんな感じなのだろうな?と思い少しだけぐぐってみたら、この記事が興味深かった。 PHPの例外 - Qiita

実際にAuraPHPもSPL例外は未使用で全ての独自例外をPHP組み込み例外\Exceptionから継承していますが、十分にクリーンで機能しています。

なるほど。。Auraの思想は好きだし、最近いろいろと参考にさせてもらっているので、「そういう考え方もあるのか〜」と思う。

Docker使ってwebアプリケーション作っているときに、logをいい感じにアクセスしやすくする

ちょーーーーー当たり前かもしれないけど、今日気づいて「なるほど!!!」と膝を打ったので恥を忍んでのメモ。

なんか /var/log にログ落ちてないんだけど〜〜と焦燥した日々でした

よくあるやつ、 ErrorLog "/var/log/httpd/error.log” みたいなのを想像していて、ひたすら /var/log/ 以下を探したんだけど、ないなーと。

でコンテナの中覗いたら ErrorLog "/dev/stderr” って書いてあって、標準エラー〜〜??てなり。

docker logs

Dockerコンテナのロギング機能を使ってみる | さくらのナレッジ こんなものがあるのね〜〜〜! KitematicやPHPStormで「(CONTAINER)LOGS」ってあるのは、これのことか・・・

で、更にこれを docker-composeを活かして良い感じにやるやつがある(会社で隣にいるインフラの人に教えてもらった・・・) docker-compose logs | Docker Documentation

これだと、コンテナにsh実行しなくていいし、「今まで知っていた、よくあるlogファイルの場所を覗きに行く」よりも、むしろ簡単だし分かりやすいし・・・

というわけで

docker-compose logs -f、さいこ〜!

コードレビュー時のコメントにemoji prefix使うっていうのはどうなの

という思念がある。

着想としては、emoji prefixed commit messageである。

goodpatch.com

自分が知ったきっかけの記事は、これじゃないのだけど・・・さすがグッドパッチさん〜〜!わかりやすいキレイ〜〜!と思ったのでw このURLを貼る。

emoji prefixいいよね〜

「テストを書くと、メソッドやクラスのスコープが意識されて、コードの結合度がいい感じになる」というメリットがあるが。
それと似たような効果で、「このコミットメッセージに、この変更内容は嘘がないか?」という歯止めである。emoji prefix。

で、副次的にでありつつファーストインプレッションとして「エモジ、タノシイ。」がある。
ここにインスパイアされて「楽しい感じで、コミュニケーションの抱える抽象的な難易度 = 人類にメッセージングは早すぎる問題」を何か解消できないか?という話
※別に「人に対して」にかぎらず、ソースコードやプログラムに対しても「対話」をしているものだ、と普段考えているので、ここで用いているのはそのくらいのスコープでの「コミュニケーション」という語。

コードレビュー難しいよね〜と思う

自分としてコードレビューにおいての難しさの最たるものの1つとして、「温度感を伝えるのがちょっと・・」というのがある。

本気で議論をしたいのか。議論をするまでもなく、絶対にこうしてほしい!というオーダーに近いのか。全然直さなくていいよ〜、でも最初に自分はこう書くかも〜と思った!なのか。

「Pull(ないしマージ)」のリクエストなのだから、それをレビューするということは、最終的には「私の書いたコレに修正が必要かどうか、ジャッジせよ」という要請と返答だと思う。
しかしながら、レビュアーもレビュイーも、コードレビューの中で非常に成長ができる・・・というのは自分の経験として本当に強く思う。職場で、この1年はめっちゃ神経質にレビューをしていた時期があり、(人として)色々と失っている気もするが間違いなく実装力や設計力がついたなーという感覚があり。

その際に何をしていたかというと、「最低限、動けばいいよ〜というレベルでは通さない」し「言いたいことをひとまず全部言ってみる」であり。
その中で、先に述べた「あ〜〜自分ならコッチの書き方が好み!スマートな気がしない?どう??」的な、投げかけを行った。そういう感覚で放り投げたレビューコメントの方が多いかもしれない、だいぶ厄介・・・

「これがパット見で使わったら楽」という手段がほしいって話

ということで、「これは真剣に言っているので!」とか 「これは、まぁ真に受けなくていいよ!!」みたいな温度感を示す、もしくは「些細なcosmetic changeの依頼です〜」とか「ここは、ついでにサクッとリファクタ入れてくれると嬉しいかも!」とか、「エンバグしてまっせ!!」とか。
そういう、「コメントの性質・内容・アラートレベル」を、メタ情報として付与できれば?と。
大概にして、「コメントされた内容を聞き流す」というのは、PRを投げる側にとっても、精神的な負荷が大きいので・・・

  • 😉(スルーしていいよ、のウィンク) 自分だったら、この変数は is よりも should みたいなprefixにするかもな〜と思いました!「状態が確定した」というよりも「判定の結果、状態を指示する」的なニュアンスが強いので
  • 🔥 (消してしまってね、の焼却) 使われていない変数です〜
  • ♲ (リファクタ、のリサイクル) このあたりの処理、別メソッドに切り出しちゃいましょ!
  • 💔 (テスト追加が💚とか使うので、その逆のハートブレーク)単体テストかいて、○○のケースもカバーしておけると安心感++ になりそうです!
  • 💥 (事故りそうなので認められないよ、のクラッシュ)
  • 💬(パット見でわかりにくいかも、の沈黙) ネストが深くなっているので、このガード節使って考える事減らしたいかも〜〜
  • 🐚(マージする前に議論したい、の貝) コード的には問題ないのですが、○○の機能と同時に使った場合、あちらがリセットされるかもしれません。要求仕様的に大丈夫ですか・・?

みたいな。よくわかんないなー