機能
現実の状況で効果的な PHP コードを開発する方法に関するこのシリーズのパート 3 では、Amol Hatwar が、パフォーマンスや管理性をあまり犠牲にすることなく使用できる最も効率的な関数を構築する方法について説明します。著者は再利用可能な関数の作成に焦点を当て、タスクに関連する最も一般的な問題のいくつかを回避する方法を示します。
おかえりなさい。このシリーズのパート 1 では、いくつかの基本的な PHP 設計ルールについて説明し、安全でシンプル、プラットフォームに依存しない、高速なコードを作成する方法を示しました。パート 2 では、変数を紹介し、PHP コーディングでの変数の使用法 (良い習慣と悪い習慣) について説明しました。
この記事では、PHP で関数を賢く使用する方法を学びます。どの高級プログラミング言語でも、プログラマは関数を定義できます。PHP も例外ではありません。唯一の違いは、関数の戻り値の型を気にする必要がないことです。
詳細
関数は次の目的で使用できます:
複数行のコードを 1 つのステートメントにカプセル化します。
簡略化されたコード。
最も重要なことは、アプリケーションを、相互に連携する小さなアプリケーションの製品として考えることです。
C/C++ などのコンパイル言語から PHP に来た開発者にとって、PHP のパフォーマンス レベルは驚くべきものです。ユーザー定義関数は、CPU とメモリのリソースを使用するという点で非常に高価です。これは主に、PHP が解釈され、型付けが緩いためです。
ラッパーかどうか
単純に関数の名前が気に入らないという理由で、使用するすべての関数をラップする開発者もいますが、ラッパーの使用をまったく好まない開発者もいます。
既存の機能を追加または補完せずに既存の PHP 関数をラップすることは、完全に受け入れられません。このような名前変更された関数は、サイズと実行時間の増加に加えて、管理上の悪夢を引き起こす可能性があります。
コード内のインライン関数は、不可解なコードやさらに大きな管理上の災害につながる可能性があります。これを行うことの唯一の利点は、コードが高速になることです。
より賢いアプローチは、コードを複数回使用する必要があり、達成したいタスクに使用できる組み込み PHP 関数がない場合にのみ関数を定義することです。名前を変更するか、必要な場合にのみ制限付きで使用するかを選択できます。
図 1 のグラフは、管理性と速度が使用される関数の数にどのように関係するかを大まかに示しています。 (数値は個人とチームの能力に依存するため、ここでは単位を指定しません。この関係を視覚化することが重要です。)
図 1. 管理性/速度と関数の数
関数の名前
前述したとおりこのシリーズの第 2 部 (「参考文献」を参照) で述べたように、効果的なコード管理には、常に共通の命名規則を使用することが不可欠です。
考慮すべき他の 2 つのプラクティスは次のとおりです:
関数が何を行うかについての良いヒントを与える名前を選択してください。
パッケージまたはモジュールを示すプレフィックスを使用します。
ユーザー管理関数を含む user というモジュールがあると仮定すると、ユーザーが現在オンラインかどうかを確認する関数には、 usr_is_online() や usrIsOnline() などの関数名が適しています。
上記の名前を is_online_checker() のような関数名と比較してください。結論としては、関数は常に何かを行うため、名詞を使用するよりも動詞を使用する方が良いということです。
パラメータはいくつありますか?
おそらく、すでに構築された関数を使用することになります。そうでない場合でも、コードのスコープを最大化したい場合があります。これを行うには、あなたと他の開発者が使いやすい機能の開発を続ける必要があります。あいまいで理解しにくいパラメーターを受け取る関数を使いたがる人はいないため、使いやすい関数を作成してください。
関数の目的を説明する名前を選択する (そして関数が受け取る引数の数を減らす) ことは、使いやすさを確保する良い方法です。パラメータの数を表すマジックナンバーは何ですか?私の意見では、パラメーターが 3 つを超えると関数を覚えにくくなります。多数のパラメータを持つ複雑な関数は、ほとんどの場合、より単純な関数に分割できます。
その場しのぎの関数を使いたがる人はいません。
高品質な関数を作成する
HTML ドキュメントをブラウザーに入れる前に、そのタイトルを設定したいとします。ヘッダーは、
... タグの間のすべてです。
タイトルタグとメタタグを設定するとします。 setHeader(title, name, value) 関数を使用してすべての作業を行う代わりに、setTitle(title) と setMeta(name, value) を使用して各作業を個別に実行する方が良い解決策となります。このスキームは、タイトル タグとメタ タグを互いに独立して設定します。
さらに考えると、タイトルにはタイトル タグを 1 つだけ含めることができますが、複数のメタ タグを含めることができます。複数のメタ タグを設定する必要がある場合は、コードで setMeta() を複数回呼び出す必要があります。この場合、より良い解決策は、名前と値のペアの 2 次元配列を setMeta() に渡し、関数がその配列をループするようにすることです。すべてを同時に実行します。
一般に、このような同時機能が望ましいです。処理する必要があるすべてのデータを指定して関数を 1 回呼び出すことは、関数を複数回呼び出してデータを段階的に供給するよりも常に優れています。関数を作成するときの主な考え方は、他のコードからの関数への呼び出しを最小限に抑えることです。
これによると、setHeader() ソリューションは実際には良い方法ではありません。明らかに、setHeader() を setHeader(title, array) にリファクタリングできますが、タイトル タグとメタ タグを互いに独立して設定する機能が失われることも考慮する必要があります。
また、実際の環境では、タイトルにはタイトルタグとメタタグだけでなく、複数のタグが含まれる場合があります。さらにマークアップを追加する必要がある場合は、setHeader() とそれに依存する他のすべてのコードを変更する必要があります。後者の場合は、関数をもう 1 つ作成するだけです。
次の方程式はすべてのプログラミング言語に当てはまります:
覚えやすい名前 + 明確なパラメータ + 速度と効率 = すべてのプログラミング言語で動作する高品質な関数
階層化アプローチで関数を調整する
関数が簡単単独で存在するものは少なくなります。これらは他の機能と連携してデータを交換および処理し、タスクを完了します。これらの関数またはモジュールのグループは再利用できる必要があるため、同じグループまたはモジュール内の他の関数と適切に動作する関数を作成することが重要です。
仮説的なページ構築例を続けてみましょう。ここで、このモジュールの役割は、HTML を使用してページを構築することです。 (この例の目的は、再利用性を向上させながら関数と関数グループがどのように簡単に連携できるかを説明することだけなので、ここでは詳細とコードをスキップしましょう。)
組み込みの PHP 関数から始めます。抽象関数を構築し、それを使用して基本的なニーズを処理するさらに多くの関数を作成し、次にこれらの関数を使用してアプリケーション固有の関数を構築できます。図 2 は、これがどのように機能するかを示しています。
図 2. 階層化された関数
これで、ページがメモリに構築され、完成したページがブラウザに配布されます。
メモリ内にページを構築することには 2 つの大きな利点があります:
独自のスクリプトを使用して完成したページをキャッシュできます。
ページの構築に失敗した場合は、中途半端なページを破棄して、ブラウザーにエラー ページをポイントできます。
これで、ユーザーのページにはエラー メッセージを含むレポートが表示されなくなります。
ほとんどのページの構造に基づいて、ページの構成要素は次の機能を実行する関数に分割する必要があります:
トップバーを描画する
ナビゲーションバーを描画する
コンテンツを表示する
脚注を追加する
以下の機能を実行する関数
ページをキャッシュする
ページがキャッシュされているかどうかを確認する
ページがキャッシュされている場合は、それを表示する
これをページ ビルダー (pagebuilder) モジュールと呼びましょう。
ページビルダーモジュールは、データベースにクエリを実行することで作業を実行します。データベースは PHP の外部にあるため、データベース抽象化モジュールを使用します。このモジュールの役割は、PHP のさまざまなベンダー固有のデータベース関数に同種のインターフェイスを提供することです。このモジュールの重要な関数は、データベースに接続する関数、データベースにクエリを実行する関数、クエリ結果を提供する関数です。
サイト全体の検索エンジンも実装したいと仮定します。このモジュールは、特定のキーワードまたはキーワードのセットに関連するドキュメントをサイト内で検索し、検索文字列の関連性またはその文字列の出現回数に基づいて結果を表示する役割を果たします。このモジュールは、監査目的で検索のログも記録したい場合に、データベース抽象化モジュールと一緒に使用されます。
ユーザーからの入力を受け入れることに注意してください。悪意があると思われるコンテンツを画面に表示し、破棄する必要があります。これには、ユーザーがフォームを通じて送信したデータを検証する別のモジュールが必要です。
この時点で、私が話している概念を一般的に理解している必要があります。最も核となる機能は論理モジュールに分割する必要があり、それらのタスクを実行するには、アプリケーションはこれらのモジュールによって提供される関数を使用する必要があります。
この階層化アプローチを使用すると、単純なページ構築レンダリング アプリケーションは図 3 のようになります。
図 3. 階層化されたページ構築アプリケーション
この例では、コア モジュールとアプリケーションを処理するモジュールの間に階層がないことに注意してください。つまり、コア モジュールは、抽象モジュールまたはその下の層で宣言された関数から関数を呼び出して宣言できますが、アプリケーション コードではそれができない場合があります。アプリケーション コードが低レベル関数によって「汚染」されている場合、またはカプセル化されている場合、アプリケーション コード内で関数を宣言しないでください。低レベルの関数のみを使用できます。これはより高速な方法であることが判明しました。
関数テクニック
関数の使い方と書き方を理解したところで、一般的に使用されるテクニックをいくつか見てみましょう。
参照を使用する
簡単に言うと、参照はC言語のポインタのようなものです。唯一の違いは、PHP では、C のように逆参照するために * 演算子を使用する必要がないことです。これらは、変数、配列、またはオブジェクトのエイリアスと考えることができます。何をしても、エイリアスは実際の変数に影響を与えます。
リスト 1 は例を示しています。
リスト 1. 変数参照
$name = 'Amol';
$nom = &$name; // $nom は $name
$nom への参照になりました .= ' Hatwar';
print("あなたは $name ?n"); // ジミー レイのパロディ?
?>
引数が関数に渡されると、関数は引数のコピーを受け取ります。パラメータに加えた変更は、関数が返されるとすぐに失われます。パラメータを直接変更したい場合、これは問題になる可能性があります。リスト 2 は、この問題を説明する例を示しています。
リスト 2. 関数に引数を渡すときの問題
functionhalf($num)
{
$num = $num / 2;
return $num;
}
$myNum = 15 ;
$result =half($myNum);
print("$myNum の半分は: $resultn");
print("$myNum に含まれる: $myNumn");
?>
$myNum を直接変更したい場合は、$myNum への参照をhalf() 関数に渡すことで簡単に行うことができます。ただし、これは良い習慣ではないことに注意してください。コードを使用する開発者は、使用された参照を追跡する必要があります。これにより、誤ってエラーが広がる可能性があります。機能の使いやすさにも影響します。
関数宣言で参照を直接使用することをお勧めします。この場合、half($num) の代わりにhalf(&$num) を使用します。このように、参照を覚えておけば、関数にパラメーターを渡すことを覚えておく必要がなくなります。
PHP は舞台裏でいくつかの処理を行います。新しい PHP バージョン (および 4.0 以降のバージョン) では、呼び出し時の参照による受け渡しが非推奨となり、いずれにしても警告が発行されます。 (ここにいくつかの提案があります: 以前の PHP バージョンに対して書かれたコードを使用している場合は、php.ini ファイルを変更して PHP の動作を変更するよりも、コードを更新する方が良いです。)
関数呼び出し間で変数を保持する
多くの場合関数呼び出し間では変数値を維持する必要があります。グローバル変数も使用できますが、変数は非常に壊れやすいため、他の関数によって破損する可能性があります。変数を関数に対してローカルにして、その値を保持する必要があります。
静的キーワードを使用するのが良い解決策です。デバッガが使用できないときに実行されたユーザー定義関数の数をカウントしたい場合に、この方法をよく使用します。すべての関数を変更し (もちろん自動スクリプトを使用)、関数本体の最初の行にカウント作業を行う関数の呼び出しを追加しました。リスト 3 では、この関数について説明します。
リスト 3. ユーザー定義関数のカウント
function funcCount()
{
static $count = 0;
return $count++;
}
スクリプトが完了する直前に funcCount() を呼び出して変数を収集します。このメソッドの値は有効です。驚くべきことに、$count はゼロにリセットされず、静的変数を初期化する行は 1 回だけ実行されます。
関数内でグローバル変数にアクセスする必要がある場合は、変数を使用する前に global キーワードを使用する必要があります。
PHP 4 以降では、関数を 2 回宣言しない限り、最初に関数を使用してからそれを定義することも可能です。
動的呼び出しを実行する
多くの状況で、次にどの関数を呼び出さなければならないか実際にはわからないことがわかります。この状況は、イベント駆動型プログラミングを行っている場合、またはシステム外部のイベントがトリガーされたときに特定の関数を呼び出したい場合に発生します。ネットワーク上で通信するスクリプトは、この状況の例です。
この方法は変数名の使用に似ています。外部イベントを使用して変数を設定し、それを関数として使用するだけです (対応する関数が宣言されていると仮定します)。混乱した?リスト 4 で明らかになります。
リスト 4. 動的関数呼び出し
functionsay_hi()
{
print("Hi!");
}
functionsay_greeting()
{
print("今日はどうですか?n ");
}
function Say_bye()
{
print("今日の機能はこれくらいです。来月また会えることを願っています。n");
print("それまでは、良い時間を過ごしてください");
}
// 誰かがログインしたふりをしてみましょう
$my_func = 'say_hi';
$my_func();
// ユーザーに挨拶します
$my_func = 'say_greeting';
$my_func();
/ / 今日はやめてください
$my_func = 'say_bye';
$my_func();
?>
手間を省きたい場合は、このメソッドを使用して、いくつかの switch-case ステートメントを作成することもできます。どの関数を使用するかを評価します。変数を設定して関数として使用するだけです。ここでは変数を意図的に設定していますが、これは動的に実行できることを覚えておいてください。これは、この手法がいかに強力であるかを示しています。
結論
この記事では、優れた関数を設計して作成する方法を説明しました。モジュールとスクリプトのセットを連携させて大規模なアプリケーションを作成する方法を実証し、コーディングの労力を軽減して優れたコードを生成できる手法を検討しました。
次の記事では、PHP のクラスとオブジェクトについて説明し、現在のスキルに基づいて構築し、キャッシュとデータベースの抽象化を実行するコードの一部を詳しく見ていきます。
参考文献
Developer Shed の「The Art Of Software Development: Understanding Need」では、icarus はアプリケーション開発サイクルの最初の部分に焦点を当て、コードの最初の行を書き始める前に行う必要があることのいくつかを説明しています。
Developer Shed にある Harish Kamith のチュートリアル「Using PHP with Java」をお読みください。このチュートリアルには、JDK 1.3.0、Apache 1.3.20、および PHP 4.1.1 を使用して Linux に実装された詳細なコード例が含まれています。 i586。
Mike Britton の記事「Scratching the Surface: Getting Started with PHP Fusebox」では、スケーラブルで効率的な Web ボックス スタイルのアーキテクチャ ツールである Fusebox の最新バージョンについて完全に紹介しています。
PHPGuy は、PHP でコーディングする際の時間を節約するために使用できる 10 個の珍しい関数を提供するチュートリアル「PHP ツールキットを構築するための便利な PHP 関数」を提供しています。
また、PHPGuy の記事「Making Sense of those Cold PHP Errors!」では、いくつかの PHP エラーの種類と、開発中にその意味を理解する方法について説明しています。
PHP デバッガーは、PHP コードのプロファイリングとデバッグに (無料で) 利用できます。
このシリーズの第 1 部「より高い視点から見る」(developerWorks、2002 年 8 月) では、PHP をマスターするための強固な基盤を構築する方法について説明します。
このシリーズの第 2 部「変数の効果的な使用」(developerWorks、2002 年 9 月) では、異なる変数名を使用する構成ファイル パーサーを構築することによって、スクリプト構成を簡素化する方法を示します。
その他の参考資料については、dW Linux Zone にアクセスしてください。
著者について
Amol Hatwar は、物心ついた頃からコンピュータを使って仕事をしてきました。 GNU/Linux の熱心な支持者である彼は、過去に Microsoft プラットフォームでプログラミングしたことに罪悪感を感じています。彼は現在、独立したコンサルタントとして、多数の企業の GNU/Linux への移行を支援しています。 Web アプリケーション開発の専門家である彼は、残されたわずかな自由時間を誰も聞いたことのないテクノロジーに費やしています。彼の現在の関心には、オープンソース ソフトウェア、Web サービス、ピアツーピア コンピューティング、および高可用性クラスタリングが含まれます。