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

という思念がある。

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

goodpatch.com

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

emoji prefixいいよね〜

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

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

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

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

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

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

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

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

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

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

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

大変に今更ながらxdebugの「リモートデバッグ」とは何か

コネクションコールバックが〜とかポートが〜とか。
いんたーねっとに転がっている「xdebug.iniに、こんな風に書いてくれよな!!」というのを丸呑みしている日々が、続いておりました・・・(恥)

で、「なんかdockerでリモートデバッグが動かないよ〜><」というのを、妥協して怠惰に目を瞑って過ごしていたのですが、この記事と出会い。

blog.shin1x1.com

見事に問題が解消されました嬉しい・・・!

これをきっかけに、「そもそもどういう仕組で、クライアントに「デバッグ」な情報を送っているのかな〜」というのを、整理したいなと思ったのでした。

全体感

なんてことはない、公式のドキュメントのこの図が1番わかりやすい・・・・ dbgp

さて、この記事を読むのが良いです。 Xdebug: Documentation

DBGp

Xdebugは、コードを評価してクライアントと相互にやりとりをしながらデバッグをしていくことを可能にするよ!」「そのやりとりに使われるのが、 DBGp っていうプロトコルなのさ!」みたいなことが書いてあります。

詳細には、こっちで書かれていますね。 Xdebug: Documentation - Protocol - DBGp

クライアント

f:id:o0h:20171029135641p:plain こんなにも・・・!

設定項目について

ここが「1番実用的な知識」であり、今このようなメモを残すきっかけとなった本題です。

In order to enable Xdebug's debugger you need to make some configuration settings in php.ini. These settings are xdebug.remote_enable to enable the debugger, xdebug.remote_host and xdebug.remote_port to configure the IP address and port where the debugger should connect to. There is also a xdebug.remote_connect_back setting that can be used if your development server is shared with multiple developers.

ってことだから、ココらへんを見る。

remote_enable

「クライアントに接続しにいかせるやつ、いる?」のOn/Off。
「もし接続が確立できなかったら、この値がOffになっているものとして扱うよ〜」と書いてある、まぁそうですよね。

remote_host

「接続しに行ってOKなクライアントはどこ!?」の項目。「ここからの通信だけでDBGpでの交渉を許可する」、ってことであっているのかな・・?

書き方は

you can either use a host name, IP address, or 'unix:///path/to/sock' for a Unix domain socket

です。

remote_connect_back

「接続してきたホストにXGDp接続をしにいくか」。
何かというと「remote_host設定に関わらず(すなわち、設定値を無視して or 設定されていなくても )、リクエスト元をリモートデバッグクライアントとみなして通信しに行く」。

個人的には、 ローカル開発ならコレ使えばいいかな〜と思っていたので、前に晒したDockerfileではremote_hostでなくてこっちをenableにしているのだけど。どうなんだろう〜

もしくは、「チームで利用するリモートの開発サーバー」とかはこれ使う感じかと

There is also a xdebug.remote_connect_back setting that can be used if your development server is shared with multiple developers.

remote_port

「接続を試みるポート」。
例えば 「macでPHPStormを使っていてDockerコンテナのPHPでリモートデバッグをする」といった場合、「コンテナからmac(ホストマシン)の9000番に接続が来る」と・・・

remote_mode

これ知らなかった。「いつ有効にする(接続を返しに行く)か?」みたいなところ、かな・・?

Allowed values for this setting are "req" (the default) which makes the debugger initiate a session as soon as a script is started, or "jit" when a session should only be initiated on an error.

stormにも記事がある。 https://blog.jetbrains.com/jp/2013/12/19/343blog.jetbrains.com

remote_autostart

本来は「特定のパラメータ名」を付与したリクエストが来たときのみリモートデバッギングが始まるところを、この設定がOnになっていると「自動的に始まる」というもの。 冒頭で紹介した記事中でも、autostartが有効化されています。

ideky

「特定のパラメータ名」の設定がこれ!
例えば idekey=session_nameだった場合、

simply add XDEBUG_SESSION_START=session_name as parameter to the URL. Instead of using a GET parameter, you can also set XDEBUG_SESSION_START as a POST parameter, or through a cookie.

ということです。

要するに、 http://blog.example.com/post/100デバッグしたいときには、 http://blog.example.com/post/100?XDEBUG_SESSION_START=session_name というようにパラメータを付与してリクエストをする必要があるということです。

それによってXDEBUG_SESSION 情報がCookieに保持されます。

GET/POSTで値を渡された or セッション情報が記録されている場合のみ、デバッグセッションに入るといったことです。
※ HTTP Debug Sessionsのセクションを参照してください

先の autostartが有効化されていたら、 even if the GET/POST/COOKIE variable was not presentデバッグが始まるよ〜!となります。

関連: remote_cookie_expire_time

全員集合!設定項目

リモートデバッグのみでなく、Xdebug全体の設定項目についてはこちらに。 https://xdebug.org/docs/all_settingsxdebug.org

assertを使いこなす(こなしたい)

もちろんコレ!のインスパイア!!

speakerdeck.com

 

の話で。

プリンシパル・プログラミングにも書いてあったが、改めて意識したい点として「コードは書く時間より読む時間(人、回数)の方が多い」であり。
読み手にフレンドリーである事がとても良い。どうやるか。考える(べき)ことを減らす。
その一環として「表明」。「ここは、こうである」と。「AかBがCかそれ以外」を考慮するよりも「AかBか、それだけ。他はあり得ない」としてくれると楽だ。件のスライドを読み返したら書いてある、「想定しな蹴らばならない状況が減った」は正にこれだな望ましいな・・・

この「あり得ない」をコード上でサクッと「表明」してしまえ、というassertである。こいつと仲良くしたいな、という話。

自分としては、割とシンプルな条件の時に限って assert()を使うかもな、みたいな好みがあって複雑なときにはそりゃもうLogicExceptionなどを投げるんだけど。
ただ、使い分けが曖昧〜・・・・

  • 「複雑な」というのは、例えばif-elseif-elseで最終のelseに入るような呼び出し方は見直したほうがいいぜ?というときは、exceptionのthrow
  • 「複雑じゃない」というのは、例えば「RDBトランザクションが発生している状況でしか呼ぶなよ?」というメソッドにおいて、 $driver->inTransaction() みたいなくらいならassertで済ませるかも

メリットとしては「本番で無視されるからコストないぜ!!!!」っていうところか、ただしこの資料にあるように、「環境の差異減らしたいぜ〜」というサイドのみかたもあるかも。とはいえerror_reportingとかは分けるだろうから、自分としては「便利さに溺れていこうぜ!!」ってことでアサートは有効にするかな


って思って書きながら調べてたら、この記事とかは基準になるかもなー。

www.infiniteloop.co.jp

さすがのインフィニットループ様やでぇ。。。


  • 悩みとしては、「実例が少ない」     * 実際にどう使うか観点で、「めっちゃ判然とした!!」ていうレベルのプラクティスに出会えてないんだよなー
  • 気持ちとしては「どんどん推進・活用していきたい」

という温度感。
「本番に入る前に確実に防止できる(発覚する)、という自信ないし保証がある」ってところか。
あーさっきの記事の例も踏まえて考えると、「publicなAPI(web api、ではなく)」での利用は慎重になるべきかもしれない。逆に言うとprivateメソッドだと「目が届く」ので「呼び出し方・使い方を間違えてしまう」というのを、防ぎやすいというか。

いずれにせよ、テストカバレッジを一定以上に保っておかないと「見落とし」確率が高まって危険かもな。。


「コードは、何をするかは示しやすい、どうやるかも示しやすい、ただし何故やるのかを示しにくい」というので。この「なぜ」の部分、背景やらコンテキストやらを埋める手段として = 筆者の気持ちを考えなさい問題を回答する際のヒントとして、assert()いいよね〜の話
LogicExceptionとの住み分け、使い方、基準を自分の中で洗練させていかないと・・・

CakePHPのpatchEntity()とisDirty()

小ネタ。ちょっとハマったので。

「patchEntityをして、差分があったときだけsave()に入る」みたいな処理を書きたかった。cake3始めたばかりの頃。

$post = $this->PostsTable->get(1);
$post = $this->PostsTable->patchEntity($post, $this->request->getData();
if ($post->isDirty()) {
    $this->PostsTable->saveOrFail($post);
}

のような。 問題は、 isDirty()の挙動というか。

dirty となるのは 正しく、更新されたフィールドがあるとき`である。
何を意味するか。
すなわち、
更新しようと思ったフィールドが、全て「適切でなかったとき」、ditryとはならない** 。

たとえば、「ブログ(post)のタイトルを更新しようとした「posts.titleには「最大30文字」のバリデーションがかかっている」「40字のタイトルを付けて更新ボタンをクリック!」というケース。 これは、 marshal() が完了する前に拒絶され、「patchEntity()の結果得られる$post->title」は 以前のままである。その点において、isDirty()はfalseのまま。 (むしろ汚れてるけどねー)

Table::save() の中を追うと、 「isNew()である」もしくは「isDirty()である」のチェックが行われている。なので、「更新すべきフィールドがあったら〜」なんて処理、思い切ってsave()にたくしてしまって良い。

$post = $this->PostsTable->get(1);
$post = $this->PostsTable->patchEntity($post, $this->request->getData();
try {
    $this->PostsTable->saveOrFail($post);
} catch (\Cake\ORM\Exception\PersistenceFailedException $e) {
    $entity = $e->getEntity();
    $errors = $entity->getErrors();
    // $errorsをさばく
}

くらいなもんである。

ローカルに雑にhttpsな環境を作る時にhttps-poralがクソ便利だ

ngrockとかlocal tunnelでもいいですが!外部からアクセスさせるようなもんでもないな〜という時ありますもんね。

  • slackやlineといったbotのwebhook先はlocal tunnel
  • oauthのredirect urlや、ただ単にsecureにしたいだけな時はhttps-portal

みらいな使い分けを個人的には。

あたり。 こんなdocker-compose.ymlを用意した。

version: ‘3’
services
  https-portal:
    image: steveltn/https-portal:1
    ports:
      - '80:80'
      - '443:443'
    restart: always
    environment:
      STAGE: local
      DOMAINS: ‘browswer-kara-tataku-url.localhost -> http://jissaino-app'
  jissaino-app
    image: 'golang:latest’
# 以下省略

これで /etc/hosts127.0.0.1 browswer-kara-tataku-url.localhost としておけば、 htt://browswer-kara-tataku-url.localhost が利用可能になるっていう算段

「雑にCakePHP3プロジェクトを始めたいな」の時のDockerfileを書いてた

最近は業務で、これまでのPJ外のレポジトリに入り浸っている。
書いているのがCakePHP3用のプラグインで、普段は「Webアプリケーション」を書くことが多いのだけど、そこら辺から全く独立したプログラムだ。 ただしテストを書くために実行環境は必要で、「サクッと動けばいいな」という欲求

なので、今までの流れを無視して「とりあえず動けばいいでしょ雑にシンプルに用意して」、をした。

https://gist.github.com/o0h/69b79dea16a3c37b180082ac6dac89a4

  1. phpが動く
    • なるべく新しいやつ!
  2. CakePHP3が動く
    • そのためにintlとかの導入もクリアされている
  3. OSはなんでもいいや〜
  4. xdebugがほしい、それでIDEと繋がるところまではやっておきたい

既存の社内PJで「ちゃんと丁寧に書かれた内容」があったのでそこをかいつまみつつ、xdebug周りだったりdocker力の低さを補うために。このあたりを大変参考にさせていただきました。

ただ、PHPStormからだとxdebug.remote_connect_back で動作させられたな・・?バージョン上がったからとかなのかしら。

ひとまず、これで「なんかやろ〜」って思ったときに気軽に始められるので嬉し

Airbrake Blogの「PHPの例外ってそうだったんだ」シリーズが凄いタメになる

ブログもっと雑に書いてこ〜みたいな気持ちがしていた次第。メモとか放り込む

で、タイトルのとおりだけどAirbrakeが「組み込まれている例外、どういうときに使うもの?」というシリーズがありまして。 これが雑学的な読み物としても面白いな〜と思っていつも読んでいる。

今回は PHP Exception Handling – UnexpectedValueException 。 あんま自分は馴染みないかも・・・・と思ったけど。

https://airbrake.io/blog/php-exception-handling/unexpectedvalueexception-2

Not to be confused with the InvalidArgumentException

ほう

For example, if a function is returning a date value, but the runtime execution of this function produces a malformed date, you may opt to throw an UnexpectedValueException

と。前者はわかるぞ(いつもお世話になっております)
しかして、後者だ。すごく名前が似ている感じがする。どう違うの?と思ってみたら、サンプルコードがとても簡潔で良かった

    public function setPublisher(Publisher $publisher) {
        // Confirm that publisher is correct type.
        if (gettype($publisher) == 'object') {
            $class = get_class($publisher);
            if ($class != 'Publisher') {
                // Not a Publisher, so throw a new InvalidArgumentException.
                throw new InvalidArgumentException("Publisher cannot be set to type ({$class}), must be a Publisher object.");
            }
        } else {
            $type = gettype($publisher);
            // Not an object, so cannot be Publisher.
            throw new InvalidArgumentException("Publisher cannot be set to type ({$type}), must be a Publisher object.");
        }
        $this->publisher = $publisher;
    }

InvalidArgument〜は「待って!なにこれ!話が違うだろ!!」って言って投げるもので、UnexpectedValue〜は「あ、やばい!ちょっとうまく約束守れないかも!!」って使う感じかなー