State dichiarando i campi su classi effettivamente dannose in PHP?

11

Considera il seguente codice, in cui il setter viene deliberatamente interrotto a causa di un banale errore di programmazione che ho fatto per davvero alcune volte in passato:

<?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(); 

?>

Il fatto che ho dichiarato $testField nella parte superiore della classe aiuta a nascondere l'errore di programmazione da parte mia. Se non avessi dichiarato il campo, otterrei qualcosa di simile al seguente avviso stampato sul mio log degli errori al momento della chiamata a questo script, che sarebbe potenzialmente utile per aiutare il mio debugging - specialmente se dovessi commettere un errore come questo in una grande e complicata applicazione del mondo reale:

PHP Notice: Undefined property: TestClass::$testField in /var/www/test.php on line 13

Con la dichiarazione, non ci sono avvisi.

Forse mi manca qualcosa, ma sono a conoscenza di due soli motivi per dichiarare i campi di classe in PHP: in primo luogo, che le dichiarazioni fungono da documentazione e, in secondo luogo, che senza dichiarazioni non si possa usare private e protected modificatori di accesso, che sono probabilmente utili. Dal momento che quest'ultimo argomento non si applica ai campi pubblici - l'assegnazione a un campo non dichiarato di un oggetto lo rende pubblico - mi sembra che io debba almeno commentare tutte le mie dichiarazioni di campo pubbliche. I commenti forniranno lo stesso identico valore di documentazione, ma trarrò vantaggio dagli avvisi se provo a leggere un campo non inizializzato.

Ad un ulteriore pensiero, tuttavia, non sembra logico fermarsi lì. Poiché nella mia esperienza il tentativo di leggere un campo non inizializzato è una causa di errore molto più comune che cercare di leggere o modificare in modo inappropriato un campo privato o protetto (ho già fatto il primo più volte nella mia breve carriera di programmatore, ma mai quest'ultimo ), mi sembra che commentare tutte le dichiarazioni di campo - non solo quelle pubbliche - sarebbe la migliore pratica.

Ciò che mi fa esitare è che non ho mai visto nessun altro farlo nel loro codice. Perchè no? C'è un vantaggio nel dichiarare campi di classe di cui non sono a conoscenza? Oppure posso modificare la configurazione di PHP in qualche modo per modificare il comportamento delle dichiarazioni di campo in modo che possa utilizzare le dichiarazioni di campo reali e trarre comunque vantaggio dagli avvisi di "Proprietà indefinita"? O c'è qualcos'altro che mi è mancato nella mia analisi?

    
posta Mark Amery 08.02.2013 - 19:58
fonte

1 risposta

10

Devi sempre dichiarare le tue proprietà di classe in anticipo. Mentre PHP è un linguaggio dinamico e andrà felicemente insieme a te creando le tue proprietà in fase di runtime, ci sono diversi aspetti negativi in questo percorso.

  • Il compilatore può ottimizzare le proprietà dichiarate. Quando dichiari dinamicamente una proprietà, si tratta di un problema di prestazioni poiché il compilatore deve creare una tabella hash dinamica per memorizzare le proprietà dinamiche.
  • Non sono al 100% su questo, ma credo che gli ottimizzatori bytecode come APC non saranno così utili poiché non avranno un quadro completo della tua classe. (E gli ottimizzatori come APC sono devono )
  • Rende il tuo codice 1000x più difficile da leggere. La gente ti odierà.
  • Lo rende 1000 volte più probabile che tu commetta un errore. (Era getId o getID? Wait, hai usato entrambi. Fail.)
  • Nessun completamento automatico IDE o tipo suggerimento.
  • I generatori di documentazione non vedranno la tua proprietà.

Il problema che hai descritto è in realtà minore rispetto al problema di non che dichiara le tue proprietà nella definizione della tua classe. Ecco una buona soluzione.

Abituati a dichiarare i valori predefiniti per le tue proprietà.

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

Ad eccezione delle proprietà che memorizzeranno oggetti, questo coprirà la maggior parte dei tipi di base che verranno memorizzati. Le proprietà che memorizzeranno gli oggetti possono essere impostate nel costruttore.

Una buona regola per la progettazione della classe è che dopo che il tuo oggetto è stato creato e il tuo costruttore è stato eseguito non dovresti avere proprietà "là fuori".

    
risposta data 08.02.2013 - 23:48
fonte

Leggi altre domande sui tag