poniedziałek, 20 maja 2013

GeeCON 2013 - rekonstrukcja zdarzeń

Programowanie Funkcyjne

Ten temat pojawił się trzeciego dnia, więc pamiętam go najlepiej bo jako odpowiedzialny kierowca byłem wtedy trzeźwy i wyspany. Generalnie do czasu tej konferencji programowanie funkcyjne kojarzyło mi się jedynie z przetwarzaniem danych pomiędzy zbiorami gdzieś tam wewnątrz aplikacji (tak jak na matematyce dyskretnej w klasie 1 studiów). Aż tu na jednej prezentacji pojawił się rysunek podobny do poniższego (odtworzone z pamięci) :

Pewnie dla wyjadaczy scali, klołżerów i innych takich ten temat jest oczywisty jak składanie pita37 ale dla mnie to był moment oświecenia, że jako funkcję można przedstawić dowolne "coś" co dostaje na wejściu "cokolwiek" i zwraca "coś innego". I teraz taki Wzorzec Dekorator wydaje się być hakiem na obiekcie gdzie czymś bardziej naturalnym byłoby wywołanie f(g(x)) albo F(f1(x),f2(x),...) - jeśli dobrze zrozumiałem F to funkcja wyższego rzędu a fn funkcje niższego rzędu - czyli tutaj to mogą być np poszczególne walidatory w trakcie jednej wielkiej walidacji.

Jest jeszcze jedna ciekawa a być może nawet ważniejsza korzyść jaką może przynieść programowanie funkcyjne. Generalnie we wszystkich książkach o OOP we wstępie jest napisane, że właśnie ten sposób jest naturalny dla ludzi i dlatego wszystko pójdzie gładko. A to gówno prawda bo ludzie myślą w sposób proceduralny przez co bliżej nam do programowania imperatywnego co ma swoje potwierdzenie w kodzie większości studentów - masa ponakładanych na siebie ifów,forów i innego świństwa zamkniętych w 8000 linijkową metodę.

A jeśli do kogoś to nie przemawia to niech pomyśli sobie co dzieje się w jego głowie gdy idzie pozmywać naczynia po obiedzie:

Czy coś takiego :

Mam do dyspozycji obiekt klasy Zlew, obiekt klasy Ludwik oraz kolekcję obiektów klasy NAczynie oraz obiekt klasy Człowiek (czyli JA)

 
zlew.umieść(naczynia)
ludwik.nalejDo(zlew)
kran.odkręć()
ja.zmyjNaczynia(zlew)


Czy Może naturalniej jednak będzie :

Jest do pozmyawania sterta naczyń
 
JA muszę wrzucić te wszystkie naczynia do zlewu
JA muszę teraz odkręcić wodę 
JA muszę teraz nalać ludwika
JA teraz dla każdego talerza
      muszę go umyć
      jeśli jest już czysty 
          to JA go odłożę na suszarkę
      jeśli nie
          to JA go myję dalej
      W międzyczasie zakręcę wodę
      Dobra zrobię sobie krótka przerwę
      (...)
      
No jeśli ktoś myśli o abstrakcjach i interfejsach w trakcie zmywania naczyń to jakieś dobre zioło namierzył albo po ASPięknych.

Generalnie zarówno programowanie obiektowe jak i funkcyjne nie jest naturalne dla naszego umysłu ALE. Klasy i obiekty to wynalazek greckich filozofów i chyba ktoś ich kalibru ma odpowiednie doświadczenie aby stworzyć poprawny model obiektowy. W przeciwieństwie do humanistycznej obiektówki programowanie funkcyjne opiera się na zrozumieniu ścisłych zasad matematyki. A enkapsulacja i re-używalność jest równie dobra.

?Nowe spojrzenie na dług techniczny

Temat długu technicznego, kompatybilności wstecz, dodawania nowych ficzerów itd pojawił się na kilka prezentacjach pierwszego i drugiego dnia. I w sumie tutaj tez jest mały mindfuck bo do tej pory TechDebt traktowałem jako coś bezpośrednio związanego z jakością kodu i architekturą systemu.

A tutaj pojawia się taka ciekawostka. Jeśli mamy np. takie wymagania :

  • Zrobić funkcjonalność 1
  • Zrobić funkcjonalność 2
  • Zrobić funkcjonalność 3


To one tak naprawdę brzmią

  • Zrobić funkcjonalność 1
  • Zrobić funkcjonalność 2 i nie popsuć funkcjonalności 1
  • Zrobić funkcjonalność 3 i nie popsuć funkcjonalności 1 i też nie popsuć funkcjonalności 2

No to teraz jeśli założymy, że mamy w naszym systemie N (dla uproszczenia) podobnych funkcjonalności, to koszt dodania funkcjonalności N+1 będzie:

  • Tam gdzie jakimś cudem osiągnęliśmy legendarny poziom modularyzacji - Cost~F(n+1)
  • Tam gdzie ficzery są od siebie zależne ale system jest gotowy na rozbudowę - Cost~F(n+1) + M(n) - gdzie M(n) koszt utrzymania przy życiu pozostałej części systemu
  • Tam gdzie jest skomplikowana interakcja (zamierzona lub nie) pomiędzy ficzerami - Cost~F(n+1)+M(n^2)
  • Tam gdzie gówno pływa swobodnie po kodzie, "big ball of mud" i wszystko jest powiązane ze wszystkim w 10000 linijkowych klasach nazwanych "Menażer" - Cost~F(n+1)+M(2^n)

Oczywiście poprzez refkatoringi, metodyki projektowe i inne takie można poprawić charakterystykę funkcji kosztu ALE - można też zmniejszyć pracochłonność zmniejszając N poprzez usunięcie częsci fukncjonalności. Niby szok kulturowy bo funkcjonalność - szczególnie ta działająca - zarabia dla nas pieniądze - no poza momentami kiedy ich nie zarabia!

Kiedyś czytałem w focusie artykuł o ludziach, którzy patologicznie kolekcjonują rzeczy przez co nie mogą się poruszać po swoim mieszkaniu. U mnie w komórce przez 10 lat też leżały jakieś deski bo a nuż kiedyś się przydadzą. Nikt ich nie używał to poszły na przemiał i podobnie trzeba wywalać jakieś dziwne opuszczone ficzery aplikacji, których nikt nie używa. Czyli nowy rodzaj długu technicznego : doskonale działąjąca funkcjonalność, której (praktycznie) nikt nie używa

Inne takie

Inna ciekawa rzecz to : http://code.google.com/p/spock/ w sumie fajna rzecz ale na Groovym . Po PHP trzymałem się z dala od języków dynamicznych ale trzeba się chyba przemów.

Brak komentarzy:

Prześlij komentarz