PHPでクラスのフィールドを宣言することは実際に有害ですか?


12

次のコードを考えてみましょう。セッターは、過去に何度か実際に行ったプログラミングエラーのために意図的に壊れています。

<?php

    class TestClass {

        private $testField;

        function setField($newVal) {
            $testField = $newVal;
            // deliberately broken; should be `$this->testField = $newVal`
        }

        function getField() {
            return $this->testField;
        }

    }

    $testInstance = new TestClass();
    $testInstance->setField("Hello world!");

    // Actually prints nothing; getField() returns null
    echo $testInstance->getField(); 

?>

$testFieldクラスのトップで宣言したという事実は、そのプログラミングエラーを隠すのに役立ちます。フィールドを宣言していなかった場合、このスクリプトを呼び出すとエラーログに次の警告に似たものが出力されます。これは、デバッグを支援するのに役立つ可能性があります。大規模で複雑な実世界のアプリケーション:

PHP Notice:未定義のプロパティ:13行目の/var/www/test.phpのTestClass :: $ testField

宣言では、警告はありません。

おそらく何かが足りないかもしれませんが、PHPでクラスフィールドを宣言する理由は2つしかありません。1つ目は宣言がドキュメントとして機能すること、2つ目は宣言なしではprivateand protectedアクセス修飾子を使用できないことです。間違いなく便利です。後者の引数はパブリックフィールドには適用されないため(オブジェクトの宣言されていないフィールドに割り当てるとオブジェクトがパブリックになります)、少なくともすべてのパブリックフィールド宣言をコメントアウトする必要があるように思えます。コメントはまったく同じドキュメント値を提供しますが、初期化されていないフィールドを読み取ろうとすると警告が表示されます。

しかし、さらに考えてみると、そこで停止するのは意味がないようです。私の経験では、初期化されていないフィールドを読み取ろうとすることは、プライベートまたは保護されたフィールドを不適切に読み取ったり変更しようとするよりもはるかに一般的なエラーの原因であるためです)、それはすべてのフィールド宣言をコメントアウトするように見えます-パブリック宣言だけでなく-ベストプラクティスになるでしょう。

私がためらうのは、コードで他の誰もそれをやったことがないということです。何故なの?私が知らないクラスフィールドを宣言することに利点はありますか?または、PHPの構成を何らかの方法で変更してフィールド宣言の動作を変更し、実際のフィールド宣言を使用し、「未定義のプロパティ」警告の恩恵を受けることができますか?または、分析で見逃したことは他にありますか?


1
間違いなく便利ですか?あなたが述べた利点は非常に重要です。私はおそらく、明示的なプロパティ宣言を持たないコードの作業をきっぱりと拒否するでしょう。
マイケル

2
本当に、これらのエラーから身を守る方法は、ユニットテストを介して、慎重にエラーをチェックすることです。
マイケル

1
事前に宣言せずに変数を使用するかどうかを通知するPHPエラー報告(通知レベル)が組み込まれています。
クレヨン暴力

3
@MarkAmery激しいペースのスタートアップは、厳密なユニットテストを採用する最も重要な場所の1つだと思います。常にコードを変更しているため、常に壊れている可能性があります。それが、厳密なテストとフラットなTDDのまさに正確な目的です。ええ、アンダースコアを使用すると、プライベートなものにアクセスしていることを思い出すのに役立つかもしれませんが、特定のコーディング標準を採用してエラーを防ぐことは私にとって不安です。やっようなTRUE === $variable誤って割り当てる代わりの比較から自分を防ぐために。
マイケル

1
@MarkAmeryまた、可視性キーワードは自動ドキュメンテーションツールによって解析されるため、手動で入力する単なるコメントよりも多くの「ドキュメンテーション値」を提供することに注意してください。
マイケル

回答:


14

クラスプロパティは常に事前に宣言する必要があります。PHPは動的言語であり、実行時にプロパティを作成するとうまくいきますが、このパスにはいくつかの欠点があります。

  • コンパイラは宣言されたプロパティを最適化できます。動的にプロパティを宣言すると、コンパイラは動的なプロパティを保存するために動的なハッシュテーブルを作成する必要があるため、これはパフォーマンスヒットになります。
  • 私はこれについて100%ではありませんが、APCのようなバイトコードオプティマイザーはクラスの全体像を把握できないため、それほど有用ではないと考えています。(APCのようなオプティマイザーは必須です
  • コードを1000倍読みにくくします。人々はあなたを嫌います。
  • 間違いを犯す可能性が1000倍高くなります。(getIdまたはgetIDでしたか?待って、両方を使用しました。失敗します。)
  • IDEのオートコンプリートやタイプヒンティングはありません。
  • ドキュメントジェネレーターには、プロパティは表示されません。

説明した問題は、クラス定義でプロパティを宣言しない問題と比較すると、実際には小さな問題です。これが良い解決策です。

プロパティのデフォルトの宣言に慣れます。

private $testField = null;
private $testField = '';
private $testField = 0;
private $testField = []; //array()
private $testField = false;

オブジェクトを保存するプロパティを除いて、これは保存する基本タイプの大部分をカバーします。オブジェクトを保存するプロパティは、コンストラクターで設定できます。

クラス設計の良いルールは、オブジェクトが作成され、コンストラクターが実行された後は、「未定義」のプロパティはないはずです。


5つのマイナス面への対応:1(パフォーマンス):これのソースはありますか?2(読みやすさ):わかりません。提案は、宣言を削除するだけでなく、コメントをコメントアウトするためのものだったので、どのような読みやすさが失われましたか?ややわかりにくい構文強調表示と、隣接するコメントとの区別が困難になる可能性があると思いますか?3:これはまったくわかりません。明確にできますか?4(IDE):結構です-私はIDEでPHPをコーディングした経験がなく、Eclipseの型ヒントについても知りませんでした。5(ドキュメントジェネレータ):十分-これらのいずれも使用したことはありません。
マークアメリー

コメントアウトについてのあなたの意見は見ませんでした。とにかく、上記のポイントはまだ適用されます-どのポイントがアクティブであるか、または正当にコメントアウトされているかをどのようにして知るのですか??
ジャロッドネトルズ

提案されたソリューションへの応答:これはまさに避けたいものです-デフォルトの割り当ては無意味であり、デフォルト値を使用しないでください。これらのデフォルトの問題(およびnullを割り当てるだけの代入なしの宣言)の問題は、プログラミングのミスにより、必要なときにコンストラクタ内の何かに値を割り当てない場合、PHPではなく後でその値を使用しようとすると警告が表示されます-エラーを見つけるのに役立ちます-クラスが壊れていてもすべてが正常に動作するようです。
マークアメリー

2
@MarkAmeryしかし、あなたのプログラミングの間違いは、本質的にタイプミスです。私たちは皆それらを持っています-しかし、あなたはここでハエを殺すために爆弾を爆発させようとしています。
ジャロッドネトルズ

君の言う通りかもね。このようなタイプミスが原因であることが判明したバグを今日数時間かけて追跡しましたが、その後フィールド宣言を使用しないと通知を受け取るという突然の認識にイライラしました。私のエラーがどこにあるのかすぐにわかりました(とにかく、これらの状況では常に起こると思っていました;宣言がnullに初期化された宣言を認識していませんでした)。その経験の即時のアクセシビリティは、おそらくそれが再発する可能性が高いか、または防御する価値があるという私の判断をゆがめています。
マークアメリー

2

動的に作成されたオブジェクトプロパティを使用するコードに取り組みました。動的に作成されたオブジェクトプロパティを使用するのはかなりクールだと思いました(私の意見では本当です)。ただし、プログラムの実行には7秒かかりました。動的オブジェクトプロパティを削除し、各クラス(この場合はpublic)の一部として宣言されたオブジェクトプロパティを置き換えました。CPU時間は7秒以上から0.177秒になりました。それはかなり重要です。

動的オブジェクトプロパティの使用方法で何か間違ったことをしていた可能性があります。私の設定が何らかの形で壊れている可能性もあります。もちろん、私は自分のマシン上で非常に単純なPHP構成を持っていると言う必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.