引っ越しました

sqlのdelete,updateによる事故(オペミス)を減らす

selectの履歴から組み立てる

select * from blog where title = 'my blog';
で結果を確認した後、上記のsqlを履歴から引っ張ってきて、
delete from blog where title = 'my blog';
に書き換える

さらに念のためにlimit句を付ける

delete from blog where title = 'my blog' limit 1;

safe-updatesオプションを付ける

whereやlimitが指定されてないと実行されない
document
起動時に指定か、my.cnfに書いておく。

緊急でないならスクリプトにする

手作業のオペミスが発生しないので確実。
それに同じオペレーションをもう一度する可能性は高い。

gitのhooksを活用する

git

gitフックについて

どのような種類のフックがあるかは、ここで確認

コミット前にテストを実行

.git/hooks/pre-commitに好きなスクリプトを置いておくと実行されます。
以下のコードでcommit時にproveが走るようになります。

#!/usr/bin/env perl
use strict;
use warnings;

chomp( my $project_dir = `git rev-parse --show-toplevel` );
system("prove", "-I${project_dir}/lib", "${project_dir}/t") == 0 or die 'Failed test';

gitのバージョンが古いためshow-toplevelオプションが無い場合は、
git-dirオプションで.gitディレクトリへのパスが取得できるので、そこから目的のパスを作るといいです。

コミット前にコードチェックorフィルター

my @modified_files = system('git diff-index --cached --name-only HEAD');

で変更ファイル一覧が取れるので、あとはお好きにできますね。

gitでPATHの先頭に'/usr/libexec/git-core:/usr/bin:'が追加される

pre-commitにperlスクリプトを置いておいたら、perlbrewではなくてシステムperlが使われていて、
調べてみるとタイトルのようなことになっていました。

xcodeがインストールしてくるgitはアップルのパッチが当たっているようです。
参考ツイート
コード

git --version
git version 1.7.12.4 (Apple Git-37)

通常のgitを使うか、perlbrewであれば環境変数からパスを組み立てることで解決できます。

テストがどこにあるのかわからない対策

perlではt/以下にテストファイルを置いておくのですが、肥大化してくるとテストがどこにあるのか分からなくなります。
対策として、1クラス1テストファイルにしてライブラリと同じディレクトリ階層を作る、があります。
しかし面倒くさいですし、そのファイルにあることは分かっても、どのテストが自分の確認したいテストなのかが、すぐには分からないことがあります。

命名規則を決めてgrep

メリット
テスト対象コード
package Hoge;

sub new {
   ....
}
sub search {
   ....
}
テストコード
use Test::More;

subtest 'Hoge::search' => sub {
    subtest 'limit' => sub {
        my $hoge_obj =  Hoge->new;
        my @res = $hoge_obj->search( limit => 20 );
        is(scalar @res, 20);
    };
    subtest '....' => sub {
        ....
    };
};

done_testing;
おれおれカバレッジ

この命名規則だとsubtestをオーバーライドすることでテストカバレッジが簡単に取れます。
既存カバレッジモジュールで、あるメソッドのテストを実行したときに中で異なるメソッドを呼び出してるだけで、そのメソッドカバレッジに追加されて、むーん、ってときに作ってました。

みんなどうやってるんだろう

この話をしたところRSpecぽいですねって言われた。

Kyoto.pm 05に参加してきました

人生初の遠距離pm参加をノリできめて発表してきました。
ツイッターアカウントは知ってるけど話したことはない、って人が多くて来てよかったなーと思いました。

いつも通り、全体的なことは他の人が書くだろー、ってことで自分の話をすると、
EPUB::Parserってモジュールを書いたので、それについて書いた動機と、それの設計などをざっくり言った感じです。
僕的にはコードの設計を教えて欲しいなって気持ちだったんですが、発表って形式でいきなり出しても難しい感じでした。

余談ですが、EPUB::Filterというモジュールも書こうとしてて、
EPUB::Parserのスクリプトが返す{ "title" : "タイトル" } ってjsonを書き換えて、Filterのスクリプトに食わすとEPUBの中身が書き変わるというものです。
けど、Filterって銘打つならHTML::Filterっぽくせにゃいかんのかなー、そこまでは、、、って感じです。

発表資料: EPUBのパーサーとビルダー

作成動機

  • 電子書籍をweb上で作成、販売するサイトを運用
  • 出版社から頂くデータがEPUB3化
  • EPUB3仕様に完全対応した既存モジュールがない
  • 都度アップデートする必要があるなら得意なPerl製モジュールでないとキツい

発表動機

  • 設計やメソッド名について意見が欲しい
  • パーサーの話が主

EPUB::Parser

github

  • サイトで提供しているインポート機能のために作成
  • 現在EPUB3のみ対応
  • インポート時に必要となるデータの整形を吸収(パスの書き換え等)
  • XML::LibXMLを使用
  • ドキュメント追加中

EPUB::Parser設計

  • ファイル毎にクラス化しており、複数ファイルを参照する必要がある場合は責務を逸脱しないよう別の名前空間を用意(EPUB::Parser::ManagerとEPUB::Parser::Fileに分割)
  • 単一ファイルの中にもmanifestやspineなど重要な役割をもつノードがあるのでそれぞれクラス化(EPUB::Parser::File::**::Context::**)


EPUB
├── Parser
│ ├── File
│ │ ├── Container.pm # META-INF/container.xml用クラス
│ │ ├── Document.pm # 本文ファイル用
│ │ ├── Navi
│ │ │ ├── Context
│ │ │ │ └── Toc.pm
│ │ │ └── Context.pm
│ │ ├── Navi.pm
│ │ ├── OPF
│ │ │ ├── Context
│ │ │ │ ├── Guide.pm
│ │ │ │ ├── Manifest.pm
│ │ │ │ ├── Metadata.pm
│ │ │ │ └── Spine.pm
│ │ │ └── Context.pm
│ │ ├── OPF.pm
│ │ ├── Parser #各ファイル用パーサー. xpathのネームスペース設定とコンテキスト切り替えを行う
│ │ │ ├── Container.pm
│ │ │ ├── Document.pm
│ │ │ ├── Navi.pm
│ │ │ └── OPF.pm
│ │ └── Parser.pm # 各ファイル用パーサーの親で、find,singleメソッドを持っている
│ ├── Manager
│ │ └── Pages.pm
│ └── Util
│ ├── Archive.pm # zip内データをイテレータで返す
│ ├── AttributePacker.pm # 任意の属性値を主キーとしたデータ構造を返す
│ ├── Context.pm # EPUB::Parser::File::**::Contextの共通メソッドエクスポート用.
│ │ # 安易にUtilに置いてしまった
│ ├── EpubLoad.pm
│ └── ShortcutMethod.pm # EPUB::Parserにメソッドエクスポート
└── Parser.pm

  • データ構造を作成するメソッド命名が難しい。ノードの任意の属性値を主キーとして、データ構造を返す処理など。
  • テストはsubtest名に完全なメソッド名を書いてgrepで特定できるようにしている
  • 面倒くさいと言われたのでショートカットメソッドを作った。$self->opf->metadata->titleが$self->titleに。しかしショートカットメソッドは作り出すとキリがなく、EPUB/Parser.pmが本質と関係ないコードで肥大化するので、EPUB/Parser/Util/ShortcutMethod.pmからエクスポートすることにした。

EPUB3::Builder(cpan化の予定無し)

github

  • 入力xhtmlのbody部をepub3用のテンプレートに流し込む
  • メタデータ等の作成
  • naviファイルは全ページ列挙してるだけ
  • テストでxmlを比較するにはXML::Compareを使った

jsでグラフ生成をためしてみたい
http://code.shutterstock.com/rickshaw/