PHP'de sınıflarla ilgili alanların beyan edilmesi aslında zararlı mıdır?


13

Geçmişte birkaç kez gerçekte yaptığım sıradan bir programlama hatası nedeniyle ayarlayıcının kasıtlı olarak kırıldığı aşağıdaki kodu düşünün:

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

?>

$testFieldSınıfın en üstünde ilan ettiğim gerçeği, programlama hatasını benden gizlemeye yardımcı oluyor. Alanı bildirmemiş olsaydım, bu betiği çağırdıktan sonra hata günlüğüme yazdırılan aşağıdaki uyarıya benzer bir şey alırdım, bu da hata ayıklamama yardımcı olmak için değerli olurdu - özellikle de böyle bir hata yapacak olsaydım büyük ve karmaşık bir gerçek dünya uygulaması:

PHP Bildirimi: Tanımsız özellik: TestClass :: 13. Satırda /var/www/test.php dosyasında $ testField

Deklarasyonda uyarı yok.

Belki de bir şey eksik ama PHP sınıf alanları ilan etmek sadece iki nedenden farkındayım: beyanlar bildirimleri kalmadan tek bir kullanamazsınız, ikincisi belgelere görevi görür ve bu, öncelikle privateve protectedvardır erişim düzenleyiciler, tartışmasız faydalı. İkinci argüman kamu alanları için geçerli olmadığından - bir nesnenin kayıt dışı bir alanına atanması onu herkese açık hale getiriyor - bana öyle geliyor ki en azından tüm kamu alanı beyanlarımı yorumlamalıyım. Yorumlar tam olarak aynı belge değerini sağlayacak, ancak başlatılmamış bir alanı okumaya çalışırsam uyarılardan faydalanacağım.

Bununla birlikte, daha fazla düşünce üzerine, orada durmak mantıklı görünmüyor. Deneyimime göre, başlatılmamış bir alanı okumaya çalışmak, özel veya korunan bir alanı uygunsuz bir şekilde okumaya veya değiştirmeye çalışmaktan çok daha yaygın bir hata nedeni olduğundan (eski olanı kısa programlama kariyerimde zaten birkaç kez yaptım, ancak asla ) bana öyle geliyor ki, sadece kamuya açık olanları değil, tüm alan bildirimlerini yorumlamak en iyi uygulama olacaktır.

Beni tereddüt ettiren, kodlarında başka kimsenin bunu yapmadığını hiç görmedim. Neden olmasın? Farkında olmadığım sınıf alanlarını beyan etmenin bir faydası var mı? Ya da gerçek alan bildirimlerini kullanabilmek ve yine de "Tanımsız özellik" uyarılarından yararlanabilmek için PHP'nin yapılandırmasını alan bildirimlerinin davranışını değiştirmek için bir şekilde değiştirebilir miyim? Yoksa analizimde kaçırdığım başka bir şey var mı?


1
Tartışmasız faydalı mı? Belirttiğiniz faydalar son derece önemlidir. Muhtemelen hiç açık mülkiyet bildirimleri vardı kod üzerinde çalışmayı reddediyor .
Michael

2
Gerçekten, kendinizi bu hatalardan korumanın yolu, dikkatli bir hata kontrolü ve daha iyi, birim testi ile.
Michael

1
Eğer bir değişken ilk bildirmeden kullanırsanız size söyleyecek yerleşik php hata raporlama (bir bildirim seviyesi) vardır.
Crayon Violent

3
@MarkAmery Ben çılgınca tempolu başlangıç sıkı birim test benimsemek en önemli yerler arasında bulunuyor düşünürdüm - Hep kodu değiştirirken beri, büyük olasılıkla her zaman konum kırarak onu. Bu, sıkı testlerin ve TDD'nin bitirilmesinin tam amacıdır. Evet, sanırım alt çizgi kullanmak, özel şeylere eriştiğinizi hatırlamanıza yardımcı olabilir, ancak benim için, hata yapmamam gereken hatalardan korunmak için belirli kodlama standartlarını benimseme fikri rahatsız edici. TRUE === $variableKendinizi, karşılaştırma yapmak yerine yanlışlıkla atamaktan alıkoymak gibi .
Michael

1
@MarkAmery Ayrıca, görünürlük anahtar kelimelerinin otomatik dokümantasyon araçları tarafından ayrıştırıldığını unutmayın , bu nedenle manuel olarak gireceğiniz bir yorumdan daha fazla "dokümantasyon değeri" verirler.
Michael

Yanıtlar:


15

Sınıf özelliklerinizi daima önceden bildirmelisiniz. PHP dinamik bir dildir ve çalışma zamanında özelliklerinizi oluştururken sizinle birlikte mutlu bir şekilde gidecek olsa da, bu yolun birkaç dezavantajı vardır.

  • Derleyici bildirilen özellikleri optimize edebilir. Bir özelliği dinamik olarak bildirdiğinizde, derleyicinin dinamik özelliklerinizi depolamak için dinamik bir karma tablo oluşturması gerektiğinden bu bir performans isabeti olur.
  • Bu konuda% 100 değilim ama APC gibi bayt kodu optimize edicilerinin sınıfınızın tam bir resmine sahip olmayacakları için yararlı olmayacağına inanıyorum. (Ve APC gibi optimize bir olan zorunluluk )
  • Kodunuzun okunmasını 1000 kat zorlaştırır. İnsanlar senden nefret edecek.
  • Daha olası olduğunu 1000x yapar Eğer bir hata yapacak. (GetId mi getID mi? Bekle, ikisini de kullandın. Başarısız.)
  • IDE otomatik tamamlama veya tür ipucu yok.
  • Belge oluşturucular mülkünüzü görmez.

Tarif ettiğiniz sorun aslında sorununa karşılaştırıldığında küçük bir tanesidir değil sınıf tanımında Mülklerinizi bildirerek. İşte iyi bir çözüm.

Mülkleriniz için varsayılanları bildirmeye alışın.

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

Nesneleri depolayacak özellikler dışında, bu, depolayacağınız temel türlerin çoğunu kapsayacaktır. Nesneleri saklayacak özellikler yapıcıda ayarlanabilir.

Sınıf tasarımı için iyi bir kural, nesneniz oluşturulduktan ve yapıcı çalıştıktan sonra orada "tanımsız" herhangi bir özellik olmamalıdır.


5 olumsuz tarafınıza yanıt olarak: 1 (Performans): Bunun için bir kaynağınız var mı? 2 (Okunabilirlik): Anladığımdan emin değilim; öneri, sadece kaldırmakla kalmayıp aynı zamanda okunabilirliği kaybolan bildirimleri yorumlamaktı. Biraz daha az kolay sözdizimi vurgulama ve komşu yorumlardan ayırt etme potansiyel zorluk sanırım? 3: Bu hiç anlamadım; Açıklayabilir misin? 4 (IDE'ler): Yeterince adil - PHP'yi bir IDE ile kodlama deneyimim yok ve Eclipse'nin tip ipucunu bilmiyordum. 5 (doktor jeneratörleri): Yeterince adil - bunlardan hiç birini kullanmadım.
Mark Amery

Onlara yorum yapma konusunda çizginizi görmedim. Ne olursa olsun, yukarıdaki noktalar hala geçerlidir - hangilerinin aktif veya yasal olarak yorumlandığını nereden biliyorsunuz?
Jarrod Nettles

Önerilen çözümünüze yanıt olarak: tam olarak kaçınmak istediğim şey budur - anlamsız olsalar bile varsayılanların atanması ve varsayılan değerler asla kullanılmamalıdır. Bu varsayılanlarla (ve yalnızca boş atayan atama olmadan bildirimle) sorun, bir programlama hatası nedeniyle, yapmam gerektiğinde yapıcıdaki bir şeye bir değer atamazsam, PHP yerine bir Bu değeri daha sonra kullanmaya çalıştığımda uyarı - hatamı bulmama yardım et - sınıf kırılmış olsa bile her şey yolunda görünecek.
Mark Amery

2
@MarkAmery Programlama hatanız aslında bir yazım hatası anlamına gelir. Hepimiz onlara sahibiz - ama burada bir sineği öldürmek için bomba patlatmaya çalışıyorsunuz.
Jarrod Nettles

Haklı olabilirsin. Böyle bir yazım hatası tamamen neden olduğu ortaya çıktı bugün bir hata izini birkaç saat geçirdi ve sadece olsaydın o ani gerçekleşme tarafından sonradan hayal kırıklığına uğradım kullanılmaz saha bildirimleri, bildirim var ve olurdu hatamın nerede olduğu hemen bilinir (ki bu şartlarda her zaman olacağını düşünürdüm; alanları null olarak başlattığı bildirimlerini fark etmedim). Bu deneyimin anında erişilebilirliği muhtemelen nüksetme olasılığının veya savunmanın ne kadar değerli olduğuyla ilgili kararımı çarpıtmaktadır.
Mark Amery

2

Dinamik olarak oluşturulan nesne özelliklerini kullanan bazı kodlar üzerinde çalıştım. Dinamik olarak oluşturulmuş nesne özelliklerini kullanmanın oldukça güzel olduğunu düşünüyorum (doğru, bence). Ancak, programımın çalışması 7 saniye sürdü. Dinamik nesne özelliklerini kaldırdım ve her sınıfın bir parçası olarak bildirilen nesne özelliklerini değiştirdim (bu durumda genel). CPU süresi 7 saniyeden 0.177 saniyeye çıktı. Bu oldukça önemli.

Dinamik nesne özelliklerini kullanma biçimimde yanlış bir şey yapmam mümkün olabilir. Yapılandırmamın bir şekilde bozuk olması da mümkündür. Tabii ki, makinemde çok sade bir vanilya PHP yapılandırması olduğunu söylemeliyim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.