多くのPHP開発者がisset()および/またはempty()のようなPHPの同様の防御機能の使用を嫌うのはなぜですか?


27

stackoverflowでは、この問題が常に発生します:

でもペッカ(固体PHPのアドバイスの多くを提供しています)恐ろしい突き当てたE_NOTICEモンスターと望んで使用するよりも、よりよい解決策のためにisset()ISSET()と醜い空()メイクコード

個人的には、アプリケーションのフローを管理するために多くの場所で使用isset()empty()ています。例えば:

public function do_something($optional_parameter = NULL) {
    if (!empty($optional_parameter)) {
        // do optional stuff with the contents of $optional_parameter
    }
    // do mandatory stuff
}  

このような単純なスニペットでも:

if (!isset($_REQUEST['form_var'])) {
    // something's missing, do something about it.
}

私には非常に理にかなっています。肥大化しているようには見えず、安定したコードのように見えます。しかし、多くの開発者はをE_NOTICE有効にしてアプリケーションを起動し、多くのフラストレーションのある「初期化されていない配列インデックス」通知を発見し、定義済み変数をチェックしてコードを「ポイ捨て」する見込みに顔をしかめますisset()

他の言語は物事を異なる方法で処理すると思います。経験から言えば、JavaScriptはPHPほど丁寧ではありません。未定義の変数は、通常、スクリプトの実行を停止します。また、(経験不足から言えば)C / C ++のような言語は単にコンパイルを拒否するでしょう。

では、PHP開発者は怠け者ですか?(ペッカ、あなたのことを言っているのではなく、古いアプリケーションをリファクタリングしていることを知っています。)または、他の言語は未定義の変数を、プログラマが定義済みかどうかを最初に確認するよりも優雅に処理しますか?

E_NOTICE未定義の変数以外にも他のメッセージがあることは知っていますが、それらは最も悔しさを引き起こすもののようです)

補遺
これまでの回答から、isset()コードの肥大化はないと考えているのは私だけではありません。だから、私は今、これをエコーする他の言語のプログラマーに問題があるのだろうか?または、これは単にPHPの文化の問題ですか?


4
悲しいことに、「警告」もオフにしてphp開発者が動作するのを見てきました。
Viper_Sb

痛い。それ悲しいです。
スティーブン

1
PHPユーザーではないのですが、なぜ未定義の変数をチェックする必要があるのでしょうか?
ウィンストンイーバート

2
@Winston:(他の多くの言語とは対照的に)PHPの問題は、PHPが多くの構成の組み合わせを許可することです。たとえば、プログラマは、警告、通知、および廃止の通知を無視することを決定できます。より経験豊富な開発者は、error_reportingセットを使用してすべてをレポートします。PHPには、例外をスローするのではなく、エラーをスローしてステータスコードを返す多くの関数もあります。防御的かつ成功してコーディングできるようにするには、言語と非常に親密でなければなりません。他の多くの言語では選択が許可されていません。通常、Strictがデフォルトの唯一のオプションです。
ウィルムーアIII

1
私はisset()が嫌いです。@のよ​​り良い形式は、優れた代替手段です。
クズカイ

回答:


34

私はE_STRICT他に何もコーディングしていません。

emptyおよびissetチェックを使用しても、コードが見苦しくならず、コードがより冗長になります。私の頭の中では、それらを使用することで起こりうる絶対的な最悪のことは何ですか?さらに文字を入力します。

最低限の警告で、それらを使用しないことの結果を比較します。


7
私の開発環境もE_STRICTです。本番環境でのすべてのエラーを抑制しますが、それは開発中に私をすり抜けないようにするためです。
スティーブン

2
+1ジョシュ、私も同じです。あなたはE_STRICTでプログラムするとき、あなたは知っているあなたのコードに驚きを持っているつもりはありませんしていること。飛ぶ唯一の方法、imo。
EricBoersma

3
@Stephen:本番では常にエラーをオフにします。ただし、これは単なる安全策です。開発は常に(IMO)でなければなりませんE_STRICT。コードを記述し、すべての警告とエラーを解決します。
ジョシュK

あなたは私をオウムにしていますか?:)
スティーブン

@スティーブン:同意します。:)
ジョシュK

17

未知の要素に関する通知は、PHPの設計ミスだと思います。私は確かにそれは今間違いを修正することができますないんだけど、それはのような定型コードの多く生成if(isset($foo['abc']) && $foo['abc'] == '123')-このコードはないはず持っているがisset、特定の場所に「123」をありますかどうかを確認することです意図から、$fooそして何もない場合は、それがあります間違いなく '123'ではありません。2倍のコードを記述しなければならない唯一の理由は、この不幸なPHPの設計ミスのためです。また、残念ながらPHPでは通知は非常に高価であるため、パフォーマンスを重視するコードでは、通知を無効にするだけでは選択肢になりません。

それで、はい、それはコードをIMい私見にし、それは私を困らせます。そして、それは経験不足のためではありません-1998年以来PHPを使用していますが、.php3拡張機能があったときのことを覚えています。たぶん私は怠け者です:)しかし、怠laz-少なくとも特定のタイプ-はプログラマにとって美徳です。

一方、issetandの有効な使用はempty、元の投稿と同じように、問題ありません。PHPは、isset/empty本当に必要のない場所での警告については熱心すぎると思います。


3
右。それは冗長性の問題です。 $eg = isset($_GET['eg'])? $_GET['eg'] : null;ばかげて冗長です。「エラー抑制」そのものではない別の演算子があり$eg = @$_GET['eg'];、「この配列キーをnullとして受け入れない」という短い意味に代わることができれば幸いです。私は最近、短い機能を使用する傾向があります。
クズカイ

7
同意した。4年後、Null Coalesceオペレーターを入力してください:wiki.php.net/rfc/isset_ternaryが私たちに与えてくれました$eg = $_GET['eg'] ?? null;
スティーブ14年

または、エラー抑制演算子を使用して今すぐ実行してください$eg = @$_GET['eg'] ?: null;。一般的には使用しませんが、この場合は明示的にそのエラーを予期し、無視することを決定しています。nullの合体よりも1文字長く、あまり良くありません(すべてのエラーを抑制し、ArrayAccessが配列だけでなくファンキーな処理を行う可能性があります)が、一般的には機能します。
エル・ヨボ

12

自由言語としてのPHPは、ウェブ上で解釈され使用されるため、防御的コーディングの必要性を十分に認識しておらず、警告を別の不必要なエラーと見なすプロではない、訓練されていないコーダーの割合が非常に高いと思います。

ジュニア開発者や独学のスクリプトコーダーから次の点を常に聞いています。

  • とにかく存在する変数を初期化するのはなぜですか?
  • 使用する前に何かが存在するかどうかを確認します。未定義はとにかくfalseと同等ですか?
  • @を前に付けてコードを修正すると、なぜ物事が複雑になりますか?

厳密に型指定された言語を一度も経験したことがない、または宣言されていない/インスタンス化されていない変数の落とし穴を経験したことがない場合は、説得力があります。コードをデバッグする喜びを1時間かそこら経験した後、問題を引き起こしている変数名のタイプミスであることがわかると、通常彼らは屈服します。

もう1つの強力な要因は、Web業界でのPHPの使用です。これは、安全性やコード品質よりもスループットにはるかに関心を持つ傾向があります。


10
「PHP [...]はプロではない、訓練されていないコーダーの割合が非常に高いと思います」専用のPHP開発者として、これ以上同意することはできません。+1
スティーブン

@Stephenまあ、私は最近、主にPHPとjQueryでコードを書いていますが、正式な教育を受けていますが、あなたが以前に責任を負うようになった専門家だと思うコードは...信じられないことがあります。;-)
10

1
それはPHPの本当の問題だと思います。言語のいくつかの奇妙な点を除けば(それぞれの新しいバージョンでゆっくりと解決している)、その周りにはアマチュアリズムの空気があります。あなたは「角を曲がった上司のne」と比較されているので、プロのPHP開発者であることは時々イライラすることがあります。
エリック

1
@Erik PHPは10年前にPerlに比べてかなり貧弱な親relativeでしたが、今では特にWebの使用において、かなり合理的なインタープリター言語になっています。Facebookのような企業がそれを使用する理由があります。しかし、それはどこでも利用できるので、アマチュアのセットはそれを広範囲に使用します、そして、これは評判を汚します。
10

5

はい、彼らは怠け者です。とにかく多くの...

残念ながら、多くのPHPコーダーのメンタリティは、「変数の欠落などに起因するエラーを言語に依存することで、同じ最終結果をより迅速に得ることができる場合、防御的にコーディングするポイントはありません」です。私は知っている、私はそれらのいくつかで働いてきました。

彼らはまた、正しいエラー処理とレポートの欠如が数時間ライブサーバーを使い果たしてしまうと、不思議なことに早めの昼食に向かう傾向があります...


5
-1は、PHPコーダーに関する主観的な意見です。
ジョシュK

4
@Joshは、1999年から4年半にわたりシニアPHPコーダーであり、PHPのオン/オフをコーディングしていたため、多少主観的だと思います。「一方で、経験豊富なPHPコーダーは怠け者ではなく、正しく動作します」
...-Gruffputs

1
あなたが持っている必要があります。
ジョシュK

5

データ転送オブジェクトとしての配列の使用を回避することにより、isset()およびempty()の使用を回避しようとしています。適切なデフォルトのプロパティの限られたセットを受け入れ、それらのプロパティへの入力を検証するように構成できるクラスを作成します。ArrayAccessインターフェイスを実装することもできるため、配列のように使用できます。これにより、メソッドシグネチャでタイプヒントを使用して、誰かが間違ったタイプのエンティティをメソッドに渡そうとしたときにエラーをキャッチすることもできます。


非常に興味深いアプローチ。
トビー

2

疑問のある質問の1つは私の質問です。繰り返します。

多くの開発者は、多くのisset()ものの存在を品質サインと間違えています。それは信頼性の外観を与え、一部の人々はそれをセキュリティ機能としてさえ考えます。

ただし、PHPはコンパイルされた言語ではないことを考慮する必要があります。動的型システムを備えたスクリプト言語です。E_NOTICEエラーは名前によるエラーのみです。そして、通知を抑制することをisset唯一の目的として多くが使用されている場合、実際には言語に対してコーディングしているだけです

では、PHP開発者は怠け者ですか?

大量の通知と警告がスローされた場合は、まさにそうです。多くの初心者は通知を気にせず、通常は完全に無効になった結果ですerror_reporting(0)

しかし、他の開発者は@やissetが抑制されていないという理由だけでE_NOTICEを認識していなかったと誤解されています。少なくともそれは通知を保持する質問の背後にある私の意図でした。それらは取り除くものではありませんが、時々重要なデバッグ情報です。

すべての一般化と同様に、issetを慎重に使用しても、最適なコードにはなりません。必要な場所issetempty必要な場所、および構文の塩である場所を区別することが重要です。

または、これは単にPHPの文化の問題ですか?

いいえ、未定義の変数「エラー」はPHPだけの問題ではありません。Bash、TCL、およびPerlまたはJavaScriptでは、未定義の変数を使用できます。ただし、この内在的な言語機能は、欠陥とは見なされません。未定義の値をチェックする同様の言語構成要素があります。ただし、undef値が「エラー」として誤って特徴付けられないため、PHPほど頻繁に使用されません。


1

面白い。私はほとんどisset()を使用しません。私のPHPコードは、変数がそもそも設定されているかどうかわからない状態になることはめったにありません。使用されるすべてのGETまたはPOST変数は、存在しない場合にデフォルトを提供する関数を介してアクセスされます。関数呼び出しのデフォルト値は通常、0または空の文字列に明示的に設定されます。


+1。関数またはクラスのメソッドに渡すのは良い解決策です。私は実際にDOこれを行うが、私の中で上記の例はまだ私にクリーンで非肥大化に見えるピンチ。
スティーブン

0

私はissetとemptyをたくさん使います。しかし、ほとんどの場合、誰かがパラメーターをいじっていた場合に備えて、$ _ REQUEST処理など、あなたが言及する場所です。飛び回るすべての変数を制御できる場合、通常は必要ないことがわかります。


0

私はissetを使うのは好きではありませんが、他の人が大量のコードを実行しているのであれば、それは恩恵になります。この問題を解決するために、以下の簡単なコードを作成しました。改善、歓迎:

//returns var or NULL (if undefined)
//$reserve optional second value is returned as $default if undefined
function isseter(&$default,&$reserve=NULL)
{
$default = isset($default) ? $default : NULL;
$reserve = isset($reserve) ? $reserve : NULL;
if ((!$default) && ($reserve)) $default=$reserve;
return $default;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.