Değer PHP birleşmeli diziler vs nesneleri

11 Cevap php

(Bu soru bağlamında olarak PHP kullanır ama sadece PHP ile sınırlı değildir. Örneğin karma inşa sahip herhangi bir dil de alakalıdır)

Bu örneğe (PHP) bakalım:

function makeAFredUsingAssoc()
{
    return array(
        'id'=>1337,
        'height'=>137,
        'name'=>"Green Fred");
}

Karşı:

class Fred
{
    public $id;
    public $height;
    public $name;

    public function __construct($id, $height, $name)
    {
        $this->id = $id;
        $this->height = $height;
        $this->name = $name;
    }
}

function makeAFredUsingValueObject()
{
    return new Fred(1337, 137, "Green Fred");
}

Yöntem # 1 ancak kolayca gibi hata neden olabilir, ders terser biridir

$myFred = makeAFredUsingAssoc();
return $myFred['naem']; // notice teh typo here

Tabii ki, bir o $myFred->naem aynı derecede doğrudur, hangi hata yol açacaktır iddia edebilir. Ancak resmi bir sınıf olan sadece bana daha sert hissediyor, ama gerçekten haklı olamaz.

Ne her yaklaşımı kullanarak artıları / eksileri olacak ve ne zaman insanlar hangi yaklaşımı kullanmak gerekir?

11 Cevap

Yüzeyi altında, her iki yaklaşım eşdeğerdir. Vb, kapsülleme, miras: bir sınıf kullanırken Ancak, standart OO faydaların en olsun

Ayrıca, aşağıdaki örneklere bakalım:

$arr['naem'] = 'John';

mükemmel geçerli olduğunu ve bulmak için zor bir hata olabilir.

Öte yandan,

$class->setNaem('John');

hiç çalışmaz.

Bunun gibi basit bir sınıf:

class PersonalData {
    protected $firstname;
    protected $lastname;

    // Getters/setters here
}

Bir dizi üzerinde birkaç avantajı vardır.

  1. Bazı yazım hataları yapmak için hiçbir olasılık yoktur. $data->setFirtsname('Chris'); hata tr atmak olurken $data['firtsname'] = 'Chris'; çalışacaktır.
  2. Ima yazın: iyi tanımlanmış class sadece belirtilen verileri içerir ise PHP diziler (hiçbir şey dahil) her şeyi içerebilir.

    public function doSth(array $personalData) {
        $this->doSthElse($personalData['firstname']); // What if "firstname" index doesn't exist?
    }
    
    
    public function doSth(PersonalData $personalData) {
        // I am guaranteed that following method exists. 
        // In worst case it will return NULL or some default value
        $this->doSthElse($personalData->getFirstname());
    }
    
  3. Biz doğrulama ya da günlük gibi, set / get işlemleri önce bazı ekstra kod ekleyebilirsiniz:

    public function setFirstname($firstname) {
        if (/* doesn't match "firstname" regular expression */) {
            throw new InvalidArgumentException('blah blah blah');
        }
    
    
    
    if (/* in debbug mode */) {
        log('Firstname set to: ' . $firstname);
    }
    
    
    $this->firstname = $firstname;
    
    }
  4. Biz böylece kalıtım, polimorfizm, tip dayatarak, kapsülleme ve benzeri OOP tüm avantajlarını kullanabilirsiniz ...
  5. Bizim "yapılar" bütün önce de belirtildiği gibi Countable, Serializable veya Iterator arayüzleri, yani bizim yapılar {kullanabilirsiniz için uygulanmasını sağlayan bazı temel sınıfından olabilir [(3)]} döngüler vs
  6. IDE desteği.

Tek dezavantajı hızı gibi görünüyor. Bunun üzerine bir dizi ve işletme oluşturulması hızlıdır. Ancak biz tüm pek çok durumda CPU zamanı programcı zaman daha ucuz olduğunu biliyorum. ;)

Sana bu soruyu soralım:

Ne $myFred['naem'] gibi bir yazım hatası yapma ve $myFred->naem gibi bir yazım hatası yapma konusunda çok farklı? Aynı sorun hala iki durumda var ve her ikisi de hata.

Ben programladığınızda KISS (aptal, basit tutmak) kullanmak ister.

  • Sadece bir yöntem bir sorgu bir alt kümesini iade ediyorsanız, sadece bir dizi döndürür.
  • Eğer sınıfların birinde bir public/private/static/protected değişken olarak veri depolamak ise, bir stdClass olarak depolamak için iyi olacaktır.
  • Daha sonra başka bir sınıf metodu bu geçirmek için gidiyoruz, sen Fred class, yani public function acceptsClass(Fred $fredObj) sıkı yazarak tercih edebilirsiniz

Bunu bir dönüş değeri olarak kullanılacak ise bir dizi karşı gibi rahatlıkla standart bir sınıf oluşturmuş olabilir. Bu durumda sıkı yazarak daha az bakım olabilir.

$class = new stdClass();
$class->param = 'value';
$class->param2 = 'value2';
return $class;

Usecase bağlı olarak ben ya da kullanabilirsiniz. Sınıfın avantajı ben yöntemlerden veya herhangi bir iç gözlem yöntemleri, Tip ve kullanım Tipi İpuçları gibi kullanabilirsiniz olmasıdır. Ben sadece bir sorgu veya bir şey bazı rasgele kümesi etrafında geçmek istiyorsanız, ben büyük olasılıkla dizi kullanmak istiyorum. Yani sürece Fred Benim modelinde özel bir anlamı olduğu gibi, ben bir sınıf kullanmak istiyorum sanırım.

On a sidenote:
ValueObjects are supposed to be immutable. At least if you are refering to Eric Evan's definition in Domain Driven Design. In Fowler's PoEA, ValueObjects do not necessarily have to be immutable (though it is suggested), but they should not have identity, which is clearly the case with Fred.

Bir süre düşündükten sonra, benim kendi cevap.

Diziler üzerinde preferring value objects ile ilgili temel şey clarity.

Bu işlevi göz önünde bulundurun:

// Yes, you can specify parameter types in PHP
function MagicFunction(Fred $fred)
{
    // ...
}

karşı

function MagicFunction(array $fred)
{
}

Niyet nettir. Fonksiyonu yazar onun ihtiyacını zorlayabilir.

Daha da önemlisi, kullanıcı olarak, ben kolayca bakmak what constitutes a valid Fred. Olabilir Ben sadece açık Fred.php ve internals keşfetmek gerekir.

Arayan ve Aranan arasında bir sözleşme vardır. Değer nesneleri kullanarak, bu sözleşme sözdizimi-kontrol kodu olarak yazılabilir:

class Fred
{
    public $name;
    // ...
}

Ben bir dizi kullanıldığı takdirde, sadece benim kullanıcı yorum veya belgeleri okurdum umut olabilir:

// IMPORTANT! You need to specify 'name' and 'age'
function MagicFunction(array $fred)
{
}

Dönüş değeri uygulamanızda bir varlık temsil ettiği zaman, bu OOP amacı olduğu gibi, sen, bir nesne kullanmanız gerekir. Sadece ilgisiz değerler bir grup dönmek istiyorsanız o zaman o kadar açık ve seçik değildir. Bir ortak API parçası olsa, o zaman bir ilan sınıf hala gitmek için en iyi yoldur.

Dürüst olmak gerekirse, ben ikisini de seviyorum.

  • Hash diziler nesneleri yapma daha hızlı şekilde, ve vakit nakittir!
  • Ancak, JSON (biraz cepten OKB gibi görünüyor) karma diziler sevmez.
  • Belki birden fazla kişi ile birlikte projeler için, iyi tanımlanmış bir sınıf daha iyi olurdu.
  • Onun zor, her senaryo için emin olmak için olsa Hash dizileri, daha fazla CPU zamanı ve bellek (bir nesne önceden tanımlanmış bir miktarda vardır) alabilir.

Ama gerçekten berbat çok hangisini kullanmak için hakkında düşünüyor. Dediğim gibi, JSON sağlamalarının sevmez. Oops, bir dizi kullanılır. Ben şimdi kod birkaç bin satır değiştirmek lazım.

Ben onu sevmiyorum, ama bu sınıflar gitmek için daha güvenli bir yol gibi görünüyor.

Uygun Değer Cismin yararı aslında geçersiz bir ve (bütünlüğü ve "değişmezliğini") var olanı değiştirmek için bir yol yapmak için hiçbir yolu yoktur olmasıdır. Sadece alıcılar ve tipi ima parametreleri ile, tabii ki kolayca işlenebilir diziler ile yapabilirsiniz, hangi Derlenebilir kodu o kadar berbat yolu yoktur.

Alternatif bir kamu oluşturucu içinde doğrulamak ve bir özel durum, ancak bu yumuşak bir fabrika yöntemini sağlar olabilir.

class Color
{
    public static function create($name, $rgb) {
        // validate both
        if ($bothValid) {
            return new self($name, $rgb);
        } else {
            return false;
        }
    }
    public function getName() { return $this->_name; }
    public function getRgb() { return $this->_rgb; }

    protected function __construct($name, $rgb)
    {
        $this->_name = $name;
        $this->_rgb = $rgb;
    }
    protected $_name;
    protected $_rgb;
}

Ben ikinci örnekteki gibi kodlanmış özelliklere sahip tercih. Daha net beklenen sınıf yapısını (ve sınıf olası tüm özelliklerini) tanımlar gibi hissediyorum. Sadece her zaman aynı anahtar adları kullanmak hatırlamak aşağı kaynar ilk örnek aksine. Ikinci ile her zaman geri dönebilir ve sadece dosyanın tepeden bakarak özellikleri hakkında bir fikir elde etmek için sınıf bakmak.

Sen daha iyi, ikinci bir yanlış bir şey yaptığınızı bileceksiniz - Eğer çalışırsanız echo $this->doesntExist Eğer bir hata alırsınız oysa echo array['doesntExist'] vermeyeceksin çalışırsanız .

Bir yanlısı karma için: Bu tasarım zamanında bilinmeyen ad-değer kombinasyonları ele almak mümkün değildir.

I have worked with OOP Languages over 10 years. If you understand the way objects work you will love it. Inheritance, Polymorphism, Encapsulation, Overloading are the key advantage of OOP. On the other hand when we talk about PHP we have to consider that PHP isn't a full featured Object Oriented language. For example we cant use method overloading or constructor overloading (straightforward).

Associative arrays in PHP is a VERY nice feature but i think that harms php enterprise applications. When you write code you want to get clean and maintainable application.

Başka bir sen ilişkilendirilebilir dizilerle gevşek size intellisense kullanamazsınız olduğunu düşünüyorum.

Yani ben size TEMİZLEYİCİ ve daha rahat kod yazmak istiyorsanız bunu temin edildiğinde OOP özelliklerini kullanmak zorunda düşünüyorum.