Magento 2 - sihirli alıcıları kullanmak / önlemek için iyi bir uygulama?


21

Varien_Object(M1) ve DataObject(M2) üzerindeki sihirli alıcılar yaygın bir uygulamadır, ancak Magento 2 ile kullanmak yanlıştır.

İyi:

  • kolay okuma / yazma

Kötü

Soru

Magento 2 ile iki yeni yöntemimiz var:

  • getDataByKey($key)
  • getDataByPath($path)

Hala kullanmak için iyi bir neden getData($key)veya sihirli alıcılar var mı?


Düzenle:

@Vinai teşekkürler. @methodYönteme değinmedim , çünkü yaklaşımım oldukça farklıydı.

Yalnızca IDE'ye yardımcı olur, ancak diğer şeyler üzerinde hiçbir etkisi yoktur.

Orada bu konuda birkaç mergedf PRs "mikro-optimizasyonlar" için döküm gibi are (int)yerine intval()ya da (hatta küçük diziler için) dizi boyutunda dış döngüler olsun.

Öte yandan

  1. Marius tarif ettiği gibi "havai" bazı büyülü getters, ....

    strtolower(trim(preg_replace('/([A-Z]|[0-9]+)/', "_$1", $name), '_'));
  2. getData($key) mehtods da 2-3 ek kontrol yapmak zorunda ...

    • if ('' === $key) {
    • if (strpos($key, '/')) {
    • if ($index !== null) {

Kendi kodu için tamamen gerçek yöntemleri tercih etmeyi kabul ediyorum, ancak aynı durumlarda muhtemelen ... örneğin özel bir etkinlik oluşturdunuz ...

$value = $observer->getVar_1();
$value = $observer->getData('var_1');
$value = $observer->getDataByKey('var_1');

3 ile kullanmak /** @var some $value */benim için en iyisidir. (?)


1
Kod çözümleme araçlarının varolmayan yöntemler hakkında şikayet etmemesi için sınıf doc bloğundaki yöntemleri ekleyebilirsiniz. Ayrıca anahtarlarda rakamları kullanmak kötü bir uygulamadır, bu yüzden burada imo "Kötü" olarak listelenmemelidir.
Lily Bergonzat

Yanıtlar:


20

Yukarıdaki soru, sihirli yöntemlerin getDataByKeyveya getDataByPath. Bence üçüncü bir seçenek daha var ve bu da gerçek alıcı ve belirleyici yöntemleri uyguluyor.

getData*Yöntemler hepsi işe tür kesmesi için açıklamalı gerektiğini dezavantajı var.
Genellikle bu, çağrının /* @var string $foo */üzerinde bir ek açıklama ile yapılır getData*.
Bu biraz kötü kokulu, çünkü veri türü çağıran sınıfı değil, verileri içeren sınıfta bildirilmelidir getData*.
Bunun nedeni, veriler değişirse, sınıfın tüm getData*arama sitelerinin değil, güncellenme olasılığı en yüksek olmasıdır .
Bu yüzden gerçek yöntemlerin getData*erişimcileri kullanmaya kıyasla sürdürülebilirliği artırdığını düşünüyorum .

Bu yüzden, sürdürülebilirlik ve daha hızlı uygulama (yazmak için daha az kod) arasında bir değiş tokuşa dönüştüğünü düşünüyorum.

Neyse ki, günümüzde IDE'ler bizim için alıcı ve belirleyici uygulamalarını yaratmada gerçekten çok iyi, bu yüzden argüman artık geçerli değil.

Yukarıdaki sorudan eksik olan sihirli alıcılara ve ayarlayıcılara karşı bir başka argüman, onlar için eklentiler oluşturmanın mümkün olmamasıdır.

Konuya ekleyebileceğimi düşündüğüm diğer tek değer @method, gerçek yöntemleri uygulamak bir sebepten dolayı söz konusu değilse, ek açıklamaları kullanmanın veya kullanmamanın nedenlerini toplamaya çalışmaktır .

Artıları

  • Bir @methodaçıklama gerçek alıcı ve ayarlayıcı uygulanması ile karşılaştırıldığında yazma için biraz daha az bir koddur. Günümüzde bu neredeyse hiç doğru değil çünkü IDE'ler erişimci yöntemleri oluşturmada iyi, bu yüzden artık gerçek bir fayda değil.

Eksileri

  • İşlerin yanlış gitmesi kolaydır.
    • Ek açıklamalar yorumlardır, kod geliştiğinde kolayca eski haline gelir ancak ek açıklamalar güncellenmez. Gerçek yöntemler daha sağlamdır.
    • Tercüman hatası olmadan farklı tip imzalarla birden fazla ek açıklama eklemek mümkündür - statik kod analizi davranışı tanımlanmamıştır ve izlenmesi zor olan küçük hatalara yol açabilir.
    • Hem @methodaçıklama hem de aynı ada sahip gerçek bir yöntem varsa, açıklama tipi imzası statik kod analizi sırasında PHP yorumlayıcısının tersi olan gerçek yöntemi geçersiz kılar. Bu yine kolayca ince hatalara yol açabilir.

Yukarıdaki nedenlerden dolayı @method, bunlardan kaçınabiliyorsam kişisel olarak ek açıklamalar kullanmam .
Uzun ömürlü olması amaçlanan kod için gerçek alıcı ve ayarlayıcı yöntemleri uyguluyorum. Sürdürülebilirlik kazancı, IDE'nin bunları üretmesi için tetikleme çabasına değer.

Bir artış sırasında daha deneysel kod için veya bir modülün basit bir uygulama detayı getData*için ben de yöntemleri kullanıyorum , çünkü tembelim.


Güzel özet. Teşekkürler Vinai. Bu aslında sorduğumdan daha fazla cevap veriyor.
sv3n

1

getData*Yöntemler hepsi işe tür kesmesi için açıklamalı gerektiğini dezavantajı var.

Genellikle bu, çağrının /*@var string $foo */üzerinde bir ek açıklama ile yapılır getData*. Bu biraz koklamak, çünkü veri türü getData * çağıran sınıf değil, veri içeren sınıfta bildirilmelidir.

Bunun nedeni, veriler değişirse, sınıfın tüm getData*arama sitelerinin değil, güncellenme olasılığı en yüksek olmasıdır . Bu yüzden gerçek yöntemlerin getData * erişimcilerini kullanmaya kıyasla sürdürülebilirliği artırdığını düşünüyorum.

Evet koklamak, ama kaçınılabilir (ve gerekir?). Bu çok yaygın bir kod olduğunu düşünüyorum ve genellikle önerilen:

/** @var Foo $product */
$product = $model->getProduct()
if ($product->getId()) {
    $product->doSomething();
}

Sorunlar, sadece dönüş değerinin Fooçağrılabilir bir yöntemle tür olduğunu tahmingetId() etmenizdir.

Sürdürülebilirlik için neden değişken türü varsaymıyor ve InvalidArgumentException?

$product = $model->getProduct()
if ($product instanceof Foo && $product->getId()) {
    $product->doSomething();
}

Bu $model->getProduct(), örneğin farklı dönüş türlerine sahip olması durumunda statik kod analizini de giderir Foo|false. İlk durumda doSomething(), olası çağrı hakkında şikayette bulunacaktır false.

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.