メニューボタン
IBMi海外記事2009.08.04

PHPを活用する

ドン・デノンコート 著

いくつかの慣行に従うことで、PHPのコードを運用環境で使える状態に保ち、コントロールする

月刊誌「System iNEWS」の記事に目を通し、PHPをインストールし、ウェブ・ページをさっと作り上げれば、運用環境用のPHPアプリケーションを開発する準備ができたといえるでしょう。でも、ちょっと待ってください。鞍にまたがって街に乗り込む前に、まずは攻撃計画を立てる必要があります。自信過剰でPHP開発に突入すれば、保守が不可能な失敗に終わることになりかねません。PHPを使用してウェブ・アプリケーションを簡単に作成できるということは、大きな強みであると同時に、大きな弱点でもあるのです。本稿では、皆さんがPHPを使って街に乗り込めるように、PHPを開発する上で現実の世界では何がベスト・プラクティスなのか、私の経験を交えて皆さんにご紹介したいと思います。

  • モジュラー・プログラミングに関する懸念を分離する
  • ソースをコントロールする
  • まずテストしてからコード化する
  • 開発、テスト、運用の複数のテスト環境を使用する
  • デバッグするのではなくログを取る
  • コードから自動的にドキュメントを作る

モジュラー・プログラミングに関する懸念を分離する

PHPを使用すると、ウェブ環境にアプリケーションを素早く構築することが、驚くほど容易にできます。PHPは、Javaとは違って、オブジェクト指向プログラミングやさまざまな層のアプリケーション・インフラストラクチャを使用しなければならないということがありません。PHPは、オブジェクトやメソッドはもちろん、関数さえ使用しなくて済むのです。RPG IIやRPG IIIで一般的に用いられているコーディング方式でPHPアプリケーションを作成する傾向に対しては、警告を発しておかなければなりません。たとえば、PHPではグローバル変数を使用することができます。RPG IIIおよびそれ以前では、プログラム中のすべての変数がグローバル変数でした。また、PHPのロジックをすべて、メインラインに記述することもできます。私が手がけたRPG IIプログラムのメインラインのほとんどは巨大なものになっています。PHPを使用すると、最初はHTMLをビジネス・ロジック内に分散させなければならないように思えます。RPG IIのプログラム定義表示ファイルとほぼ同じような方法です。私が言いたいのは、PHPをRPG IIIのコードのようにプログラムしてはいけないということです。ILEのプログラマが記述するようにPHPのプログラムを記述してください。これはモジュラー・プログラミングの話です。私を信じてください。モジュラー・プログラミングに沿っていないPHPは、モジュラー・プログラミングに沿っていないRPGよりも、はるかに保守するのが難しいのです。

しかしPHPを使用すると、ILE RPGで利用可能なモジュラー・プログラミング機能を超えた機能を使用することができます。PHPは、オブジェクト指向プログラミングのコンストラクトやデザイン・パターンをサポートしています。では、PHPの開発を始めたばかりのときは、オブジェクト指向のデザイン・パターンをどこで使用するのが適切なのでしょうか。私は皆さんに、オブジェクト指向プログラマやデザイン・パターンの専門家になるよう勧めているわけではありません。私がお勧めしているのは、オブジェクト指向デザイン・パターンを使いやすく実装できるようなフレームワークがいくつかあるので、それらを利用してみてはどうか、ということです。こうしたデザイン・パターンの中には、モデル-ビュー-コントローラー(MVC)やデータ・アクセス・オブジェクト(DAO)なども含まれています。MVCは、ページ・フロー・ロジックを処理して、ビジネス・ロジックからプレゼンテーション層を分離します。DAOのパターンは、ビジネス・エンティティに対するオブジェクト・ラッパーとデータベース抽象層を提供します。

PHPで利用可能なフレームワークはかなりの数がありますが、私がお勧めするのは、Zendフレームワーク(framework.zend.com)です。Zendフレームワーク(ZF)は、他のフレームワークに比べると歴史は浅いですが、Zend社という、体重360キロのゴリラ版PHPで作られています。Zend社は、オープン・ソース(無償で参照可能)のフレームワークというすばらしい功績を残しました。ZFは「思いのままに使用してもらう」という設計思想に基づいています。「思いのままに使用してもらう」というのは、いつでも好きなときにZFのコードの一部を組み入れることができるという意味です。ZFを使用すると、私が今まで使ってきたJavaフレームワークに見られるような、「一度始めたら止められない」ような強固なカップリングや複雑さを経験することはありません。

ZFを使用するのがどれくらい簡単なのかは、図1のPHPの例をご覧ください。Sample.phpではZendデータベース・アダプタを使用して、NOSESという名前のファイルから主キーを使用してレコードを取り出しています。fetchOneメソッドはRPGチェーン・オペレーションと考えることができます。これと同じデータ抽出をする、フレームワークに沿っていない基本的なPHPコードの方が、コードの量がかなり多く、ずっと分かりづらいコードになっています。データベース・アダプタ・クラスは、fetchOneの他にもいくつか便利なメソッドを提供しています。

ソースをコントロールする

ソフトウェア開発プロジェクトはすべて、ソース・コントロールを採用すべきです。ソース・コントロールは必要ないという人でも、手操作によるソース・コントロールの手続きを使用しています。そうした人たちは、コードを削除せずにコメント・アウトしています。ソース・メンバーを修正する前にコピーを作成し、ソースのバックアップを何代にも渡って作ります。つまり、ソース・コントロールをせずに開発するのは、シートベルトを締めずに、あるいは保険に入らずに、車を運転するようなものです。ソース・コントロール用の良いツールを使用すると、 (特に単体テストと組み合わせるときは) 自信を持って大胆にコードを変更できます。

最初の実運用PHPプロジェクトを始める際には、最初から良いソース・コントロール用のツールを使用してください。私のお勧めは、Subversionです。Subversionはオープン・ソースで、広く使用されており、専用のツールがたくさん存在します。Subversionを使用するには、Subversionサーバーとクライアント・ツールセットが必要です。IBM i上でSubversionをホストできることを知っておいてください。私は、SoftLanding Systems社のウェブサイト(softlanding.com/subversion/index.htm)から無償でダウンロードできるSubversionを、おそらく何十というSystem iサーバー上にインストールし、セットアップしてきました。また、Subversionサーバーは名の通ったほとんどすべてのオペレーティング・システム上にインストールできるので、自分のネットワークのどのサーバー上でもSubversionをホストすることができます。Subversionサーバーを入手するもう一つの選択肢は、無数にある低価格のSubversionサービスのどれかを申し込むという方法です。

Subversionのクライアントも多数ありますが、私がここで触れておきたいのは、Subclipse (easyeclipse.org/site/plugins/subclipse.html) と TortoiseSVN (tortoisesvn.tigris.org)の2つです。SubclipseはEclipseのプラグインで、WDSCとの相性も良いものです。TortoiseSVNは、Windows Explorer上から使用できるツールです。SubclipseをPHPの実運用アプリケーションで使用した例を、例2に示します。画面キャプチャ上で照らされている部分のSubclipseの機能をいくつかメモしておいてください。

  • 一番左側のPackage Explorerタブで、各ファイルには最新のSubversionのコミット・タイムスタンプとコミットしたユーザーの名前が示されています。
  • 右側のソース・タブには、レポジトリ中のコードに対するローカルの変更を、Subclipseを使ってどのように比較するのかが示されています。黄色の矢印のアイコンをクリックすることで変更点を探し、コードのブロックをレポジトリからローカルファイルに移動します。Historyタブには、ファイルに関連するすべてのコミットに対して記されたコメントが表示されます。

Subversionをレポジトリとして使用してアプリケーションを開発する際の注意点をいくつか挙げておきます。

  1. コードをコメント・アウトせず、削除してください。コードはレポジトリ中にあるので、いつでも取り戻せます。
  2. コードの変更が正しいかどうかテストで確認したら、変更点を必ずレポジトリに反映させる。
  3. Subversionタグを使用して、アプリケーションの正式版を作成する。
  4. コードの変更をレポジトリに対してコミットしたときは、コメントを必ず追記する。

まずテストしてからコード化する

レグレッション・テストをするのは良いことだと誰もが認めるのに、レグレッション・テストに時間を割く人はほとんどいません。私たちに必要なのは、思想を変えることです。単体テストを実施して、開発サイクルを短縮するのです。どういう意味かご説明しましょう。ウェブ・アプリケーションを開発する際、変更点をテストするには、コードをサーバーに配布して、新しいコードが実行されるポイントにたどり着くまで、手操作でページをたどらなければなりません。たどりついた時点で、コードの変更が正しく動作していることを視覚的に検証するわけです。このシナリオの最初の問題点は、時間と手間がかかりすぎるということです。2番目の問題点は、ページに表示されている情報では、コードが正しく動作していることの証明にはならない可能性があるということです。そこにあるレコードを、データベースに追加していないかもしれないからです。

こうした時間がかかるプロセスに必要な条件を、レグレッション・テストに追加しながらも取り除く方法は、PHP Unitという、オープン・ソースのPHPユーティリティを活用することです。図3に示した、SampleTests.phpというファイルのテスト・コードを見てみましょう。このコードは、図1のSample.php中にある、getNoseIdFromNoseSnメソッドをテストします。コマンドラインから単体テストを実行するには、phpunitのあとにPHPのテスト名を入力するだけです。

[begin output]
C:\work\getreal>phpunit SampleTests.php
PHPUnit 3.3.4 by Sebastian Bergmann.

F

Time: 0 seconds

There was 1 failure:

1) testGetNoseIdFromNoseSn(SampleTests)
Failed asserting that two strings are equal.
expected string <123>
difference
got string   <2123>
/var/www/getreal/SampleTests.php:9

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

[end output]

どのように単体テストが失敗した結果を見つけたかに注目してください。行番号まで見てください。繰り返しの開発プロセスでは、正しい出力結果が出るまで、コードの修正と単体テストを繰り返します。正常に終了したテストをお見せするために、SampleTests.phpの2123をチェックする文を変更して、phpunitを再実行しました。

[begin output]
C:\work\getreal>phpunit SampleTests.php
PHPUnit 3.3.4 by Sebastian Bergmann.
Time: 0 seconds
OK (1 test, 1 assertion)

[end output]

コードの全体的な品質を改善し、プログラマとしての満足度を増大させるには、周知のとおり、「まずテストしてからコード化する」という慣行に従ってください。基本的な方法は、1) PHPのスケルトン(つまりAPI)を作成する。2) PHP内の各メソッドに対して単体テストを記述する。3) 単体テストを実行する。これは、コードのスケルトンの細部を記述していないので、すべて失敗となるはずです。4) PHPの細部を記述し、すべて合格となるまで、単体テストを実行し続ける、というものです。

単体テストを実行することには、2つの大きな利点があります。1つめは、「まずテストしてからコード化する」という慣行にしばらく従うことで、かなりの数の単体テストを実行することになり、それはレグレッション・テストを実行していることになるのです。2つめは、PHPのコードをデザインし、テストができるように手直ししていくにつれ、結局はモジュール化されたコードを書いていることになる点です。

さて、運用中に出たバグを修正するための単体テストの使用方法について、考えてみましょう。バグが混入したときの最初のステップは、単体テストでそれを再現することです。再現ができれば、その問題を修正し、単体テストを再実行し(修正がうまくいっていることを確認するため)、レグレッション・テストをすべて再実行し(修正が他の箇所に悪影響を与えていないことを確認するため)、修正したコードを運用環境に移します。こうして、この新しい単体テストはレグレッション・テストの一部となって、その結果、素早く修正したコードがアプリケーションのライフサイクルを通じてテストされるようになります。

「まずテストしてからコード化する」という思想に従うようになれば、そうせずに開発をすすめたいと思わなくなるでしょう。単体テストを実行することで開発サイクルが短縮されて、誤ったコードの数が減り、その結果、達成感が増し、プログラマとして成長することができて、作業が楽しくなるからです。

開発、テスト、運用の複数のテスト環境を使用する

PHP、Java、Groovyなどのクロス・プラットフォーム用言語のすばらしい点の1つは、複数の開発環境を使用することができるということです。最低限でも、開発、テスト、運用の3つの環境を持つのが一般的です。これらの環境はそれぞれ、独自のデータベースをもっている必要があります。いくつかの理由から(オフラインの開発やパフォーマンスなど)、開発データベースはローカルのPCにおくことをお勧めします。ローカル・データベースをどれにするかについては、MySQL、MS SQL、DB2 for Windowsなど、いろいろな選択肢があります。(こうしたデータベースについて知っておくことは、履歴書に記載できることを考えても、決して悪いことではありません。) 運用データベースのベンダーと異なるベンダーの開発データベースを使用すると、PHPのデータ・アクセス・コードに問題が発生する原因となりうるので、注意が必要です。この問題に対する解決方法の1つとしては、ZFファクトリー・クラスを使用して、データベースに対する適切なデータベース・アダプタ・クラスを動的に読み込むようにすることです。このアダプタ・クラスは、どの環境にもあるphp.ini構成ファイル中に設定されています。

テスト環境は、チームの誰もがアクセスできるシステム上になければなりません。テスト・データベースは、レグレッション・テストが一貫して同じデータベースのコンテンツに対して実行できるように、厳格に管理されていなければなりません。テスト・データベースを保守する方法には、通常、insert文の集合からデータベースに値を再入力するためのSQLスクリプトを使用することなどが含まれます。さらにもう一歩先に進んで、PHPUnitのDatabase Extensionツールを使用し、単体テスト間で動的に行に値を入れても構いません。

多くの情報システム部門では、テスト用システムへの導入を自動化しています。標準的な戦略は、ソース・レポジトリに対してコミットがされたときは必ず、実行するプロセスを識別するというものです。このプロセスは最新のPHPをテスト用サーバーに導入してから、レグレッション・テストの実行を開始します。失敗に終わったテストがあれば、開発者やチーム・リーダーまたは管理者にメールが送信されます。

運用環境は、いつもそうですが、神聖な環境です。運用サーバー上では決して編集してはいけません。php.iniファイルは、実行速度を最適化してセキュリティを最強に保つような設定となるように構成されていなければなりません。

デバッグするのではなくログをとる

私はビジュアルなデバッガはどうも好きになれません。実際のところ、トレーニングやメンタリング・セッションを実施する前に、利用可能なデバッガの使い方について、自分の記憶をリフレッシュしなければならないことがしばしばです。ではどうして、運用に耐えうる品質のコードを、デバッガを使わずに書きつづけられるのか、不思議に思われるかもしれません。私の場合、ログ機能を使っているからだ、というのがその答えです。実際、ログ機能は、開発者の間では一般的に使われています。有名なオープン・ソース・ソフトウェア製品のほとんどのコードを分解してみると、大量のログ機能が見つかると思います。

ビジュアルなデバッガを使うことの何が問題なのでしょうか。それは、バグを見つけてそれを解決した瞬間に、デバッグのセッションを設定するのに費やした時間が無駄となることです。ログ機能を使用する際は、デバッグ・セッションのときだけでなく、プログラムを作成するときも、コードの中にログ記録用の文を挿入します。デバッグ・セッション中にコードに追加されたログ記録用の文は、決して失われることはありません。

ログ文は通常、テキストファイルに書き出されますが、オプションとして、コンソールやAS/400のジョブ・ログに書き出すこともできます。ログ機能は非常に大量のログ・ファイルを作成し、実行速度を低下させることもありますので、ログ機能のフレームワークにはいくつかのログ・レベルがあります。たとえば、Zend社のログ機能のフレームワークには、EMERG、ALERT、CRIT、ERR、WARN、NOTICE、INFO、DEBUGといったログ・レベルがあります。コード中の各ログ記録文は、これらのログ・レベルのうちから1つを指定します。そして、php.ini構成ファイル中で、そのサーバー上でのログ・レベルを設定します。実行中にログ文に到達すると、php.iniファイル中のレベルがログ記録文で指定されているレベルと同等か、それ以上であれば、そのメッセージがログされます。開発中は、php.iniファイルのログ・レベルをDEBUGに設定します。運用環境では、通常はWARNにセットされます。しかし、運用環境で問題が発生すれば、php.iniのログ・レベルをDEBUGに簡単に替えることができます。ログ・ファイルを見ただけで運用環境上の問題の原因を発見できるというのは、驚くほど便利です。

コードから自動的にドキュメントを作る

ドキュメントの作成が好きな人はいません。しかも、ドキュメントの作成はプロジェクトにおける最後の仕事であるため、省略されることがしばしばです。コードからドキュメントを生成することができたら、便利だと思いませんか。それが、できるのです。phpDocumentor (phpdoc.org)というフリーのユーティリティで、それが可能です。phpDocumentorは、複数行のコメント中で「@」という特別なタグ(コメントの初めのスラッシュ記号に続く、特別な2個のアスタリスクがついたもの)を探します。図1のPHPをもう一度見てください。このコードを最初にご覧になったときは、@author、@param、@returnなどのタグに気がつかなかったかもしれませんが、phpDocumentorコマンドにPHPのソース・ディレクトリを指定して実行すると、これらの特別なタグが図4に示すHTMLを生成します。各PHPのソースに対して、HTMLページ、インデックス、そしてツリーの一覧が生成されます。

phpDocumentorの利点を最大限に生かすには、特別のphpDocumentorタグを含んだコメント行を追加するという、基本的なコーディング標準に従うだけでよいのです。@author、@example、@global、@method、@name、@package、@param、@property、@return、@see、@staticなど、数十のタグがあります。

モジュール化されたコードを記述するときは、PHPファイルの数の多さだけでなく、そこに含まれている関数やメソッドの数にも辟易しやすいものです。phpDocumentorによって生成されたHTMLは、PHPアプリケーションのAPIをレビューしたり、理解したりする際の、簡単な道具となります。

PHP開発への考慮点

PHPは急速に、IBM iのVisual Basicとなりつつあります。Visual Basicはコードがあまりに簡単に記述できるが故に、誰もがVBアプリケーションを書くことができました。問題は、VB (そして今やPHPも)のコードが急速に、手に負えないくらい保守しづらいものとなってきていることです。本稿で紹介したPHPの慣行に従うことで、PHPをコントロール下におくことができますが、それ以外にも、以下の考慮点をご紹介して、本稿を終えたいと思います。

  • コーディング標準
  • ツールセットの習得
  • テンプレート化
  • 共同作業

自分の情報システム部門のために、特別なコーディング標準を含んだ簡単なドキュメントを作っておくのは名案です。RPGのスタッフにとってPHPは新しい言語ですので、インデントとか、タブとスペースの使い分け、名前の付け方のルール、などといったスタイル決めに、プログラマたちが時間を無駄にしないように注意して下さい。

PHP開発で利用可能なIDEは、何十とあります。私はPHP Development Tools Eclipseプラグインを使用していますが、Zend社製のIDEもありますし、Eclipse用の汎用プラグインもあります。PHP用のIDEを選び、そのIDE内で利用可能な機能をマスターしてください。

数百ものページを記述することが予想されるのであれば、さまざまなテンプレート・エンジンを試してみてもいいかもしれません。PHPには、ビューとロジックの分離を促進するように設計されたページ・テンプレート戦略がいくつかあります。最も有名なテンプレート・ツールは、Smarty Pages、Savant、Zend社のview/layoutです。

そして最後に、共同開発について、少し私の考えを述べたいと思います。Subversionなどといったソース・コントロール・ツールは、数多くある共同開発ツールの1つです。プロジェクトWikiは、無料で、しかも設定が容易な便利なツールです。また、インスタント・メッセージング(IM)というツールもあります。IMは会議を減らし、電子メールよりもリアルタイムにコミュニケーションでき、電話をかけるという肩苦しさも低減してくれます。あなたのチームの開発者が、緑色画面のSEU開発から最新のツールセットを使ったPHPの世界に移ろうとしているのであれば、さまざまな無料のウェブ・ツールを有効活用して、プロジェクトの共同作業を促進することを考えてみてください。

あわせて読みたい記事

PAGE TOP