読者です 読者をやめる 読者になる 読者になる

YAPC::Kansai 2017に行ってきたのでトークの感想など

日記 Perl

YAPC::Kansai 2017に行ってきました。去年のPHPカンファレンス大阪に続いて、カンファレンス2回目。今回は初懇親会も。

とりあえず駅までのバス、停留所逆側で待ってて、一本逃がして開場前に余裕で着く予定がぎりぎりに。

さらに、新大阪で下りてからだいぶ迷う。なぜか大阪駅だと思い込んでいたのだった。大阪駅ならまあ駅から出るくらいはなんとかなるだろうと、せっかく公式ブログで会場への行き方とか丁寧に説明されているのに読んでいなかった。そもそも大阪駅から出られるってのも怪しいんだが……。

まあでもなんとかオープニング中に入り込めたのでよかった。朝イチでかなり見たいトークがあってな。

10:20 ~ 10:40 メールフォームからメールを送る近代的な方法 | YAPC::Kansai 2017 OSAKA

最近HTTP APIでメール送る系にちょっと興味があったので。思ったより「近代的」な方の比重は小さかった。まあ時間の問題もあったみたいだが。

SMTPsendmailの割と基本的な話から入った。基本的とはいっても自分はそんなに詳しいわけじゃないので、あれこれ新しい知見も。

HTTP APIでの送信の方では、APIと同時にSMTPインターフェイスもあったりするというのがまったく知らなくて、興味深かった。

ある程度規模の大きなメール送信するならHTTP API試したいなあという気持ちが強まった。今のところsendmail経由で問題になるような規模でやることないんだが……。

あとバウンスメール処理のモジュールがあるようでこれがちょっと気になってる。

これだね。 Sisimai | bounceHammerの後継となるバウンスメール解析ライブラリ | Sisimai: Mail Analyzing Interface

10:50 ~ 11:10 オープンデータを利用したWebアプリ開発

トークはちょっと方向性が不明瞭だったが、オープンデータには興味が湧いた。国勢調査ベースのデータなんかが公開されてるらしくて、それけっこう使えるんじゃね? と。

PostGISGoogle Maps APIであれこれするのも楽しそう。

オープンデータあまり流行ってる感じじゃないので、今後流行るといいなあ。

11:20 ~ 11:40 高速化の初歩

基礎的な話。そこまで効果的ではないあたりから始めて、けっきょくいいアルゴリズムが大事だったり~みたいな流れ。ちゃんと無駄な高速化への戒めもあってよくまとまっていた。

11:40 ~ 12:00 Vue.jsで作るSPAから学ぶMVVM、非同期処理、その光と影

個人的に今回いちばん楽しかった話。事前にはそんなに期待してなかったんだけど。Vue.jsあまり関係なく、SPAもそこまで関係なく、MVVMとかPDSに関してのとてもわかりやすい話だった。

MVVMとかはかなり気になるネタだったので、ちょっとわかった気になれてよかった。わかった気になるだけじゃなくてちゃんとわからないとな……。

この辺いい本ないのかねー。

ベストトークに応募したのはこれ。

12:10 ~ 12:50 レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

これも事前から期待していた話。DDDまでは行かず、割と基本的なオブジェクト指向の話という感じだった。

「Serviceは状態を持つべきか否か」のあたりが興味深かった。状態を持つというか、staticメソッドだけのクラスじゃなくてコンストラクタでオブジェクト突っ込んでも、イミュータブルであれば別にいいと思う。

ただこの場合、Service側自体が不変でも、突っ込んだオブジェクトの方が可変になったりでややこしい気もする。

この辺はCQRSとかでなんとかするべきところなのかなあ。難しい。

13:40 ~ 14:00 コミュニティを開発していた元RubyエンジニアがPerlでゲーム開発を始めて感じたこと

この時間帯、B会場でやるトークも面白そうで迷ったんだけど、続く2トークがC会場だしとこっちに決め。楽しい話だった。

今時なかなかほかの言語からPerlに移ってくるような人っていない感じだし、こういう話はなかなか貴重。

14:00 ~ 14:20 Perl to Go

Perlで書かれた割とローレベルなことをやっているモジュールをGoに移植した話とかそんな感じ。

PerlはforkやりやすいがGoではそうではないらしいとか、PerlでハッシュでやっているものはGoでそのまま対応するデータ型でやるんじゃなくて、structにしてしまった方がいいとかそんな感じだったかな。

内容はもちろん、話し方も勢いがあって楽しかった。

14:20 ~ 14:40 なぜからはじめる開発

これも割と聞きたかった話なんだけど、時間配分甘かったのかいまいち頭に残らなかった。

あとこの辺から座りっぱなしのせいでつかれてきた。去年のPHPカンファレンスのときはこんなことなかったはずなんだが。YAPCの方がちょっとトークの密度高いかな?

14:50 ~ 15:50 GUEST: スペシャルセッション

リファクタリングの話……になったようなならなかったような。機材トラブルも含めて笑えるトークではあった。

16:00 ~ 16:20 Perl ウェブ開発の中世 〜CGIPlack の間〜

今回いちばん期待していたトーク。スライドも高品質で楽しい話が進んでいくが、残念ながら時間のせいで後半早送り気味。

後で懇親会をお聞きしたところ、話の中心をどこにするかで迷っていたとのことだったので、元々スライドの枚数も多めだったのかも。

でもこれは40分で聞きたかった。

PSGIは低機能なCGIに寄せたのがすごい」というのはまったく考えたこともなくて、はっとさせられた。

16:20 ~ 17:00 はてなシステムの考古学

はてなでの技術の変遷の話。夕方に見るにはちょうどいいゆるめのトークだった。

17:10 ~ 17:40 Lightning Talks

この辺もうだいぶつかれてきていて(座ってただけなのにな)、記憶も曖昧。ただ最初と最後の人の勢いがすごかったり、全体的に話しのうまさではトークの方より平均値上なんじゃねーのとか思ったのは覚えてる。

17:45 ~ 18:50 Keynote

割とだらだらといろいろなお話をされていた。尺長いしね。未踏の話とか、バイナリの話とか、Shibuya.pmの話とか。

19:30 ~ 懇親会

カンファレンスは二回目だが、懇親会は初めて。お店までちょっと迷ったが、今度は遅刻はせずに済んだ。

知り合いとかいるわけじゃないのでどんなもんかなーと思ってたが、一応何人かの方とお話できてとても楽しかった。

それほど広くない店の中に100人近いんじゃないかってくらい詰まってたが、これくらいの密度だったからこそ話せたのかも。

電車の時間の関係で途中で抜けなきゃならなかったのは残念だったけどなかなか楽しかった。

今後

今回LT応募したけど不採択だったのが心残りなので、その辺もっと頑張っていきたいなあとか。

そのためにはとにかく、話のネタになるようなことやってかなきゃだよね。

Gitの導入はなぜ失敗したか、どうすれば成功したか

日記

YAPC::Kansai 2017のLTに応募してたんだけど不採択になったのでブログ記事にする。落ちるだけあって、大した内容ではないです ;-)

あとこの話はフィクションです。一応ね。

経緯

去年一年くらい、地方の中小企業的な某社(以後B社とする)に雇われて働いていた。PHPで、既存システムのリファクタリングとか、機能追加とかをやった。なおすべてリモートワーク。

B社はIT関係ではなく、自社システムのために社内にプログラマが多少いる、みたいな環境。半分内製、半分外注みたいな感じ。

B社のソフトウェア開発体制は、 ジョエル・テスト で0点取りそうな感じでまあ微妙。

VCS使ってないし、デプロイは自動じゃないし、バグ管理もスケジュール管理もできてないし、仕様書もない。

でも現状がいいとは思ってないみたいで、打ち合わせのときにも改善点ないか聞かれて、どうにかしようという意識はあるようだった。

ので、なにより自分のためにGitその他いろいろ提案したのだが……。

ツールは導入されました。しかしワークフローは改善されませんでした、みたいなことになった。

B社の開発ワークフローでつらかったのが、

  1. ソースコードのマスタが本番サーバにあるファイル。
  2. 作業がコンフリクトしないように、作業前に作業箇所を報告。
  3. 毎回本番サーバからダウンロードして、変更があれば手もとにマージ。手もとでは当然Git使ってるので。
  4. デプロイ前にもう一回ダウンロードしてきて、マージするなり。
  5. デプロイはFTPで手動。なお日付つきバックアップをしてからアップする。

みたいなあたり。

Gitを導入して、Gitリポジトリがマスタになれば、ほとんどの問題は解決するはずだった。

が、じっさいにはいろいろ問題が出て、なに一つ解決しなかった。

  • リポジトリの単位がおかしくて、一つのシステムが複数に分割されたりしていた。
  • ブランチが使われなかった。
  • コミットの粒度もおかしかった。

とかまあどうしようもない感じで、Gitリポジトリがマスタになれば、自動デプロイもすぐだなー、とか甘く考えてたのがぜんぶ駄目になった。

最初はこう思った

とにかく、もっとちゃんと使ってくれよ、わからないなら自分で学ぶか、せめて俺に聞けよ、と。

けどまあ、開発体制の改善が俺の仕事ではなかったし、リモートワークなんでコミュニケーションも取りづらいし、けっきょく行動しないままに仕事は終了。

終わってから今更ながら反省すると

落ち着いて考えると、目に見えるモチベーションなしに勉強なんてしないよね普通。そして、日付つきバックアップ作っていたような環境でいきなりGit使っても、便利さ感じるまで遠過ぎるよね、と。

じゃあ目に見える便利さがあればよかったんじゃないかな、便利さ駆動でなら学んだんじゃないかな、という結論に。

で、どうすれば便利だったか。いろいろ考えてみたけど、リモートで密なコミュニケーション取れるわけでもなく、立場的にあれこれ強制するわけにも行かず、みたいな前提だと、ワークフローを与えるみたいなのは却下。

じっさい、Gitやほかにもツール類はいくつか導入されたが、ワークフローの変更が必要な提案はどれも通らなかったし。

  • ツールの形で、
  • 一目瞭然な便利さがあって、
  • その便利さを継続して受けるためにGitをきっちり使う必要がある。

みたいなのが欲しい。

最終的には、Git + Jenkins + lftp使った自動デプロイスクリプトあたりで、とにかくワンタッチでデプロイできる形にした仕組みを丸ごと提案。

とかすればよかったんじゃないかなあと。

次機会があったら今回の反省を踏まえて、もっとうまくやりたいですね。

Redmineで細かなバグの扱いで悩んだけど、使い方の改善だけでなんとかなりそう

Redmine

1つあたり平均5分もあれば直せそうな細かなバグが数十個とか報告されて、Redmine上での扱いをどうしようか悩んだ。

Redmineの使い方は割と普通。デフォルトからあまりいじっていない。プラグインも入れていない。ちょっと変わっているのが、自分一人で使っているということくらいだけど、ま今回はあまり関係ない。

RedmineとGitの連携はしていないが、チケット単位でブランチを切っている。また、作業時間のログを別途取っているのだが、それもチケット単位で、かつ30分単位でやっている。

という感じの前提。

まず思ったのが、こんな報告一つにつきチケット一つなんて面倒臭えよ、ってこと。

ただ、なんとなく面倒臭えよと思ってるだけじゃ駄目なので、具体的になにを面倒臭いと感じているのか、考えてみた。考えたというよりただ思い付いたことをメモっただけか。

  • 細かなバグがたくさんある。
  • いちいちチケットにするの面倒。
  • ぜんぶチケットにしたら、わざわざブランチ切ったり、作業時間のログ切り替えたりするの面倒。
  • ぜんぶチケットにしても、同じ原因のバグとかどうするの。
  • Redmineのチケット一覧性いまいちなんでまとめた後に内容を確認するのが面倒。
  • Redmineのチケット、テンプレートとかなくて不定形になるのでそこも面倒。

こうして羅列したものを一つずつ、どうすればいいか考えていった。

  • 細かなバグがたくさんあるのは、面倒だけど仕方ない。
  • ブランチや作業時間のログとの不一致は俺の作業方法の問題。ただこれは、Redmineの親チケット機能でまとめればなんとかなりそう。
  • 同じ原因のバグは、後から重複チケットとしてまとめればいい。
  • チケット切ること自体の面倒さと、テンプレートがない件は、URLクエリでデフォルト値を突っ込む方法 http://atotto.hatenadiary.jp/entry/2013/08/27/212556 で緩和できそう。
  • 一覧性の問題は、カスタムクエリで頑張れ、かな。今回知ったが一応チケットの本文も一覧に出すことはできるっぽい。

ということで、ほとんどの問題は解決するか、完全にはしなくても緩和できそうだった。


特にオチもないのだが、つらいと思ったときに思っただけで終わってちゃ駄目だよね、という話。

WindowsでVagrantでPageant使ってSSHエージェント転送

Vagrant

なんかはてなブログの下書きの仕様が変わったのか、書いてたの途中で消えちゃったので面倒なので適当に。

WindowsVagrantでPageant使ってSSHエージェント転送するのは簡単だよという話。provisionでGitとか叩くときとかに必要になるアレ。

  • GIT_SSHplink.exeのパスを。
  • Vagrantfileにconfig.ssh.forward_agent = trueを。
  • もちろんPageantにキー突っ込んでおく。

だけで行ける。簡単。

ただこれだけだと、provisionerからroot以外にsuとかsudoするとかした場合にそのままだと行けない。ので、

  • provisionerでSSHする前に、Defaults env_keep += "SSH_AUTH_SOCK"とかをsudoersに突っ込んで、環境変数を渡しつつ、
  • setfacl -R -m u::rwx "${SSH_AUTH_SOCK%/*}"なりして、権限も与える。

とやる。

SSH Agent-Forwarding works, but what about sudo -u username no shell/ permissions? composer - Unix & Linux Stack Exchange

その他数ヶ所参考にしたんだが、どこだったやら……。

vagrant-cachierはvagrant-vbguestと競合するっぽい

Vagrant

WindowsVagrant 1.9.1にcachier, vbguestのプラグインを入れた状態で、

Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"
  config.vm.synced_folder ".", "/vagrant", type: "virtualbox"

  config.vm.provision "shell", inline: "sudo yum update -y kernel"

  config.cache.scope = :box
end

みたいなVagrantfileを用意。vagrant upして、続いてvagrand reloadすると、

$ vagrant reload
==> default: Attempting graceful shutdown of VM...
==> default: Checking if box 'centos/7' is up to date...
==> default: Clearing any previously set forwarded ports...
==> default: Fixed port collision for 22 => 2222. Now on port 2200.
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 (guest) => 2200 (host) (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2200
    default: SSH username: vagrant
    default: SSH auth method: private key
==> default: Machine booted and ready!
[default] No installation found.
Loaded plugins: fastestmirror


Error making cache directory: /var/cache/yum/x86_64/7/base error was: [Errno 2] No such file or directory: '/var/cache/yum/x86_64'

==> default: Checking for guest additions in VM...
    default: No guest additions were detected on the base box for this VM! Guest
    default: additions are required for forwarded ports, shared folders, host only
    default: networking, and more. If SSH fails on this machine, please install
    default: the guest additions and repackage the box to continue.
    default:
    default: This is not an error message; everything may continue to work properly,
    default: in which case you may ignore this message.
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!

yum install -y kernel-devel-`uname -r` gcc binutils make perl bzip2

Stdout from the command:

Loaded plugins: fastestmirror


Stderr from the command:



Error making cache directory: /var/cache/yum/x86_64/7/base error was: [Errno 2] No such file or directory: '/var/cache/yum/x86_64'

こんな感じのログを吐いて失敗する。

vagrant reloadでなく、vagrant haltしてからvagrant upだったり、あるいはcachierプラグインが入っていなかったりする場合は問題ない。

(なお、もう一つVMが立ち上がっているためポートが競合しているが、そこは本題とは関係ない)

かなり調べても原因が確定できなかったのだが、とにかくvagrant reloadの場合、GuestAdditionsインストールのためのyum update前にcachierのディレクトリが用意できないとか、その辺の理由で失敗しているようだ。

この問題自体もやっかいだが、この問題を調べている途中に気付いた以下の点がさらに酷いと感じている。Vagrantは正直、仕事で使いたいと思わない。

  1. 公式ドキュメントに書いてある"The equivalent of running a halt followed by an up."が思い切り嘘であること。
  2. プラグインを一時的に無効にすることなどが不可能なこと。
  3. 同じVagrantfileでもインストールされているプラグイン次第で挙動が変わること。

つらい。

追記。

追試しやすいようVagrantfileを最小限にしたからアレな感じになったけど、yum updateでぜんぶ更新、とかやると(カーネルを更新しないよう除外していなければ)同じようになる。

じっさい、Ansibleでyum: name='*' state=latestしてはまった。

composer updateでよくわからないエラーメッセージが出たが、指定したブランチがないだけだった

PHP

あるアプリケーションが依存している Git リポジトリがあったのだが、master 以外のブランチを参照することになった。ので、composer.json を更新して composer update したら、

The requested package <VENDOR>/<REPO> <BRANCH> exists as <VENDOR>/<REPO>[dev-master] but these are rejected by your constraint.

というよくわからないエラーが出た。

指定したブランチが別名で(というか master として)存在しているがあなたの制約でリジェクトされた、ってどういうこと?

いろいろ調べたがけっきょくわからず、もしやと思って依存リポジトリの方を確認したらけっきょく、参照したいブランチがリモートに push されていなかっただけだった。

master はあるけど指定されたブランチはないよ、master はあなたが指定していないから使わないよ、と言いたかったのだろうか。わからんって。

Vagrantのsynced_folderにはあまり期待してはいけない

Vagrant Ansible

そもそもなにがしたかったか

Vagrant + VirtualBoxで開発環境を作ろうとしていて、デフォルトのvagrantユーザで作業するのもアレなんでprovision(今回はansible_local)でユーザを作って、そのユーザのホームディレクトリをホストOSと共有したかった。

試したことと当たった問題

  1. config.vm.synced_folderowner, groupにユーザ名・グループ名を普通に指定。
    • id: magai: no such user
    • フォルダの同期→provisioningの順番なのか。
  2. provisioner側でmountする。
    • mounting failed with the error: Protocol errorとか言われる。
    • どうも、ホストOS側からVirtualBoxに指示(GUIなどから?)しないとホストOS側のパスが見えない? ちょっとここ原因が最後までわからなかった。
  3. 仕方ないので、synced_folderで、uid, gidで直接指定しつつ、provisioner側で、uid, gid指定でユーザ、グループを作成。
    • mount_optionsがおかしいのか、これも動かない。普通にvagrant:vagrantのままになっていた。

そして、解決しないままいろいろ試していて気付いたのだが、ホームディレクトリを共有するとなると、~/.ssh/なども共有することになるが、ご存知の通りこの辺パーミッションが厳密でないと動作しない。

なのにsynced_folderではディレクトリ・ファイルのパーミッションを1つ設定するだけで、細かいことはできないし、そもそもホームディレクトリを共有しても問題ばかりで駄目かなと。

あきらめた。

おまけ: 関連して引っかかった細かい問題

  1. Ansibleのmountモジュールのpathパラメータが、今回使ったバージョンのAnsibleではまだnameだった。
  2. Ansibleのsudo: yesがbecome: yesになっていた。
  3. Ansibleのuserモジュールにgidパラメータがなかった。issueは立っているので、今後修正されるかもだが、今はいちいちgidを指定してgroupを作ってから……と二度手間になる。

今後確認すること

  1. ユーザが存在する場合のみsynced_folderを設定する、ということはできないか?
  2. VirtualBoxの共有機能のパーミッション周りにはどれくらい制限があるか。