Magiczne pobieracze na Varien_Object
(M1) i DataObject
(M2) są powszechną praktyką, ale w Magento 2 korzystanie z nich jest niewłaściwe.
Dobry:
- łatwy do odczytu / zapisu
Zły
- Powoduje to problemy podczas używania cyfr w kluczach (patrz: Magento 2: w inny sposób uzyskaj pole kolekcji lub uzyskaj atrybut produktu niestandardowego za pomocą skrzynki na wielbłąda )
- narzędzia do analizy kodu narzekają na nieistniejące metody
Pytanie
W Magento 2 mamy dwie nowe metody:
getDataByKey($key)
getDataByPath($path)
Czy jest jakiś dobry powód, aby nadal używać getData($key)
lub magicznych pobieraczy?
Edytować:
@Vinai dzięki. Nie wspomniałem o @method
metodzie, ponieważ moje podejście było zupełnie inne.
Pomaga tylko IDE, ale nie ma wpływu na inne rzeczy.
Istnieje kilka scalonych PR, które są „mikrooptymalizacjami”, takimi jak rzutowanie na (int)
zamiast intval()
lub uzyskanie rozmiaru tablicy poza pętlami (nawet dla małych tablic).
Z drugiej strony są
magiczne pobieracze, które mają pewne „narzuty”, jak opisał Marius…
strtolower(trim(preg_replace('/([A-Z]|[0-9]+)/', "_$1", $name), '_'));
getData($key)
mehtods muszą także wykonać 2-3 dodatkowe kontrole ...if ('' === $key) {
if (strpos($key, '/')) {
if ($index !== null) {
W przypadku własnego kodu całkowicie zgadzam się na preferowanie prawdziwych metod, ale w tych samych przypadkach nie jest to możliwe ... np. Utworzyłeś niestandardowe zdarzenie ...
$value = $observer->getVar_1();
$value = $observer->getData('var_1');
$value = $observer->getDataByKey('var_1');
Używanie 3. z /** @var some $value */
wydaje mi się najlepsze. (?)
Odpowiedzi:
Powyższe pytanie dotyczy użycia magicznych metod w porównaniu z
getDataByKey
lubgetDataByPath
. Myślę, że jest też trzecia opcja, a mianowicie wdrożenie metod getter i setter.Wszystkie
getData*
metody mają tę wadę, że muszą być opatrzone adnotacjami, aby wnioskowanie typu działało.Zwykle robi się to z
/* @var string $foo */
adnotacją nadgetData*
połączeniem.Jest to nieco śmierdzące, ponieważ typ danych powinien być zadeklarowany w klasie, która zawiera dane, a nie w klasie, która wywołuje
getData*
.Powodem tego jest to, że jeśli dane się zmienią, klasa najprawdopodobniej zostanie zaktualizowana, nie wszystkie
getData*
witryny wywołujące.Dlatego uważam, że prawdziwe metody zwiększają łatwość konserwacji w porównaniu do korzystania z
getData*
akcesoriów.Myślę więc, że sprowadza się to do kompromisu między łatwością konserwacji i szybszą implementacją (mniej kodu do napisania).
Na szczęście w dzisiejszych czasach IDE są naprawdę dobre w tworzeniu dla nas implementacji gettera i settera, więc ten argument tak naprawdę nie ma już zastosowania.
Kolejnym argumentem przeciwko magicznym modułom pobierającym i ustawiającym, którego brakuje w powyższym pytaniu, jest to, że nie można dla nich tworzyć wtyczek.
Jedyną inną wartością, którą, jak sądzę, mogę dodać do tematu, jest próba zebrania powodów użycia lub
@method
nieużytkowania adnotacji, jeśli z jakiegoś powodu nie ma mowy o zastosowaniu prawdziwych metod.Plusy
@method
Adnotacja jest trochę mniej kodu do zapisu w porównaniu do realizacji prawdziwego getter i setter. Nie jest to jednak do końca prawdą, ponieważ IDE są dobre w generowaniu metod akcesorów, więc nie jest to już prawdziwą korzyścią.Cons
@method
adnotacja, jak i prawdziwa metoda o tej samej nazwie, podpis typu adnotacji zastępuje prawdziwą metodę podczas analizy kodu statycznego, co jest przeciwieństwem działania interpretera PHP. To znowu może łatwo prowadzić do subtelnych błędów.Z powyższych powodów osobiście nie używam
@method
adnotacji, jeśli mogę ich uniknąć.Dla kodu, który ma długo żyć, implementuję metody getter i setter. Zwiększenie łatwości konserwacji jest warte wysiłku, aby uruchomić IDE w celu ich wygenerowania.
Aby uzyskać bardziej eksperymentalny kod podczas piku lub prosty szczegół implementacji modułu, używam również
getData*
metod, ponieważ jestem leniwy.źródło
Tak, śmierdzi, ale można (i należy?) Tego uniknąć. Myślę, że jest to bardzo popularny kod i często sugerowany:
Problem polega na tym, że zgadujesz, że zwracana wartość jest typu
Foo
z wywoływanągetId()
metodą.Jeśli chodzi o łatwość konserwacji, dlaczego nie założyć typu zmiennej i dodać
InvalidArgumentException
?To również naprawia analizę kodu statycznego w przypadku, gdy
$model->getProduct()
ma różne typy zwracanych danych - jakFoo|false
. W pierwszym przypadku narzekałbydoSomething()
na możliwość wezwaniafalse
.źródło