composer installをめっちゃ早くできるのかな?

という話を、社内でしておりました。
「そういえばprestissimoって本体に取り込まれる?とかって話なかったっけ」てな話題となり、PR見てみたら「難がありそ」と。

それが I think that it’s difficult to support conflict, suggest, provide and replace dependencies.かな?と思った。。

なるほどな〜たしかにな〜難しそう〜〜と思いつつ、それにしたって「composer isntallがめっちゃ早くなるよ」は魅力。

逆に言うと、「インストールの時だけならパラレルでDLしても大丈夫じゃない?」って言う気もしたのでした。
composerでパッケージの取り込みを行うのは、主に

  1. install
  2. require
  3. update

であって、このうち「1」については「依存パッケージの衝突が起きていないか」というチェックは、すでに終わっているフェーズにあるのでは? と。 (雑な見方の気もする・・・

あまりcomposerの内部処理を追ったことがないのだけど、「installのときだけこのプラグインを有効にする!」ということができれば、もしかしたら大丈夫だったりするのかなー。

どっかで実験してみよ

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、さいこ〜!