読者です 読者をやめる 読者になる 読者になる

前略、PHPとかプログラミングに対して思ってること

PHP

http://webbingstudio.blog10.fc2.com/blog-entry-564.html からはじまり、

と、リアクションが起こってるので、流行に乗って、思ってたことを書いてみた。

そもそも、PHPは何がどう「駄目な言語」なのか

いろんなプログラム言語に対して感じる不満を挙げると、

というリストができあがります。
あれ?最後の「オープンソースのランタイム」について以外、ほとんどに該当しますね。字句構造のレベルでいえば、いろんな言語の嫌なとこ取り言語という感じです。

さらに輪をかけて、PHP独特な欠点は他の言語の追従を許しません(w

  • 言語ランタイムが激しく環境設定に依存し、同じコードが同じ挙動になることを保証できない
  • ↑たとえばショートタグ無効という発想、でも、<?php=...?>はない
  • どの設定項目が何に影響するのかを明確に区分けしていないデザインのまずさ、そして、増えすぎた設定項目
  • 基本APIの実装が場当たり的すぎて、ドキュメントが例外条件まみれ
  • セキュリティリスクのある機能が使いやすすぎる
  • Magic quote GPCやオートグローバルをリリースしたナンセンスさ
  • mb_stringの自動エンコーディング変換
  • モジュールを追加すると、全アプリケーションに無条件にグローバル関数が注入される(普通は、include/require/importしたものだけだよね)
  • 配列と辞書を区別しないという、他に類を見ないぶっとんだデータ構造(辞書機能があれば配列を実装しなくていいという間違った考え)のために、APIの挙動が想像つかない
  • リファレンス代入の設計コンセプトのひどさ、他の言語にないいびつな仕様
  • 配列の代入が参照でなく浅いコピー、文字列がミュータブル、その結果、深い関数呼び出しにおける過剰なスタック消費
  • クラスを定義できるようにしたとき、配列にネイティブなメソッドを実装しなかった----おかげで、引数順序がバラバラのあのarray_シリーズが健在
  • 文字列と数値を型区別しないため、演算子で用途を表す習慣
  • コールバック関数の指定が文字列
  • 等価性の推移性がない、つまり "0"==0 and 0=="" and !(""=="0")
  • htmlspecialcharsスペル長すぎ(w

というわけで、言語としてみればイマイチです。が、PHPは本気のプログラム言語に達していない、「ホームページマクロ」だと思います。ここでけして、PHPがダメなものだと言いたいわけじゃありません。PHPとは、「言語の優劣競争とは違うところにあるもの」だと思います。むしろPHPの良さは、マクロならではの軽快さにあると思うのです。競うこと自体がナンセンス(w

Zendさん自身もたしか以前、「PHPの言語としての側面には興味がない」と自分で言ってたような…。彼ら曰く、PHPとは「Webサーバに膨大な機能をくっつけるための環境」だそうですよ、あらら。言語としてどうすれば良くなるか、考えてないんなら、そりゃまあ、それぞれに特性のある「本当の言語」のどれとも差別化できないよね。

だとすれば、プログラム言語だと思っているPHPというのは、実は、そのZend環境ソフトのマクロ言語でしかなく、VBAとか秀丸マクロとかRPGツクールとか、そういう類のものじゃないか、と思うのです。これでプロプライエタリだったら絶対流行ってないだろうけど、幸いオープンソースだったのが良かったんでしょうね。自分のUnixでコンパイルできない、初代ASPやColdFusionがどうなったかは…以下略。

ただ、PHPオブジェクト指向強化に向かっているのは、本当はちょっとおかしいと思う。PHPが一番うまく動くのは、本当に実行されるコードしか読み込まれず、そのステップが最短記述だったとき。Java/C#なら、JITコンパイル済みの機械語コードがメモリに常駐しているから、その余力を細切れメソッドのたらい回しに使えるけど、PHPだと、巨大オブジェクトの初期化が毎リクエスト起こってたら重くてしょうがない。そんな、プログラム言語に興味のないZendがミスリードした結果できあがったコミュニティの有様こそが、「駄目な言語」の本当の意味じゃないかと思う。

問題がある関数とはどれのことを指すのか

その1:
php.iniで指定できる設定に動作依存するすべての関数。なぜなら、異なる環境に移した瞬間、単体試験の意味がなくなり、コードの完全なポータビリティが保証できないから。.htaccessで変更できない設定値に依存するものは特に問題の度合いが高い。

その2:
ランタイムのバージョンが異なると仕様が変わる関数。マイナーバージョンチェンジでも、平気で関数増えます。もうどのPHP4.xにどの関数があったか、憶えきれません。

その3:
array_*シリーズと配列操作系。
「全員使うもんじゃないんだから、作れよそれぐらい」ってな関数がごろごろある。ないほうがマシな関数もある。なかでも悪名高いのはeach関数。使いどころを間違えると非常に危ないのが、extract関数。
一部の関数は極めて安直な名前がついていて、短命なユーザ定義関数と喧嘩する。本当は配列オブジェクトのメソッドにして欲しいけど、少なくとも、array_*で名前をつけなおし、短い名前の関数はユーザが上書きしてもいいようにすべき。

その4:
セッション。サンプルプログラムとして、

<a href="next.php?<?php echo SID; ?>">次のページ</a>

とあったとき、これを使ってもいい案件の条件をすぐに決められる?
ひとつ解っているのは、行った先のページに任意の外部サイトにリンクする動的要素を入れてはいけないこと。なぜでしょう?
こたえ「外部サイトがリファラーを見てセッションIDを盗めるから」
機能そのものより、「こんなのも選択肢の一つだよ〜」と平気な顔で提供してるのは問題。ヘその態度〜が気に入らないのよ〜♪

その5:
mb_stringによる入出力変数の自動コード変換。文字化け必至、絶対使ってはいけない。

その6:
全体。もう空いてる関数名がありません。自分の関数はクラスのメソッドに逃がすしかない?そのためのオブジェクト指向

PHP演算子が何種類もあるのだが

コメントも何種類もあるのよね。このあたりは、PHP初期開発当時に流行っていた言語の書き方を、何の疑いもなく全部取り入れようとしたせいだと思う。当時はC++Perlプログラマが業界最多数だったから、「どっちの流儀でもいけるようにしよう、同じ中括弧族だもの(本当は全然違う)」ということじゃないだろうか。ちなみに、andとorはSQLではなくPerlに由来するような気がします。

で、ちゃんと言語として設計してないもんだから、こんな間違った実装が修正できないまま「仕様です」になってしまったり…。

$a = 1 && 0;    echo $a; //No output.
$a = (1 and 0); echo $a; //No output.
$a = 1 and 0;   echo $a; //"1" shown, why!?

これ、バージョン5.2.5でも発生。驚きですね。

PHPをDisってるブログエントリを集めてみた - kなんとかの日記 で間違いじゃないことを指摘され、演算子の優先順位の仕様上、これが正しいことを確認しました。PHPの言語仕様のまずさについてのお話は、こっちに続いています。

追記
http://d.hatena.ne.jp/uskz/20080903/p6
こんなのもあります。

なんでPHP以外の言語のアプリケーションは普及しないのか

CGIほどデメリットはなく、かつ、CGI並みにタフだから。あるリクエストがクラッシュしても、次のリクエストや別の機能には何の影響もない。そのうえ、リクエスト応答中でないときは、メモリに残るインスタンスがひとつもない。なので、単一のサーバに、複数のプログラム(すぐに暴走するバグバグなヤツでもOK)を、メモリをどれだけ圧迫するか意識せずに、どんどん詰め込めるんです。常時1つ以上のいずれかのプログラムが実行されていて、CPUが休む間がないぐらい、アクセスが頻度が高くならなければ、ですけどね。CMSの管理画面なんかは、アクセス頻度にキャップがかかってるいい例かも。
アプリケーションサーバ方式は、何も考えずにひたすら「Webコンテンツ」のノリで増やしていくには、あまりにもデリケートすぎるんでしょうね。でも、いくらなんでもCGIは…。
ということで、PHP自体が優れているかどうかに関係なく、PHPはもっとも幅広くユーザをサポートできるために、PHPのアプリケーションが目立つんだと思います。滅多に使わないphpMyAdminのせいで、自分のサーバのメモリを常に数十MB損しているとしたら、イヤでしょ?

コマンドラインを使うのはどうしてなんだろう

自作ツールプログラムのインターフェースをもっとも簡単に実装できるから。しかもそのインターフェースはOSのGUIシステムを問わず、また、リダイレクトとパイプとプロセス生成とを駆使すれば、組み合わせて使えることが保証できるから。さらに、お決まりの手続きをスクリプト化すれば、すぐに同じ操作を何度でも再現できる。それと、短い実験コードを動かす最短ルートでもある。

コマンドラインでのコーディングは、sshでヘッドレスなサーバマシンに接続して、そこでviを使うとか。ローカルファイルで作業するなら、アプリケーション間でコピペができる、GUIテキストエディタを使う。でないとグラフィックソフトとテキストをやり取りできないし。

jEditFTPプラグインを使えば、ftp/sftpを仮想フォルダとしてマウントできるので、sshコンソールでvi使うのを避けることもできる。これはよっぽどの時、たまに使う。

変数名やオブジェクト名はどうやってつけたらいいんだろう

$hensuu とか function kansuu() とかでなければ…。後で読むときに困らないかという配慮が徹底できていれば、あとはチームの好みで。読むとき困らないかを考えるには、過去にコードを読む経験を積んでいることが必須。
プログラムを書くときの名前付けの悩みは、たとえば小説を書くことにたとえれば、「どんな単語を選べばいいんだろう」と問うようなものだと思う。いろんな人が口出しするだろうけど、そもそもが「ここではこう」と決められるようなものじゃなくて、むしろ、頭の中にアイデアがある人自身が、過去にどれだけ小説を読んできたかで決まる。ボキャブラリのセンス。

どの言語でも、デザイナーにフレンドリーなHTMLは出力できるのか

言語、というより、テンプレートエンジンとそのAPIについて問うといいかも。言語と言ってしまうと、print文に根性入れたら何でもできるので。
Tapestry(Java)やGenshi(Python)が、デザイナフレンドリなテンプレートとしてオススメで、改行やインデントの制御が可能なコードタグを書けるという点では、eRubyがいい。