本連載が書籍化されました。
『良いコードを書く技術 ─ 読みやすく保守しやすいプログラミング作法』
縣俊貴 著/A5判・240ページ
価格2394円(本体2280円)
ISBN 978-4-7741-4596-9
おっす、おらメタプログラマ!
前回まで「良いコードとは?」という観点から,「名前付け」「スコープ」「処理の分割」といったプログラミングで必須の基礎内容を解説してきました。今回は少し趣向を変えてメタプログラミングを取り上げます。メタプログラミングは「プログラミングをプログラムする」と言われますが,なんだかつかみどころがない概念に感じませんか? 実際,「メタプログラミングとは何ですか?」と聞くと,人によって回答がまちまちです。そんなメタプログラミングですが,使いこなすとたいへん強力です。それでは,メタプログラミングについて考えを深めていきましょう。
メタプログラミングの悩み
まずは毎回好例,各界の代表者にメタプログラミングについての所信表明演説をしてもらいましょう。
良い仕事をしたい普通のプログラマ

達人プログラマを目指す 初級~中級のプログラマ

達人プログラマ

さすがに今回は達人プログラマ以外は歯切れが悪いですね。言葉が難しく感じる,使いやすく作るのが難しいという意見が多いようです。まずは「メタプログラミングとは何なのか?」を見ていきましょう。
メタプログラミングとは?
メタプログラミングとはいったい何でしょうか? 普通のプログラムを「普通に処理を並べたプログラムを書くこと」だとすると,メタプログラミングは「ある特定の問題を解決するプログラムを生み出すプログラムを書くこと」です。これではよくわからないので,いくつかの適用場面ごとに具体例を見ていきます。
コードの自動生成
プログラムを自動生成するプログラムはメタプログラムです。たとえばSeasarプロジェクトのS2JDBCGenやDBFluteなどは,データベースのスキーマをもとにエンティティクラスなどたくさんのソースコードを自動生成してくれます。Ruby on RailsなどのモダンなWebフレームワークにもビューやコントローラを自動生成してくれる機能があります。また,Visual Studioなどの統合開発環境(IDE)で「ぽとぺた」でGUIフォームやデータベースにアクセスできるアプリが作れるのも,マウスからの指示を入力にしたコードの自動生成であり,メタプログラミングの一種です。
自動生成のうれしい点として,単純作業の繰り返しコードを書かなくてよいことや,自動生成されたコードは基本的にエラーや間違いがあり得ないことが挙げられます。
このように「コードを自動生成するプログラム」をプログラミングすることが「メタプログラミング」です。要件が変わった場合は「生成されたコードを修正する」のではなく,「コードを自動生成するプログラム」を修正することで,「自動生成されたコード」が変更されるようなプログラミングスタイルになります。
DSL
ある特定の問題領域を解決するための小さな言語のことを「DSL」(Domain Specific Language; ドメイン特化言語)といいます。DSLを用いることでホストとなる言語でプログラムを書くことなくプログラミングできるようになるので,DSLはメタプログラミングの一種であるといえます。
外部DSL
Javaで一番使われているDSLはJSPでしょう。JSPは「HTMLを出力する」という領域を満たすテンプレート言語です。JSPではもととなるテンプレートがプリコンパイルされてJavaコードに変換されます。その後さらにJavaコードがコンパイルされて実行されます。以下は,JSPとプリコンパイル後のJavaコードです。
JSP
<body>
<h1>Cuuby archetype sample app : /hello/</h1>
<c:import url="/common/errors.jsp"/>
プリコンパイル
Javaコード
out.write("<body>\n");
out.write("<h1>Cuuby archetype sample app : /hello/</h1>\n");
if (_jspx_meth_c_005fimport_005f0(_jspx_page_context))
return;
out.write('\n');
JSPのようにホストとなる言語(Java)とは別の言語(JSP)を外部から読み込むことで実現するDSLを「外部DSL」(または言語外DSL)と言います。外部DSLとしてはXML形式の設定ファイルが利用されることが多いです。以下はSeasar2の設定ファイルです。
<component class="helper.Printer">
<initMethod name="addPrinterName">
<arg>"Printer1"</arg>
</initMethod>
</component>
XML形式の外部DSLでは,プログラム(通常はフレームワーク)がXMLを読み込み,内容を解釈しながら処理を組み立てて実行していきます。たとえば上記のXMLをSeasar2が読み込むと次の処理が実行されます。
- helper.Printerクラスのオブジェクトを動的に作成する
- 作成したオブジェクトに対して"Printer1"を引数にaddPrinterNameメソッドを実行する
このように外部DSLは,ときとして設定ファイルと見分けがつかないことがあります。メタプログラミングの入り口としては,外部DSLを「設定ファイルに毛が生えたようなもの」ぐらいの軽いものとして考えてもよいのではないかと思います。
まったくオリジナルのミニ言語を作成して外部DSLとして利用する場合もあります。その場合はパーサ作成のコストやオリジナル構文を新たに考えるコストが必要なので,通常は何かの言語に似せるかXMLなどのような汎用データ形式を利用することが多いようです。本稿ではのちほど汎用データ形式であるExcelを使ってDSLっぽい小さなフレームワークを作成します。

