kなんとかの日記 このページをアンテナに追加

2009-11-29

PHPの言語仕様がウンコな理由個人的トップ10

| 09:49 |  PHPの言語仕様がウンコな理由個人的トップ10を含むブックマーク

「PHPerの問題点はPHPしか知らずに的外れなことを言うことだ」と、Javaしか知らなくて的外れなことを言っている連中にすら言われちゃってるPHPerのみなさん、こんにちは。

PHPは「使える道具」であることは事実です。しかし同時に言語仕様がウンコなのも事実。

ここでは、個人的にウンコだと思っているPHPの仕様を挙げてみたよ!



htmlspecialchars() の名前が長すぎる

これはほんとウンコ。おまえWebアプリのための言語やろが!なんでこの関数の名前がこんなに長いねん!こんだけ長かったらめんどくさがって echo $var としてまうやろが!WordPressのthemeでHTMLエスケープ忘れが多いのはおまえの名前が長すぎるせいだ!

そんなわけで、全PHPerはこんな関数を定義するといいと思うよ。

## echo $var; よりも短く h($var); と書ける!
function h($arg) {
  echo htmlspecialchars($arg);
  # or echo htmlspecialchars($arg, ENT_QUOTES);
}

やっぱり安全なほうは短く簡潔に、安全じゃないほうは長くめんどくさくなるようにすべきだよね。


try-catch はあるくせに finally がない

意味分からん。finallyないと例外処理の魅力が半減してまうやん。PHP開発陣は何を考えているんだろうか。

finallyを実装するのってそんなに難しいの?


ほとんどの関数がエラー時に例外を投げない

最初から例外機構がなかった言語なんだからどうしようもない。せっかくtry-catchがありながら、未だに関数戻り値をチェックしなければいけないんだから、ウンコだよなあ。


配列がListとMapの両方を兼ねている

これはawkとかを真似たんだろうけど、はっきりいって失敗。この仕様のせいで、たとえばソート関数がごちゃごちゃになっているし、そもそもreadabilityが低くなっている。

## listとして使おうとしているのか、それともmapとして
## 使おうとしているのか、あとのコードを見ないとわからない。
## (つまりreadabilityが低い)
$arr = array();

'&&' や '||' の評価結果が必ず TRUE または FALSE

これはなんでこんな仕様にしたんだろうなあ。これじゃあまるでJavaじゃないか。

## たとえば他のスクリプト言語ならこう書けるのに
$tmpdir = $ENV{TEMP} || $ENV{TMP} || '/tmp';     # Perl
$tmpdir = $ENV['TEMP'] || $ENV['TMP'] || '/tmp'  # Ruby
e = os.environ; tmpdir = e.get('TEMP') or e.get('TMP') or '/tmp' # Python
## PHPだとこうですよ。まるでJavaのようなめんどくささですよ。
$tmpdir = $ENV['TEMP'];
if (! $tmpdir) $tmpdir = $ENV['TMP'];
if (! $tmpdir) $tmpdir = '/tmp';
## 5.3からはこう書けるけど、もっと早くに登場してほしかった。
## これ使ってコード書くのが許されるようになるのは、少なくとも2年後だろう。
$tmpdir = $ENV['TEMP'] ?: $ENV['TMP'] ?: '/tmp';

静的言語なら論理式の結果を強制的にbooleanにする意味はわからんでもないけどさ、動的言語PHPではあんまり意味ないだろ。


三項演算子の結合規則が変

## たとえばこんなのがあったとして、
$x = 1;
$v = $x > 0 ? 'positive' :
     $x < 0 ? 'negative' :
              'zero';

## これはふつう、こうだと期待する (し、他の言語ではそう動作する)
$v = $x > 0 ? 'positive' : ($x < 0 ? 'negative' : 'zero');

## しかぁし、ウンコなPHPではこう評価される
$v = ($x > 0 ? 'positive' : $x < 0) ? 'negative' : 'zero';

## 実行結果は 'negative'。おかしいやろ?
echo $v;

すごい素人くせー仕様。


(new ClassName())->method() ができない

これ、どういう理由があってこうなっているんだろう?こういう*意味不明な制約*が、PHPがウンコな原因なんだよな。


配列の作成がarray()

おまえそれでもスクリプト言語か!とっとと [ ] を導入しろや!

## これはださい
echo tag('input', array('name'=>'name', 'type'=>'text'));
## これならまだ許せる
echo tag('input', ['name'=>'name', 'type'=>'text']);

できれば [ ] と { } の両方を導入してくれるとreadabilidyが上がるんですけど、無理ですかそうですか。

$arr = ['A', 'B', 'C'];     ## これはlistとして使う配列
$arr = {'A'=>10, 'B'=>20};  ## これはmapとして使う配列
$arr = array(10, 'B'=>20);  ## これは混在させて使う配列

存在しないキーを使って配列アクセスするとwarning

error_reporting(E_ALL);
$arr = array('A'=>123);
$val = $arr['B'];   #=> Notice: Undefined index

これなあ。気持ちはわかるんだけど、だったらnoticeが出なくてかつ簡単にアクセスできる方法を用意してほしいよね、Pythonのdict.get()のように。

## めんどくせー
$val = isset($arr['B']) ? $arr['B'] : NULL;
## 動作おせー
$val = @$arr['B'];

関数名がいいかげんすぎ

歴史的な理由があるにせよ、PHP関数名は統一感がなくて残念。その残念な仕様を立派なドキュメントでカバーしているから、みんなあんまり文句言わないんだろうけど。

今からでも遅くないから、文字列関連はstr_xxx()、配列関連はarr_xxx()で統一してくれればいいんだけどな。

あー、array_xxx()は長いから却下したい。


配列を代入したらコピーされる

んー、これは慣れといえば慣れなんかもしれん。でもなあ、コンテナの挙動がデフォルトで丸ごとコピーってのはどうなん?コンテナであるはずの配列スカラー値のような扱いにしてほしくないんだよね。

配列が勝手にコピーされて嬉しかったことなんか一度もないや。


and や or のあとに throw が置けない

つまりだな、「式 or die()」はOKなのに「式 or throw new Exception()」はNGっつーのが残念なんだよね。たぶんthrowは文であって式じゃないからなんだろうけどさ。

## こういうのを
$user = User::get_by_id(123);
if (! $user) throw new Exception("123: not found.");
## こう書きたい
$user = User::get_by_id(123)  or
    throw new Exception("123: not found.");
## こうだとエラー行番号がずれるし。
function raise($errclass, $errmsg) {
    throw new $errclass($errmsg);
}
$user = User::get_by_id(123)  or
    raise('Exception', "123: not found.");

でもまあこれでウンコ呼ばわりするのはちょっと言い過ぎか。


配列関数の第1引数配列じゃない

array_xxx()の第1引数配列じゃないっていうのは何か理由があるのかな。配列を対象とした関数なんだから、それを第1引数にしてほしいんだけど。


クロージャがない(なかった)

なくてもなんとかなるのも確かだけど、あったほうがずいぶん楽なのも確か。

個人的には function() { return ; } は長すぎて読むのも書くのも楽じゃないので、もっと簡潔に書ける記法が良かった。

## JavaScriptでもそうなんだけど、これって読みにくくね?
$users = arr_sort_by(User::find_all(),
                     function($user) { return $user->name; })
## これに関してはやっぱりRubyが書きやすく読みやすい
users = User.find_all().sort_by {|user| user.name }

 * * * * *


10個じゃ足りんかったね。なんかほかにもあった気がするけど、忘れた。思い出したら追記するかも。

あと繰り返すけど、「言語仕様の優劣」と「道具としての優劣」は別の話だからね。いい言語仕様だからといって必ずしもいい道具なわけではないし、ましてやいいアプリケーションが生まれるわけでもない。

  • PHPは言語仕様がウンコだけど、ドキュメントはすごく頑張ってるし、道具としてはけっこう使い物になる (使い道を間違えなければ)。
  • Rubyの言語仕様はすごくいいけど、cgi.rbがアレだし、ドキュメントにはサンプルコードが少ないし、実は初心者にとっては厳しい道具かも。
  • Pythonの言語仕様もすごくいいけど、標準ライブラリにはセッション機能が欠けてるし、プロセス起動がかなり重いし、import cgiはトロいしで、レンタルサーバでちょろっとCGI作りたいときにはあんまり向かない道具だよな。
  • Javaはheavyでwordyな言語仕様だけど、EclipseXMLDIコンテナとHotDeployとSAStrutsを使えばスクリプト言語よりもLightweightな道具だよ!

  ・・・と、スクリプト言語をろくに知らない人間が主張してたりしてなかったり。

#いやおまえ、その前提条件からしてLightweightじゃないことに気づけよ。

pp 2009/11/29 13:17 これも嫌ですね。

class Foo {
const DIR_OK='./bar'; // ok
const DIR_NG=dirname(__FILE__).'/bar'; // error
const DIR_NG2='.'.DIRECTORY_SEPARATOR.'bar'; // error

function baz_ok($arg='./bar'){} // ok

function baz_ng($arg=self::DIR_OK){} // error
function baz_ng_repair($arg=null){ // ↑これはこう書かなきゃいけない
if(is_null($arg)){$arg = self::DIR_OK; }
}
}

ko1kunko1kun 2009/11/29 17:37 そうですね、言語仕様もそうだけど、脳みそがウンコになる言語ですね。
Java、Oracle、Linuxなどのように、PHPプログラマ認定試験ができたら、その中でも一番難易度が高い試験になるかも知れませんね。言語仕様がひどすぎて。

groundground 2009/11/29 18:00 > 配列関数の第1引数が配列じゃない
についてですが、Pythonでもmapとか最後ですよ?
あと、PHPは言語はダメだけど環境としてはとても良いです。

どようびどようび 2009/11/29 19:57 htmlspecialcharsにENT_QUOTESが必須なうんこ仕様の件はもうあたりまえ過ぎて書く必要もないとwwwwwww
あと名前空間の解決が\になっちゃったのは日本人的にはうんこっすねー

nursenurse 2009/12/01 01:46 arrayの略語はaryがいいなー

sisyasisya 2009/12/02 14:01 もう書くまでも無いのかもだけど、「echo strlen(array()); の結果が5になる」とかは、恥ずかしくて死にそうになります。

tanakahisaterutanakahisateru 2009/12/03 18:56 変数の名前は大文字小文字区別するけど、関数やメソッドだと、TostRing()とtoString()が等価だったりするくせに、標準APIのネーミングがJavaっぽくなってきたのはそろそろ勘弁して欲しいです。

tanakahisaterutanakahisateru 2009/12/03 19:04 横槍ですいません、上の echo strlen(array()); は int strlen(obj) { return obj.toString().length; } みたいな実装だろうから、まあ妥当じゃないかとも思いました。

berobero 2009/12/07 17:11 htmlspecialcharsは文字コードを指定しないと日本語ではデータが腐ります。
その意味でも(アプリ共通の文字コードを内部で指定する)ラッパ関数はふつーに必要ですね

aaaaaa 2010/12/29 15:58 うんこは、お前だろwwwww

aaaaaa 2010/12/29 15:58 うんこは、お前だろwwwww

aaaaaa 2010/12/29 15:58 うんこは、お前だろwwwww

aaaaaaaa 2010/12/29 15:58 うんこは、お前だろwwwww

aaaaaaaaaa 2011/01/05 15:14 確かに、うんこはお前だなwwwww