ありがとう。また会おう。

ゆるいかんじで。かたのちからぬいて。やってます。

レコードがなかったらINSERTして返すみたいなのをもっと確実にやる

元ネタ

レコードがなかったらINSERTして返すみたいなのを確実にやる | おそらくはそれさえも平凡な日々
http://www.songmu.jp/riji/entry/2014-03-02-find-or-create-surely.html

このソースコードの処理だと

# エラーが発生していて重複エラーだったら取り直す

# ロックかけたいときは取り直す

の処理の間に、該当レコードがDELETEされてしまうと
空行にFOR UPDATEしてしまい、ギャップロックの悪夢再び、になってしまうかと。

どうしても確実にやりたい、でも、ON DUPLICATE KEY UPDATEも
INSERT IGNOREも、(元ネタには言及ないけど)REPLACE INTOも嫌!ってことなら
「ロック専用テーブル」を作るのがいいのではないかなと。

処理をかけたいテーブルと同じPKを持つテーブルを作る。(複合キーなら同じく複合で)
このロック専用テーブルには他のカラムは要らない。

で、トランザクションの最初に、
ロック専用テーブルにこれから処理しようとしているデータのPKをINSERT。

本来やりたい処理(レコードがなかったらINSERT)を行う

ロック専用テーブルにINSERTしたデータを削除してからコミット

こうすれば、いけるんじゃないかしら。
並行スレッドは、処理をしようとしても、最初のロック専用テーブルのINSERTに失敗するから
処理できないはず。
一方、ロック専用テーブルにはPKを直接指定してINSERTしてるので
このケースの時はネクストキーロックはかからないんじゃなかったかな。。。ちょっと記憶が曖昧。
実際動作確認したわけじゃないので
嘘書いてたらごめん。

まぁ、このためだけに、一見何も入ってないテーブル
トランザクション開始時にINSERTして、コミット直前にDELETEしちゃうから)
を作らなきゃいけないってのがうざいので
許容できる状況なら ON DUPLICATE KEY UPDATEがおすすめかな。

退職のご挨拶

2014年8月末で、現職の株式会社トライフォートを退職することになりました。
本日(8月25日)が最終出社のため少し早いですが、退職エントリーを書きます。

トライフォートでは最終的にはサーバサイドエンジニアを束ねる部門
インフラエンジニア束ねる部門、2つの部門長という肩書で活動をしておりました。
身に余る光栄であるとともに、短期間で会社を去る決断をしたことについては
関係各位にはご迷惑おかけすることをお詫び申し上げます。

トライフォートに入社したのが、2013年の9月で、ちょうど在籍は1年ということになります。
終わってみれば、たった1年だったのですが
1年だったのか!?と自分でも思ってしまうくらい
この1年はとても勉強することも多く、実りも多く
自分の職歴では最短の在籍期間となったものの、得たものは本当にたくさんあった
充実した1年間であったと思っています。

サーバおよびインフラ部門の長として
マネジメントとして心がけていたことが2つあります。

1つは、書籍「Team Geek」に取り上げられている「HRT」です。
Humility(謙虚)
Respect(尊敬)
Trust(信頼)
現場のメンバーと謙虚に向き合い、尊敬し、信頼する。
言葉で言うのは簡単ですが、実践するのはなかなか難しい。
時には「これ自分がやった方が早えし」とか「ちょwおまw」と思ってしまうこともあるんですが
できるだけそこは堪えて、
皆の心(Heart)に届くマネジメントをしてきたつもりです。

もう1つは、「情報の共有、アウトプット」です。
トライフォートのエンジニアは、技術レベル高い人が揃っていると
贔屓目にみても思ってはいるのですが
ただ、情報を共有する場があまりなかったり、アウトプットを積極的にする文化がまだ足りないと感じていて
そこは力を入れて仕組み、仕掛けをいろいろしてきました。
「社内Lightning Talks」なんてのも始めて
普段は人前で発表しない人にも、強制的に発表する場を仕掛けたりもしました。
正直最初は反発もあるかな…と危惧していたのですが
初めて見ると、意外とみんなそれぞれにアイデアをだして良いネタを披露してくれて
この人はこういうところに興味が向いてるんだなという発見もあったりで
始めた当初の想像以上に、良い効果が出てるんじゃないかなと自負しています。

ただ、アウトプットに関して言うと、やりきれなかった部分として
社内にとどまらず、社外に発表できるレベルまで引き上げたかったな...というところが心残りです。
というか、内容的には社外に発表しても問題ないものも多いのですが
恐らく文化的な部分で、社内向けだからということで
ちょっと詰めの甘い部分があったり
あとは社内PJに関する情報が多くて、公表できないだけ、というのもあり
それはもうちょっとエッセンスを抽出すれば、公表して、
それもまた一つ会社のバリューにも、そのエンジニアのバリューにもなると思うのですが
そこまで組織力を持ちあげられなかったのが、自分の力不足を痛感している次第です。

ほんとはもう少し有休残ってたので
のんびりできたらという気持ちもあったのですが
諸々事情があって、休暇も取れず、この時期になってしまったのですが
8月25日に最終出社というのは、ちょっと思うところもありまして。
25日なので、給料日なんですよね。
事情あって、退職公表から最終出社まであまり時間がなかったので
せめて、最後の給与明細くらいは、部門長としてきちんと手渡したいなという気持ちもありました。
(何人かは夏休み中で叶わなかったのですが)
きょうび、給料明細なんて、単なる記録でしかないので
特別な思い入れなんか無い人が多いのかもしれないですが
やはり現場のみんなが尽力してくれた上でのお給料ですので
今までの感謝の気持ちを込めて最後の明細をお渡ししたかった
・・・そんな思いもありました。

退職理由については、退職エントリとしてはもはや常套句ですが
「音楽性の違い」とだけ記載しておきます。
(それにしても便利な言葉だw これ最初に退職エントリで言ったの誰だろう... 起源を知りたい)

次の職場でも、相変わらずサーバサイドのエンジニアはしています。
ただ、ここ半年くらいはほぼマネジメント寄りだったので
手を動かすってことに対してちょいと鈍っているので、勘を取り戻せるかが若干不安だったりもしますが...
まぁ、なんとかなるでしょう(笑)

株式会社トライフォートの皆様、および業務にて関わった皆様、本当にありがとうございました。

のりぃ流、保守性・可読性の高いコードの書き方

先日、「保守性・管理性が劇的に上がるPHPのスマートなコードの書き方」という某社のブログエントリが話題になってましたが
それについては、もういろんな方がいろんな言及をしているので
改めて僕が言及することも無いと思うので。

で、じゃあ自分ってそういう「人に読まれること」を前提にしたコード書く時
(仕事上のプログラムは99%そうだと思うのですが)
どんなことに気をつけてるか、ブログ書いてみようかなぁ…とFacebookにぽつと書いたら
意外と需要ありそうだったので、つらつらと書いてみた。

といっても、そんな特別なことはしてない・・・と思ってます。
あと、プログラム設計上こうすべき、とか、もあることはあるんですが
それよりも、もっと「これだけは心がければ」という根本的なポイントだけ。
実際、僕がいろいろなソースコード見てて、読みやすいな、メンテしやすいなと思うのも
このポイント抑えてあるものが多いので。

英単語を省略しない

昔ながらの慣習で、返り値用の変数を「ret」「rtn」とか、
msgとかstrとかはまだ可愛いと思うのですが
例えば、「カテゴリ」を「Ctg」みたいな、母音を抜いて省略する表記を多用されると辛いなと。
で、これがスコープ範囲狭いローカル変数ならいいんですが
クラス名とかでこういう省略をされると結構厳しい。

一昔前の、iアプリ出始めの頃のプログラミングならそういう省略も必要だったでしょうが
もうきょうびそういうのはいいんじゃないかなと。*1

英語のスペルミスをしない

英単語を省略しない、てのとも近いのですが、地味に気になるのがこれ。
率いる人の意味の「リーダー」を「reader」と平然としてあったり。
ガラケー全盛期によくあったのは、携帯キャリアの「Carrier」を「Career」(こっちは経歴の意)とか。
アバター」も「Avater」って頻出間違いパターン。(正しくは「Avatar」)

複数形変化の間違いも多いっすね。「Abilitys」とか。(正しくは「Abilities」)

こういうのが積もり積もると、地味に読みにくい。ストレスになる。

例えば、コーディングしている環境が、セキュリティの都合上、インターネットに繋がりません
ってのであればしょうがないですが
きょうび、英語のスペルなんて、Web辞書で1分もあれば調べられるじゃないですか。
さらに言えば、今どきのIMEカタカナ語辞典ってのがあって、
「いんたーねっと」って打てば「Internet」が候補にでてくるでしょ。
スペルチェック機能があるようなエディタやIDEもあるでしょうし。

で、ここが大事なところで、一番言いたいところなんですが
そういう細かいところに行き届かない人が書いたコードって
実際のプログラムも、動作的に行き届いてない、残念なものが多いような傾向があるように思います。

あと、いい加減、IT業界最頻誤用英語「regist」*2も撲滅したいなぁ。。。
(registという英単語はありません。正しくはregister)

同じ概念を示すものは言葉を統一する

例えば、課金を扱う処理を書いていて
あるところでは「Payment」って単語が使われているんだけど
別のところでは「Purchase」が使われているとか。そういうこと。

ソシャゲ業界あるあるとしては、「ガチャ」が「Gacha」だったり「Gatya」だったり。
そういう表記ゆれを許さない。統一する。

以前の仕事で、自分が某ソシャゲを設計した時は
最初に「用語集と使用英単語」の表を作ってました。
「風」は「wind」を使いましょう(airではなく)とか。

ここまで3つは、プログラムとは全然関係ない
どちらかというと、英語力というか、それ以前の(日本語で文章書く時だって同じ問題あるし)
表記ゆれをさけるとか、そんなことばっかですね。
人によっては、そんなの下らねえよ、って思う人もいるかもですが
こういったところにきちんと行き届いているソースコードって
ほんと読みやすいし、メンテしやすいですよ。


これだけでも充分かと思うのですが、一応プログラムに関したことも2つほど。

ネストをできるだけ抑える。elseもできるだけ避ける

有名な「オブジェクト指向エクササイズ」というやつにもでてきますが
できるだけネストを避ける。
できれば1段階まで。
許容できたとしても3段かな。
その3段全体が、エディタ1画面で収まるボリュームという前提で。
それ以上になるようなら、そもそも設計がおかしいです。

elseもできるだけ避けたいですね。
returnで早返しするテクニック使えば、結構elseは削減できるはず。

関数・メソッドの引数の数をできるだけ抑える

これも、個人的な理想値は2つまで。
座標系を扱うコンストラクタだと、3つ4ついっちゃうけど、それは例外かな。
これも、引数が5個も6個もいるような関数・メソッド
そもそも設計がおかしいことが大半だと思ってます。

まとめ

もちろんもっと細かいルールとか、先人の知恵を踏襲すべきところは
たくさんあるとは思うのですが
そういうのは「リーダブルコード」とか「リファクタリング」とか
「Clean Code」読んでね、ということにして。

ネストの話と引数の話は、やや付け足し感あるのですが
その前の、命名に関する部分はほんとすごく大事だと思ってます。
ソースコードは書くことよりも読むことのほうが圧倒的に多いので
それこそ、ブログ文章を校正するのと同じように(校正しない人も多そうだけど)
ソースコードもそういう意識で書いていくと
それだけでも、だいぶ読みやすいコードになるよ、と思っております。

おまけ

最初に触れない、と言っておきながら、やっぱ事の発端になったブログの件。
超カンタンにだけ触れると。

  1. カッコの省略 原則ダメ。*3
  2. 三項演算子 あれは例が悪い。ネストはダメ、節度もって使うならあり。
  3. switch文 ポリモーフィズム使え…という人もいて、そうした方がいい時ももちろんあるけど、そこまで複雑性持ち込まなくて良い場合はswitchでもいいかと。
  4. for文 これも例が悪い。でも他の人も指摘してるけど、そもそもPHPだとforeach使うほうが圧倒的に多いのでは?
  5. 配列への要素追加 array_push()そういやそんな関数あったねw
  6. 引数のデフォルト値 例が悪すぎる
  7. global宣言 これは全力でダウト。ダメ、絶対。
  8. 条件式での代入 これ、今どきならIDEが警告するっしょ。これも原則ダメ。
  9. 文字列への変数挿入 僕ならsprintf()使う。
  10. empty() PHPの暗黙の型変換という闇の世界に誘われるよw 原則、イコール3つの厳密比較使うべき
  11. 再帰処理 再帰自体はもちろんいいんだが、この他の11個の並びと比べると、この中に再帰がでてくるのは違和感ある
  12. 結合代入演算子 これも例が悪くて、変数の使い回し自体が問題かな。あと、ピリオドって見落としやすいからそもそも可読性悪くない? なのでsprintf()派。

*1:自分はサーバサイドのプログラマなんで、ネイティブ側だとまた事情違うかな。パフォーマンス最重要ってケースもあるでしょうから

*2:あと「エンカウント」もありますね。encountって英単語はない。encounterが正解

*3:単にreturn、break、continueするだけの時はついやっちゃいますが

defined()はクラス定数もチェックできる

define()で定義する(グローバルな)定数が、定義されているか否かをチェックするdefined()関数
http://php.net/manual/ja/function.defined.php
ですが、この関数、実はクラス定数に対しても使えます。
(Version 5.4.17にて確認)

<?php
class Hoge
{
    const FUGA = 1;
}

var_dump('Hoge::FUGA'); // 出力bool(true)
var_dump('Hoge::BAR'); // 出力bool(false)

定数の値を返す constant()関数
http://www.php.net/manual/ja/function.constant.php
には、

この関数は クラス定数に対しても動作します。

って明記されてるんですけどね。
なぜがdefined()の方には書いてない。

2014年

あけましておめでとうございます。もう1月5日になってしまいましたが。

新しい年を迎えたってことで
一応人並みに?何か、一年の計というか、今年はこうしよう!みたいなことを書こうか。。。

・・・と思ったのですが。
あんまりパッとしたことというか、気の利いたことが思いつかなかったので
なんとなくツラツラと思いのままに書いてみることにします。

とは言え、何もありませんってのもどうなのよ、と思うので、個人的に今年頑張りたいと思っていることは

  • アウトプットする
  • 手を動かす

この2つ。
アウトプットについては、自分はどうしてもインプットは得意なんですが
いろいろ情報漁るだけ漁って、読んで満足、みたいなところがあるので
ちゃんとアウトプットに繋げたいなと。
あと、アウトプットするためには、自分で実際に手を動かさないと、というところで。
目標というには、じゃあどこまでできたら達成と言えるのよ?という定量的な目標ではないのですが
先日出版されたトム・デマルコ先生の「ピープルウェア」第3版にも
目標も設定しないチームがもっとも生産性が高かった、みたいな調査結果もあり
(プロジェクトマネジメントと個人の目標を置き換えれるのか、という点もありますが)
あまり具体的な目標に縛られすぎると
時代の流れが変化した時に、目標を達成することが目的になってしまうようなことにもなりかねないので
敢えてメジャラブル(測定可能)なものにせず、羅針盤的なものを持つようにしようかなと。

アウトプットという意味では
今年はもう少し会社外での活動にも積極的に関われたらなと考えています。
会社人としての自分も大事だし
立場的にも、会社をアピールしていく役目が必要ってのもあるんですが
それ以上に1エンジニアとして、業界全体に少しでも貢献したいなと。
コミュ障の自覚あるので、なかなか難しいのですが、なんとか殻を破っていきたいなと。

あとは今年ついに40歳を迎えるので
自分自身今後どう身をふっていくのか、を真剣に考えないとなぁと思っています。
自分は何かにすごいエッジな才能を持っているわけではないので
いわゆるキャリアパス的なことを考えてもなかなか自分に相応なものってのが思いつかんのですが
ただ、ありがたいことに今まで仕事で関わった人からは
また一緒に働きたいと言っていただけることが多いので
・・・自分でまだそこがどうしてそう評価していただけるのか、自分自身の強みの分析がそもそもできてないのですが
自分の強みをより活かしていける道を模索したいなと思っています。

会社では、今、マネジメント的な立ち位置にいるのですが
もしかすると、そういうところよりも
アーキテクトとか、エバンジェリストとか、そういう方向性の方が向いているのかもなぁ・・・とかおぼろげには考えているのですが。

予想通り、なんかとりとめない文章で、これといったオチもないんですが
今年もどうぞよろしくお願いいたします。

MySQL Casual Talks vol.5に行ってきた

MySQL Casual Talks vol.5
http://www.zusaar.com/event/1086003

MySQL Casual Talks、日程的に今までなかなか行けなくて、今回ようやく参加できました。
Casualといいつつ、内容はなかなかDeepだったんじゃないかなと、個人的には思いつつ。
自分の実力が以下に井の中の蛙かということを思い知らされました f^^;

誤解を恐れずに全体的なところをざっくりまとめると

  • GTIDとmemcached APIは・・・今後に期待(・・・しなければいけない、現状があるということ。。。)
  • Performance Schemaは・・・まぁoffにしておいたほうがよさそうな雰囲気

でもこの3つの(現時点では)地雷を除けば、5.6の新機能、改善は良い面も多々あるので
使える環境にあるなら、積極的に使っていけばいいのではと思います。
もしバグに当たったら、bugsに上がっていないかをチェックして、すでに報告されていたら「Affect Me」ボタンを押すと。
なかったらバグ報告あげましょう、ってことですね。OSSなのだから。

最後に、ざっと拾えたところまでですが、当日発表された資料へのリンクを張っておきます。

そうそう、うちの会社のサービスのDDLも、yoku0825さんにレビューされたら
「跪け、命乞いをしろ」と言われそうだなぁ。。。(´・ω・`)


MySQL5.6でGTIDを試してそっと閉じた
http://www.slideshare.net/Yuryu/mysql56gtid

全文検索付きMySQL5.0から5.6への移行にまつわるお話をMySQL Casual Talks Vol.5にて発表しました #mysqlcasual - Y-Ken Studio http://y-ken.hatenablog.com/entry/mysql-casual-talks-vol5-mysql-migration

ストレージエンジンであそんでみた // Speaker Deck
https://speakerdeck.com/chobie/sutorezienzindeasondemita

殿堂入りのアレ~Multi-Source Replication を添えて~
http://www.slideshare.net/do_aki/ss-27565738

20131025 my sql casual talks vol.5
http://www.slideshare.net/monry84/20131025-my-sql-casual-talks-vol5

MySQL Casual Talks vol.5でLTしてきました #mysqlcasual - nekogeruge
http://onigra.github.io/blog/2013/10/25/lightning-talked-at-mysql-casual-talks-5/

僕らのMySQL5.6移行記(仮) http://www.slideshare.net/conmame/mysql56-27565355

とあるイルカのバーボンハウス
http://www.slideshare.net/yoku0825/ss-27597161

MySQL Casual Talks vol.5 - MySQL Labs - @RKajiyama http://www.slideshare.net/rkajiyama/20131025-casual-uppt

【追記】
yoku0825さんの発表の中で、スライドに記載ない(口頭でだけ言ったこと)思い出したのでメモ。

Datetime型はVer5.5では8バイトとあるが、Ver5.6からは5バイトになった。
(これは個人的見解→)データサイズ的にはそれでもTimestamp型(4バイト)の方が有利だが、たしかTimestampは今後非推奨になるとかだったはずなので、よほどサイズに厳しくなければ、Datetimeを選択したほうがいいのでは。

varbinaryについては、kamipoさんの以下発言も。

DateTimeのインスタンス達はmax(), min(), sort()できる

PHPerのみなさん、DateTimeクラス使ってますか?
意外とまだPHP4由来の関数(date()、strtotime()など)使っているケースもよくみかけるのですが
DateTimeクラス使えばいろいろスマートにプログラム書けるし、例外処理もできる*1んで
これからはこっちを使うようにしましょうよ、と思うのです*2

で、これも意外とまだ知らない人多いようなので触れておくと
PHP5.2.2以降、DateTimeクラスのインスタンス同士を、比較演算子で直接比較できるようになりました。
http://www.php.net/manual/ja/datetime.diff.php
の例2のところに記載されています。

<?php
$date1 = new DateTime("now");
$date2 = new DateTime("tomorrow");

var_dump($date1 == $date2);  //false
var_dump($date1 < $date2);     //true
var_dump($date1 > $date2);     //false

日付の比較って、Webアプリケーション書いていると大抵必要になるシチュエーションだと思うので
この書き方ができることを知ってると、読みやすくスマートにコード書けるんじゃないかなと。

で、さらにこの「DateTimeクラスのインスタンス同士は比較演算子で直接比較できる」ことの帰結として
2つのインスタンスを比較できるということは、もっと多数のインスタンスがあれば、それらも比較できる。
つまり、max(), min(), sort() といった関数にDateTimeクラスのインスタンス(の配列)を渡すこともできます。

<?php
$date1 = new DateTime;
$date2 = new DateTime('Yesterday');
$date3 = new DateTime('Tomorrow');
$dateList = array($date1, $date2, $date3);

//max()
var_dump(max($date1, $date2, $date3)); 
var_dump(max($dateList));
//min()
var_dump(min($date1, $date2, $date3));
var_dump(min($dateList));
//sort()
sort($dateList);
var_dump($dateList);

実行結果

object(DateTime)#3 (3) {
  ["date"]=>
  string(19) "2013-10-22 00:00:00"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(10) "Asia/Tokyo"
}
 
object(DateTime)#3 (3) {
  ["date"]=>
  string(19) "2013-10-22 00:00:00"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(10) "Asia/Tokyo"
}

object(DateTime)#2 (3) {
  ["date"]=>
  string(19) "2013-10-20 00:00:00"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(10) "Asia/Tokyo"
}

object(DateTime)#2 (3) {
  ["date"]=>
  string(19) "2013-10-20 00:00:00"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(10) "Asia/Tokyo"
}

array(3) {
  [0]=>
  object(DateTime)#2 (3) {
    ["date"]=>
    string(19) "2013-10-20 00:00:00"
    ["timezone_type"]=>
    int(3)
    ["timezone"]=>
    string(10) "Asia/Tokyo"
  }
  [1]=>
  object(DateTime)#1 (3) {
    ["date"]=>
    string(19) "2013-10-21 01:01:03"
    ["timezone_type"]=>
    int(3)
    ["timezone"]=>
    string(10) "Asia/Tokyo"
  }
  [2]=>
  object(DateTime)#3 (3) {
    ["date"]=>
    string(19) "2013-10-22 00:00:00"
    ["timezone_type"]=>
    int(3)
    ["timezone"]=>
    string(10) "Asia/Tokyo"
  }
}

max()、min()とかは、例えばいくつかの日時候補があって、そのうちもっとも現在日時に近いものを採用したい、というケースで使えます。
ソシャゲでいうと、レイドボスの討伐期限が普通はエンカウントして2時間後なんだけど、イベント終了やメンテナンスがある場合は
その日時と比較して、もっとも現在日時に近いものを討伐期限として採用する、みたいなことができます。

*1:例えば、strtotime('hoge')のように日付書式として正しくない引数が与えられた場合、strtotime()はfalseを返します。DateTimeのコンストラクタはExceptionをthrowします。

*2:PHP5.5からは、インスタンス生成時以外値を変更できない(代わりに新しいいインスタンスを生成して返す)DateTimeImmutableも使えます。個人的にはこちらの方がお勧めです。