1人Advent最終日

1人AdventのDay- 25 です。やった〜

adventar.org

1人Advent Calendar戦績

カレンダーを全部埋めることに成功しました・・・

f:id:o0h:20181226032844p:plain
そして、このエントリーが最後の1マスに・・

  1. daisuki.nichiyoubi.land
  2. cake.nichiyoubi.land
  3. daisuki.nichiyoubi.land
  4. daisuki.nichiyoubi.land
  5. daisuki.nichiyoubi.land
  6. daisuki.nichiyoubi.land
  7. daisuki.nichiyoubi.land
  8. cake.nichiyoubi.land
  9. cake.nichiyoubi.land
  10. daisuki.nichiyoubi.land
  11. daisuki.nichiyoubi.land
  12. daisuki.nichiyoubi.land
  13. cake.nichiyoubi.land
  14. cake.nichiyoubi.land
  15. daisuki.nichiyoubi.land
  16. cake.nichiyoubi.land
  17. daisuki.nichiyoubi.land
  18. daisuki.nichiyoubi.land
  19. cake.nichiyoubi.land
  20. daisuki.nichiyoubi.land
  21. cake.nichiyoubi.land
  22. cake.nichiyoubi.land
  23. cake.nichiyoubi.land
  24. cake.nichiyoubi.land

改めて、こうやって並べてみると感慨深いというか。長かった。

1番時間かかって、1番「やべー楽しーー」ってなってたのはコルーチンのやつ。

何でやり始めたか

最初の記事に書いたとおりですけど、まぁやる前は「あんまり大きい口叩けない・・」という心理もあったのですが。
今なら「いくらでも調子に乗れる」と思い、解放された気持ちで少し整理してみますと。

個人的に、今年の1年を通じて 「自分がやってきたことや、やれることに対して、ふわふわっとした自信のようなものはあるが、(とりわけ会社などの身内に対して)ふんぞり返っているだけのような、エゴの増長だけがある」というような感覚があり。そういうのは誰しもあるのだとは思うのだけど、今年はとりわけひどかった。
結局のところ「強くなっていそうな感覚はある」のに「本当に強くなっているのかが分からない」という渇きであり、じゃあ「今までにやってないよーな、"明確にハードルが高そうなこと"を1つ・・やってみるか!?」といった動機でした。
自分の等身大の知識や思考を「削り出し」するような形で、25本の記事にまとめる。そのくらいなら"今なら"できるのでは?と思ったので。

ということで、何かしらの挑戦的な意識であり、自罰的な追い込みであり、とりあえず「量」と「テンポ」でやってみよ〜なAdvent Calendarでございました。

何となくこだわったこと

最初は、「よ〜し時間があるときに書き溜めておこ!」と思っていたのですが、とあるツイートを見かけて「書き溜めやクロスポストなんて、私はしない」といった旨のことを言っており。
ああ・・・やるなら・・・俺も邪道に落ちずに・・・・・堂々と・・・「やりきった」と・・・・言ってみてぇ・・・

という悪魔に取り憑かれていました。
ので、それは貫徹。ただ家に帰るのが大体25時前とかですし、「当日24時まで」縛りは一切してないです。私が寝たところが日付変更線だ

会社のやつを2、CakePHPのものを2本とそれぞれやりきった上で1人Advent25。

やってみてどうだったの

最初の方

開始3日目くらいで、「あ。いつもの会社のブログや自分の(行動主導でなく)テーマ主導で書くようなノリと同じ気持ちでいると、相当つらい」というヤバみを感じます。
なんか おもっていた のより たいへん そう

そのモヤモヤが深淵に落ちていって、取り組み方として「修行のようだ」と思い始めてきた時のツイート

まぁそれでも、2本、3本と書いていくと「途切れさせたくない」という気持ちも芽生えてくるし、そういう「やってる感」を得られていくと、良いもんですね。

中盤戦

この記事から、Cake縛りブログの方はフォーマットができて来てよかった。 ずいぶんと昔(この辺からの動き)に作ったCake縛りブログの品数を拡充しよう、というのも今回のAdventで狙っていた事柄の1つだったので、これは全体を通じて得られたもののなかでも特筆したいポイントの1つ。

あと、結局エントリーを1本上げるのに油断すると2時間とか調べながらやって3時間とかかかっていく中で、「睡眠時間削れまくる・・・」というのに絶望し始めてきたり。
「毎日やる」「習慣としてやる」ような話は、何より生活リズムに組み込んで、例えば朝起きてシャワーを浴びる様な「取り掛かって当たり前」みたいなビルトインをしないといけない。そう思います。

第4週

個人的な他の事柄と相まって、17日の週からがマジで辛かった・・連日、「とにかくチョロくかける記事はないか!?」とネタを探していた気がします。ローカルにあったDockerファイルを転写しただけの「ギリギリ形になるかな!?」という内容を繰り出したり、Cake3.7.1キタ!何も考えずにかけそう!!と歓喜したり*1
やり始める前や、最初の数日くらいは「25本出すぞ、それだけでいい!いのちを大事に!」みたいな気持ちでいたのに、結局「とにかく書けばいいから・・・」って状態にまで陥ったのは、多分このあたり。なんというか「命からがら」って気持ちだった。

あとは、この辺りからだんだんと「本を読んだり・・・ペットプロジェクト動かしたり・・・あれしたり・・それやったり・・・・したいな・・・」って感情がたくさん湧いてきて、「あ、なるほど、今は抑圧されてるんだな」と悲しい気持ちを自覚していったりしていました。

終盤

その第4週の低調から、華金+忘年会+システムトラブル+深夜対応of徹夜・・みたいなのが続いて連休中が最悪になってた。
ここまで、少なくとも「翌日朝*2までに出す」は死守できていたのに、MPカラカラ過ぎて22日のエントリー更新がめっちゃ遅れた。悲しい。
連休中にどうにか追いついて、「最終日は振り返り記事だけ書けばいいぞ!!」という状態にどうにか持っていき、今日に至る。

そうか・・・今日に至ったのか・・・・・・・

Adventやってみてどうだったの

当初の予定より、「CakePHP中心」ではなかったような。
まず前提として、自分は「Cake系の発信はもっとしていきたいな、自分の経験はコミュニティに還元できる部分もあるだろうしな」という感覚は強く。なので、このAdventもそれをするつもりだったのですが。
まぁ、別に「そうじゃないことをやっていた」のは何も悪いとは思ってないけども、何となく、蓋を開けてみてこの結果〜というのが自分的には少し意外でした。

さて。

整ったもの

Hugo + GitHub Pagesでのモノ書き環境が整った。これは地味に成果なのです。

  • VS codeでMarkdownの編集&Git commit/pushをサクサクっと
  • Hugoのarchtype(テンプレート)を整えた
  • Cake縛りブログのテンプレートを確立できた
    • 先述の通り!
  • 「コードリーディングをしてその内容をそのまま書く」みたいなやり方は、アリだと思った
    • 何だかんだコードリーディングは力になる
    • それをテキストや言語化する時の学習性よ

(Adventと関係なく)12月に新しく1つ「書く場所」を増やした*3のと関連して、ずいぶんと「markdownで書く→pushする」みたいな動作が洗練された。

ちゃんと、何かしたくなったときの武器 = 億劫でないレベルのハードルの低さを備えた選択肢になったな、と。

身を絞りきってみたらアウトプットできることはあるんじゃないの

という感覚を、改めて得ました。
頭では、例えば「普段コードレビューで指摘した内容や示した補足など、そういうのを体裁整えてあげるだけでブログ記事になるんじゃないの?」という考えを持っています。
が、それを「テンションが上ったときだけでなく、毎日毎日やる」というのは、出汁でもとられているような、自分の身を削るような思いもありました。
そして、「そのくらいすればまぁ何かあるよ」というのを体験できたのは、自分にとって新しいゾーンでした。

普段は、ここまで「書くこと」が純粋に目的化するような状態はないので。
先程触れた「修行のような感じ」というのは、この「搾り取られる」という部分から来ています。

毎日毎日毎日・・・

「やらなきゃいけないこと」って、だいたい先延ばしにするじゃないですか。俺の魂がやる気になるのを待つ。まぁ明日やろう、週末にひっくり返そう、とか。
「毎日やる」って決めると、すごいんですね!1つ先延ばしにすると、即借金。明日サボると明後日の負荷が200%。やばい、コレは非常に逃げられない。
今年は、個人的に会社のブログの方で「月1本くらいは書こうかな」をやっていたんですが、(こちらは全然雑にやっつけてるとはいっても)25連続で来るんですよ。

1ヵ月弱を通じて、ひどい体験をしたなぁ・・・・

ただ、マゾ的な快感も一部はあると思って、この「習慣」ってやつはいいなーと思いました。自分を強くしてくれそう。

有言実行が重い

別に誰かが見てたとは思ってないのだけど・・・Adventarに入れて、「やってみるぞ!」と放言してしまった以上、「やらなきゃいけないやらなきゃいけないやらなきゃいけないやらなきゃいけない」って完全に自分で自分の首を絞めていた。
しんど・・

ただ、「やって当たり前」をちゃんとやるのは、やはり「良い」と思うので、自分の中での真っ当さみたいなとこに水を与えていくような感覚は良かった。

総論

年の瀬に、ちょっとした「やりきった感」を自ら生み出すことができたんじゃないかな〜と思います。
最後の最後で公開おくれたりとか、深夜から始めて雑なままになったりとか、とにかく「自分の理想としていたものからかけ離れてる」とか「何でこんなにうまくいかないのか」とかの嫌悪感はあるものの。
それでも、カタチとして「25記事作る」は主観客観どちらに立ってもブレずに「25本」のままそこにあるので、達成はしたんです。否定のしようのない成果というのは良い。

この先どーすんべ

「たまたまノリでやってみましたww」っていうだけのAdvent Calendarが、なにか自分を明確に1つ上のステージに押し上げてくれたりだとか、新しい扉が開くだとか、別にそういうものではないと思うのですが。
ただ、「ちゃんと続けること」という軌道を作り出せてハイになっているところは、今後もスイッチを入れて置けるとよいな〜と思います。せっかくなら。

  • やるぞ!ということ
    • Cake縛りブログはもうちょいどうにかする、まずは50本くらいは記事入れたいなぁ
    • 直近の話でいうと、年末年始の休暇で「手を動かす」系の積読をつぶしておきたい。今の自分は心身的に「無理に向き合う」耐性が一時的に上がっているはずなので。具体的には次の2つのいずれか、もしくは両方
      • 7つの言語7つの世界
      • Kotlin Webアプリケーション
  • やってみたいこと
    • なんかコード書きたい〜〜〜我慢してる〜〜〜〜〜〜〜もう我慢しなくていいんだ〜〜
  • やれるのかな・・・やれるとかっこいいぞ・・
    • いい加減にxUTPを読み進めていきたいのです
    • やるかな・・・ xutp.nichiyoubi.land か・・・・?*4

ということで!おわり!
メリークリスマス〜〜〜〜〜〜

*1:それでも、関連PRさぐってコード読んでissueよんで〜ってやるのは時間そこそこ要るんですが。久しぶりにやったら、「あ、コレ思ったより辛い」て感想

*2:朝とは?人による

*3:http://daisuki.nichiyoubi.land/entry/2018/12/04/183259

*4:レポジトリはずっと前からあるんだ https://github.com/o0h/reading-xutp

PhpStormを使ってOSSにコントリビュートをする

1人AdventのDay-20です。完全に師が走っておる・・・

adventar.org

今日は、こんな 強そう なタイトルでブログを書いてみます。
ただ、「技術論」や「ハイレベルテクニック」というよりは、コレはもう心構えの話です。

CakePHPへのコントリビュート

私は、過去に数度CakePHPやその周辺のプラグインなどにPRを送って、取り込んでいただく!という経験をしております。

Commits · cakephp/cakephp · GitHub

ただ、これらはすべて、enhancement系や大幅なロジックの変更をキメるぜ!!といったものではなく、些細なphpdocの修正や型宣言の修正などがほとんどです。

PRを作るタイミング

「自分で使っていて困ったとき」に送る、という程度のものです。
バランスさえとれれば、「業務時間中にちょちょっとパッチ書いて投げちゃう」程度のことは許してくれるよね〜という職場環境も大いに手伝ってくれていると感じます。

例えば「ここの型宣言が実際的ではなく、静的解析をパスしない」から「PR作ってるんだけどCI通らなくて困る」なんて動機で、書いちゃったりします。

それでもPRはPRで、contributeはcontributeだと思う

あまり小さいパッチでコアメンバーの手を煩わせるのも何だかなぁ、人によってはナンセンスに感じる面もあるよなぁ〜と感じる面もあります。
それでも、「日常的な開発を行っていく中で、些細なところで感じるストレスポイントはゼロに近いに越したことはないよな」という風に思います。

普段触っているフレームワークやOSSは、めちゃくちゃお世話になっており、そこに恩義を背負っているハッキリとした自覚があります。それであれば、何かお礼をしたいし、そのやり方として些細なことでも貢献したい。
もし、自分がパッチを書くことで、同じフレームワークを利用している人が、この「オヤ?っと思ったちょっとした点」について一切の違和感を覚えなくなったり。もしくは、その品質に対して全く当たり前に「よく動くもの」という認識を持って信頼しながら開発に取り組めるようになるのであれば、とても良いな〜と思うのです。

どうやって「貢献」のハードルを下げるか

一重に「PhpStormはいいぞ」というのがあります。コレは、めちゃくちゃ大前提としている部分といえます。

例えば、 #12770などは、「本来は可能である使い方が、パッと見ではできなさそうに見える」ので直したいなという修正でした。
これは、(内部実装的には)問題なく通る部分なので、そのまま使っていても構いません。しかし、IDEを利用していることで「arrayを期待できないけど大丈夫か?」ということで、ハッキリと警告が出ます。
その段になって初めて、「じゃあパッチを書いて正しい姿にしてしまおう」というモチベーションが生まれるわけです。

同様にphan/phpstanを通したときに生じたエラーについて修正を数度投げたりもしているのですが、これも「機械が勝手に見つけてくれて、自分は折角だし数文字だけ直しちゃおう」というリアクションによるものです

普段からソースコードを読みまくる

これまでガッツリとCakePHPを触っている中で、すっかり内部での処理の流れを追うことへの抵抗は薄れてきたと感じています。
このソースコードリーディングも、優秀なIDEに依る部分が大きいです。クラス探索はもちろん、ポップアップでのdoc表示やGo to declarationに何度救われたことか。
何ならドキュメントより生のコードを読むことがすっかり当たり前になってしまったのですが、そうしていくと自然に「コードに手を入れる」ことの抵抗が薄まってきます。フラットに「ここはちょっとおかしそうだよね」と感受できるからこそ、ごくごく些細な修正も「まぁ書いちゃったほうが早いかな」という発想に立てるようになりました。

なんかあったら、パパっと直しちゃう

やはり自分が好きなもの、お世話になっているものが「より正しい姿になっていく」のは嬉しいものです。
今後も、より深い部分での設計思想や描き出す世界観を理解していきたいし、引いては機能追加だったりRFCみたいな形で貢献できたら、もっと楽しいんだろうな〜とも感じます。

現状でも「普段の労力の延長線上でできること」があるということで、それに対して「目をつぶったりスルーしないで向き合う」という形で、自分なりの貢献の仕方を考えられるとよいなぁと思うのでした。

ストームを使いこなしたい〜〜〜〜〜〜!

CakePHP3アプリケーションをPHP7.3で動かす

1人AdventのDay-18です。

adventar.org

手元で作っていたアプリケーションをPHP7.3に乗せて見たので、その時の内容を晒してみようというのが今回の目論見です。
ちゃちゃっと。

構成について

Herokuで動くようにしています。
ということで、以前に作成したPHP7.2用のイメージをベースにしました。
o0ho0h/heroku-php72-fpm - Docker Hub

これについては、以前まとめたものです。

daisuki.nichiyoubi.land

ファイルの内容

こんな感じになっております

 $ tree -L 2
.
├── Dockerfile
├── README.md
├── app
│   ├── README.md
│   ├── bin
│   ├── composer.json
│   ├── composer.lock
│   ├── config
│   ├── index.php
│   ├── logs
│   ├── phpunit.xml.dist
│   ├── plugins
│   ├── src
│   ├── tests
│   ├── tmp
│   ├── vendor
│   └── webroot
├── composer
└── docker-compose.yml
$ cat .docker/etc/nginx/conf.d/default.conf
server {
  listen __NGINX_LISTEN_PORT__;
  server_name _;

  root /var/www/html/app/webroot;
  index index.php;

  location / {
    try_files $uri $uri/ /index.php?$args;
  }

  location ~ \.php$ {
    try_files $uri =404;
    include fastcgi_params;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_intercept_errors on;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  }
}
$ cat .docker/usr/local/etc/php/conf.d/xdebug.ini
zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20180731/xdebug.so
xdebug.remote_enable = On
xdebug.remote_autostart = On
xdebug.remote_host = docker.for.mac.localhost
xdebug.idekey = PHP_XDEBUG_IDE_KEY_HERE
FROM php:7.3-fpm-alpine

RUN apk add nginx supervisor \
    && mkdir -p /etc/supervisor.d/

RUN apk add \
    vim \
    git \
    zsh

RUN apk add --no-cache \
  libgcc \
  libtool \
  pkgconfig \
  re2c \
  libressl \
  xdg-utils \
  openssh-client \
  ca-certificates

RUN apk add  --virtual build-dependencies \
  autoconf \
  automake \
  make \
  gcc \
  g++ \
  libmcrypt-dev \
  zlib-dev \
  gmp-dev \
  libzip-dev \
  libxslt-dev \
  icu-dev \
  libmcrypt-dev \
  libressl-dev

# php7
WORKDIR /usr/src/php/ext
RUN git clone https://github.com/xdebug/xdebug
RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) \
  && docker-php-ext-install -j${NPROC} \
  intl \
  xdebug \
  zip

RUN docker-php-ext-enable \
  #opcache \
  xdebug \
  && docker-php-source delete

# setup web
COPY .docker/supervisor.programs.ini /etc/supervisor.d/

COPY .docker/etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf
fpm.d/www.conf
RUN rm /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini

COPY .docker/run.sh /
RUN chmod a+x /run.sh
RUN adduser -D myapp \
    && apk add --update sudo \
    && echo "myapp ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

 COPY ./ /var/www/html


 WORKDIR /var/www/html
CMD ["/run.sh"]
$ cat docker-compose.yml
version: '3'
services:
    web:
      build: .
      ports:
        - "9002:8888"
      volumes:
        - ./:/var/www/html
        - .docker/usr/local/etc/php/conf.d/xdebug.ini:/usr/local/etc/php/conf.d/xdebug.ini

これで、「xdebugの有効なPHP7.3でCakePHPを動かす」ができると思います。

xdebugについて

Dockefile内でxdebug.inをrmすることで、xdebugを無効にしています。
その上で(localでのみ使う想定の)docker-composeではiniファイルをマウントさせており、これによって「xdebugの有効・無効を環境に応じて切り替える」ということをしています。

opcache

ちょっと問題がある?っぽく、opcacheは無効化しています・・・
最初はうまくいかなかったのですが、外してみたら無事にPHPを動作させることができました。はて・・・

まとめ

今日はかなりさっくりです!!
これだけで、簡単にherokuにCakeアプリケーションを放り込めるかな〜と思います。
あとでGitHub/Dockerhubにあげる!

コーディング規約 for small team 2018

1人AdventのDay-17です。17っていうとFLCLプログレを思い出す数字だな〜

adventar.org

コーディング規約というものがあります。
私は、割と「社内(のサーバサイドというかPHPというか)のコーディング規約をちゃんと皆で定めていきたいよね」側にいます。
その中にありながら、昨今では私も含めIDE/PhpStormの導入が進み、PHPCSもいるし、Phan/PHPStanもいるし、「機械的にやれること」は増えてきております。

原則として「既にあるコード」や「コードを書いた人(とその気持)」は尊重すべきだよな〜という気持ちがありまして、そういう意味で「わざわざtrailing commaをつける」だけとか「空白行を挟む」だけのコミットはしたくない、と思います。もしくは「コメントを消すだけ」とか。
自分が飛ばすPR、もしくはレビュー依頼を受ける事になる変更において「極力、diff行数が少なくなる」ように個人的には目指したかったりはするので、ケツカンマを入れる(配列に新しく要素を追加しても「前の行にカンマがついた」diffを出さなくて済むから)とか、「段落ごとに空白業を挟む」みたいなのは気をつけるわけです。
が、 それはあくまで個人的な話だ
コレを「チームで利用するコーディング規約に入れるか」という話を、・・・まぁ合意が取れたら規約として採用してもいいんでしょうけど、何か議論するのが疲れるってレベルのものがある。*1

規約というのはあくまで「健全性」「気持ちよさ」「効率」を引き出すためのものであって、「ストレスを抱えさせる」ためのものであってはならないよな〜と考えるのです。


愚痴を吐いたので、ここから本題です。

(先程述べた通り)私は「規約整備していこうぜ!」側でして、新しくサーバーサイドのエンジニアが入って共同のチームで動くよ!と決まったタイミングで整備をしたり、その後にはgithub管理移行とかも仕掛けたりをしました。
そうした活動を通して、自分なりに「健全性を高めるためにこういうポイントを抑えておきたい」と感じた部分があります。
その辺りの話を、少し整理してみようかなというのが今回のエントリーです。

前提のような方針のようなもの

「整備し直した」ものはCakePHP3のプロジェクト用のものでして、その「第0章」みたいな文章を書いてあったのでそれをそのまま引用してみます。

### コーディング規約の役割

チーム内で、「誰が書いても」「誰がレビューしても」同じ様にコードが書けて、違和感を持たずにコードが読めて、迷いを少なくしながら開発を進められる状態を理想とします。
狭義のスタイルガイドにとどまらず、推奨されるイディオムやプラクティスやフレームワークのバージョンアップ等に伴い生じる「注意の必要な書き方」をも示すことで、日常の開発業務において従うべき新鮮なガイドラインが欠かせません。

これを踏まえて、本文書は以下の役割を果すべきものと定義します。

* CakePHP3の経験の浅い新規参加者が、「どういう風に書くか」を把握できる
* CakePHP3の経験者が、「こうやると書きやすい/読みやすい」を普及できる

このくらいでいいんでないかな〜という規約

OSSのフレームワークを利用している場合、そのフレームワークの採用している規約がある場合が多いと思います。
なので、スタイルに関しての「守らないといけないもの」は、ベースとして「フレームワークが言っていることをそのまま」で良い、くらいに思っています。

これによって、コミュニティが持っているアセットを活かしやすくなるというのも重要。拡張改変バリバリの「本来のそれとは相入れない」ようなものを制定したら茨の道に突入していきます。

その上で、やってもいいかなと思っているもの

基本的に、自分たちのために作っているプロダクトというのはOSSなフレームワークほど「汎用的である必要」がない、と思っています。
そのため、実装についてもより(自分たちのための)アグレッシブな方針を取れるものと思います。例えば、「言語バージョンを新しくしたら使える機能」などです。

これらについては、「フレームワークの本家にはなくても、快適さを向上させる見込みがある」と判断できる場合もあるのではないでしょうか。そういったものは、あっても良いと思います。

あった方がいいかなと思っているもの

逆に、自分たちで作った機構やライブラリについては「利用するように規約で縛る」事でコーディングのし易さを支援できる可能性がある、と考えています。そうしたものは、積極的に「使っていく」ことに決めても良いかと思います。
なぜなら、「自分たちが自分たちのために作ったもの」であれば、サービスドメインやチームメンバーのレベルに合わせて開発されたものであり、フィットするはずだからです。

例えば、私の場合はenumのような機構を作りました*2が、これは「使うべき」としました。オプショナルでなく「使えるときは使う」ことによって、この機構の保守改善を行っていく恩恵が、プロジェクト全体に浸透していく状況を生み出せるようになるからです。
何より「メンバーがそれぞれに同様の書き方を扱えるようになり、リーディングにも実装にも没頭しやすくなる」ことが規約を定める目的でもあるので、足並みを揃えられられたのは良い点でした。

あると良いかなと思っているもの

私の仕立てた「コーディング規約」では、規約やガイド・・の範疇を超えた「プラクティス」の賞も設けています。
「こう書くべき」というとかなり強い制約になると思うのですが、ここには「こう書くとCakePHPぽいよ」といったものを拡充させていっています。
実は(規約自体はフレームワーク本体が抱えているにもかかわらず)「社内規約」を管理したい、というモチベーションの1つはこの「プラクティスを管理してみたい」という部分にもありました。

例えば、「CakePHPのEntityに値を入れるときに、どういった場合にはpatchEntity()メソッドを利用して、どういった場合にset()を使うのか?」といった内容に触れています。

当然ながら、「全員が守るべき・意識するべき」という規約よりも、周知徹底すべきなのはどのレベルからだっけ・・・?というのがファジーになるので、メンテナンスを続けていくのは中々ハードルが高かったりします。それでも、「プルリクで何度も指摘される」ような話は、こういった仕掛けで担保できないかな?とも思うわけです。

いずれにせよ

「なぜなのか」を示していくことが重要なのでは、と感じています。
もちろん、規約の中には「スペース4つで示す」といった、理論立てて説明し/されて納得感を持ちながら扱う・・というのとはそぐわないものもあります。他方で、例えば(実際にCakePHP3が採用している例で)「privateメソッドには引数の型宣言を行わない」という話をするときに「型宣言を行った場合、それを解釈し実行するコストが必ずしも0ではない」から、スコープが限定されるときは「なるべく負荷がないようにしよう」という理屈があると、助かるだろうな!と思うわけです。更に、「根拠を示す」ことが「改定を望むときにpros/consを明確にしやすくなり、本質的な議論に進みやすくなる」という利点もあります。

理屈をしっかりと明示していくことで、「コーディング規約」が「押し付けられるもの」ではなく「民主的に取り組み、常にアップデートされていくべきもの」へと進化させ得ると考えています。

まとめ

規約は堅苦しかったりストレスになる危険性もないではないわけですが、「関わる人全員をハッピーにしようぜ」というモチベーションから生まれるものだと思います。
コミュニティに開かれたソフトウェアのコーディング規約と社内やチームに適用されるべき規約とでは、そもそも目的も異なるはずで。なので、「自分たちのチームには何が必要で、どういったものがあればコーディング時の憂いがなくなるか」という原点に立ち返りながら、「ぼくらのかんがえたさいきょうのこーでぃんぐきやく」を以てして、最高のコーディングライフを手に入れられたらハッピーなのではないでしょうか!

*1:prettierくらい強烈に書き換えてくれるものやgofmtとか、救いだな〜!と感じる

*2:https://speakerdeck.com/o0h/bye-bye-magic-number

yieldとコルーチンと非同期処理

1人AdventのDay-15です。もう2週間経ったのか、12月よ・・

adventar.org

最近、ちらちらっと「Swoole」という単語を聞くようになった気がしており、それについて調べてみよう〜という予定でした。が、「まずコルーチンとかについて頭の中を整理したいな・・」と思ったので、このようなタイトルになっております。

きっかけ

Swooleについて初めて意識したのが、TLにこのツイートが流れてきたときかなあーと思います・・

Swooleってなんなのさ

BEAR.Sundayのサイトに載っている説明はシンプルにまとまっていました。

SwooleとはC/C++で書かれたPHP拡張の1つで、イベント駆動の非同期&コルーチンベースの並行処理ネットワーキング通信エンジンです。 Swooleを使ってコマンドラインから直接BEAR.Sundayウエブアプリケーションを実行することができます。パフォーマンスが大幅に向上します。

bearsunday.github.io

ググったら「副題: 最近Swooleが楽しい話」というUzullaさんの記事が出てきました。

最後まで読んでみて、いろいろと「なるほど」がありました。結構ボリュームがありますね。 スライドを見ていたら、サイトも出てきました。

www.swoole.co.uk

「プロダクション品質の非同期PHPプログラミングフレームワーク」ふむ。

・・・なんだか「こんにちは、闇の方から来ました。私、色々できます」みたいな凄みを感じます。

Sooleと非同期プログラミング

私が「Swoole気になるな」と思ったのは、「非同期」があるの?と思ったのが強いきっかけの1つです。
非同期、よいですね、ふふふ。

先のuzullaさんのスライドを見ると「Swoole、めっちゃ機能多そうだな」という感想をいだきます。何か新しい仕組みや概念を理解しようとするときに、私は「なにか1つポイントを見つけて、それを軸としてイメージを具体化していく 」というアプローチを好みます。それをしながら、「 必要になったら時点で他の筋に移動したり、行ったり戻ったりする」を繰り返して、全体像を掴んでいこうという感じです。

多機能だからこの記事で全部触れるの無理よな〜っていう思いもあり、まず「非同期プログラミング」をキーワードとして調べている内に、主題が入れ替わった形です。

PHPとコルーチン

先のスライドの中にも、「コルーチン」が出てきますね。

[f:id:o0h:20181216010344p:plain f:id:o0h:20181216010434p:plain

PHPでの非同期処理を得意にさせるrecoilなどにもcoroutineについて言及があります。

では、コルーチンとは一体なにで、どうしてそれが非同期処理と関係があるのでしょう?

そもそも「コルーチン」がなにか、という話をつまみ食いしておきます。

まずは、例によってWikipediaです。

コルーチンはいったん処理を中断した後、続きから処理を再開できる

とか

接頭辞 co は協調を意味するが、複数のコルーチンが中断・継続により協調動作を行うことによる。

(https://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%AB%E3%83%BC%E3%83%81%E3%83%B3)

なんて書かれています。
「継続」「中断」「再開」という言葉が出てきました。これらを意識することができれば、意味がつかみやすくなるのかもしれません。

継続

継続については、こちらの記事が良かった。
なんでも継続

「意識することができれば」と書きましたが、「今までもそこにあったのに、見えてなかった/認識することができなかった対象を、ふと「当たり前」に存在を感じられるようになれば」ということで、この書き方をしました。そして、この「なんでも継続」の記事が、正にそのスタンスで書かれていて良かったな〜と。。

すんごいザックリといって「なんかの処理をしていて、途中でどっか行って、戻ってきたらその 続き から処理を行う」というのを強調するために「継続」という概念が必要な気がします。「どっか行って」=中断、「戻ってきて」=再開。

関連: 制御構造 - Wikipedia

yield

さて、PHPにおいても「中断」「再開」といった単語を(サブルーチンのそれとは違い)強く意識する場面があるのではないでしょうか。
イテレータ、ジェネレータ、yieldといったキーワードを思い出してください。

ジェネレータ(Generator)とは、イテレータコンパチなインターフェイスを持つけど、 指すべきコレクションがあるわけでもなく、そのたんびに 値を作り出して返すようなモノを作るモノをいいます。

ジェネレータ と コルーチン - みねこあ

PHPはyieldによってジェネレータを作成できます。

  • 中断:
    • ルーチンの内部の任意の箇所で、(呼び出し側に値を返して)処理を終わらせ
  • 再開:
    • 「さっきやったとこ」の続きから処理を始める

という内容を備えています。「一旦処理を中断した後、続きから処理を再開できる」ということであれば、コルーチンの定義に当てはまると言って良いのでしょうか?

ジェネレータ/コルーチン

yield(PHP)はジェネレータ関数を作るのだから、じゃあyeildを使えばコルーチン?コルーチン = ジェネレータ?と思い、今度は「ジェネレータ」についてWikipediaでみてみます。

ジェネレータの実装としてはコルーチンやcall/ccやマルチスレッドを使う方法が考えられる。

ジェネレータ (プログラミング) - Wikipedia)

ということで、どうも一致する概念ではないようです。
どういう差なのかな、と調べてみたらPythonに関しての例を説明している記事に行き当たりました。

yieldした後にコントロール出来るという点がジェネレータと違うようです。

Pythonのyield(コルーチン編) | KISO-REN

この「コントロール可能か否か」というところで、コルーチンは分類されるぞ!というような事をStackoverlowの問答で発見しました。

In the asymmetric coroutine model, "asymmetry" refers to the fact that there is a stack-like caller–callee relationship between coroutines. A coroutine can either call another coroutine or suspend itself by yielding control to its caller, typically also yielding a value to the caller at the same time.

What is the difference between asymmetric and symmetric coroutines? - Stack Overflow

ジェネレータを含む「非対称コルーチン」においては、「一旦処理に入ったら、そのまま、最後まで内部生成された値を返す」ということになり、これを「一方的(= callerには制御権がなく、コルーチンにのみ自身の制御権がある)」と言っている・・のでしょうか?そんな感じと理解しました。

そしてさらに、Pythonの例を見つけました。

魅力的なPython: ジェネレーターによるステート・マシン

かなり前のバージョンにおける言及をしている記事で、この中では「(Python2.2で導入された)yieldでのジェネレータは半コルーチンで、本当のコルーチンを実装したよ」とされています。

内容を見てみると、「ジェネレータの中から別のジェネレータを呼ぶ事は可能」というのを応用して、「ジェネレーター同士がお互いを呼び合う」ようにしている・・というのがポイントでしょうか。

先の「Pythonのyield(コルーチン編) | KISO-REN」の記事で言及されているPython Coroutineの元ネタPEPを見てみると、次のように書かれています。

However, if it were possible to pass values or exceptions into a generator at the point where it was suspended, a simple co-routine scheduler or trampoline function would let coroutines call each other without blocking -- a tremendous boon for asynchronous applications.

PEP 342 -- Coroutines via Enhanced Generators | Python.org

ということで、IBMの記事にて実装されている内容も今のPythonならシュッとかけるのかもしれません。
これ以上は、今回のエントリーの本題から外れていきそうなので話を戻します!

PHPにも同様の機能が導入されています。

qiita.com

yieldと非同期処理

ここまで見てきたとおりで、コルーチンは「別の何かをする処理」であると言えます。そして、「中断して(=処理を呼び出し元に戻して)」「再開して(=自身の中に状態を維持・継続ができる)」というのがポイントです。
ということは、「コルーチン内部の処理を行っている最中に、呼び出し元の処理をブロックしない」もしくは「取り急ぎ呼び出し元にコントロールを戻しつつ、自分の処理もちょいちょい進めておく」事が可能なら、実質的に非同期処理が可能という着想で合っていますか。

まさに、そのような内容を扱っている資料が上がっていました。

これは、以下の条件によって実現されているものと思います

  • non-blocking APIを備えた実行内容がある
    • curl_multi
  • coroutineをstackさせておく
  • stackされたリクエストの解決まで、無制限のループ処理によって状態のチェックを行う

そうすることで、「すべての解決を待つ」ことをしつつ「個別の処理は並列的に行う」という操作が可能になったという理解をしています。

「PHPでコルーチンを利用することはできるが、それ自体は「あらゆるものをノンブロッキングにする」ような能力はなく、あくまで並列化の可否は処理内容としてノンブロッキングAPIを利用出来るか次第で、また「整いました!」とイベントを拾いに行くのは自分で監視をじっそうしなければならない・・・」 こんなところでしょうか。

ReactはイベントループとノンブロッキングI/Oの実現を目指した、ループ機構です

感想

「なんでもすぐに並列化できちゃうすごいやつ!」というのは、PHPという言語上は存在しないんだなーというのを改めて認識しました。
その一方で、ノンブロッキングな処理が実装されている領域についてはPHP上で実装が可能そうにも思います。例えばMySQLからのデータ取得などは、個人的な関心からいっても恰好のターゲットです。
実際に手を動かしてみないとイメージ湧かないな〜とも感じたので、「引き続き模索してみたいな」と思っています。

qiita.com

その他の文献

本文中では触れなかったものの参考にした記事です

個人的にPHPのassert()の使い方を整理する

1人AdventのDay-12です。12ですかぁ〜

adventar.org

PHP*1にはassertというものがあります。

www.infiniteloop.co.jp

これ便利だし、コードを「良くする」ことのできる嬉しい機能だと思っています。
ただ、往々にして「開発を健全に続けていく」という目的の下にあっては、「曖昧さ」「ゆるさ」は罪になることもあります。そんなつもりはないのに・・・

ここでいう「曖昧さ」というのは、「自分以外の、他の人が、同じようなことを書いたり書こうとした時に、同じ感じでかけるか?」という、悩ましさの大きさだと思ってください。
プログラミングをやっていて、醍醐味で貼りますが、こういう風に動けばいいな!って思いついてから「あ〜どうやって書こう、何が正解かな?」って考えさせられる部分というのは、苦しみを招きます。

処方箋として。
「やり方を決める」っていうのは、1つの手だと思います。「これはこういう時に」「こういう風に使いましょう、使って良い」っていうガイドラインがあれば、気持ちが軽くなりますね。

さて、話を戻して「assert」や・・・いつなら使っていいんだ・・・

実際に業務のコードにチラホラと織り交ぜて見ているのですが、自分なりに「ここはOK、これは微妙」っていうラインを形にしてみようと思いました。
今日はそういうブログです。

前提として

  • assertは、プロダクション環境では使わない。実行されるのは、開発環境においてのみである
  • すなわち、実行時にデータを守ったり、ユーザーを守るためのものではない
  • 要するに、「開発時に実装のミスをしないように」、「開発者を支援するため」のもの

と思っています。

「実行されるコメント」という感覚。

私の場合

「assertは使って良いもの」としつつ、先述の「曖昧になっていく」のを恐れています。そのため、限定的な使い方をしています。
とりわけ、 LogicException とはなぁ。。。という風に感じています。

かなり探り探りでありつつ、「このくらいなら・・・」というのを書き連ねてみます。

privateメソッド内での利用

assertを「実装ミスをあぶり出す」という目的で使うとなると、「どういう使われ方をしそうか」というのは限定して考える必要があります。

その点、privateメソッドに関しては「まぁ、うっかりミスは少ないかな・・」という自信を持ちやすいかと思います。
protected, publicだと、どう使われるか保証できるとは言い切れないので、LogicExceptionをしっかりつかうかもしれません。

「ここに来る前に、このメソッドを実行されているか」みたいなチェックなど。インスタンスメンバーの設定状況だったり、DIの注入状況だったり・・・といったケースでしょうか。

自作トレイト内での呼び出し元クラス設定状況

インターフェイスや抽象クラスでは「メソッドの定義を強制できる」と思うのですが、クラス定数・クラスメンバーについてはどうでしょう。 「このトレイトを使うには、 $this->config に arrayをいれてある」とかは、「実相時点で拾える必要がある」と思います。

そういった意味で、assert()を安全に使えるのではないでしょうか。

テスト中の前提条件

これを結構よく使っているかもしれません。

テストなんて「検査」しかしなくない?という話もあると思います。
たとえば、「ユーザー削除処理を行うAPIの実行時に、ユーザーの持っている投稿をすべて削除する」など。

この場合、「このユーザーIDに紐付いている投稿が0件になっている」ことをテストケースに絡めることが可能です。
が、それを実行する場合、利用するフィクスチャデータに「そもそも投稿がなかった」という状況だと、「検査は通るけどテストの意味を持たない」ことになってしまいます。
とはいえ・・・「もともと、なにか投稿していたよね?」という確認は、このテストケースにおいて「やりたいこと」ではないわけです。

そうした場合、「やりたいこと」と「守らないといけない前提」を明示的に区別するために、PHPUnitのconstraintとassertを併用するのはありかな〜と思います。

まとめ

もう少し使ってもいいんじゃないかな〜活躍してくれ!!という気持ちはあります。
その一方で、別にどんな機能も「無理に使う」必要はないと思います。
それでいて、「どっちでも良い部分」という根拠の説明がふわっとしやすい部分は辛いのです。とりわけ、チーム開発を行っていると、「なんとなくこう!」というのは、レビュイーに対して出来ることではありません。でも許容していると、「緩さ」が蔓延していき、より辛く・・・・誰も幸せになれないわけです。

なので、「チームとしての基準を決める、合意をとっていく」「アイディアや思考プロセスも含めて、プラクティスを蓄積していく」ことが重要なのかな〜と思っています!

*1:ここで言っているのは7.xですね

PhpStormでのGit/GitHub利用

1人AdventのDay-11です。

adventar.org

今日は、すでに10,000,000回くらい言及されていると思いますが、今年ちゃんと使い始めたかも!そしてすっげ、便利!!系のネタで、「PhpStormからGit/GitHubを利用する」をしたいと思います。
この辺りを気にしなくていいのが自分のブログの醍醐味じゃろ、っていうノリです。

なぜ「エディタ」でそこまで

1つに、「ウィンドウを行き来する必要が減る」というのは、やっぱりでかいです。
IntelliJ IDEA含め、世のIDEは「ショートカットを覚えたもん勝ち」「いかに思考より早く必要な機能を起動できるか、体に馴染ませるか」みたいなところがあると思っています。

その中にあっての、Git。便利です。
あと、こまめにコミットしておくと安心感がすごいんですよね。PR飛ばす前にrebaseをかけることで、コミットにもちゃんと意味をもたせる〜観点で整えよう!というくらいの木基で、本当はバシバシとコミットしていくのが良いのかも・・・というくらいに思っています。

commitをする

⌘+k です。

(大いに、私の好みの問題ではあるのですが!)
「コミット前に整える」機能がstormの力を遺憾なく発揮する形で充実しており、そして「Amend commitがすぐにできる」というのが嬉しいのです。 f:id:o0h:20181212022121p:plain

何が嬉しいのか?
とりあえず、一旦wipでコミット が、非常にやりやすいな〜と・・

Reformat codeや Optimze importsというのは、「どっか弄ったときに、直し忘れてた」みたいなのを消してくれます。 useされているけど使っていないよ とか 50音順に並んでいないよ とか、そういう。
この辺りは、当然「レビュアーに失礼のないように整えましょ」という話ではあるのですが、ここまでくると、「通常作業の自然流れの中に『細かいコミット』を組み込んで見ようかな?」という気にもなります。

commit messageを入力したら、 ^+k でコミットを実行してください

pushする

⌘+⇧+k です。

f:id:o0h:20181212022920p:plain

pushは、commitほど「細々と実行する」ようなメリットはないと思います。
ここで便利なのは、「pushする前に気づいちゃったことをさくっと開く」のが億劫でない、やはり「エディタとの距離が近い」ことによる恩恵があるな〜といった感じです

checkout

f:id:o0h:20181212023328p:plain f:id:o0h:20181212023254p:plain f:id:o0h:20181212023413p:plain

clickだけで、すすす〜っとブランチを移動することが可能に。
嬉しくないですか?

view pull requests

reviewするときに、「このブランチをじゃあ実際に落としてきて」って絶対にやるじゃないですか。

f:id:o0h:20181212024440p:plain

f:id:o0h:20181212024842p:plain

左カラムがPRの一覧です。
各PRを右クリックすると、「Create new local branch」「Open on GitHub」というメニューが現れます。すごい。

find pull request

「この行の変更は、どういう経緯だ・・・?」ってなるときに使います。

f:id:o0h:20181212025138p:plain エディタ上の、気になる箇所を右クリック→コンテクストメニューから「Find Pull Request」です。 ブラウザ上で該当のPRが表示されます。

annotate

コードの行番号を右クリックすると、「annotate」というメニューがあります。

f:id:o0h:20181212025350p:plain

これで簡単にblameができて、大助かりです。
authorの表示されている部分にhoverすると、コミットメッセージが表示されます。

f:id:o0h:20181212025538p:plain

また、クリックするとコミットの詳細が表示されます

まとめ

今の所、私に「馴染んでいる」という感覚のある機能はこのくらいです。
まだまだ知らない機能、使えていない機能がある・・・・・・というのは大いに自覚しております。探していきたいな、という所存。