PHP organize Sınıflar

8 Cevap php

Ben projemde aşağıdaki sınıfları ettik varsayalım:

  • class Is / / valkimlikation class
  • class Math / / number manipulation class

Ben primality için verilen bir sayıyı doğrulamak istiyorsanız Şimdi, nerede Prime () yöntemini eklemek için mantıklı bir yer olurdu? Ben aşağıdaki seçeneklerden düşünebilirsiniz:

  • Is_Math :: Prime ()
  • Math_Is :: Prime ()

Ben yavaş benim düşünme süreci aşağı, bu belirsizlikleri nefret ve hataları sık sık beni neden. Bazı örnekleri:

  • :: Image () veya Görüntü :: (IS)?
  • Is_Image :: PNG () veya Image_Is :: PNG (?)
  • Is_i18n_US::ZipCode() or i18n_Is_US::ZipCode() or i18n_US_Is::ZipCode() ?

I18n örnekte ben sonuncuyu tercih ederken Görüntü örnekte ilk tercihi bana daha mantıklı. Bir stveart sahip değil bütün kod tabanı dağınık gibi hissettiriyor.

Is there a holy grail solution for organizing classes? Maybe a different paradigm?

8 Cevap

Ben hiç belirsiz olduğunu sanmıyorum. Bu örneklerin her birinde birinci olmalı mı "", ve neden ben size söyleyeyim: Matematik üyesi :: mi hangi doğrulama işlemleri superset "mı".

Is :: Matematik durumunda, ne yapıyorsun? Eğer matematik işlemleri yapıyor musunuz? Yoksa matematiksel objeleri doğrulayarak edilir? İkincisi, tabii ki, aksi takdirde sadece "Matematik" olurdu.

Bu iki operasyon hangisi daha büyük kapsamı vardır? Mı? Yoksa Matematik mi? Matematik Matematik belirli ise Is, birçok sivil-Matematik kurumlara kavramsal geçerlidir, çünkü belli ki,. (Math Faktör ait olan üst kümesidir çünkü Aynı şekilde Math :: Factor durumunda, bu, Faktör :: Math olmaz.)

OOPing bu tür bütün amacı mantıklı bir şekilde, grup şeyler etmektir. Onlar (PNG resim vs Asal sayılar) varlıklar çılgınca farklı uygulamak bile doğrulama işlevleri, onlar karşılaştırdığınız şeyler yapmak daha birbirlerine daha benzerlikler var. Onlar aynı veri tiplerini dönecektir, onlar durumların aynı tür denir.

Bir numara Math sınıfında asal olup olmadığını Matematik Örneğin, kontrol gerçek işlevini koymak istiyorum. Lütfen Is sınıfında bir doğrulama gerçekleşmesi için gereken zaman denebilecek bir yöntem koymak istiyorsunuz. Daha sonra oradan Math::Prime() kullanmak istiyorsunuz.

Image ile, bu tip çek bulunuyor. Emin geçerli bir resim veri yüklendi yapıyoruz sürece muhtemelen bunun için bir yöntem yapmak gerekmez.

Ile aynı PNG yöntemi ile, Math. Image gerçek PNG veri denetimi algoritması koyun ve Is diyoruz daki onaylayıcı yöntemi yapmak.

Posta kodu örnek, (okumak sadece bir regexpi kullanacak muhtemelen ilkel ve bir dize üzerinde çalışır yalnızca beri Is sınıfta olmalıdır: karmaşık bir yöntem olmayacak, PNG denetimi aksine hangi muhtemelen olacaktır ) olacak.

SRP saygı istiyorsanız (http://en.wikipedia.org/wiki/Single_responsibility_principle), küçük alıştırmayı yapın:

Sınıfınızı seçiniz ve / yapabileceği ne yaptığını açıklamak için deneyin. If you have an "AND" in your description, you must move the method to an other class.

Sayfa 36: http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf

Diğer Hukuku (çok fazla var) size sınıfları düzenlemenize yardımcı olacaktır: Demeter Hukuku (http://en.wikipedia.org/wiki/Law_of_Demeter).

Bir şey öğrenmek ve doğru seçimi yapmanıza yardımcı olmak için, sana MISKO blogu (A google evangelist) tavsiye: http://misko.hevery.com

Umarım bu yardımcı olur.

: handling validation in itself sizin Is-sınıflara uyabilecek hakkında herşey

  • O geçmek mi?
  • Hangi parçalar geçemedi?
  • Doğrulama hataları yere açmış olmalı?

Zend_Validate Zend Framework belki ondan biraz ilham alabilir, böyle bir yaklaşım sağlar. Bu yaklaşım, tüm doğrulama-sınıflarında aynı arayüzü uygulayan olurdu beri, kolayca olabilir

  • doğrulama için aynı sözdizimini kullanır, bağımsız olarak hangi veriler doğrulandıktan
  • kolayca Is_Prime adında tüm sınıflar, Is_Image için kontrol yerine Math_Is, Image_Is her yerinde denetleyerek kullanılabilir hangi doğrulama kuralları tanımıyor yer.

Edit:
Why not use a syntax like this:

class Math {
    public function isPrime() {
        $validation_rule = new Is_Prime();
        return (bool) $validation_rule->validates($this->getValue());
    }
}

Ve böylece de izin verir

class Problem {
    public function solveProblem(Math $math) {
        $validation_rule = new Is_Prime();
        if($validation_rule->validates($math->getValue())) {
            return $this->handlePrime($math);
        } else {
            return $this->handleNonPrime($math);
        }
    }
}

Ben hayır belirtilen soruna "Doğru Cevap" olduğunu düşünüyorum. Bazı insanlar Matematik İş'in de Prime koymak ve bazı olacak. Belirsizlik var. Aksi takdirde bu soruyu soran olmaz.

Şimdi, bir şekilde belirsizliği çözmek zorunda. Sen sınıf / metodu nereye gider, hangi söyleyebilirim bazı kuralları ve sözleşmeler hakkında düşünebilirsiniz. Kurallar her zaman açık değildir, ve çok karmaşık hale gelebilir, ve o noktada artık yararlı konum olarak Ama bu, kırılgan olabilir.

I'd suggest that you design the classes so that it's obvious by looking at the names where some method should go.

Doğrulama paketi mi bir isim yok. Neredeyse her şey gider böylece genel isim. IsFile, IsImage, IsLocked, IsAvailable, IsFull - Tamam, iyi gelmiyor? Hiçbir cohesion bu tasarım ile vardır.

(Eğer güvenlik ve iş kurallarını uygulamak zorunda olduğu) alt sınırından doğrulama bileşeni filtre veri yapmak için muhtemelen daha iyi, başka bir şey.

Bu karar yaptıktan sonra, örnek belirginleşmektedir. Başbakan Matematik aittir. :: Resim muhtemelen çok genel olduğunu. Muhtemelen de bir resim (daha fazla uyum) çalışan başka yöntemler var olacak çünkü ben, Görüntü :: isValid tercih ederim. Otherwise "Is" becomes a bag for everything, ben başında söylediğim gibi.

Ben de tüm sınıf isimleri aittir "olduğunu" düşünmüyorum. Ben bu yöntemleri için olduğunu düşünüyorum.

abstract class Validator {}

class Math_Validator extends Validator
{
  public static function isPrime( $number )
  {
    // whatever
  }
}

class I18N_US_Validator extends Validator
{
  public static function isZipCode( $input )
  {
    // whatever
  }
}

class Image_Validator extends Validator
{
  public static function isPng( $path )
  {
    // whatever
  }
}

Math_Validator::isPrime( 1 );
I18N_US_Validator::isZipCode( '90210' );
Image_Validator::isPng( '/path/to/image.png' );

Sınıfları düzenlemek için bir kutsal kase çözüm var mı? Belki farklı bir paradigma?

Hayır, bu sınıf temelli oop temel bir kusurdur. Bu öznel.

Fonksiyonel programlama (prosedürel programlama ile karıştırılmamalıdır) temel yapı taşları çok daha küçüktür, çünkü çoğunlukla bu madde ile daha az sorunları var. Sınıfsız oop de oop ve türlü fonksiyonel programlama bir melez olmanın, daha iyi fırsatlar.

Sınıflar kendilerini doğrulayarak gibi şeyler fantezi türleri olarak kabul edilebilir.

abstract class ValidatingType 
{
  protected $val;
  public function __construct($val)
  {
     if(!self::isValid($val))
     {  // complain, perhaps by throwing exception
        throw new Exception("No, you can't do that!");
     }
     $this->val = $val;

  }
  abstract static protected function isValid($val);
}

Biz bir doğrulama türü oluşturmak için ValidatingType uzanır. Bu bir isValid yöntemi oluşturmak için bize zorlamaktadır.

class ValidatingNumber extends ValidatingType
{
   ...
   static protected function isValid($val)
   {
      return is_numeric($val);
   }
}

class ValidatingPrimeNumber extends ValidatingNumber
{
   /*
    * If your PHP doesn't have late-binding statics, then don't make the abstract 
    * or overridden methods isValid() static.
    */
   static protected function isValid($val)
   {
      return parent::isValid($val) 
             or self::isPrime($val); // defined separately
   }
}

class ValidatingImage extends ValidatingType
{
   ...
   static protected function isValid($val)
   {
      // figure it out, return boolean
   }
}

Bu yaklaşımın bir avantajı yeni doğrulanıyor türleri oluşturmak için devam edebilirsiniz, ve bir balon sınıf mı alamadım olmasıdır.

Bu yaklaşımın daha şık varyasyonları vardır. Bu basit bir çeşididir. Sözdizimi temizlik gerekebilir.