Perl: Net::FTP使ったコードをデバッグしたくて引数全部printするラッパ書いた
PerlのNet::FTPモジュールをラップして、メソッドを呼ぶごとに引数をプリントアウトするクラス書きました。
あとAUTOLOADを少し勉強しました。
コード
{ package FtpDebug; use Net::FTP qw//; sub new { my $this = shift; bless { me => Net::FTP->new(@_) }, $this; } sub AUTOLOAD { my $this = shift; our $AUTOLOAD; my $method = (split /::/, $AUTOLOAD)[-1]; # 次の行はお好みでファイルに出すとかカスタマイズ print "Calling method $method (", join(', ', @_) . ")\n"; $this->{me}->$method(@_); } sub DESTROY {} }
使い方
- クラスを読める位置にコピペするか、useできる場所にpm切ります。
- Net::FTPを使ったコードで
new Net::FTP
またはNet::FTP->new
しているところをFtpDebug->new
で置き換えます。 - 置き換えたコードでFTPのメソッドを呼ぶたびに引数がプリントアウトされます。
AUTOLOAD要点
- Perlで未定義のメソッド呼ぶとこれが呼ばれるらしい?
sub AUTOLOAD
で書いて中にグローバル変数our $AUTOLOAD
書くとFQNでメソッド名が得られる。- 上記コードでは、FQNそのまま呼ぶとDeep Recursionになってよくないのでsplitして最終要素取っている。
- そのままではDESTROYというメソッドもこれに捕まってしまうので、空メソッドとして定義する必要がある。
- なおDESTROYはPerlシステムの処理なので通常深入りしない
- (参照カウンタが0になってオブジェクトが消滅するときに自動で呼ばれる処理)
- なおDESTROYはPerlシステムの処理なので通常深入りしない
なぜ作ったか、あるいはタダの愚痴
クソ長いメソッド書いたPerlで、$workFile
だのftpDataDir
だの妙に抽象的な変数名使ってるわ、
逆に処理手順はファイルをカウントアップとかやたら具体的で全体で何をするかという抽象が書かれてない。
そんなクソコードとの出会いがあり、怒りに震えてました。
- 変数名は具体的に、処理は抽象的なのが俺が思うよいコードです。これでは俺の理想と真逆です。
で突然「あれ?コードがわかんなきゃとにかく全部プリントアウトすりゃいいんじゃね?」という発想が浮かんで作った。
クソコードとの出会いは案外多いから会っても泣かないために、これからもクソコードを力で殴るコード書きたいです。