2011年3月23日水曜日

新人さんに覚えてもらいたい事 その1【プログラミング】

今までやってた仕事を新人にもやらせなさいとの事なので、必要な事をあげてみます。
ついでに、このまま新人さんに読んでもらう為の文章にします。

できるだけ自分の言葉で書いたつもりですが、僕が下で紹介している本から多大な影響を受けており、同じような事を書いているかもしれません。まあそれも僕自身の復習という事でご容赦くださいw


うちは基本的にはRubyを主に使っているのでRubyの構文の知識は最低限必要です。
ただ、うちの場合、プログラミングだけでなく仕様案作成、設計、バージョン管理からWebサーバだのデータベースだののソフトウエアの選定からセットアップ、ネットワーク設計、そしてサーバへのデプロイ等、基本丸投げになるので(笑 それらの知識も必要になります。


構文
社内では主にRubyを使っています。ですのでRubyの基礎的な構文の知識は必要です。
僕はプログラミング自体初心者の時に下の2冊を常に手元に持っていました。

最初の一冊としては「Ruby プログラミング入門」がオススメです。初心者にもわかりやすく丁寧に解説してありますし、実践的で読みながら直ぐにプログラムを作ってみる事ができます。


Ruby Way」はもう少し詳しく解説してくれている本です。「Ruby プログラミング入門」では物足りない場合はこちらも購入を検討されると良いでしょう。こちらもとてもわかりやすく実践的な内容だと思います。


もちろん上記以外にも良い書籍があります。自分に合った書籍を常に手元に持っておきながら、まずは自分の手でプログラムを組んでみるのが習得への早道だと思います。

Hellow World はお約束として、その後はとりあえず以下の点を学ぶと簡単なプログラムが組めるのではないかと思います。


Step
  1. 条件分岐(if文)
  2. イテレータ(配列に対する"each"によるループ処理等)
  3. 文字列(String)の扱い。+による連結された文字列の生成やsubによる置換等
  4. 数値演算
  5. 配列
  6. ハッシュ
  7. クラスとメソッドの定義
  8. ファイルへの書き出し、ファイルからの読み込み


もちろんまだまだ覚える事は沢山ありますが、まずは自分の手を動かしてコードを書く事だと思います。本を見てると簡単そうに見える事が実際書いてみると思った以上にうまくいかないことがあります。その理由がわかったとき、一歩成長したと言えるのだと思います。
それを繰り返しているうちにだんだんと自由に思った通りの動きをするプログラムを組めるようになってきます。

設計
ただ、前述のように丸投げになって誰も指示してくれないので、設計もきちんとしておく必要があります。ポリモーフィズムを応用したりシングルトンなインスタンスを検討するなど基本的な設計については最初から考えてコーディングに取りかからねばなりません。

またWebサービスであれば(X)HTMLやCSS、Javascriptも当然必要になってきます。これらも単に

(σ´∀`)σ動いた動いた♪

的な知識ではなく、どう動かすか、つまり設計を自分なりに考えてとりかかる必要があります。そうしないと後でバグだらけになって手に負えないものになったり修正に時間のかかるものになってしまうからです。

この点について、コーディングにかかる前に新人さんには「どのような設計で作ろうと考えているか」を話してもらうと良いかもしれません。その際にテストフレームワークは何を使うか、データベースの設計はどうするか、Railsを使うかMerbやSinatraも検討するか、しないのならそれは何故か。そして最終的なリリースをいつにするかなど、完全に答えられなくても自分の考えを述べる事で技術的経験的に足りない部分が早い段階で浮き彫りになるかもしれません。

ソフトウエアの設計についてはこの業界では読み継がれている本があります。できれば以下の本には目を通しておいて欲しいです。
特に「リファクタリング:Rubyエディション」と「達人プログラマー」は必ず読んでください。





Step

  1. 上記のうち、少なくとも2冊を自費で購入して読んでください。自費で購入することで、自分に対する投資感覚を身につける事につながります。
  2. 上記以外で良さそうな書籍を自分で探して読んでてください。


トレーニング
プログラミングを仕事をはじめて最初のほうは必ずなにかしらの失敗をします(いや、今でも色々と失敗をしますがw)。ある程度できてきた頃に、あちこちに気に入らない所がでてきて、全部作り直したくなったりもします。そうならない為にはどうすれば良いのでしょうか。
上記の本を読む事で予備知識や、陥りがちな失敗を知る事ができ、それによって事前に対策を打つ事ができますが、それはあくまで机上の知識です。やはり実践に勝るトレーニングはありません。

まずは自分の普段の仕事を、「小さなプログラム」を作る事で自動化しましょう。普段の仕事の中には自分でも気づかずに実行している無駄な仕事があると思います。

もし、その作業が「手でやる場合」と「自動化するプログラムを作る場合」とで同じ時間がかかるならプログラムを組んで自動化しましょう。かりに2、3倍かかったとしてもやはりプログラムを組んで自動化するべきです。そうすれば明日からはその作業にかかる時間は飛躍的に短くできます。

しかし、それ以上に重要なのは「自分が日々使うプログラムを自分で作り保守する」ことにより、ある面では素晴らしい本を読む以上の経験が得られる事です。

ユーザが自分なのですからリスクは最小です(データベースから全ユーザを削除したりしなければw)。そして最終ユーザからのフィードバックが即座に得られます(最終ユーザが自分なのですから当然ですがw)バグはもちろん、使いにくいと感じた所もどんどん直していきましょう。時間がなかったりすると作り手故に知っている”回避方法”を使ってバグのあるままに使い続ける事もできると思いますが、ずっと微妙な「嫌な気持ち」を感じながら使う事になると思います。嫌な気持ちになったらすぐに直しましょう。そうすると今度は逆に少し幸せな気持ちになれるはず...と思われますw

僕も今まで小さなスクリプトを幾つも作ってきました。例えば複数のサーバに同じアプリケーションをデプロイする際にコマンド一つで、最新のソースのチェックアウトから再起動までを自動的にやってくれるようにしたり、同じくコマンドひとつでテキストファイルに登録された全サーバにpingを打ったりポートオープンしてサービスの稼働状況を監視したりするプログラムです。
あるいはもっと地味に、単に特定のサーバへSSHトンネルを張るコマンドを1行書いただけのbashスクリプトだったり。

小さなプログラムなら失敗しても直ぐに作り直せます。失敗はできるだけ他人に影響の無い範囲で経験しておいて、その教訓を他の人が使うプログラムの開発に活かすように心がけましょう。

Step

  1. 自分の普段の仕事、定期的に行っている仕事を自動化するプログラムを作りましょう。
  2. 作ったプログラムを実際の仕事の中で使いましょう。不具合や使いにくい箇所を見つけて修正しましょう。


2010年12月20日月曜日

バージョン管理をSubversionからgitへ移行しました。

今まで会社のバージョン管理にはSubversionを使っていたのですが、このたびgitに乗り換えました。理由は簡単で、gitの方が速い、使いやすい、というところでしょうか。

もともと今年の夏から作り出して既にリリースしておりますiPhoneアプリの「Now Playing Friends」でgitを使っていたのですが、とにかくコマンド実行がスピーディであること、そしてブランチの作成とマージがとってもやりやすくて気楽な所が気に入っていました。

もちろんSubversionも良いのですが、URLの入力がめんどくさいのと、マージにいちいちリビジョン番号を覚えるか、マージの為だけにスタートとエンドのブランチを別に切ってやらないといけないのが手間でだんだんとブランチを切らなくなってました。

gitだと単にブランチ名を指定してマージすれば、後は既にマージしてある内容は無視して、よしなにやってくれるのでらくちんです。こう書いてると単なる怠け者みたいですが、できれば開発の際には開発物そのものに気持ちを集中したいのでバージョン管理のちょっとした作業で多少なりとも頭を使わないといけないようなものはさけたいのです。それに自分以外の新入りの人にも使ってもらわないと行けないので、ちょっとしたミスで面倒な事になるようなものだとコレも困ります。

あと、ウチの会社の場合は仕様書なるものが事実上存在せず、結構その場その場で「こうした方が良くない?」って感じで仕様を決めながら作ってる所があるので、”手元でサクッとブランチを切ってそっちで試しに作ってみる”という動きが高速にできるgitは理想的とも言えます。

subversionからgitへの乗り換えは実に簡単でした。
まずはgitosisサーバをセットアップします。こちらの”プログラミング/gitosisによるgitサーバの管理”を参考にさせて頂き、Debian GNU/Linux上にgitosisをセットアップしました。

subversionからの乗り換えは、一旦subversionからgit svnを使ってチェックアウトします。
$ git svn clone -s http://hogeserver/svn/tara-project
このとき指定するURLは対象プロジェクトのルートディレクトリを指定します。上記だとhttp://hogeserver/svn/tara-project/trunk 以下に実際のソースがあるのが通常の配置だと思いますが、trunkではなくその上位のプロジェクトディレクトリを指定するとあとはgit svnがよしなに判断してくれます。

続いてできたディレクトリ内に移動してプロジェクトをgitサーバに登録します。事前にgitサーバにプロジェクトを登録する事をお忘れなく。
 $ git clone gitosis@localhost:gitosis-admin
 $ cd gitosis-admin
 $ vi gitosis.conf

  ...
  [group gitosis-admin]
   writable = gitosis-admin  #<=ここにスペース区切りで新規追加するプロジェクトの名前を登録する。
   ↓
   writable = gitosis-admin tara-project
   # 保存してvi終了
  $ git commit -m "add new project" -a
  $ git push

以上でプロジェクトの登録作業は終了です。
以下が実際のsvnからgitへの移行です。
 $ cd tara-project
 $ git remote add origin gitosis@localhost:tara-project
 $ git push origin master
これで登録できました。

別の場所でチェックアウトしたいときは
 $ git clone gitosis@localhost:tara-project
とすればチェックアウトできます。

おそらくはsubversionで多くの場合問題ないのでしょうが、自分の環境でより使いやすいツールを常に選択しつづけていく事で作業環境が劇的に変わる事は結構あります。それは必ずしも新しいツールとは限らず、古くから使われているUNIX向けのソフトウエア群だったりする場合も多いです。Emacsなどは非常に多機能なので普段から使っていても知らない機能は沢山ある事と思います。たまにUNIXコマンドや使い慣れているエディタについての専門書を読んでみたり、以前から聞いた事はあったけど使ったことのないツールを試してみる事をお勧めします。もしかしたら大幅な時間短縮に繋がるかもしれません。

gitを使うにあたっては以下の書籍を参考にしました。

Amazon: 入門git 

2010年10月28日木曜日

PostgreSQLのセットアップ

データセンター立ち上げの為にPostgreSQLを久しぶりにセットアップしました。

構成は2台のPostgreSQLを用意しておき、通常はプライマリで動作させつつPTR(ポイント イン タイムリカバリ)で差分バックアップをもう片方に数分置きに送ります。

こうしておけば何かの事故でプライマリが動作不能に陥ってもすぐにセカンダリに切り替える事ができます。いわゆるホットスタンバイというのかな?

以前は同期レプリケーションを使ってた頃もありましたが、これがしょっちゅうロックして音信不通になるのでこの方法に落ち着きました。

同期レプリケーションは十分考えてテストを繰り返した上で採用すべきだと反省しました。少なくとも覚えておかないと行けないのは「停止した時の自動引き継ぎは魅力だが、そもそも停止する頻度があがる」という事です。
同期レプリケーションは冗長性確保の為ではなくあくまで更新系クエリの負荷分散の為に(リスクも考えて)使うべきものです。

インストール
インストールは一般的なLinuxディストリビューションではパッケージが提供されてると思います。ただ今回は別のデータセンターとバージョンを合わせたかったのでソースからインストールしました。

ソースは日本PostgreSQLユーザ会のホームページから取得します。
$ wget wget ftp://ftp.jp.postgresql.org/source/v8.1.8/postgresql-8.1.8.tar.gz
バージョンはそのときの最新バージョンを確認して落としてください。

落としたら解凍してディレクトリ内に移動します。

$ tar xvzf postgresql-8.1.8.tar.gz
$ cd postgresql-8.1.8

postgresql用のユーザを作っておきます。

$ sudo adduser postgres
...

お決まりのパターンで
$ ./configure
$ make
$ sudo make install

インストール後の設定
インストール後は用途に応じて設定を行います。
まずはマシン起動時に自動起動する設定。自動起動の設定方法はディストリビューションによって異なります。ここに書いたのはDebianでの設定です。

以下のようなファイルを用意します。内容は適せん書き換えてください。

#! /bin/bash

export PGDATA=/var/pgsql/data
export LD_LIBRARY_PATH=/usr/local/pgsql/lib
export PATH=/usr/local/pgsql/bin:$PATH

case "$1" in
    start)
        echo -n "Starging PostgreSQL..."
        su - postgres -c "pg_ctl start -D $PGDATA &gt; /dev/null"
        echo "done"
        ;;
    stop)
        echo -n "Stopping PostgreSQL..."
        su - postgres -c "pg_ctl stop -D $PGDATA &gt; /dev/null"
        echo "done"
       ;;
    reload)
        echo -n "Reloading PostgreSQL..."
        su - postgres -c "pg_ctl reload -D $PGDATA &gt; /dev/null"
        echo "done"
        ;;

    *)
       echo "Usage: /etc/init.d/pgcluster {start|stop|reload}"
       exit 1
       ;;
esac

exit 0

上記をファイルを/etc/init.d/以下に追加して自動起動の設定を行います。

$ sudo cp postgresql /etc/init.d/
$ sudo update-rc.d postgresql defaults 90


上記のようにすると全てのランレベルで自動起動自動停止し、起動順が90に設定されます。ここでの90は90番目という意味ではなく、あくまでそのランレベルでの起動順の優先度を示していますのでこの数字の小さい順に起動されるだけのものです。

あとはpostgresql関連の実行ファイルは/usr/local/pgsql/bin以下におかれるので、よく使うコマンドに関しては特別な設定をしなくても通常のコマンドと同じように使えるように/usr/local/bin以下にシンボリックリンクを張っておきます。
$ cd /usr/local/bin
$ sudo ln -s ../pgsql/bin/psql psql
$ sudo ln -s ../pgsql/bin/createdb createdb
$ sudo ln -s ../pgsql/bin/dropdb dropdb
$ sudo ln -s ../pgsql/bin/initdb initdb
$ sudo ln -s ../pgsql/bin/pg_ctl pg_ctl

そしてデータベースを作成します。今回は/var/pgsql/dataに作成します。

$ sudo mkdir /var/pgsql
$ sudo chown postgres:postgres /var/pgsql $ sudo -u postgres initdb --encoding=EUC_JP --no-locale /var/pgsql/data



いろいろと表示されて最後に起動方法が表示された後プロンプトが帰ります。ここで表示されて起動方法は先ほどの/etc/init/postgresqlに保存した起動ファイルに書いてありますので、手動で起動するには
$ sudo /etc/init.d/postgresql start
手動で停止するには
$ sudo /etc/init.d/postgresql stop
でできます。

起動確認の為にデータベースにログインしてみましょう。

$ psql -U postgres template1

上記コマンドで
Welcome to psql 8.1.8, the PostgreSQL interactive terminal.

Type:  \copyright for distribution terms
       \h for help with SQL commands
       \? for help with psql commands
       \g or terminate with semicolon to execute query
       \q to quit

template1=#
のように表示されたら正常に動作しています。¥qと入力して一旦抜けます。
template1=# ¥q

ただ、初期状態ではPostgreSQLの動作しているホストからしかアクセスできません。他のホストからのアクセスも許可するには設定を変更する必要があります。

$ sudo vi /var/pgsql/data/postgresql.conf
変更箇所は"listen_addresses"の項目です。
#listen_addresses = 'localhost' #変更前
listen_addresses = '*'          #変更後

このように変更するとどこからでも接続できます。ただこの時点では接続できるだけでローカル以外からログインする事はできません。
他のホストからのログインを許可するにはdataディレクトリ以下の"pg_hba.conf"を修正する必要があります。
$ sudo vi /var/pgsql/data/pg_hba.conf
設定方法に関してはここに詳しく書いてあります。

設定を変更したら再起動すると反映されます。

チューニング
ここでは基本的なチューニングを行います。ただしチューニングの内容は用途やアクセス頻度など様々な条件によって異なります。あくまで実際の用途に応じてチューニングしますし、現時点で問題が発生するかわからないのなら取り敢えず初期状態で運用開始してみるのも良いと思います。ただ、初期設定は低スペックマシンでも動作するように設定されていますので、すでにある程度の負荷がかかる事が想定できるなら、いくつかの設定に関しては変更した方が良いようです。

私たちの用途ではデータベースの数が多くなる事が既に解っています。別の場所で運用している同じ用途のデータベースでは既に100以上のデータベースがあり一つ一つのデータベースに多数のテーブルが存在しています。またデータベースは今後も増える可能性があります。

以前初期状態で運用していた所、Warningが発生するようになってしまいました(設定を変更して以来発生していません)。
従って、そのWarningへの対処を含めていくつかの設定値をあらかじめ変更しておきます。

まずは"shared_buffers"を増やしました。
ただし、ここでの共有メモリの指定はあくまで1プロセスがOSから使用を許可される共有メモリサイズ分ですのでOSから許可されるサイズ以上のサイズは得られません。ですので必要に応じてOS側の共有メモリのサイズを先に増やしておく必要があります。

OSの共有メモリサイズは"/proc/sys/kernel/shmmax"に記載されています。
$ cat /proc/sys/kernel/shmmax

一時的に変更したい場合はここにそのサイズをかき込めばいいです
# echo "400000000" > /proc/sys/kernel/shmmax
とすれば変更されます。
ただしこの値はマシンを再起動するたびに戻ってしまいますので戻らないようにする為には"/etc/sysctl.conf"に以下を追加します。
kernel.shmmax=400000000

設定変更後は一応再起動して値が反映されている事を確認してください。

その上で"/var/pgsql/data/postgresql.conf"のshared_buffersを修正します。
該当項目の先頭の#を消して値を変更します。デフォルトの1000から16000に増やしました。
shared_buffers = 16000

また、アプリケーション側で1トランザクションで数十クエリを投げる処理もしているので一応デッドロック検出時間も少し長めにしました。
deadlock_timeout = 5000

あとは最大接続数を増やしましたデフォルトの100を256に増やしています。
max_connections = 256

そして共有メモリ上に作成されるwalバッファの1ページ分のサイズを大きくする事で不必要なタイミングでトランザクションが書き出されるのを防げるようです。デフォルトの8KBを32KBに増やしました。
 wal_buffers = 32

そしてトランザクションのチェックポイントセグメント数を増やしました。
checkpoint_segments = 16

上記の修正は殆どここにかいてある通りに行っています。

さて、それに加えて最初に書いた、テーブル数が多すぎる際に出るWarningですが、これはどうやら"max_fsm_relations"で設定したテーブル数より実際のテーブル数(全てのデータベースでのテーブルの総数)が上回っていた為に発生していたようです。
ここに実際の数を書くのは控えておきますが、max_fsm_relationsには全データベースのテーブルの総数を書けば良いです。もちろん将来増えて行くシステムならその分もある程度見込んでおいた方が良いでしょう。

そこでまずはmax_fsm_relationsをテーブル数に。そんでもってmax_fsm_pagesをテーブル数x32に設定しました。

AUTO VACUUMの設定
私自身が自分でソースを読んだ訳ではないのですが、PostgreSQLはdelete文などによるデータの削除時に実際にディスク上のデータの削除を行っている訳ではないようです。そのような場合、PostgreSQLはディスク上のデータに対して削除されたというマークをつけて後でその領域を再利用するらしいのですが、その為にはvacuumという処理をしてやらないといけません。
これを忘れると領域の再利用ができない為に、頻繁にデータの削除と追加を繰り返すようなシステムではデータベースのディスク上のサイズがどんどん増えていき、ディスク領域を圧迫するようになります。7系まではvacuumは自分でコマンドを発行して実行するか、cronで自動実行するように設定する必要がありましたが、8系からは別のデーモンが立ち上がって自動でやってくれる機能が追加になりました。

ただ、このauto vacuum は初期設定では無効になっているので設定で動作するようにしてやらないといけません。
編集するファイルはdataディレクトリ内のpostgresql.conf。設定変更した場所は以下です。

stats_start_collector = on # 統計情報を保存する場合は true
stats_row_level = on         #行レベルのパフォーマンス統計を収集するか否か。
autovacuum = on             #autovacuumを起動する


これでとりあえずのPostgreSQLの設定を完了します。あと差分バックアップによるホットスタンバイの設定がありますがそれは次回に。

2010年10月17日日曜日

Twitter連携型音楽プレーヤ「Now Playing Friends 1.0.1」をリリースしました。


Now Playing Friends



Now Playing Friends はTwitter検索APIを利用してあなたと同じ曲を聴いている、または聴いていたTwitterユーザを表示します。 同時に#nowplayingハッシュタグ付きのつぶやきを投稿する事もできます。投稿内容は編集可能です。 簡単な音楽プレーヤとしての機能もありますのでnowplayingツイート時にipodとアプリを切り替えずにツイートできます。


プレーヤー画面では曲のアートワークを表示し、Twitter検索APIにより同じ曲を聴いていた人を半透明で表示します。
また、5分以内に同じ曲を聴いていた人のアイコンは透明にならず、かつアイコンに"♬"マークが入ります。



右下の"i"をタップする事で画面が半分めくり上がってプレーヤとしての制御を行う事もできます。


プレーヤの左上のボタンをタップする事で画面がクルッと回転して選曲画面に変わります。
上部でアルバムリストとプレイリストを切り替える事ができます。
アルバムまたはリストをクリックすると即座にそのリストを最初から(シャッフルモードの場合はランダムに選曲して)再生します。
リスト右のディテイルボタンをタップするとアルバムまたはリストの中身が表示され、自分で曲を選べます。




Song画面では同じ曲を聴いていた人をリスト表示します。ここで表示される人はプレーヤ画面でアイコンが表示された人と同じです。


アーティスト画面では同じアーティストの曲を聴いている人が表示されます。
なを、これらのリスト画面では5分以内に同じ曲、アーティストを聴いていた人の行が茶色で表示されます。


Now Playing画面では#nowplaying および同様の用途のタグ(#BGM #Playingなど)を含む投稿が表示されます。


上記のリスト画面でユーザーのアイコンをタップするとそのユーザのプロフィールを表示し、"Follow"をタップする事で実際にフォローする事ができます。
また、右のフキダシボタンをタップするとそのユーザーのツイート内容も確認できます。フォローするかどうかの判断に必要かと思い追加しました。



その他、通常のツイッタータイムラインも見る事ができます。
これは自分のnowplayingツイートが反映されたか確認したい場合や自分宛のMentionやホームタイムラインの確認の為にいちいちツイッタークライアントに切り替えなくて良いように追加しました。



2010年10月6日水曜日

初めての投稿

今日からブログを再開する事にしました。以前もいくつかのブログを書いていて、それなりに続いていたのですが、なんとなくやめてしまったりしていました。

ここでのブログは非ソフトウエア系、端的に行って製造業の企業で働くシステムエンジニアとしての僕の記録です。

基本的には技術者として、そのとき思った事を書いて行くつもりですが、たまに技術的覚え書きも書くかもしれません。あと愚痴とかw

誰かに読んで頂けたら嬉しいです。よろしくお願いします。