Perl Hackers Hub

第40回 Perl開発への動的な型制約の導入(1)

この記事を読むのに必要な時間:およそ 4 分

本連載では第一線のPerlハッカーが回替わりで執筆していきます。今回のハッカーは,はてなでPerlを利用したWebアプリケーションを開発している@shiba_yu36こと柴崎優季さんで,テーマは「Perl開発への動的な型制約の導入」です。

本稿のサンプルコードは,WEB+DB PRESS Vol.94のサポートサイトから入手できます。

なぜ動的な型制約を導入したいのか

動的な型制約とは,関数の引数や変数に受け付ける型を制約として記述しておき,プログラムの実行時に制約を満たしているかのチェックを行うしくみのことです。静的な言語ではコンパイル時に型チェックを行っているのですが,それを動的な言語で実行時に行います。

動的な型制約をPerlへ導入する方法の解説に入る前に,本節でまず,なぜPerlに動的な型制約を導入したいのかについて説明します。

型がないことによる問題

Perlを使うメリットにはたとえば次のものがあります。

  • 枯れている言語でドキュメントも多く,安定して利用できる
  • CPANモジュールにたくさんの資産があり,かつそれらのドキュメントは同じような形式で書かれていて扱いやすい
  • さまざまな環境にデフォルトで実行環境が入っている
  • 動的言語でコンパイルがなく,型を意識する必要がないため,学習コストが比較的小さく,すばやく開発できる

しかし,メリットの一つである型を意識する必要がないことは,問題もあります。問題の一つは,関数の呼び出し方を間違えても気付けないことです。動的言語では,関数の呼び出しで次のどちらかの間違いを犯しても,エラーが起こるまでその関数の実行を進めてしまいます。

  • 2つの引数を必要としている関数に1つしか引数を渡さなかった
  • Blogクラスのオブジェクトを必要としているところに,別のクラスのオブジェクトを渡した

エラーが起こるまで実行を進めることは,最悪の場合,扱うデータを不整合な状態にする可能性があります。

リスト1は,関数呼び出しを間違えてデータが不整合な状態になる例です。funcは1つ目の引数に文字列を,2つ目の引数に数字を受け取り,処理を行う関数です。func内では最初に(1)$stringを使った処理を,次に(2)$numberを使った処理を行います。しかし,(3)の呼び出しでは2つ目の引数を渡し忘れています。このとき(1)の処理は実行されますが,(2)の処理でエラーが発生し実行が終了します。もし(1)の部分でファイルの変更やデータベースの更新などの副作用のある処理をしていたら,関数は適切に動作を終えられず,データは不整合な状態になってしまいます。また,(4)のように数字を期待しているところに文字を渡しても,(2)でエラーが発生し中途半端な状態になります。

リスト1 関数の間違った呼び出しによる不整合の発生

sub func {
    my ($string, $number) = @_;
    // (1)$stringを使った処理
    ...
    // (2)$numberを使った処理
    ...
}

// (3)引数を1つしか渡していない
func('aiueo');

// (4)2つ目の引数に数字以外を渡す
func('aiueo', 'abcde');

動的な型制約での解決

この問題を解決するにはどうすればよいでしょうか。

一つの方法は使用する言語を静的言語に変えることです。しかし,これまで開発してきたアプリケーションの言語を変えることは多大な労力が発生しますし,また社内の資産を活かすためPerlを使いたい場合もあるでしょう。

言語を変えずにPerlのまま問題を解決する方法として,動的な型制約の導入があります。動的な型制約では,関数の引数や変数に受け付ける型を制約として記述しておき,プログラムの実行時に制約を満たしているかのチェックを行うことで,関数呼び出し時に制約を満たさなかった場合,関数を実行する前にエラーで終了します。

リスト1の例なら,func関数は文字列と数字の2つの引数を必要とする」と制約を記述すれば,(3)(4)のように間違えた呼び出しをした瞬間にエラーで終了します。そのため呼び出しの間違いでは関数が中途半端に実行されず,データが不整合な状態になりません。

このように実行時に引数の型をチェックすることによって,アプリケーションの堅牢性を高められます。

Smart::Argsで引数に型制約を導入する

それでは,動的な型制約の具体的な導入方法を説明していきましょう。

関数の引数に対して動的な型制約をかけるためのCPANモジュールには,Smart::ArgsやData::Validator,Params::Validateなどがあります。本節では,その中でも実行速度と記法の使いやすさを兼ね備えたSmart::Argsについて解説します。

Smart::Argsは自分で定義した関数の最初に簡潔な記法を記述することで,関数の引数に動的な型制約をかけるモジュールです。このモジュールによって,動的な型制約をかけた関数に間違った引数を渡しても呼び出した瞬間にその場で例外を投げるため,関数が中途半端に実行される問題を防げます。

Smart::Argsは,argsargs_posという2つの記法の使い方と,どんな型を指定できるかだけを覚えれば導入できます。また,関数単位で導入するかどうかを決められるので,新しく書くコードから導入したり,堅牢性を高めたい部分にだけ導入したりと気軽に使い始められます。

Smart::Argsのインストール

Smart::ArgsはCPANモジュールとして提供されているので,cpanmコマンドでインストールします。モジュールをロードできれば,正しくインストールできています。

$ cpanm Smart::Args
$ perl -MSmart::Args -E 'say $Smart::Args::VERSION'

著者プロフィール

柴崎優季(しばざきゆうき)

1989年福井県生まれ。株式会社はてな所属。

Webアプリケーションエンジニアとして,はてなブログなどのWebサービスの開発に携わってきた。

Twitter:@shiba_yu36
Blog:http://blog.shibayu36.org/

コメント

コメントの記入