2010-09-03 7 views
9

Czytałem tę stronę - http://deaduseful.com/blog/posts/50-php-optimisation-tips-revisitedPHP - Zend powiedzieć unikać magicznych metod?

Jednym z zaleceń było unikanie używania metod Magic, cytowanych z pliku Zend Performance PDF, który nie podaje powodów, dla których zaleca się ich unikać.

Po pewnym wyszukiwaniu w Google (i rozwiązaniu tutaj niepowiązanego z nim pytania) zastanawiałem się, czy ktoś ma jakieś rekomendacje na tym froncie?

Używam wiele __get() w moim kodzie, zwykle do zapisywania zmiennych, których nie zawsze używam, np.

może mam tabelę z nazwy, opisu, category_id, time_added

Moja get będzie wyglądać mniej więcej tak:

 
public function __get($name) { 
    switch($name) { 
     case 'name': 
     case 'desc': 
     case 'category': 
     case 'time_added': 
      $result = do_mysql_query(); 
      $this->name = $result['name']; 
      $this->desc = $result['desc']; 
      $this->category = $result['category']; 
      $this->time_added = $result['time_added']; 
      return $this->{$name}; 
     break; 
     default: 
      throw Exception("Attempted to access non existant or private property - ".$name); 
    } 
} 

wydaje się to świetny sposób, aby robić rzeczy, jak ja tylko kiedykolwiek coś z bazy danych, jeśli jest to potrzebne i mogę przywrócić rzeczy takie jak $ article-> time_added, a nie błądzić po tablicach.

Czy uznano by to za złą praktykę i dodatkowe obciążenie na serwerze?

Często poszerzam klasy za pomocą magicznych metod i robię coś takiego, jeśli klasa dzieci nie pasuje do czegoś w zdobywaniu.

 
public function __get($name) { 
    switch($name) { 
     case 'name': 
     case 'desc': 
     case 'category': 
     case 'time_added': 
      $result = do_mysql_query(); 
      $this->name = $result['name']; 
      $this->desc = $result['desc']; 
      $this->category = $result['category']; 
      $this->time_added = $result['time_added']; 
      return $this->{$name}; 
     break; 
     default: 
      return parent::__get($name); 
    } 
} 

Czy to byłaby zła praktyka i zła wydajność? Maksymalna liczba poziomów, jakie mam przy rozszerzaniu magicznych metod to trzy.

+0

możliwe duplikat [__get/__/__ zestaw pytań wydajności połączenia z PHP] (http://stackoverflow.com/questions/3330852/get- set-call-performance-questions-with-php) – Gordon

Odpowiedz

15

To prawda, są wolniejsze ... ale różnica jest tak mała, że ​​współczynnik prędkości w stosunku do kodu jest czynnikiem. Czy warto martwić się o różnicę dla szybszego rozwoju i konserwacji?

Zobacz magic benchmarks na statystykach

+17

+1: Nie możesz przecenić tego sentymentu. Pamiętaj, że "Przedwczesna optymalizacja jest korzeniem wszelkiego zła" ... Jeśli spędzasz cały swój czas na martwieniu się drobnymi różnicami prędkości, nigdy nie dostaniesz nic. Zbuduj to, co działa dla ciebie, a następnie ** jeśli masz problemy, stamtąd refaktor. Jednak największe ulepszenie wydajności, jakie można wprowadzić, to przejście ze stanu niepracującego do działającego. Wszystko inne blednie w porównaniu ... – ircmaxell

+1

Pozdrawiam link jest bardzo pomocny, a twój punkt jest bardzo prawdziwy, bardzo trudno nie dać się złapać w pragnienie doskonałego kodu i nigdy właściwie go nie wypuszczać: D – Rob

+4

Kod możliwy do utrzymania IMHO jest WELL więcej ważniejszy niż kod o wysokiej wydajności. Pomyśl o tym. Tańsze jest poświęcanie większej ilości sprzętu na problem, niż wyrzucanie na niego większej liczby programistów. To jeden z powodów, dla którego PHP jest tak popularny ... Teraz zawsze jest kompromis, więc nie zalecam ignorowania wydajności, ale nie próbuj mikro-optymalizacji, jeśli nie wiesz, czy istnieje jakiś problem. – ircmaxell

1

rozważyć użycie array accessors.

class Record implements ArrayAccess { 

    /** 
    * @see ArrayAccess::offsetExists() 
    * 
    * @param offset $offset 
    */ 
    public function offsetExists($offset) { 

    } 

    /** 
    * @see ArrayAccess::offsetGet() 
    * 
    * @param offset $offset 
    */ 
    public function offsetGet($offset) { 
     //fetch and cache $result 

     return $result[$offset]; 
    } 

    /** 
    * @see ArrayAccess::offsetSet() 
    * 
    * @param offset $offset 
    * @param value $value 
    */ 
    public function offsetSet($offset, $value) { 

    } 

    /** 
    * @see ArrayAccess::offsetUnset() 
    * 
    * @param offset $offset 
    */ 
    public function offsetUnset($offset) { 

    } 
+2

A to inaczej? Po prostu zamieniasz cztery magiczne metody na cztery inne magiczne metody ... – ircmaxell

+0

@ircmaxell Metody interfejsu nie są metodami magicznymi. Chociaż nie mogę tworzyć kopii zapasowych z numerami, twierdzę, że będą działać szybciej niż poleganie na przechwytywaczach. – Gordon

+0

@Gordon: Jest wolniej, sprawdź link w powyższej odpowiedzi. I tak, chociaż nie jest to "magiczna metoda" w ścisłym tego słowa znaczeniu, to magia w tym sensie, że interfejs umożliwia funkcjonowanie podobne do magii (możliwość korzystania z podstawowych funkcji i konstrukcji językowych na obiekcie) ... – ircmaxell

1

Zrobiłem kilka testów z PHP magicznych metod i rodzimy get/set operacji (na własności publicznej)

Wyniki:

metody magiczne są znacznie wolniejsze niż natywny dostęp. ALE czas dostępu jest wciąż tak mały, że nie będzie miał znaczenia w 99,9% wszystkich przypadków.

Nawet jeśli 1 Million magiczny sposób uzyskuje dostęp w ciągu jednego wniosku, że nadal trwa tylko około 0,1 sekundy ...


„tylko do odczytu” oznacza dostęp za pomocą magicznych metod. Obrazek pokazuje wyniki w PHP 5.5.9 i PHP 7.0.

benchmark results

Oto scenariusz odniesienia: https://github.com/stracker-phil/php-benchmark/blob/master/benchmark.php