poniedziałek, 28 listopada 2011

Programistyka na Google+ i Facebooku

social networks, I'm coming:)

Witam, dzisiaj krótki wpis całkowicie nie powiązany z programowaniem obiektowym.

Chciałem zaprosić wszystkich zainteresowanych programowaniem obiektowym do obserwowania mojej strony na facebook'u lub/oraz na google+.

piątek, 18 listopada 2011

Jak programować obiektowo cz. 4 - metody klas II

ciągle o tym samym

W dzisiejszym wpisie kontynuuje wątek z poprzedniego wpisu, a więc nadal będzie o metodach:)
Dzisiaj zbiór wszelkich różnych rzeczy dotyczących metod, czyli trochę informacji, a trochę dobrych praktyk, które warto przestrzegać, aby z kodem przyjemniej się pracowało:)

czwartek, 10 listopada 2011

Jak programować obiektowo cz. 3 - metody klas I

po długiej przerwie

Trochę to potrwało zanim znalazłem chwilę czasu, żeby coś napisać, ale mam nadzieję, że warto było czekać:) Postaram się, żeby kolejne wpisy z tej serii pojawiały się częściej, a że w najbliższym czasie nie planuję już żadnych długoterminowych prac, myślę, że jest to założenie, które uda mi się zrealizować.
Dobra, bez dłuższego przynudzania, zaczynam. Dzisiaj kilka słów o metodach, czyli:

sobota, 8 października 2011

Jak programować obiektowo cz. 2 - atrybuty klasy

wstęp

Na potrzeby wszystkich wpisów z tej serii zdecydowałem się, w miarę możliwości, skupić je wokół jednego przykładu. Oczywiście nie będę przeprowadzał żadnej analizy wymagań, ani specjalnie rozwodził się nad całą strukturą i pełną funkcjonalnością, będę poruszał jedynie te aspekty aplikacji, które będą bezpośrednio powiązane z danym wpisem. Dzięki takiemu praktycznemu przykładowi mam nadzieję, że uda mi się przedstawić myślenie, które kryje się za większością decyzji projektowych oraz pozbędę się zbędnego teoretyzowania i przykładów, które nijak nie pokrywają się z rzeczywistością.
Dzisiaj chciałbym skupić się na atrybutach klasy, więc na początek trochę teorii.

wtorek, 20 września 2011

Jak programować obiektowo cz.1 - wstęp

trochę przydługi wstęp...

Jest szereg tutoriali pokazujących jak wykorzystać techniki obiektowe, jak je zastosować w kodzie, ale w większości z nich brak jednej ważnej informacji - OOP to przede wszystkim obiektowe myślenie. Techniki i sposób ich implementacji w danym języku programowania są jak język mówiony i gramatyka, są czymś zmiennym. Natomiast sposób myślenia obiektowego, umiejętność podejmowania decyzji w kwestiach relacji między klasami jest czymś stałym. Nie ważne, czy piszesz kod w PHP, Javie, C++ itp., ponieważ, jeżeli potrafisz poprawnie zaprojektować strukturę, to będzie ona uniwersalna, zmieni się jedynie sposób przetłumaczenia tego na język zrozumiały dla interpretera/kompilatora.

A więc o czym to będzie?
Właściwie to o tym samym, co wszędzie, czyli podstawy takie, jak: dziedziczenie, interfejsy, abstrakcje, hermetyzacja itd. Z tym, że oprócz przykładu użycia postaram się jeszcze przedstawić tok myślenia, który się za tym kryje. Tak, więc np. w dziedziczeniu nie chodzi tylko o to, że mamy dwie klasy Samochód i Samolot, które dziedziczą po abstrakcyjnej klasie Pojazd:)
Postaram się zaprezentować przykłady, kiedy dane rozwiązanie jest niekoniecznie dobre lub całkiem złe.
Tak naprawdę najwięcej będzie o myśleniu, bo w gruncie rzeczy do tego OOP się sprowadza. Ostatnim etapem dobrego programowania obiektowego jest pisanie kodu.

poniedziałek, 19 września 2011

self, parent i static

W PHPie istnieją trzy przydatne słowa kluczowe będące referencją do metod oraz atrybutów klas. Wykorzystuje się je przy dziedziczeniu i są to: self, parent, static.

piątek, 12 sierpnia 2011

public, protected czy private? Oto jest pytanie!


O tym czym różnią się operatory widoczności można przeczytać tutaj.
Ostatnio zauważyłem dziwną tendencję do używania jedynie dwóch z nich, a mianowicie protected i public. Publiczne są metody (ewentualnie dane), które mają być dostępne na zewnątrz, a wszystko inne jest chronione. W myśl zasady: może kiedyś będę tą klasę rozszerzał. Osobiście nie zgadzam się z takim podejściem. Projektując klasę wiemy, co chcemy aby robiła, a takie wybieganie w przyszłość 'bo może coś się przyda' powoduje niepotrzebny śmietnik.

Moim zdaniem głównymi operatorami, na których powinien się opierać programista projektując klasę, to private i public, a dopiero w dalszej kolejności protected.

Decyzja o tym, którego operatora należy użyć będzie łatwiejsza o ile będzie się pamiętało o kilku rzeczach:
  • Enkapsulacja, czyli atrybuty klas powinny być prywatne. Dlaczego? Krótko i rzeczowo jest to wyjaśnione tutaj.
  • Gdy już mamy atrybuty klasy, trzeba zastanowić się do czego ta klasa będzie wykorzystywana i na tej podstawie należy zdefiniować metody publiczne, czyli te, które będą wykorzystywane przez inne klasy.
  • Jeżeli nie planujesz w obecnej chwili, aby klasa była rozszerzana, to wszystkie metody, które nie są wykorzystywane poza klasą powinny być prywatne. Jeżeli zakładasz, że "może w przyszłości", to również zostaw je jako prywatne. Kod nie jest stałym bytem, może ewoluować, a więc jeżeli zajdzie potrzeba, to zawsze możesz go rozszerzyć lub zmienić.
  • Jeżeli klasa będzie rozszerzana, to metodami chronionymi powinny być jedynie te, które są potrzebne w klasie pochodnej, a nie wszystkie niepubliczne.
  • Jeżeli klasa pochodna powinna mieć dostęp do atrybutów klasy, do których nie ma akcesorów, to nie oznacza, że należy zmienić widoczność atrybutów na protected. To oznacza, że można dodać chronione settery i/lub gettery.
  • Zastanów się trzy razy zanim podejmiesz decyzję o zmianie operatora private na protected w metodach, dziesięć razy jeżeli chcesz to zrobić z atrybutem.
  • Gruntownie przemyśl decyzję o wyciągnieciu metody na zewnątrz, czyli zmianie operatora na public. Rób to tylko wtedy, gdy metoda jest rzeczywiście potrzebna poza klasą.
  • Rzadko istnieje rzeczywista potrzeba zmiany operatora widoczności atrybutu z private na mniej restrykcyjny - protected. Jeszcze rzadziej zachodzi potrzeba upublicznienia atrybutu.

Mam nadzieje, że tych kilka wskazówek się przyda:)

wtorek, 9 sierpnia 2011

Zmienne globalne - a dlaczego nie?


Mimo rozwoju PHP pod kątem OOP, nadal zdarza się niektórym programistom uparcie tworzyć zmienne globalne. Dlaczego? Powód jest prosty i sensowny - w większości aplikacji występują zmienne, które powinny być dostępne w kilku miejscach. Oczywiście można przekazywać ową zmienną z obiektu do obiektu, ale z dwojga złego decydują się na użycie zmiennych globalnych.

Dlaczego takie rozwiązanie nie jest dobre? Abstrahując od faktu, że nie ma zbyt wiele wspólnego z programowaniem obiektowym, to zawsze istnieje możliwość przypadkowego nadpisania jej w innym miejscu w kodzie. Prawdopodobieństwo to zwiększa się, gdy nad kodem pracuje większa ilość programistów.

Więc jakie mamy alternatywy?

Jeżeli zmienna ma być jakąś stałą wartością, niezmienną w całym kodzie i jest typu podstawowego (int, float, bool, string, null), to można skorzystać z metody define() w celu utworzenia wartości stałej (constant).

Co innego, gdy naszą zmienną jest obiekt. W takim wypadku możemy skorzystać z wzorca Singleton, aby mieć pewność, że obiekt będzie posiadał jedną instancję, do której będziemy mogli się dostać w każdym fragmencie kodu poprzez wywołanie statycznej metody zwracającej tą instancję.

Czasami jednak mamy potrzebę przekazywania większej ilości zmiennych różnych typów. Z pomocą przychodzi wzorzec Property. Jest to pewnego rodzaju kontener na zmienne, do których dostęp powinien być możliwy z każdego miejsca w kodzie.

Wybranie dowolnego z tych rozwiązań powinno być jednak gruntownie przemyślane, ponieważ tego typu obiekty utrudniają testowanie (szczególnie klasy implementujące wzorzec singleton). Poza tym nadużywanie któregokolwiek rozwiązania może przyczynić się do zmniejszenia czytelności kodu.

sobota, 23 lipca 2011

Własne wyjątki - a na co mi to?


O tym, czym są wyjątki można przeczytać w wikipedii lub na php.net. Ogólnie rzecz biorąc wyjątki powinny być wyrzucane wtedy, gdy w jakiś sposób nasza aplikacja podejmie próbę wykonania niedozwolonej operacji lub nie będzie w stanie wykonać operacji.
Od wersji 5 PHP jest dostarczany z bardzo ciekawą biblioteką SPL, która narzuca pewną hierarchię wyjątków i dzieli je na dwie główne grupy:
  • RuntimeException - są to wyjątki, które powinny być wyrzucane, gdy aplikacja z pewnych względów nie może poprawnie działać np. zerwanie połączenia z bazą danych.
  • LogicException - są to wyjątki, które powinny być wyrzucane, gdy aplikacja próbuje wykonać operacje, które są błędne np. wywołanie nieistniejącej metody na przekazanym obiekcie.
Szerszy opis wszystkich wyjątków, które są dostarczone wraz z biblioteką SPL znajdziecie tutaj.

Dobra, po trochę przydługim wstępie, wracam do głównego wątku:) A więc po co tworzyć własne wyjątki? Przecież można z łatwości wpisać odpowiedni message do konstruktora tego bazowego (Exception) i po sprawie. Oczywiście, że tak można, ale tylko do momentu, gdy wyjątki są rzeczywiście tylko i wyłącznie kontenerem na jakąś informację.

Oczywiście powodów stosowanie wyjątków jest kilka, ja jednak pozwolę sobie skupić się na, moim zdaniem najważniejszym, czyli utrzymywaniem spójnej logiki tzn. jeżeli mam klasę Product, Product_Factory, Product_Collection etc. to dobrze jest mieć jeszcze Product_Exception, który będzie wykorzystywany w tych właśnie klasach i tylko w tych. Dzięki temu już po samym typie wyjątku wiem, gdzie się wysypała aplikacja, a do dokładniejszego określenia miejsca załamania powinno się wykorzystywać wartość $message.
Oczywiście można tutaj popaść w pewną skrajność i zacząć tworzyć wyjątki dla wszystkiego i tak dostajemy: Product_Exception, Product_Factory_Exception, Product_Collection_Exception etc., gdzie każdy wyjątek jest wyrzucany jeden, no góra dwa razy w całym kodzie. I po co to? Niestety jest to częsta przypadłość programistów, którzy dopiero odkryli tą cudowną możliwość dziedziczenia po klasie Exception - po prostu zapominają o tym, że wyjątek posiada jeszcze argument $message.

Niestety złotego środka nie ma i już we własnym zakresie trzeba zdecydować, czy to już powinien być kolejny typ wyjątku, czy jeszcze ten sam, z odpowiednią wiadomością. Granica jest płynna, ważne jest to, aby pamiętać o dwóch rzeczach:
  • Dziedziczyć po klasie Exception jest w PHP dozwolone.
  • Konstruktor klasy Exception posiada możliwość przyjmowania parametrów m.in. $message i $code.

czwartek, 21 lipca 2011

foreach() i for() - subtelna różnica


Pewnie dla wielu osób, które z php mają do czynienia od dłuższego czasu, ten wpis nie będzie niczym odkrywczym.
Czym różni się foreach() od for()? W wielu przypadkach nie ma żadnej różnicy dla logiki aplikacji, której pętli się stosuje i można je stosować zamiennie bez wpływu na jej działanie.

Więc gdzie jest różnica? Otóż foreach() przechodzi po elementach tablicy w kolejności dodawania wartości, natomiast for() jest używany do iterowania tablicy w zdefiniowany przez nas sposób.
Poniższy kod wyjaśnia wszystko:
<?php
$a = array();
$a[3] = 'a';
$a[1] = 'b';
$a[0] = 'c';
$a[2] = 'd';

$arrayCount = count($a);

echo "FOR: \n";
for ($key = 0; $key < $arrayCount; $key++)
    echo 'key: ' . $key . ', value: ' . $a[$key] . "\n\n";

echo "FOREACH: \n";
foreach ($a as $key => $value)
    echo 'key: ' . $key . ', value: ' . $value . "\n";

Wykonanie go daje taki wynik:
FOR:
key: 0, value: c
key: 1, value: b
key: 2, value: d
key: 3, value: a

FOREACH:
key: 3, value: a
key: 1, value: b
key: 0, value: c
key: 2, value: d