sobota, 4 kwietnia 2015

Filary programowania obiektowego - Hermetyzacja

Hermetyzacja jest częściej znana pod angielskim odpowiednikiem "encapsulation" - enkapsulacja.

Czym jest? W prostych słowach to osłonięcie pewnej części lub całego obiektu przed wścibskimi oczami innych obiektów/odbiorców. To co jest za zasłoną to struktura obiektu, jego dane w postaci zmiennych oraz funkcjonalności w postaci metod/procedur. Poza zasłoną pozostawione powinno być tylko to co jest potrzebne - jakkolwiek enigmatycznie to brzmi, w istocie jest proste - nie pokazuj tego co nie potrzebne/nie używane/nie potrzebne przez innych.

Po co? Stosowanie w odpowiedni sposób hermetyzacji po części zwalnia programistę z konieczności pamiętania lub znajomości implementacji, ale moim zdaniem przede wszystkim pozwala na zachowanie kontroli, spójności funkcjonalności oraz uniknięciu wielu błędów. Jeżeli nie pozwolimy innym obiektom modyfikować właściwości obiektu hermetycznego i pozwolimy korzystać tylko z danych funkcjonalności możemy być pewni że obiekt zachowa się w sposób przewidywalny. Co więcej  obiekt hermetyczny jest bardzo łatwy w obsłudze i utrzymaniu przez innych programistów, a to z punktu widzenia utrzymania projektu i jego rozwoju w przyszłości jest już wyraźną wartością dodaną.

Jak ją uzyskać? Najprostszym sposobem jest użycie odpowiednich modyfikatorów dla pól i metod. W przypadku Javy takimi modyfikatorami są: private, protected, public i modyfikator pakietowy (domyślny). Są to już konkretne funkcjonalności języka programowania, który jeżeli chce nazywać się obiektowym musi taką funkcjonalność zapewniać. Nie wchodźmy na razie w szczegóły danego języka.

Często w mojej pracy zawodowej pisałem pewne klasy od podstaw i nie raz zastanawiałem się czy po prostu nie wygodniej byłoby uczynić wszystkie zmienne publicznymi. Będzie się wtedy łatwiej wszystko ustawiać, nie tracąc czasu na pisanie metod które pozwalają na dostanie się do danych zmiennych. Spójrzmy na przykład.

class Samochód {

       public Silnik silnik;
       public Kierownica kierownica;

       public void jedź() {
            // Tutaj mamy jakąś logikę odpowiedzialną za jazdę
            // która oczywiście wykorzystuje silnik i kierownicę
       }
}

Czyż nie łatwo w takim samochodzie wymienić silnik i kierownicę? Wszystkie obiekty mają taką możliwość i robią to bez problemowo. Zastanówmy się nad konsekwencją takiego działania.

Raz wywołana metoda jedź() pozwoli na jazdę samochodowi. Ale skoro wszystkie obiekty mają łatwość zmiany silnika i kierownicy, możemy założyć że jakiś "złoczyńca" ustawi nam kierownicę na jakąś nie ciekawą wartość (np. w Javie na null).

Kolejna próba wywołania metody jedź() może już się skończyć tragicznie dla kierowcy i pasażerów auta. Jeżeli uniemożliwimy innym obiektom dostęp do silnika i kierownicy w tym przypadku możemy spać i jeździć spokojnie.

Widać wyraźnie jak bardzo się myliłem w stwierdzenie zawartym w pierwszym akapicie tego paragrafu. Nie mniej jednak co by było gdyby nie było metody jedź(), gdy obiekt miałby służyć tylko przekazaniu pewnej grupy obiektów dalej. Taka sytuacja ma miejsce dość często. Jest to typowy błąd architektoniczny, który trzeba rozwiązywać jak najwcześniej na etapie pisania kodu. Tworzenie obiektów transferowych (do przeniesienia innych obiektów) nie jest najlepszą praktyką.


środa, 18 marca 2015

Filary programowania obiektowego - Polimorfizm

Początek

Zawsze musi być jakiś początek. Gdy chcemy zacząć przygodę z programowaniem obiektowym warto poznać pewne podstawowe pojęcia, nazwijmy je tutaj filarami. W kolejnych postach postaram się opisać każdy z nich.


Filary programowania obiektowego

  1. Polimorfizm
  2. Hermetyzacja
  3. Dziedziczenie

W liceum nauczyłem się programować w języku Turbo Pascal. W mojej  głowie nie istniały wówczas pojęcia "paradygmatu", "obiektowości", "programowania strukturalnego", a programowanie rozumiałem jako lista instrukcji wydana magicznemu interpreterowi, który zamieniał je w funkcjonujący byt.

Próbując poznać sekrety programowania obiektowego jednym z pierwszych pojęć był polimorfizm. Ten pochodzący z greki wyraz skrywał w sobie wówczas wiele tajemnic. Samo pojęcie polimorfizmu używane jest przez wiele nauk.


Polimorfizm w kontekście

Polimorfizm to mechanizm, który pozwala obiektom danego typu zachowywać się różnie, adekwatnie do implementacji.

A może konkretniej? 

Ludzkie zachowanie może być rozumiane jako polimorficzne. Przykładem jest np. jedzenie.Załóżmy, że typem jest Człowiek. Konkretną implementacją abstrakcji jaką jest Człowiek niech będzie konkretna osoba, np. Jan Kowalski (konkretna osoba). Drugą implementacją człowieka niech będzie mieszkający w Chinach Ju Li Wang.

Człowiek człowiek1 = new Polak("Jan Kowalski")

Człowiek człowiek2 = new Chińczyk("Ju Li Wang")
 

Polimorficzne wywołanie

Polimorficznym wywołaniem nazywamy wywołanie metody danego obiektu na konkretnej jego implementacji. Obiekt zachowa się wówczas adekwatnie do swojej implementacji.

Załóżmy, że Człowiek definiuje metodę 'jedz()'.

człowiek1.jedz()
człowiek2.jedz()

Zauważmy, że każdy z obiektów zdefiniowany jest jako typ 'Człowiek' i jest osiągalny przez referencję tego typu. Tutaj dochodzimy do warunku wywołania polimorficznego. 

Warunek polimorfizmu

Polimorficzne zachowanie obiektu będzie możliwe tylko wtedy gdy odwołujemy się do niego za pomocą wskaźnika/referencji.

Polimorfizm pozwoli tutaj każdemu z obiektów zachować się zgodnie ze swoją implementacją.
Polak zje danie nożem i widelcem, a Chińczyk używając pałeczek, tak jak został nauczony i tak jak potrafi (bardziej abstrakcyjnie - obiekt zachowa się tak jak został zaprogramowany)

Polimorfizm sam w sobie jest cechą. Cechą, którą mają wszystkie obiekty (w programowaniu obiektowym) i wcale nie jest taki straszny na jaki brzmi i jak go malują. Pozwala pisanym programom być w łatwy sposób rozszerzalnymi, poprzez dopisywanie nowych implementacji w nowych klasach a w połączeniu z dziedziczeniem daje wprost mieszankę wyjątkową ale o tym w następnym poście.


piątek, 13 marca 2015

Pierwszy post!

To jest pierwszy post na moim blogu

Witam wszystkich entuzjastów programowania. Na moim blogu postaram się nieco przybliżyć zagadnienia związane z programowaniem obiektowym oraz funkcjonalnym. Będę również poruszać tematy związane z programowaniem w konkretnych językach min. JAVA, Scala.

Na początek kilka słów jak zaczęła się moja przygoda z programowaniem.

Nieświadomy początek

Swoją przygodę z programowaniem zaczynałem na przełomie gimnazjum i liceum. W tych latach premierę swoją miała gra Neverwinter Nights. Razem z moim siostrzeńcem spędzaliśmy bardzo dużo czasu przed ekranem komputera - co przełożyło się na mój wzrok (po minus jednej dioptrii na każdym oku) - nie widzieć czemu - oczy siostrzeńca nie ucierpiały wcale.

Po wielu godzinach spędzonych na walce z potworami i zdobywaniu punktów doświadczenia dobrnęliśmy do końca rozgrywki. Dopadło mnie wtedy uczucie pustki i braku celu. Odkryłem wtedy moduł do tworzenia własnych plansz i questów. Kolejne godziny mijały mi na tworzeniu rozległych lokacji. Najciekawsze rzeczy jednak dotyczyły możliwości oskryptowania akcji, wykorzystywania czarów zdefiniowanych w grze oraz wprowadzania interakcji gracz/NPC i gracz/środowisko.

Opierając się na bardzo nielicznych przykładach z internetu, do którego jeszcze wtedy łączyliśmy za pomocą antycznego już numeru 0202122 i magicznych credentiali ppp/ppp, tworzyliśmy swoje pierwsze skrypty, a czasami całe programy niekiedy sięgające setek linii kodu. Co najdziwniejsze, tworzyliśmy to jedynie na podstawie przykładów i metod prób/błędów nie mając jakiegokolwiek pojęcie o programowaniu.

Po latach z łezką nostalgii wspominam te niewinne czasy, gdy nie miało się świadomości z tego że używa się C++. Umysł wolny był wtedy od matematycznych podstaw programowania, czy jakichkolwiek tzw. "dobrych praktyk". Tworzyło się rzeczy tak aby działały, często spędzając wiele godzin na uzyskaniu zamierzonego efektu. Jak mawiają miłe złego początki, a te początki rzeczywiście dostarczyły mi wiele radości i satysfakcji że udawało się coś doprowadzić do działania.

Duch niepokorny



Czasem warto iść pod prąd. Na IV-tym roku studiów wyjechałem na wymianę studencką do Finlandii gdzie zapisałem się na kurs Javy i od tamtej pory już się nie rozstaliśmy. Po powrocie do Polski już wiedziałem co chcę w życiu robić. Całą energię poświęciłem na to by kończąc studia mieć na tyle wiedzy by zostać programistą. Bardzo cieszyłem się z tego, że kolejny raz ciężka praca dała swoje efekty i do dzisiaj mogę realizować swoje marzenia.