Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM    Subskrybuj kanał ATOM dla tagu php Kanał ATOM (tag: php)

Autor wpisu: l3l0, dodany: 24.03.2011 22:20, tagi: symfony, php

Nauka przez testy jednostkowe

Ostatnio dowiedziałem się jaką wartość ma pisanie testów, gdy uczymy się nowej technologii lub biblioteki. Otóż napisałem klika testów do Symfony2. Chociaż było to tylko klika testów, naprawdę dużo się nauczyłem. Powiedzmy żę chcemy nauczyć się czegoś o routingu w Symfony 2.

Jak zacząć?

Najpierw powinniśmy objerzeć testy które są w komponencie. Często to wystarczy żeby zroumieć jak on działa. Jeśli mamy jakieś wątpliwości powinniśmy je rozwiązać pisząc nowy test i próbując, nawet coś popsujmy żeby zobaczyć co się stanie. Możemy próbować nieograniczoną liczbę parametrów i kombinacji. Testy jednostkowe mają tą zalete że wykonują się szybko więc szybko upewnią nas czy nasze przypuszczenia są poprawne. To podejście jest nawet lepsze gdy mamy jakiś gówniany kod.

Stary kod i też może… być testowany

Napewno znasz to uczucie gdy musisz dodać nowy kod do 6 letniego projektu o którym wszyscy zapomieli… ty nawet nie wiesz gdzie zacząć. Ja, w takim wypadku, zaczynam od ustawienia mojego środowiska testowego (albo od naprawienia i posprzątania środowiska testowego o ile istniało). Nastepnie powinniśmy przeanalizować kod i stwierdzić w których miejscach będziemy musieli zrobić zmiany. Przed dodaniem nowego kodu trzeba stworzyć test, jednak ważniejsze w tym momencie są testy dla functionalności w której grzebiemy. Jeśli nie ma testów musimy je utworzyć. Aby utworzyć testy musimy zanalizować kod. Czasami (nawet często) kodu nie da się przetestować, wtedy musimy troche pohakować (ostrożnie!) tak aby kod stał się testowalny. Po tym procesie możesz dodać nowe funkcionalności, co powinno być już łatwiejsze – twoja wiedza o kodzie wzrosła. Kodowanie teraz powinno być przyjemne, a testy powinny dać Ci większą pewność i oszczędzić dużą ilość stresu. Oczywiście twój kod jest teraz jakościowo lepszy.

Jakość i prostota kodu, a testy jednostkowe.

Testowanie powinno pomóc Ci tworzyć prosty kod, powinno Ci też pomóc tworzyć kod wysokiej jakości. Owszem ale tylko gdy robisz TDD. O ile pisanie testów po kodzie ma sens w czasie nauki, o tyle nie jest to dobre podejście z punktu widzenia projektowego, nie pomaga też tworzyć prostego kodu bo kod jest już stworzony. Pisanie testów przed kodem pomaga ustalić publiczne API oraz przede wszystkim wymagana od nas (programistów) myślenia przed napisaniem kodu. W TDD napierw piszemy test, potem kod ale tylko taki który sprawi że nasz test przejdzie (nawet głupi). Następnie musimy sprawić aby następne testy przeszły, jednak po każdej takiej iteracji powinnismy usuwać duplikaty kodu (zasada DRY czyli że nie powtarzamy się). Testy powinny być zdefiniowane tak aby otestować jak najbardziej nasze oczekiwania w stosunku do klasy.

Jest naprawdę wiele powodów żeby używać testów jednostkowych, tymbardziej nie mogę zrozumieć czemu istnieje tak wiele aplikacji bez testów.

Tutaj mam prośbę: Aplikacje potrzebują pomocy, gdy znajdziecie jakąś smutną aplikację bez testów, zlitujcie się i napiszcie parę testów!

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: singles, dodany: 24.03.2011 18:26, tagi: javascript, php, zend_framework

W dzisiejszym wpisie z serii ZFQT chciałbym przybliżyć temat helperów z rodziny head[type]. Oprę się na przykładzie headScript, ponieważ jest on jednym z najczęściej używanych helperów podczas tworzenia aplikacji ZF. Służy do zarządzania/dołączania skryptów JS w ramach naszej aplikacji.

Niektórzy powiedzą pewnie:

Po co mi jakaś klasa do dołączania skryptów? To przecież takie proste jest.

W przypadku większych projektów zdarza się, że posiadamy jeden/dwa główne skrypty – najczęściej jest to jakiś framework JS + biblioteka UI. Jednak, niektóre ze stron naszej aplikacji wymagają specyficznego dla siebie kodu. A dołączanie wszystkich potrzebnych plików dla każdej strony, nawet jeśli nie są one tam wykorzystywane, ciężko nazwać postępowaniem rozsądnym. Najlepiej byłoby załączać najczęściej używane pliki w głównym layoucie, a specyficzne skrypty tylko w przypadku niektórych akcji.

Jeśli by się głębiej nad tym problemem zastanowić, to fajnie byłoby mieć taki „koszyk”, do którego można by wrzucać potrzebne skrypty – w zależności od potrzeb – podczas wykonywania kodu, a wyświetlać je na samym końcu. W takim właśnie celu powstał helper headScript w ZF (oraz jego „bracia”). Konkretniej mówiąc, powstał helper placeholder, po którym wspomniane helpery head dziedziczą. Ich działanie (w skrócie) polega właśnie na agregowaniu tekstu/kodu/danych. Dobre wyjaśnienie znajdziecie w dokumentacji do ZF – jest tam także lista wszystkich klas dziedziczących po placeholder.

Nieprawidłowa kolejność skryptów w przypadku headScript

Jest jeden konkretny powód, dlaczego napisałem, że oprę się na helperze headScript. Otóż to, w przeciwieństwie do jego „braci”, w jego przypadku ważna jest kolejność, w jakiej skrypty dołączone. Prosty przykład – mamy jQuery, jQueryUI oraz kawałek kodu, który wspominane biblioteki wykorzystuje. Po szybkim przejrzeniu dokumentacji pierwsze podejście będzie wyglądało pewnie tak:

<?php echo $this->doctype(Zend_View_Helper_Doctype::HTML5); ?>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>SampleApp</title>
</head>
<body>
    <p>[menu] | [menu] | [menu] | [menu] | [menu] | [menu]</p>
    <?php echo $this->layout()->content ?>
 
<!-- scripts -->
<?php echo $this->headScript()->appendFile('http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js')
                              ->appendFile('ttps://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js'); ?>
</body>
</html>
 
//application/views/index/index.phtml
<div id="dialog-content" title="Basic dialog">
	<p>This is the default dialog which is useful for displaying information. The dialog window can be moved, resized and closed with the 'x' icon.</p>
</div>
<?php $this->headScript()->appendScript(<<<JS
$(document).ready(function(
    //RB używamy pluginu dialog z jQuery UI.
    $('#dialog-content').dialog();
));
JS
);

Dlaczego dołączyłem skrypty na samym końcu? Ponieważ jest to dobra praktyka prowadząca do powstawania wydajniejszych aplikacji – patrz Yahoo Developer Network.

Po uruchomieniu takiego kodu otrzymamy jednak błąd.

error

Błąd JS przy nieprawidłowej kolejności skryptów

Zend Framework najpierw dołączył kod z widoku, a następnie te zdefiniowane w layoucie. Patrz screen:

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: matipl, dodany: 23.03.2011 08:20, tagi: php

php-logoKażdy programista PHP jest bardzo przyzwyczajony do wyglądu głównej strony projektu PHP. Strona nie zmieniała się mimo upływu lat (ostatnie zmiany w 2002), zmianie mody. Ostatnio nawet strona domowa Debiana zrobiła się bardziej trendy.

Nową stronę główną PHP.net możecie zobaczyć dodając do URL-a ?beta=1 albo wchodząc na http://www.php.net/my.php i włączając opcję PHP.net alpha.

php.net - nowa odsłona

Czy to rewolucja? Nie, raczej krok w dobrym kierunku. Strona jest teraz lżejsza wizualnie. Cały nagłówek jest nieznacznie niższy. Na stronie głównej w nowej wersji od razu rzuca się w oczy aktualna wersja PHP oraz tutorial dla początkujących. Mnie najbardziej cieszy zmiana w menu. Z poprzedniego w ogóle nie korzystałem, nawet nie pamiętam jakie tam sam linki, a teraz…

Nowe menu jest zgrabniejsze i zawiera mniej pozycji. Sekcje Documentation, Community oraz Help są rozwijalne dzięki czemu mamy szybki dostęp do najważniejszych haseł. Będziemy mogli od razu ze strony głównej przejść chociażby do działu dot. Garbage Collection. Nowy pasek menu będzie dostępny także w manualu.

php.net - nowy i stary manual

W manualu niewielkie zmiany. Dzięki niższemu nagłówkowi, pozbyciu się submenu z poprzednią i następną pozycją, oraz zmianie paska językowego widzimy teraz więcej na ekranie (o jakieś 100 pikseli,~ 4 linijki tekstu). Niestety nie mogę znaleźć informacji od kiedy trwają prace i kiedy się zakończą.

Dla potomnych zrzut ekranu aktualnej wersji php.net:

php.net - wersja 2002-2010

Autor wpisu: batman, dodany: 23.03.2011 08:00, tagi: php

Przy okazji pisania biblioteki do wysyłania powiadomień z aplikacji opartej o Zend Framework, odświeżyłem (a w zasadzie poznałem na nowo) bibliotekę PHPUnit. Nie obyło się bez zgrzytów, zwłaszcza podczas korzystania z PEAR. Aby w przyszłości nie musieć szukać kolejny raz szukać tego samego postanowiłem przygotować ten oto poradnik instalacji PEAR oraz PHPUnit na serwerze WampServer.

Instalację zaczniemy od PEAR. Wbrew pozorom nie jest to czarna magia i jedyne co trzeba robić, to uważnie czytać komunikaty pojawiające się na ekranie. Zatem do dzieła.

  1. Przed instalacją musimy upewnić się, że mamy zainstalowane i działające rozszerzenie Phar. Warto również w pliku php.ini odkomentować opcję phar.require_hash oraz ustawić jej wartość na Off.
  2. Następnie otwieramy wiersz poleceń (cmd) i przechodzimy do katalogu, w którym zainstalowany jest PHP. W moim przypadku jest to C:\wamp\bin\php\php5.3.5
  3. Znajdując się we wspomnianym wyżej katalogu uruchamiamy skrypt go-pear.bat
  4. Proces instalacji PEAR rozpoczyna się od wyboru rodzaju instalacji. Wpisujemy local i zatwierdzamy enterem.
  5. Postępujemy zgodnie ze wskazówkami pojawiającymi się w kolejnych krokach instalacji. Wszystkie ustawienia pozostawiamy domyślne oraz zezwalamy na dokonanie zmian w php.ini
  6. Podczas instalacji pojawi się najprawdopodobniej błąd ERROR: unable to unpack phar://C:/wamp/bin/php/php5.3.5/PEAR/go-pear.phar/PEAR/go-pear-tarballs/Structures_Graph-1.0.2.tar. Błąd ten oznacza, że jeden z najbardziej potrzebnych komponentów nie zainstalował się i trzeba zrobić to ręcznie. W tym celu ze strony http://pear.php.net/package/Structures_Graph/download pobieramy paczkę, następnie ją rozpakowujemy i kopiujemy katalog Structures wraz z zawartością do głównego katalogu PEAR. W moim przypadku znajduje się on tutaj – C:\wamp\bin\php\php5.3.5\PEAR
  7. Pozostało jeszcze dodać odpowiednie zmienne środowiskowe. Pomoże nam w tym plik PEAR_ENV.reg znajdujący się w katalogu instalacyjnym PHP (u mnie jest to C:\wamp\bin\php\php5.3.5). Zanim go wykonamy musimy upewnić się, że zmienna PHP_PEAR_PHP_BIN poprawnie wskazuje na plik php.exe. Jeśli nie, to musimy poprawić ten wpis.
  8. Na koniec pozostało przetestowanie czy PEAR działa. Doskonale nadaje się do tego próba aktualizacji pear-a. W wierszu poleceń wpisujemy pear upgrade i czekamy na zakończenie aktualizacji. Jeśli po drodze nic niespodziewanego się nie wydarzyło, oznacza to, że pear jest poprawnie zainstalowany. Podczas wykonywania aktualizacji może się okazać, że będziemy musieli włączyć dodatkowe rozszerzenia w PHP. Będą to XML_RPC oraz Curl.

Po przebrnięciu przez instalację PEAR, instalacja PUPUnit będzie formalnością. Wygląda on następująco.

  1. Dodajemy niezbędne kanały: pear channel-discover pear.phpunit.de pear channel-discover components.ez.no pear channel-discover pear.symfony-project.com
  2. Instalujemy PHPUnit pear install phpunit/PHPUnit
  3. Aktualizujemy PHPUnit pear upgrade phpunit/PHPUnit

Na koniec pozostało sprawdzić, czy wszystko działa jak należy. W tym celu w wierszu poleceń wpisujemy phunit. W wyniku powinniśmy otrzymać informację z pomocą.

Autor wpisu: Kamil, dodany: 23.03.2011 00:52, tagi: php, javascript

Każdy kto używał jQuery i tworzył pod niego pluginy to zdążył już zapoznać się z genialną metodą $.extends służącą w głównej mierze do łączenia kilku obiektów z nadpisywaniem istniejących już metod / własności. Najczęstszym wykorzystaniem niniejszej metody jest łączenie dwóch obiektów: z domyślnymi parametrami danego obiektu, z ustawieniami zdefiniowanymi przez użytkownika. Najlepiej i najłatwiej będzie [...]

Autor wpisu: sokzzuka, dodany: 22.03.2011 22:38, tagi: javascript, php

Kolejny odcinek serii o języku Scala zajmie się kwestią traits – cech. Jest to o tyle ciekawa część języka, że w PHP również zostaną one wprowadzone w najbliższej wersji 5.4 . Traits w PHP zainspirowane zostały właśnie bezpośrednio implementacją z Scali.

Czym jest trait ? Trait jest elementem języka służącym do zapewnienia dziedziczenia poziomego. Co oznacza dziedziczenie poziome ?

Ażeby dowiedzieć się czym jest dziedziczenie poziome, najpierw musimy ustalić czym jest dziedziczenie pionowe. Dziedziczenie pionowe, takie jakie znamy np. z PHP i Javy zakłada, że każda klasa potomna może dziedziczyć tylko z jednej klasy bazowej. Wszelkie metody i pola oznaczone przez „protected” obecne są też w klasie potomnej.  Jednak co najważniejsze – klasa potomna jest podtypem klasy bazowej. Dziedziczenie oznacza, że klasa B jest również typu A .Ilustruje to poniższy przykład hierarchii klas znany z lekcji biologii:

Zwierzęta -> Strunowce -> Kręgowce -> Ssaki -> Walenie -> Delfiny -> Delfin Słodkowodny

Dziedziczenie poziome natomiast jest sytuacją gdy jakiejś klasie chcemy rozszerzyć funkcjonalność nie zaburzając wcześniej przedstawionej pionowej hierarchii klas. Weźmy dla przykładu naszego delfina i jego kolegę po miedzy – szympansa. Załóżmy, że chcemy zarówno delfina jak i szympansa nauczyć jakiś sztuczek np. salta w tył. Oczywiście moglibyśmy dodać metodę „salto w tył” abstrakcyjnej klasie „ssaki” z której dziedziczą szympans i delfin lub dodać kolejną klasę pośrednią. Natomiast pada pytanie jaki ma to sens ? W końcu tylko szympansy i delfiny umieją takie śmieszne sztuczki, natomiast inne ssaki nie są na tyle sprytne, żeby to wykonać. Generalnie wtłaczanie takiej cechy  w dziedziczenie pionowe jest działaniem troszkę „na siłę”.  Na szczęście mamy traity zwane też cechami. Traity w dowolnej ilości można „wczepić” do dowolnej klasy.

Traity często opisywane są jako interfejsy posiadające implementacje. Jest to dobre skojarzenie – implementacja przez jakąś klasę interfejsu oznacza, że posiada ona pewną funkcjonalność. Dołączenie traita do klasy znaczy dokładnie to samo, z tą różnicą, że trait może posiadać konkretną implementację.

Najwyższy czas pokazać, jak traity wykorzystywane są w praktyce w języku Scala. Trait, który przedstawię, będzie posiadał tylko jedną metodę – „toArray”.  Będzie ona zwracała wszystkie zmienne istniejące w obiekcie w postaci obiektu klasy HashMap, który jest odpowiednikiem PHP-owego „arraya„. Przy okazji dowiemy się co nieco o refleksji oraz o domknięciach leksykalnych i iteracji.

Kod:


trait ToArray {
  def toArray: HashMap[String, Any] = {
    val vars = new HashMap[String, Any]()
    val className = this.getClass.getName

    def extractFields(className: String):HashMap[String, Any] = {
      val currentClass = java.lang.Class.forName(className)
      val superClass = currentClass.getSuperclass

      if(superClass == null){
        return vars
      }
      val fields = currentClass.getDeclaredFields

      fields.foreach((field:java.lang.reflect.Field) => {
          field.setAccessible(true)

          val name = field.getName
          val value = field.get(this)
          vars += name -> value

          field.setAccessible(false)
        })

      return extractFields(superClass.getName)
    }
    extractFields(className)

    return vars
  }
}

Metoda „toArray” jest funkcją zwracającą obiekt typu HashMap, gdzie klucz ma postać tekstową (String), natomiast wartość może być dowolnego typu (Any), jest ona również zadeklarowana jako stała – „vars„.

By pobrać nazwę klasy, w której znajduje się trait, używamy metody this.getClass, która zwraca nam Javowy obiekt reprezentujący klasę. Posiadający metodę, która zwraca nam jej nazwę „getName„. Następnie zdefiniowana jest funkcja extractFields, która jest jednocześnie domknięciem – importuje do swojego kontekstu stałą „vars„. Rekurencyjnie przemieszcza się ona w górę hierarchii klas i pobiera listę zadeklarowanych pól i dołącza je do stałej vars. Pragnąłbym zwrócić tutaj szczególną uwagę na sposób w jaki jest dołączany kolejny element do „arraya„. W PHP zrobilibyśmy coś takiego:

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Autor wpisu: Wojciech Sznapka, dodany: 22.03.2011 17:13, tagi: php, apache

If you are developing PHP application on your own PC, you probably have some vhost based configuration of your Apache. With some tricks, you can turn your Linux box into powerful development server without configuring vhost for every app . In the minimum configuration effort, you need to pass those steps: checkout repository to disk [...]
Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.