ことさら−古都プログラマーの更級日記

京都でお寺を回りながら御朱印集めをしていたエンジニアのブログ。おもに技術的なはなしとか日常的なはなし。たまにカメラの話や競馬の話も書きます。

【雑談】github.ioとmarkdownでいい感じに知見を管理・共有したい

これは技術的な記事というよりも、最近思っていることを書いただけの記事です。

最近、GitHubMarkdownで知見をいい感じに管理・共有したいと思っています。

会社や研究室でのドキュメント管理について

仕事や研究室などで、でAtlassianのConfluence、GitHub (Enterrise) のWikiやREADME、あるいはPukiWikiなんかを使ってドキュメントを管理しているところは多いと思います。リポジトリディレクトリ構造の考え方についてGitHubのREADMEに書いたり、ある本番更新の手順書をConfluenceで管理したりしています。僕は、個人的なメモもConfluenceのパーソナルスペースというところで管理したりしています。個人的なメモですが他の人の役に立つこともあるからです。例えば、Memcacheの中身をコンソールから確認する方法など...

とにかく社内ドキュメントに残すことは良いこと

Confluenceなどの社内ドキュメントにこういったことを残すのは非常に良いことです。 最近だとPHPのバージョンアップ(PHP5.6からPHP7へ)を行っているサービスもあることでしょう。なるべくユーザー影響が出ないように、慎重にPHP7しようと手順を作成します。この時、過去PHP5.3からPHP5.6にバージョンアップした時のドキュメントが残っていたとすると、、、PHP7へのアップデートの手順も作りやすくなりますよね。

「仕様」をドキュメントに残すことは良いことですし、「手順」をドキュメントに残すことも、後に似たようなことを行う時に参照できるので非常に便利です。

社内のドキュメントは知見の塊。公開できるものは公開したい。

社内ドキュメントは社内の人しかみられません。自分が転職などでその会社を離れても見られなくなってしまいます。

会社というのは、大きくなればなるほど知見の塊です。例えば、chefのリポジトリGitHub EnterpriseやGitLabにあったとします。社内のサービスの保守をしている場合(新規プロダクトを0から作るという案件でない場合)、chefのリポジトリというものは既に存在していて、せいぜいそこにちょっと何かを付け足す程度の変更しか行いません。その際に、なんの違和感や手間なく、簡単にchefリポジトリへの追加や変更ができるのは、そのリポジトリの保守性が高いからです。すでに美しいディレクトリ構成が出来上がっているのです。

さて、転職したとします。転職先では新規サービスを作ることになりました。chefで構成管理をすることになりました。さて、今までchefにはちょっとしたコードの追加したことしかありません。すでにあるリポジトリに追加することと、新しく1から作成することは全然違います。 ここで規模の大きい会社の場合、成功している他のプロジェクトのchefリポジトリを参考にすればいいです。が、スタートアップだったりした場合は参考になる他のリポジトリはないかもしれません。chefのドキュメントは前の会社においてきてしまいました。

こういった場合に、自分がドキュメントをpublicに公開していれば、それを参照できるので便利です。

社内ドキュメントにまとめるのは非常に良いことですが、公開できるのであれば公開されるのに越したことはありません。自分のためにもなりますし他人のためにもなります。ただし、社内の情報は簡単に公開できることではありませんので、公開できることは(汎用的な部分は)公開する、出来ないことは社内のドキュメントにまとめる、という分類が重要になります。なんでも公開、あるいはなんでも社内のConfluenceだと困るということです。

では技術をどうやって公開していくのか

では、公開していくことを決めた時に、どうやって公開していくか、を考えることになります。

今は主にブログで情報を公開している

僕は、今はブログで情報を公開していくようにしています。超個人的に学んだことはもちろん、会社で何かをして学んだことのうち、公開して良さそうなものについては積極的にブログに書いていっています。

しかしブログにはいくつかの欠点があります。

  • 古い記事は流れてしまう
  • 長い記事は読みづらい

ブログは「タイムライン」なので、記事の「管理」という側面から見ると向いていません。Confluenceみたいに、記事をツリー構造で管理したいのです。

そこで GitHub IO を使いたい

そこで GitHub IO を使って管理したいのです。問題はコンフルみたいにツリーで管理したい点ですね...

例えば過去にこういうページを作ったことがありますが。

トップページ - @yoshiki_utakata

このツリーは自分で書いているだけなんですよね。mdからhtmlへの変換はgithubにpushされたら自動で行ってくれるようになっているのですが、あとはページのツリーをなんか簡単にいい感じに表示してくれる方法が知りたいと思っている今日このごろでした。

このてブログは簡単に公開できるので、しばらくはブログをつかっていくかもしれません。

sshしてスクリプト回した時にネットワークが切れる心配も不要になる screen コマンドの使い方

ssh接続した先のサーバーで、ちょっと時間がかかるスクリプトrsync とか)を回した場合、実行中にネットワークが切れたりPCが落ちたりして「うわああああああ」ってなる経験をした方がいるかもしれません。そういった時に利用するのが screen コマンドです。screenコマンドを使えばスクリプト実行中にサーバーからログアウトしても実行を続けてくれます。

screen コマンドの流れ

  1. screen コマンドで新しいscreenを作ります
  2. そのscreenの中でスクリプトを実行します
  3. そのscreenから離れます。サーバーからログアウトしてもscreenの中でスクリプトが続きます。
  4. ある程度時間がたってスクリプトが終了することを確認するために、サーバーにsshして先程のscreenを開いてみる。
  5. 終わったらscreenを閉じる

まずはサーバーにsshして、 screen でscreenを作成してみます。

$ ssh target-server
[username@target-server ~]$ screen
[username@target-server ~]$

screen コマンドを打つとなんか画面が切り替わった感じがするはず。これで新しいscreenができました。ここで適当に時間が掛かりそうなスクリプトを実行したりします。

screenから抜けてサーバーからログアウトしてみます。screenから抜けるには Ctrl-a d (Controlキーとaを同時押しした後にControlを離してd) または Ctrl-a Ctrl-d です(Controlキーを押しながらaを押した後、Controlキーを押しながらd)。

[username@target-server ~]$ screen
[detached]
[username@target-server ~]$

[detached] と表示されて元の画面に戻ってきたと思います。これで exit とかしても、さきほどのscreenでスクリプトは実行されつづけます。今動いているscreenを見るには screen -ls です。

[username@target-server ~]$ screen -ls
There are screens on:
    5689.pts-10.target-server(Detached)
1 Sockets in /var/run/screen/S-username

一つのscreenが動いていることがわかります。このscreenに戻るには screen -r <id> です。idは 5689.pts-10.target-server これの 5689 の部分です。

[username@target-server ~]$ screen -r 5689
# さっきの画面に戻る

screenを終了させるいは、この状態で(screenを開いた状態で)exitすればよいです。

[username@target-server ~]$ exit
[screen is terminating]
[yoshiyuki_sakamoto@nv-sysmanage01 ~]$

[screen is terminating] と表示されて元の画面に戻ります。

screenは2つ以上作ることが可能です。

screenにいる時は、 Control + a がscreenコマンドに取られるのでemacsとか使っている人は注意しましょう。

まとめ

screenコマンドを使ってscreen上でスクリプトを実行すれば、時間のかかるスクリプトsshして実行する時でも安心!

PHPのSplPriorityQueueで複雑な実装をしようとするとたまにおかしい時がある?

SplPriorityQueue を継承したらちょっと複雑なPriorityQueueが実装したりできるのですが、なんかたまにうまく動かないことがあります。

正常に動く例: 長方形を面積が大きい順に並べる

SplPriorityQueue を継承して、 insertRectangle というメソッドで面積を計算してinsertします。

<?php

/** 長方形クラス */
class Rectangle {
    public $width, $height;
    public function __construct($width, $height) {
        $this->width = $width;
        $this->height = $height;
    }
}

/** Priority Queue */
class MyPriorityQueue extends SplPriorityQueue {

    /** 面積を計算してそれを優先度としてinsertするメソッド */
    public function insertRectangle(Rectangle $rectangle) {
        // 面積をpriorityに突っ込む
        $this->insert($rectangle, $rectangle->width * $rectangle->height);
    }
}

$queue = new MyPriorityQueue();

// 長方形を突っ込む
$queue->insertRectangle(new Rectangle(2, 4));
$queue->insertRectangle(new Rectangle(3, 3));
$queue->insertRectangle(new Rectangle(1, 7));

// 面積が大きい順に取り出される筈
while(!$queue->isEmpty()) {
    var_dump($queue->extract());
}

これを実行すると

$ php PriorityQueue3.php                                                                                                                                                                                                                      [master]
object(Rectangle)#3 (2) {
  ["width"]=>
  int(3)
  ["height"]=>
  int(3)
}
object(Rectangle)#2 (2) {
  ["width"]=>
  int(2)
  ["height"]=>
  int(4)
}
object(Rectangle)#4 (2) {
  ["width"]=>
  int(1)
  ["height"]=>
  int(7)
}

ちゃんと面積が大きい順に出てきますね。

正常に動かない例: 長方形を面積が小さい順に並べる

今度は面積が小さい順にするためにcompareメソッドをオーバーライドします。

/** Priority Queue */
class MyPriorityQueue extends SplPriorityQueue {
    /** priorityが低いものから取り出すようにする */
    public function compare($priority1, $priority2) {
        if($priority1 === $priority2) return 0;
        $priority1 < $priority2 ? -1 : 1;
    }

    /** 面積を計算してそれを優先度としてinsertするメソッド */
    public function insertRectangle(Rectangle $rectangle) {
        // 面積をpriorityに突っ込む
        $this->insert($rectangle, $rectangle->width * $rectangle->height);
    }
}

このようにします。これで

// 長方形を突っ込む
$queue->insertRectangle(new Rectangle(2, 4));
$queue->insertRectangle(new Rectangle(3, 3));
$queue->insertRectangle(new Rectangle(1, 7));

こうすると

$ php PriorityQueue3.php                                                                                                                                                                                                                      [master]
object(Rectangle)#2 (2) {
  ["width"]=>
  int(2)
  ["height"]=>
  int(4)
}
object(Rectangle)#4 (2) {
  ["width"]=>
  int(1)
  ["height"]=>
  int(7)
}
object(Rectangle)#3 (2) {
  ["width"]=>
  int(3)
  ["height"]=>
  int(3)
}

面積が小さい順にソートされず、かといって入れた順とも違う順で出てきてしまいます。

んー、何か継承して複数メソッドをオーバーライドするとバグるのか、継承の仕方とかが良くないのか。PHPの闇な感じがあります。もし何か実装ミスとかに気づいた人がいたら教えてほしいです。

詳細!PHP 7+MySQL 入門ノート

詳細!PHP 7+MySQL 入門ノート

PHPのPriorityQueueの実装についてとSplPriorityQueueの使い方

JavaC++だとPriorityQueueが標準ライブラリで用意されているイメージがありますが、PHPはあまりそういったイメージがありません。しかし、PHPでもちゃんとPriorityQueueが標準で用意されています。

SplPriorityQueue の使い方

PHPのPriorityQueueの実装がSplPriorityQueueです。その基本的な使い方は以下の通りです。

<?php

$queue = new SplPriorityQueue();

// insert メソッドで要素を挿入
// $queue->insert(<挿入するオブジェクト>, <そのオブジェクトのPriority>); 
$queue->insert('Hoge', 1);
$queue->insert('Fuga', 3);
$queue->insert('Piyo', 2);

// isEmpty() でqueueが空かどうかを判断
while(!$queue->isEmpty()) {
    // extractは先頭の要素を取り出しつつその要素をqueueから削除
    var_dump($queue->extract());
}

これの実行結果は以下のようになります。

string(4) "Fuga"
string(4) "Piyo"
string(4) "Hoge"

Queueの中から、Priorityが高い順に取り出されていることがわかります。

主なメソッドは以下の通りです。

  • insert() : Queueに要素そ挿入
  • isEmpty() : Queueが空ならtrue
  • extract() : Queueの先頭の要素を取り出しつつその要素をQueueから削除
  • top() : Queueの先頭の要素を取り出す。Queueからの削除は行わない
  • count() : Queueの中身の数を取得

発展 - 優先度が低い順に取り出したりする時は...?

SplPriorityQueueのデフォルトの実装では、優先度が高い順に要素を取り出すようになっていますが、優先度が低い順に取り出したかったり、優先度を複雑に設定したかったりする場合があると思います。

優先度が低い順に取り出したい

SplPriorityQueue を継承したクラスを作り、compare メソッドをオーバーロードすることで可能となります。

<?php

class MyPriorityQueue extends SplPriorityQueue {
    /** Queueの中身を昇順でソートするように変更 */
    public function compare($priority1, $priority2) {
        if($priority1 === $priority2) return 0;
        $priority1 < $priority2 ? -1 : 1;
    }
}

$queue = new MyPriorityQueue();

$queue->insert('Hoge', 1);
$queue->insert('Fuga', 3);
$queue->insert('Piyo', 2);

while(!$queue->isEmpty()) {
    var_dump($queue->extract());
}

こうすることで結果は以下のようになり、昇順で取り出されるようになります。

string(4) "Hoge"
string(4) "Piyo"
string(4) "Fuga"

パーフェクトPHP (PERFECT SERIES 3)

パーフェクトPHP (PERFECT SERIES 3)

Canonの初心者EOS Kissに新しいモデルX9, X9iが出ていた

7月にCanon EOS Kiss X9とCanon EOS Kiss X9i が発売されていた。

Canon EOS Kiss シリーズとは

Canon EOS Kiss シリーズとは、Canonのカメラの中のエントリーモデルです。初めて一眼レフを買う人はまずこれを買ってみましょうというものになっている。機能は控えめで価格を抑えたモデルである。

今回は X9i だけでなく X9 も出た

これまで、 Canon EOS Kiss X7, X7i, X8i とKissシリーズが発売されてきた。僕はX8iを買った。

「i」が付いているものは i が付いていないものよりチョットだけ高性能だ。一方で i がついていなものは小型軽量化に重点を置いたようなモデルになっている。

X8i が発売された時は同時に X8 が出なかったので、もうiが付かないシリーズがでないのかな?と思ったが、今回X9が発売された。

X8iはほぼ選ぶ理由がなくなったかな

X9とX9iが発売された結果、X8iをわざわざ選ぶ理由がなくなった(と個人的には思う)ので、主にX9とX9i、そしてX7について比較しようと思う。

Canon EOS Kiss X7 と X9

何故いまだにX7との比較なのか

何故X7が人気なのか。それは、X9が発売された今でも Canon Kiss シリーズの中で一番軽いのはX7だからである。X9の453gより更に軽い407gであり *1 さらに大きさも最も小さい。

X7の一番の欠点はWi-Fi/Bluetooth

X7がX9とくらべて大きく劣るのは、カメラにWi-Fi機能とBluetooth機能がついていないことだ。これらは主にスマホとデータをやり取りする時に使うので、撮った写真をスマホtwitterinstagramにすぐ投稿したい!という場合には無いと不便だろう。X7で取った写真をすぐにスマホに送りたい場合は、Bluetooth機能付きのSDカードを利用するなどになるが、カメラの電池の消費が激しくなるためあまりオススメできない。

性能差は初心者にはあまり関係ない

他の大きな点は液晶がバリアングルになっているかどうか(回転したりするかどうか)くらいだ。性能は上がっているが、初心者はX7で困ることは何もない。先程述べたBluetoothなどを「絶対に」使わないなら、サイズが小さく軽いX7が良いが、そうでなければ個人的にはX9を強くオススメする。

X7は上記のように最軽量であるため未だに人気があり価格もそこまで落ちてはいない。と入っても1万5000円ほどX9の方が高いが*2、機能の向上とBluetooth、バリアングル液晶を考えるとX9の方が圧倒的に便利である。

Canon EOS Kiss X7

Canon EOS Kiss X9

X9iはどうなのか

X9iだが、オートフォーカスの性能は上がっているもののほんの僅かな差で、初心者にはあまり関係ないうえに、重量が532gと80gほど重くなっているうえに大きさも大きいので、X9ではなくX9iを選択する意味はあまり無いだろう...

結論!X9を買おう

結論としては、X9を買えということになるのだが、不安な人のために Canon の紹介ページを見ながらもっと詳細な比較をしてみよう。

もっと詳細な比較

以下のCanonの比較表を見て、その意味を解説しつつ詳細に比較していく。

cweb.canon.jp

映像エンジン

数字が上がるほど、手ブレ補正とかの性能がよくなるが、正直違いについては良くわからないのであまり気にしなくていい。開発者でしか分からないレベルでしか変わらないと思う。*3

常用ISO感度

X7だとISOが12800までだったがX9から25600になった。これは数値が高ければ高いほど、暗いところで撮影した時の「画像のブレ」(手ブレによるブレや被写体が動いてしまったことによるブレ)が少なくなる。ただ、25600とか相当真っ暗なところでしか効果を発揮しない。夜に外で人が走っているところを取りたい、星を取りたい、とかだと若干生きてくる可能性はあるが個人的には12800ですらほとんど使ったことがないレベル。本当に暗い所で綺麗に撮るなら、もっといいカメラやレンズを買わないと厳しい。

ファインダーオートフォーカス

これは X9 と X9i の間でも値が異なっているので気になる所だろう。この数が増えるとオートフォーカスの精度が上がる。具体的には「自分がピントがあって欲しい所に合う」ことが増える。例えば以下の写真を見て欲しい。

f:id:yoshiki_utakata:20171118114740j:plain

この写真、今は右下の寿司にピントが合っていると思うが、オートフォーカスの点が少ないと、どうしても真ん中にフォーカスが合ってしまいやすくなるので、奥の寿司にピントが合ってしまう。このようにピントを合わせて欲しいところに「合いやすく」なるのだ。

ただ、結局「合いやすく」なるだけで絶対合うわけではない。どうしても「自分がフォーカスを併せたいところにオートフォーカスしてくれない」というシーンは出てきて、結局オートフォーカスを切ったりするので、個人的にはこの精度はそこまで必要ではないのかなぁと思っている。

色検知AF(オートフォーカス

これも同様、オートフォーカスの精度が上がる。肌色だったらそれは人だと認識してそっちのフォーカスをあわせる、みたいなことをしてくれる。ただ、人以外に肌色があったら反応してしまうし、人にフォーカスをあわせたくない場合もあるだろう。結局「必ずしも自分があわせたいところにフォーカスが合うわけではない」ので必須ではないと思っている。

連続撮影速度

5コマ/秒でも十分なんじゃないかなって思う。

ライブビューフォーカス方式

「ライブビュー撮影」というのは、ファインダーを覗いて撮影するのではなく、液晶を見ながら撮影するモードのことである。このモードの時のフォーカス速度が「デュアルピクセル CMOS OF」のほうが早いらしい。動画を撮る時にも影響してくるので、(バリアングル液晶のことも考えると)動画を取りたい場合は間違いなく X9/X9i の方が(X7と比較して)良い。

バリアングル液晶

液晶が回転する。自撮りとかの時で使える。*4

撮影可能枚数の目安

要するにバッテリーの持ちのことだが、基本的に2,3日なら電池は切れないので問題ないし、バッテリーは取り外せるタイプなので不安なら予備のバッテリーを持ち歩けばいい。

BluetoothWi-FiNFC

BluetoothWi-Fiは主にスマホに写真を移動する時に使う。X8iはこれがWi-Fiだけだったため、スマホWi-Fi接続してデータのやり取りをしている間はインターネットができなくなるという欠点があった。Bluetoothが追加されることによりこの欠点はなくなるだろう。

NFCというのはSuicaとかPasmoみたいにかざしてデータやり取りできる機能だが、基本的にWi-FiBluetoothがあったらそちらを使うだろう。

まとめ

Bluetooth接続ができて軽い Canon EOS Kiss X9 が凄いので欲しい!(X8iあるからかわないけど)

*1:レンズ込み

*2:これを書いているタイミングではX7は5万3000円、X9は6万7000円

*3:個人の感想です

*4:スマホみたいな自撮りじゃなくて三脚で自撮りする時とかね