Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [php] optymalny zapis
Forum PHP.pl > Forum > Przedszkole
S3L41N
Witam, poszukuję optymalnego sposobu na zapis poniższej funkcji (metoda w klasie, której nie wklejam):

  1. public function __get($key)
  2. {
  3. if (isset($this->$key))
  4. $value = $this->$key;
  5. elseif (isset($this->data[$key]))
  6. $value = $this->data[$key];
  7. else
  8. $value = NULL;
  9. return $value;
  10. }


Gdyby w isset() można było dokonać przypisania, to całość sprowadzałaby się do:

  1. public function __get($key)
  2. {
  3. return (isset($value = $this->$key) OR isset($value = $this->data[$key])) ? $value : NULL;
  4. }


Niestety się nie da. Ma ktoś może jakiś pomysł jak to zoptymalizować?
zelu
  1. return isset( $this->key ) ? $this->key : ( isset( $this->data[$key] ) ? $this->data[$key] : NULL );
Wicepsik
  1. return $this->$key ? $this->$key : ($this->data[$key] ? $this->data[$key] : null);
zelu
Cytat(Wicepsik @ 2.08.2010, 18:41:55 ) *
  1. return $this->$key ? $this->$key : ($this->data[$key] ? $this->data[$key] : null);


Twoja wersja zwróci Notice'y jeżeli nie będzie któreś z wartości smile.gif

Pozdro
S3L41N
No zgadza się, isset()-y celowo dałem. Dzięki za pomoc Panowie.
Crozin
Od kiedy to optymalny równa się maksymalnie krótki i nieczytelny?
  1. if (isset($this->$key)) {
  2. return $this->$key;
  3. } else if (isset($this->data[$key])) {
  4. return $this->data[$key];
  5. }
  6.  
  7. return null;
Nie kombinuj tam gdzie nie potrzeba.

EDIT: Ogólnie to masz paskudną strukturę danych.
zelu
Cytat(Crozin @ 2.08.2010, 18:54:55 ) *
Od kiedy to optymalny równa się maksymalnie krótki i nieczytelny?



A to inna sprawa. Zapis typu ?: jest wolniejszy niz zwykly if - else, wiec Twoje rozwiązanie jest najlepsze smile.gif Źle się zasugerowałem postem kolegi smile.gif

Pozdro
skarabe.pl
Cytat(zelu @ 2.08.2010, 19:02:56 ) *
A to inna sprawa. Zapis typu ?: jest wolniejszy niz zwykly if - else (...)


Czemu?
zelu
Nie wiem dlaczego tak jest winksmiley.jpg Tak wynikało z moich testów winksmiley.jpg
skarabe.pl
Cytat(zelu @ 2.08.2010, 19:14:22 ) *
Nie wiem dlaczego tak jest ;) Tak wynikało z moich testów ;)

Trochę bez sensu, no ale :)
Fifi209
Cytat(skarabe.pl @ 2.08.2010, 18:21:08 ) *
Trochę bez sensu, no ale smile.gif

Dlaczego bez sensu? Czy coś co jest mniej czytelne, musi być wydajniejsze? smile.gif
croc
Cytat(zelu @ 2.08.2010, 10:02:56 ) *
A to inna sprawa. Zapis typu ?: jest wolniejszy niz zwykly if - else, wiec Twoje rozwiązanie jest najlepsze smile.gif

Wątpię - a nawet jeśli, to co z tego? Tworzysz grę, która ma śmigać w 60 FPS? Panowie, nie popadajcie w paranoję. Zapis ? : jest tu jak najbardziej w porządku.
skarabe.pl
Cytat(fifi209 @ 2.08.2010, 19:24:53 ) *
Dlaczego bez sensu? Czy coś co jest mniej czytelne, musi być wydajniejsze? :)

Nie nie nie nie - czytelność jest kwestią gustu, bez sensu jest tylko to, że zapis:
  1. $var = condition ? true : false;

który znaczy dokładnie to samo co:
  1. if (condition) {
  2. $var = true;
  3. } else {
  4. $var = false;
  5. }

może być wolniejszy od tego drugiego. Tak przy okazji - nie wyobrażam sobie zapisania skryptu typu:
  1. $zmienna_1 = isset($_POST['zmienna_1']) ? $_POST['zmienna_1'] : '';
  2. $zmienna_2 = isset($_POST['zmienna_2']) ? $_POST['zmienna_2'] : '';
  3. $zmienna_3 = isset($_POST['zmienna_3']) ? $_POST['zmienna_3'] : '';
  4. /* ... */
  5. $zmienna_100 = isset($_POST['zmienna_100']) ? $_POST['zmienna_100'] : '';

W taki sposób:
  1. if (isset($_POST['zmienna_1'])) {
  2. $zmienna_1 = $_POST['zmienna_1'];
  3. } else {
  4. $zmienna_1 = '';
  5. }
  6. if (isset($_POST['zmienna_2'])) {
  7. $zmienna_2 = $_POST['zmienna_2'];
  8. } else {
  9. $zmienna_2 = '';
  10. }
  11. if (isset($_POST['zmienna_3'])) {
  12. $zmienna_3 = $_POST['zmienna_3'];
  13. } else {
  14. $zmienna_3 = '';
  15. }
  16. /* ... */
  17. if (isset($_POST['zmienna_100'])) {
  18. $zmienna_100 = $_POST['zmienna_100'];
  19. } else {
  20. $zmienna_100 = '';
  21. }

nawet w tej, w sposób oczywisty mniej wydajnej wersji:
  1. $zmienna_1 = '';
  2. if (isset($_POST['zmienna_1'])) {
  3. $zmienna_1 = $_POST['zmienna_1'];
  4. }

Dla mnie to pierwsze jest znacznie bardziej czytelne. Ale jak już napisałem - kwestia gustu.
Crozin
Zacznijmy od tego, że jak masz taką konstrukcję to jest coś nie tak z Twoimi umiejętnościami. Ale rozumiem, że to tylko na potrzeby przykładu.

Jeszcze tak raz podkreślę: nie szukaj wydajności w takich miejscach - to, że zyskasz 0.00000213 sekundy nic Ci nie da.
zelu
W Twojej wersji jak najbardziej zapis skrócony jest sensowniejszy. Kwesta kompromisu pomiędzy czasem wykonania a przejrzystością kodu. Poza tym rozchodzi się o czas rzędu 3E-6 smile.gif Więc strasznie dużej straty na tym nie ma. Niemniej jednak takowa występuje.

Jednak przy pierwotnym problemie w tym temacie zapis Crozina wydaje mi się najsensowniejszy. Szybszy i jednak bardziej przejrzysty niż zagnieżdżanie ?:

Pozdro
skarabe.pl
Cytat(Crozin @ 2.08.2010, 19:51:01 ) *
Jeszcze tak raz podkreślę: nie szukaj wydajności w takich miejscach - to, że zyskasz 0.00000213 sekundy nic Ci nie da.

Spoko spoko - nie ja podniosłem kwestię wydajności. Ale to trochę tak jak z ++$i zamiast $i++ - nikt nikomu nie każe przeglądać wszystkich swoich skryptów i zamieniać jedno na drugie. Ale nie zaszkodzi, jeśli to pierwsze wejdzie w krew (i szablony kodu :)).
S3L41N
No dobrze, ważna jest czytelność kodu, a czy poniższy zapis jest nieczytelny?
  1. public function __get($key)
  2. {
  3. return (isset($this->$key) ? $this->$key :
  4. (isset($this->data[$key]) ? $this->data[$key] :
  5. NULL;
  6. }

Jeżeli ktoś posiada konkretną wiedzę czy i jeśli tak to kiedy wskazane jest używanie skróconego zapisu za pomocą ternary operator-a będę niezmiernie wdzięczny za wytyczne.
Fifi209
Cytat(skarabe.pl @ 2.08.2010, 18:47:27 ) *
Nie nie nie nie - czytelność jest kwestią gustu, bez sensu jest tylko to, że zapis:
Dla mnie to pierwsze jest znacznie bardziej czytelne. Ale jak już napisałem - kwestia gustu.

Jeżeli robisz to w sposób, który przedstawiłeś na forum to nie skomentuję...
Co do wydajności - wrzuć sobie w pętlę z 100 tysięcy raz, wyciągnij czasy, podaj czas średni i porównaj - może się mylimy... smile.gif Ja nie idę w zapartego, że jest tak jak My piszemy i nie podważam za wszelką cenę Twoich teorii.
Cytat(skarabe.pl @ 2.08.2010, 18:54:57 ) *
Ale to trochę tak jak z ++$i zamiast $i++ - nikt nikomu nie każe przeglądać wszystkich swoich skryptów i zamieniać jedno na drugie.


No i tutaj byś się zdziwił, jest różnica czy używasz ++$i czy $i++
Miłego czytania
kapuch
Cytat(fifi209 @ 3.08.2010, 00:53:27 ) *
No i tutaj byś się zdziwił, jest różnica czy używasz ++$i czy $i++
Miłego czytania

wystarczy ze wklepie echo winksmiley.jpg
  1. $i = 0;
  2. echo $i++; // 0
  3. echo $i; // 1
  4. echo ++$i; // 2
Fifi209
Cytat(kapuch @ 3.08.2010, 00:00:41 ) *
wystarczy ze wklepie echo winksmiley.jpg
  1. $i = 0;
  2. echo $i++; // 0
  3. echo $i; // 1
  4. echo ++$i; // 2

No i moim zdaniem jest to BARDZO duża różnica i jeżeli ktoś nie widzi tej różnicy lub o tym nie wie, znając życie przyleci na forum i będzie pytał: Dlaczego mi skrypt źle działa?
Crozin
@fifi209, @kapuch: Chodziło o sytuację gdzie zależy nam tylko na inkrementacji wartości zmiennej, np.:
  1. for (...; ...; ++$i)
  2. if () {
  3. ++$j;
  4. }
W tych przypadkach nie ma realnej różnicy.

Szczerze to jestem zdziwiony jak długo się ten wątek ciągnie, więc tam na zakończenie (oby)
1) Mikroptymalizacja z reguły jest pozbawiona sensu w "zadaniach wysokiego poziomu" - to odnośnie pre/postinkrementacji, używania bloków if/else lub ?: itp.
2) Kod powinno się pisać czytelny. Jeżeli jeden zapis jest czytelniejszy od drugiego to można z niego skorzystać. A to kiedy coś jest czytelne... no tyle to już chyba potraficie sami ocenić?
S3L41N
No dobrze, ale są jakieś konkretne wytyczne kiedy używać jednego zapisu, a kiedy drugiego?
Których z zapisów jest bardziej poprawny, czytelny i zalecany w następujących sytuacjach?
Sytuacja 1:
  1. //1.1
  2. $syshelpers = file_exists($syspath = trim(FRAMEWORKSDIR.'/'.HELPERSDIR, '/')) ? array_slice(scandir($syspath), 2) : array();
  3. //1.2
  4. if (file_exists($syspath = trim(FRAMEWORKSDIR.'/'.HELPERSDIR, '/')))
  5. $syshelpers = array_slice(scandir($syspath), 2);
  6. else
  7. $syshelpers = array();
  8. //1.3
  9. $syshelpers = array();
  10. if (file_exists($syspath = trim(FRAMEWORKSDIR.'/'.HELPERSDIR, '/')))
  11. $syshelpers = array_slice(scandir($syspath), 2);

Sytuacja 2:
  1. //2.1
  2. $type = (substr($type, -1) == 'y') ? substr($type, 0, -1).'ies' : $type.'s';
  3. //2.2
  4. if (substr($type, -1) == 'y')
  5. $type = substr($type, 0, -1).'ies';
  6. else
  7. $type = $type.'s';

Sytuacja 3:
  1. //3.1
  2. return (isset($this->$key) OR isset($this->data[$key])) ? TRUE : FALSE;
  3. //3.2
  4. if (isset($this->$key) OR isset($this->data[$key]))
  5. return TRUE;
  6. return FALSE;
  7. //3.3
  8. if (isset($this->$key) OR isset($this->data[$key]))
  9. return TRUE;
  10. else
  11. return FALSE;

Sytuacja 4:
  1. //4.1
  2. return (isset($this->$key) ? $this->$key : (isset($this->data[$key]) ? $this->data[$key] : NULL));
  3. //4.2
  4. return (isset($this->$key) ? $this->$key :
  5. (isset($this->data[$key]) ? $this->data[$key] :
  6. NULL));
  7. //4.3
  8. if (isset($this->$key))
  9. return $this->$key;
  10. elseif (isset($this->data[$key])
  11. return $this->data[$key];
  12. else
  13. return NULL;
  14. //4.4
  15. if (isset($this->$key))
  16. return $this->$key;
  17. else if (isset($this->data[$key])
  18. return $this->data[$key];
  19. else
  20. return NULL;
  21. //4.5
  22. if (isset($this->$key))
  23. return $this->$key;
  24. if (isset($this->data[$key])
  25. return $this->data[$key];
  26. return NULL;

Sytuacja 5:
  1. //5.1
  2. return isset(self::$instance) ? self::$instance : self::$instance = new self;
  3. //5.2
  4. if (isset(self::$instance))
  5. return self::$instance;
  6. else
  7. return self::$instance = new self;
  8. //5.3
  9. if (isset(self::$instance))
  10. return self::$instance;
  11. return self::$instance = new self;
  12. //5.4
  13. if (!isset(self::$instance))
  14. self::$instance = new self;
  15. return self::$instance;

Które z nich, a może jakieś inne są najbardziej poprawne?
Crozin
No ileż można - który zapis wydaje Ci się najbardziej przejrzysty? Wariant pierwszy, drugi lub trzeci - używaj który Tobie najbardziej pasuje. Mnie pasuje czwarty Tobie drugi - używaj sobie drugiego. Nie ma żadnych wytycznych - to tylko forma zapisu!
S3L41N
No ok, to poprostu napisz, które zapisy Ty byś wybrał...
attimo
Ja też wole 4. może i wdurgim kod jest krótszy prawie 4 krotnie, ale jeśli musiałbym tam coś zmieniac to rozszyfrowanie tego zajeło by mi wiecej czasu dlatego wole już wiecej linijek ale czytelniej choc slowo czytelniej jest subiektywne i dla kogos innego sytuacja 2 moze byc czytelniejsza.
S3L41N
attimo widzę, że chyba nie wczytałeś się w posta. Jest pięć sytuacji z różnymi możliwościami rozwiązań (kolejne rozwiązania dla poszczególnych sytuacji są wypunktowane w komentarzach).
Crozin
#1
  1. $syspath = trim(FRAMEWORKSDIR.'/'.HELPERSDIR, '/');
  2. $syshelpers = file_exists($syspath) ? array_slice(scandir($syspath), 2) : array();
#2
  1. $type = substr($type, -1) == 'y' ? substr($type, 0, -1).'ies' : $type.'s';
#3
  1. return isset($this->$key) || isset($this->data[$key]);
#4
  1. if (isset($this->$key)) {
  2. return $this->$key;
  3. } elseif (isset($this->data[$key]) {
  4. return $this->data[$key];
  5. }
  6.  
  7. return NULL;
#5
  1. if (!isset(self::$instance)) {
  2. self::$instance = new self;
  3. }
  4.  
  5. return self::$instance;
Tylko nie wiem po co to podaję. Naprawdę tak ciężko ocenić co dla siebie samego jest wygodne?
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.