Drukowana wersja tematu

Kliknij tu, aby zobaczyć temat w orginalnym formacie

Forum PHP.pl _ Oceny _ [inny]Własny framework z auto wstrzykiwaniem

Napisany przez: primosz67 4.08.2017, 07:28:51

Witam,

Hobbistycznie napisałem własny framework. Czy ktoś mógłby się wypowiedzieć co o nim sądzi.

https://github.com/primosz67/tahona-spark-mvc




Napisany przez: nospor 4.08.2017, 10:21:34

Skoro piszesz teraz cos od podstaw, to wypadaloby isc z duchem czasu i pisac to juz w php7 a nie stac w starociu.

Unikaj zbednych zagniezdzen
Nie

  1. public function getRootNamespace() {
  2. if ($this->hasMultipleNamespaces()) {
  3. return $this->namespace[0];
  4. } else {
  5. return $this->namespace;
  6. }
  7. }


a:
  1. public function getRootNamespace() {
  2. if ($this->hasMultipleNamespaces()) {
  3. return $this->namespace[0];
  4. }
  5.  
  6. return $this->namespace;
  7. }


Unikaj zbednych linii kodu
Nie
  1. public function getNamespaces() {
  2. if ($this->hasMultipleNamespaces()) {
  3. return $this->namespace;
  4. } else {
  5. return http://www.php.net/array($this->namespace);
  6. }
  7. }


a:
  1. public function getNamespaces() {
  2. return (http://www.php.net/array)return $this->namespace;
  3. }



ps: przenosze

edit:
zaprzyjaznij sie z PSR
zaprzyjaznij sie z UNIT TESTS - teraz to podstawa


return isset($obj) && false === is_null($obj);
czemu poprostu nie:
return !is_null($obj);
?

return is_null($obj) || false === isset($obj);
czemu poprostu nie
return is_null($obj);
?

  1.  
  2. public http://www.php.net/static function getYearsBetween(DateTime $from, DateTime $to) {
  3. $da = new DateTime();
  4. $interval = date_diff($from, $to);
  5. return $interval->y;
  6. }

Po co tworzysz obiekt $da, ktory nigdzie nie jest wykorzystywany? Polecam dobry edytor do pracy, ktore wylapuje takie bledy.
Rowniez przydatny moze byc statyczny analizer, ala PHAN

isExist()
a moze poprostu exist()?

Po co tworzysz kilka funkcji, ktore robia dokladnie to samo?
  1. public http://www.php.net/static function isExist($directoryPath) {
  2. return http://www.php.net/file_exists($directoryPath) && http://www.php.net/is_dir($directoryPath);
  3. }
  4.  
  5. public http://www.php.net/static function isDirExist($dir) {
  6. return http://www.php.net/is_dir($dir);
  7. }
  8.  


Na bakier tez jestes z warunkow logicznych
  1. public http://www.php.net/static function div($a, $b) {
  2. if (http://www.php.net/empty($a) || http://www.php.net/empty($b) || $b == 0 || $a == 0) {
  3. return 0;
  4. }
  5. return $a / $b;
  6. }

Przeciez to:
if (empty($a) || empty($b) || $b == 0 || $a == 0)
to jest poprostu to
if (empty($a) || empty($b))

Poza tym jak juz tworzysz funkcje do dzielenia to od kiedy 2/0 daje 0?

Jaki sens maja takie funkcje?
  1. public http://www.php.net/static function upper() {
  2. return function ($x) {
  3. return http://www.php.net/strtoupper($x);
  4. };
  5. }
  6.  
  7. public http://www.php.net/static function http://www.php.net/trim($string) {
  8. return http://www.php.net/trim($string);
  9. }

I cala masa innych podobnych?

Dalej juz mi sie nie chce. Idee moze i miales sluszna, ale wykladasz sie na drobnostkach. Jesli pisales to tylko dla nauki to i moze ok. Dla innych celow srednio sie nadaje

Napisany przez: primosz67 4.08.2017, 16:00:39

Cytat(nospor @ 4.08.2017, 11:21:34 ) *
Skoro piszesz teraz cos od podstaw, to wypadaloby isc z duchem czasu i pisac to juz w php7 a nie stac w starociu.

edit:
zaprzyjaznij sie z UNIT TESTS

mam ale w innym projekcie

Cytat(nospor @ 4.08.2017, 11:21:34 ) *
return is_null($obj) || false === isset($obj);
czemu poprostu nie
return is_null($obj);
?


Fajne

Cytat(nospor @ 4.08.2017, 11:21:34 ) *
  1.  
  2. public http://www.php.net/static function getYearsBetween(DateTime $from, DateTime $to) {
  3. $da = new DateTime();
  4. $interval = date_diff($from, $to);
  5. return $interval->y;
  6. }

Po co tworzysz obiekt $da, ktory nigdzie nie jest wykorzystywany? Polecam dobry edytor do pracy, ktore wylapuje takie bledy.
Rowniez przydatny moze byc statyczny analizer, ala PHAN


O dzięki. korzystam z PHP storm,ale on nie wyłapuje takich rzeczy sam. jak Sonar w javie.

Cytat(nospor @ 4.08.2017, 11:21:34 ) *
isExist()
a moze poprostu exist()?

Po co tworzysz kilka funkcji, ktore robia dokladnie to samo?


By je trochę pogrupować. Przyjemniejsze api.


[quote name='nospor' post='1220019' date='4.08.2017, 11:21:34 ']

  1. public http://www.php.net/static function isExist($directoryPath) {
  2. return http://www.php.net/file_exists($directoryPath) && http://www.php.net/is_dir($directoryPath);
  3. }
  4.  
  5. public http://www.php.net/static function isDirExist($dir) {
  6. return http://www.php.net/is_dir($dir);
  7. }
  8.  


Na bakier tez jestes z warunkow logicznych

  1. public http://www.php.net/static function div($a, $b) {
  2. if (http://www.php.net/empty($a) || http://www.php.net/empty($b) || $b == 0 || $a == 0) {
  3. return 0;
  4. }
  5. return $a / $b;
  6. }

Przeciez to:
if (empty($a) || empty($b) || $b == 0 || $a == 0)
to jest poprostu to
if (empty($a) || empty($b))
[/quote ]

I mówisz mi że to jest logiczne w PHP że $a==0 to to samo co "empty($a)" ?. a jak $a=int (0) to empty ($a) zwróci true ?!.


[quote name='nospor' date='4.08.2017, 11:21:34 ' post='1220019']
Poza tym jak juz tworzysz funkcje do dzielenia to od kiedy 2/0 daje 0?

[/quote ]

Akurat trafiłeś na klasę do wywalenia:D

[quote name='nospor' date='4.08.2017, 11:21:34 ' post='1220019']
Jaki sens maja takie funkcje?
  1. public http://www.php.net/static function upper() {
  2. return function ($x) {
  3. return http://www.php.net/strtoupper($x);
  4. };
  5. }
  6.  
  7. public http://www.php.net/static function http://www.php.net/trim($string) {
  8. return http://www.php.net/trim($string);
  9. }

I cala masa innych podobnych?
[/quote ]

Lepsze Api. Również przełożenie metod do utilsów pozwala mi na szybsze programowanie.
Część funkcji jest zgodna z Javovym Apache Commons. (Jestem javovcem, a utilsy tworzyłem tylko dla siebie.). Utilsy nie są tu najważniejsze.



Bardziej chodziło mi o idee i to co użytkownik tworząc nowy projekt uzyska.

Napisany przez: nospor 4.08.2017, 16:07:42

Cytat
O dzięki. korzystam z PHP storm,ale on nie wyłapuje takich rzeczy sam. jak Sonar w javie.

Zainstaluj plugin "Php inspections"

Cytat
By je trochę pogrupować. Przyjemniejsze api.

Znaczy duplikujesz funkcje by je pogrupowac? Prosze cie... wink.gif

Cytat
I mówisz mi że to jest logiczne w PHP że $a==0 to to samo co "empty($a)" ?. a jak $a=int (0) to empty ($a) zwróci true ?!.

Zamiast sie glupio pytac to sprawdz. To sa podstawy. Nawet jak nie masz php pod reka, to mogles zajrzec do manuala
http://php.net/manual/en/function.empty.php
naprawde, po cos go wymyslono.
Cytat
The following things are considered to be empty:

"" (an empty string)
0 (0 as an integer)
0.0 (0 as a float)
"0" (0 as a string)
NULL
FALSE
array() (an empty array)
$var; (a variable declared, but without a value)


Cytat
Akurat trafiłeś na klasę do wywalenia:D

Do wywalenie czy nie do wywalenia nie zmienia to faktu, ze na jakims tam etapie uznales ze 2/0 to 0 tongue.gif

Cytat
Bardziej chodziło mi o idee i to co użytkownik tworząc nowy projekt uzyska.

Z takim api to raczej nic nie uzyska wink.gif Z calym szacunkiem, ale po przejrzeniu pobierznie kodu odechcialo mi sie analizowac co ktos moze na tym zyskac. Moze komus innemu bedzie sie chcialo zastanawiac co mozna na tym zyskac smile.gif

Napisany przez: primosz67 4.08.2017, 17:46:30

Cytat(nospor @ 4.08.2017, 17:07:42 ) *
Znaczy duplikujesz funkcje by je pogrupowac? Prosze cie... wink.gif


Nie wiem czy znasz taki termin : syntactic sugar biggrin.gif. Myślę że na tym możemy zakończyć.

Cytat
Zamiast sie glupio pytac to sprawdz. To sa podstawy. Nawet jak nie masz php pod reka, to mogles zajrzec do manuala
http://php.net/manual/en/function.empty.php
naprawde, po cos go wymyslono.


Wymyślono go po to by programiści się mylili biggrin.gif. Mogliby ją usunąć, zapewne nie jestem pierwszą osobą, która na takie rzeczy się nadziała.
W takich sytuacjach zrobienie klasy String::empty(), która zwróci "false" dla 0 w PHP miałoby więcej sensu. Mniejsza, to tylko mój błąd, że nie sprawdziłem w dokumentacji .

Cytat
Do wywalenie czy nie do wywalenia nie zmienia to faktu, ze na jakimś tam etapie uznałeś ze 2/0 to 0 tongue.gif


Z tego co pamiętam to chciałem rozwiązać jakiś przypadek biznesowy, w którym metoda zwraca 0 w przypadku błędu lub braku jakiejś wartości.

Cytat
Z takim api to raczej nic nie uzyska wink.gif Z calym szacunkiem, ale po przejrzeniu pobierznie kodu odechcialo mi sie analizowac co ktos moze na tym zyskac. Moze komus innemu bedzie sie chcialo zastanawiac co mozna na tym zyskac smile.gif


Rzeczywiście Api, ma swoje błędy, wiele też błędów zrobiłem. Rozumiem też, że patrzysz na kod z punktu widzenia programisty PHP, to dla mnie wiele znaczy.

Zerknij w przykładowy projekt może powie ci to coś więcej. https://github.com/primosz67/spark-mvc-example,

Napisany przez: viking 4.08.2017, 17:56:37

Czemu te klasy nie mają normalnych nazw Spark\Core\Costam?

Napisany przez: primosz67 4.08.2017, 18:55:30

Cytat(viking @ 4.08.2017, 18:56:37 ) *
Czemu te klasy nie mają normalnych nazw Spark\Core\Costam?


Przez pomyłkę. nie zauważyłem, że PHP ma inny standard niż JAVA.
Jak jeszcze kiedyś programowałem w PHP to było Spark_Core_Costam (:sick). Teraz mam nadzieje, że PHP zmieni standard na mała\mała\User biggrin.gif . Też zauważyłem że lepiej się czyta np. Utils\StringUtils ,a utils\StringUtils - od razu widzisz co jest nazwą klasy, a co pakietem.

Cytat(primosz67 @ 4.08.2017, 18:46:30 ) *
Wymyślono go po to by programiści się mylili biggrin.gif. Mogliby ją usunąć, zapewne nie jestem pierwszą osobą, która na takie rzeczy się nadziała.
W takich sytuacjach zrobienie klasy String::empty(), która zwróci "false" dla 0 w PHP miałoby więcej sensu. Mniejsza, to tylko mój błąd, że nie sprawdziłem w dokumentacji .


Właśnie zainstalowałem PHP Inspection i dostałem taką odpowiedź - "'empty(...)' counts too many values as empty, consider refactoring with type sensitive checks".

PS:PHP Inspection właśnie polizał moje ego biggrin.gif

Napisany przez: nospor 4.08.2017, 20:28:12

Cytat
Nie wiem czy znasz taki termin : syntactic sugar biggrin.gif. Myślę że na tym możemy zakończyć.

Co ma slodzenie do bezsensownej duplikacji funkcji?
Stworzyles dwie funkcje, obie robia dokladnie to samo i teraz user ma zagwostke, ktora funkcje ma uzyc i sie zastnawaia czy moze raz ma uzyc tej a raz innej.
Na dodatek nazwy funkcji sa bzdurne bo jedna to isExist a druga isDirExist co sugeruje, ze druga sprawdza katalog a pierwsza sprawdza cos innego podczas gdy tez sprawdza katalog.
No i te nieszczesne isExists.... Po polsku tez mowisz "jest istnieje"? Bo uwierz, po angielsku tez tak nie mowia.
Wiec skoro juz poruszasz kwestie slodzenia to chociac zastanow sie czy wszyscy tez uwazaja ze sol jest slodka tongue.gif

Cytat
Właśnie zainstalowałem PHP Inspection i dostałem taką odpowiedź - "'empty(...)' counts too many values as empty, consider refactoring with type sensitive checks".

PS:PHP Inspection właśnie polizał moje eg
Mi ani razu nie podkresla empty a uzywam tego pluginu dluzej od ciebie.
I jesli uwazasz, ze dzieki temu podkresleniu ten kod
if (empty($a) || $a == 0)
jest teraz ok to nadal jestes w duzym bledzie wink.gif

Cytat
Z tego co pamiętam to chciałem rozwiązać jakiś przypadek biznesowy, w którym metoda zwraca 0 w przypadku błędu lub braku jakiejś wartości.
No wlasnie, to jest kolejny problem w twoim kodzie. Juz nie raz napisales, ze cos zrobiles bo ma to sluzyc tobie. Czyli z jednej strony piszesz kod, ktory ma sluzyc tobie, a z drugiej sie pytasz nas, czy sie nadaje dla innych. Nie, z faktu, ze wiekszosc piszesz pod siebie to sie nie nadaje dla innych.

Napisany przez: primosz67 4.08.2017, 21:20:37

Cytat(nospor @ 4.08.2017, 21:28:12 ) *
Co ma slodzenie do bezsensownej duplikacji funkcji?
Stworzyles dwie funkcje, obie robia dokladnie to samo i teraz user ma zagwostke, ktora funkcje ma uzyc i sie zastnawaia czy moze raz ma uzyc tej a raz innej.
Na dodatek nazwy funkcji sa bzdurne bo jedna to isExist a druga isDirExist co sugeruje, ze druga sprawdza katalog a pierwsza sprawdza cos innego podczas gdy tez sprawdza katalog.
No i te nieszczesne isExists.... Po polsku tez mowisz "jest istnieje"? Bo uwierz, po angielsku tez tak nie mowia.
Wiec skoro juz poruszasz kwestie slodzenia to chociac zastanow sie czy wszyscy tez uwazaja ze sol jest slodka tongue.gif


A właśnie zauważyłem, że chodzi ci o duplikacje isExist i isDirExist, , a nie isDirExist i is_dir . Sorki źle cię zrozumiałem. Z tym exist masz racje.

Cytat
Mi ani razu nie podkresla empty a uzywam tego pluginu dluzej od ciebie.
I jesli uwazasz, ze dzieki temu podkresleniu ten kod
if (empty($a) || $a == 0)
jest teraz ok to nadal jestes w duzym bledzie wink.gif


Nie. Podkreślam tylko, że w ogóle używanie metody empty(), to "duży" błąd.

Cytat
No wlasnie, to jest kolejny problem w twoim kodzie. Juz nie raz napisales, ze cos zrobiles bo ma to sluzyc tobie. Czyli z jednej strony piszesz kod, ktory ma sluzyc tobie, a z drugiej sie pytasz nas, czy sie nadaje dla innych. Nie, z faktu, ze wiekszosc piszesz pod siebie to sie nie nadaje dla innych.


Masa rzeczy tak powstaje, że najpierw piszesz coś z własnej potrzeby, a potem dostosowujesz dla innych.


Napisany przez: nospor 4.08.2017, 22:36:58

Cytat
Nie. Podkreślam tylko, że w ogóle używanie metody empty(), to "duży" błąd.
Bledem co najwyzej bylo powstanie tej funkcji. A skoro juz jest, to uzywanie jest ok. Sam zreszta jej uzywasz tylko nie znales jej "wszyskich mozliwosci" wink.gif

Cytat
Masa rzeczy tak powstaje, że najpierw piszesz coś z własnej potrzeby, a potem dostosowujesz dla innych
Moze i tak. Nie mniej jednak uwazam iz na chwile obecna twoj kod nie nadaje sie dla wiekszej publicznosci.

Napisany przez: com 20.08.2017, 14:44:04

Sonar jest tak samo do PHP jak do Javy, tylko dorzucić trzeba bo go nie dają w paczce tongue.gif
vendor, composer.lock wrzuć do gitignora, bo one w repo są zbędne wink.gif

Cytat
Z tego co pamiętam to chciałem rozwiązać jakiś przypadek biznesowy, w którym metoda zwraca 0 w przypadku błędu lub braku jakiejś wartości.

To świadczy o tym, ze ten przypadek biznesowy ma złe założenia, a sama metoda robi więcej niż powinna.

Brak testów dla takiego frameworka strasznie ogranicza jego używalność, bo tylko Ty wiesz i znasz wszystkie jego możliwości, a nikt z nas nie wie nawet czy to działa poprawnie.

Napisany przez: nospor 20.08.2017, 15:02:16

Cytat
composer.lock wrzuć do gitignora, bo one w repo są zbędne
No chyba nie do konca...

Napisany przez: com 20.08.2017, 16:14:25

Wersje zależności określone są i tak w właściwym pliku i raczej jeśli nie piszemy w Laravelu, to nie dostaniemy nagle BC breaka, wiec zaciągniecie nawet nowszego minora nie powinno mieć wgl wpływu na nasz kod. Ale oczywiscie jak ktos sie uprze to niech zostanie, vendor jednakże trzeba wyrzucić, szczególnie, że tu jest niekompletny nawet biggrin.gif

Ok, oczywiście jest jeszcze druga kwestia, wtedy lock jak najbardziej powinien się znaleźć, kiedy repo to służy do pusha na produkcje, ale to jest akurat biblioteka, która ciągle się zmienia, wiec i zmienia się wersja naszych zależności i silne wiązanie w tym wypadku jest niekoniecznie dobrym pomysłem biggrin.gif

Napisany przez: nospor 20.08.2017, 16:16:23

Cytat
i raczej jeśli nie piszemy w Laravelu, to nie dostaniemy nagle BC breaka,

Wlasnie, "raczej"....

composer.lock zawiera aktualnie zainstalowane i przetestowane pakiety. To z niego ma isc wszystko na produkcji a nie na produkcji radosnie pobieramy sobie wszystko co nowe bez zadnych testow.
w vendor mamy mase zewnetrznych bibliotek pisanych przez ludzi i jak wszystko zawierajacych bledy. I nie mowa tu tylko o Laravel.

Ostatnio w symfony zrobili BC break i zamiast strony logowania mialem komunikat o wyjatku. Wszystko dlatego ze ktoryms momencie chlopaki od symfony zmienili kolejnosc Exception Handlerow. Na szczescie composer update robimy na dev/test i zostalo to wylapane w mig i wstrzymane z wrzuta na serwer live. Na bugfixa od symfony musialem czekac prawie miesiac po tym jak im to zglosilem.
Nie wyobrazam sobie robic composer update na serwerze live. To jakis zart. tongue.gif

Napisany przez: com 20.08.2017, 16:42:21

nospor

Ok, w tym wypadku się z Tobą w 100% zgadzam, tylko że jak mamy dobrze zorganizowany deploy, to najwyższej wyłoży się nam na budowaniu i testach, oczywiście jak rzucamy żywcem paczkę wprost z naszego repo to jak najbardziej, to ma znaczenie, o czym i Ty wspominasz i ja wspomniałem, ale się minęliśmy bo to dodałem chwile później biggrin.gif Dobrze uznajmy że lock zostaje, będzie bezpieczniej biggrin.gif
update na produkcji, nigdy w życiu biggrin.gif mówiłem o wersji dev, bo to tutaj to dopiero jest baza do kodu produkcyjnego, to jest tylko zależność w composerze, nie sam kod produkcyjny tongue.gif

I w tym momencie właśnie kuleje to co kolega przygotował, przez brak testów. Bo nic nie wiemy o integracji z zewnętrznymi zależnościami i czy tak jak u Ciebie nie ma gdzieś BC breaka. Akurat tego typu framework/biblioteka, powinna być dobrze pod tym względem przetestowana i wtedy mamy aktualny i działający kod. Tu bez wątpienia ratujemy się własnie tym lockiem, ale to nie znaczy, ze to dobre podejście jest biggrin.gif

Osobiście locka bym widział tu: https://github.com/primosz67/spark-mvc-example, dałeś przykład Symfony tu: https://github.com/symfony/symfony też go nie ma, a tym jest w teorii https://github.com/primosz67/tahona-spark-mvc, za to jest tutaj https://github.com/symfony/symfony-demo, czyli tak jak wspomniałem u nas było by to https://github.com/primosz67/spark-mvc-example tongue.gif bo dopiero tam defakto piszemy kod który wyleci na produkcje biggrin.gif

Napisany przez: nospor 20.08.2017, 18:57:45

Cytat
Osobiście locka bym widział tu: https://github.com/primosz67/spark-mvc-example, dałeś przykład Symfony tu: https://github.com/symfony/symfony też go nie ma, a tym jest w teorii https://github.com/primosz67/tahona-spark-mvc, za to jest tutaj https://github.com/symfony/symfony-demo, czyli tak jak wspomniałem u nas było by to https://github.com/primosz67/spark-mvc-example tongue.gif bo dopiero tam defakto piszemy kod który wyleci na produkcje biggrin.gif
ok, teraz ja sie z toba zgadzam smile.gif

Napisany przez: Pyton_000 21.08.2017, 06:48:58

Tu jest dobrze wyjaśnione: https://stackoverflow.com/questions/12896780/should-composer-lock-be-committed-to-version-control

Napisany przez: primosz67 23.08.2017, 16:09:46

Cytat(com @ 20.08.2017, 15:44:04 ) *
Sonar jest tak samo do PHP jak do Javy, tylko dorzucić trzeba bo go nie dają w paczce tongue.gif
vendor, composer.lock wrzuć do gitignora, bo one w repo są zbędne wink.gif


Hm o sonarze nie pomyślałem, ale chyba tak zrobie. Bo kod sam w sobie jest bliżej php 5.3 z przebłyskami tongue.gif

Napisany przez: emp 25.08.2017, 08:32:32

Cytat(nospor @ 4.08.2017, 09:21:34 ) *
Unikaj zbednych linii kodu
Nie
  1. public function getNamespaces() {
  2. if ($this->hasMultipleNamespaces()) {
  3. return $this->namespace;
  4. } else {
  5. return http://www.php.net/array($this->namespace);
  6. }
  7. }


a:
  1. public function getNamespaces() {
  2. return (http://www.php.net/array)return $this->namespace;
  3. }


No tu mnie zaskoczyłeś że wolisz taki nieczytelny "syf" z dwoma returnami w jednej instrukcji. Ja tam stanowczo wole więcej linii kodu jeśli tylko objaśnia to lepiej sam kod i powoduje że kod staje się czytelniejszy. Nie wiem czy dalej cie lubię. Musze to teraz przemyśleć wink.gif

Napisany przez: nospor 25.08.2017, 09:24:45

Haha, dzieki emp za zwrocenie uwagi. Kopiowalem na szybko i nawet nie dolukalem. Oczywiscie mialo byc

  1. return (http://www.php.net/array) $this->namespace;


Wielki brat czuwa smile.gif

Cytat
Ja tam stanowczo wole więcej linii kodu jeśli tylko objaśnia to lepiej sam kod i powoduje że kod staje się czytelniejszy.
No wlasnie, slowo klucz: JESLI wink.gif W tym wypadku wydaje mi sie iz moja (poprawiona) wersja jest bardziej czytelna

Napisany przez: emp 29.08.2017, 11:26:41

Cytat(nospor @ 25.08.2017, 08:24:45 ) *
Haha, dzieki emp za zwrocenie uwagi. Kopiowalem na szybko i nawet nie dolukalem. Oczywiscie mialo byc

  1. return (http://www.php.net/array) $this->namespace;


Ja myślałem że to jakaś sztuczka z tymi 2 returnami. Nie potrafiłem zrozumieć jej działania ani przeznaczenia, ale nie chciałem się do tego przyznać że nie rozumiem ( bynajmniej nie na forum wink.gif ). Założyłem że prędzej ja nie rozumiem niż ty się mylisz wink.gif
Oczywiście wole krótszy, zwięzły kod od dłuższego.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)