Tygodniowe wyzwanie programistyczne – #2

By 15 października 2016ITlogy, Wydarzenia

Kontynuujemy wyzwanie! Wraz z początkującymi będziemy zastanawiali się jak zdefiniować pewne określenia, a praktycy będą musieli odbyć nieco sentymentalną wycieczkę. Gotowa?

Wyzwanie dla początkujących

Przed przystąpieniem do zadania, zastanów się nad rezultatem Twojej wczorajszej pracy: Czego dowiedziałeś się o swoich umiejętnościach? Czego się nauczyłeś? Co zrobisz z tą wiedzą?

Zapewne pamiętasz, jak na początku swojej nauki spotykałaś wiele pojęć, których znaczenia nie znałaś. Szukanie ich w Google też niewiele pomagało – definicje były napisane zbyt zawiłym językiem i nie były proste w zrozumieniu. Wraz z tym, jak nabywasz coraz więcej wiedzy, coraz łatwiej jest Ci rozszyfrowywać tak zapisane definicje i samodzielnie uczyć się dalej na podstawie materiałów w sieci.

Niesie to jednak za sobą ryzyko – chcąc przekazać innym swoją wiedzę, sama najprawdopodobniej używasz coraz więcej specjalistycznych słówek i żargonu.

Prawdziwym sprawdzianem czy opanowałaś dane zagadnienie jest prosty test – czy umiesz wytłumaczyć daną rzecz swoimi słowami, w prosty sposób tak, aby nawet laik zrozumiał o co chodzi. To jest Twoim dzisiejszym zadaniem – stworzenie definicji do poniższych zagadnień tak, jakby o wyjaśnienie ich zapytało Cię młodsze rodzeństwo/dziecko. Możesz wybrać np. 4 określenia z poniższej listy lub sama wymyślić własne przykłady:

  • aplikacja / program
  • kod źródłowy
  • metoda / funkcja
  • pętla
  • instrukcja warunkowa
  • konsola
  • test
  • tablica

Po stworzeniu definicji zastanów się, jaka jest jej najtrudniejsza część (np. najtrudniejsze użyte słowo lub odwołanie do jakiejś innej wiedzy) i spróbuj je wyeliminować. Powtarzaj aż do momentu, kiedy zabraknie elementów do wyeliminowania.

Jeśli masz w domu ‚obiekt testowy’ to idealnie – możesz od razu sprawdzić, czy faktycznie dziecko zrozumie :) Tak czy inaczej nie zapomnij podzielić się swoimi definicjami w komentarzu do eventu na FB!

Nasza odpowiedź

Do tłumaczenia wybraliśmy trzy określenia z podanej przez nas listy i jedno spoza niej (kompilacja). Nasze definicje znajdziesz poniżej:

aplikacja / program – to taka instrukcja dla komputera co ma robić po kolei; mogą w niej być zadania, żeby coś policzył, zapytał się człowieka o coś lub powiedział mu wynik. Komputer może też rysować na ekranie różne rzeczy, jeśli instrukcja opisuje jak to dokładnie zrobić

kompilacja – jest to proces tłumaczenia z języka ludzi (kod źródłowy) na język komputerów potrzebny, żeby komputer rozumiał polecenia wydawane przez człowieka. Po kompilacji powstaje aplikacja / program.

kod źródłowy – instrukcja dla komputera co dokładnie ma robić krok po kroku, ale zapisana w sposób zrozumiały dla ludzi. Można ją ‚zamienić’ na zapis zrozumiały dla komputera (program) po uruchomieniu kompilacji

tablica – tablica to taka szufladka na różne informacje, które przechowuje komputer – podobnie jak szuflada, ma określony rozmiar (pojemność) i przegródki – mieszczą się do niej tylko ściśle określone informacje (a innych nie możemy tam umieścić)

W naszych definicjach największy problem mieliśmy z tym, że ciężko nam było wytłumaczyć jedną bez wyjaśnienia drugiej. Mimo wszystko udało nam się chyba opisać te kilka terminów w prosty sposób :)

Wyzwanie dla praktyków

Przed przystąpieniem do zadania, zastanów się nad rezultatem wczorajszej pracy: Czego dowiedziałeś się o swoich umiejętnościach? Czego się nauczyłeś? Co zrobisz z tą wiedzą?

Refaktoryzacja kodu to jedna z tych czynności, które wszyscy twierdzą że warto i należy to robić, ale w praktyce często nie ma na to czasu w projekcie. Jako że przez cały czas się uczysz, poznajesz nowe rozwiązania, sposoby podejścia do pewnych zagadnień i zauważasz dodatkowe zagrożenia lub problemy, kod który napisałeś kiedyś, dziś zapewne napisałabyś lepiej i w bardziej przemyślany sposób.

Podobnie jak i my na pewno nie raz musiałaś napisać coś ‚na szybko’, obiecując sobie że jak tylko skończy się ten sprint to wrócisz i poprawisz ten fragment. Pewnie podobnie jak nam, nie zawsze udaje Ci się do niego w końcu wrócić ;) Dzisiejsze zadanie polega na tym, żeby odnaleźć jakiś fragment kodu, który napisałaś w przeszłości (założenie: powinien być starszy niż 6 miesięcy), a następnie zrobić refaktoryzację i – w idealnym przypadku – usunąć jakiś związany z tym dług techniczny.

Jeśli masz problem, żeby zidentyfikować co można poprawić, pomocne mogą okazać się katalogi np. na stronie refactoring.com (gdzie znajdziesz konkrente przykłady i sytuacje oraz ich analizę) lub refactoring.guru (gdzie z kolei są opisane ‚zapachy’ – sygnały, które mogą wskazywać na potrzebę refaktoryzacji). Możesz też skorzystać z narzędzi do analizy kodu jak np. opisywany przez nas SonarQube.

Dodatkowo, zastanów się, jaki wpływ na działanie aplikacji miałoby niepoprawienie tego fragmentu oraz jakie korzyści to przyniosło? Czy zmieniło to jej wydajność? Czy łatwiej jest teraz rozszerzyć funkcjonalność aplikacji? Czy pozwoliło to zaktualizować lub pozbyć się starej biblioteki?

Takie cofnięcie się do kodu, który pisaliśmy jakiś czas temu to także świetny sposób na zobrazowanie sobie, czego się nauczyłaś przez ten czas!

Jeśli to nie jest kod firmowy, pamiętaj, żeby podzielić się z nami swoim kodem ‚przed’ i ‚po’ w komentarzu na FB!

Nasza odpowiedź

Jako projekt do refaktoryzacji Ania wybrała swoją pierwszą aplikację – learning webapp. Z uwagi na to, że czas był ograniczony, wykonała tylko częściowy refaktoring – jego wynik znajdziesz na githubie: https://github.com/apietras/competence-today/commit/45c9171a0e1ce68234c0df195b418751d9b67642

To, co zmieniła to przede wszystkim:

  • zrezygnowała z konfiguracji XML wszędzie, poza Security (na przepisanie tej części nie starczyło mi już czasu)
  • dołączyła Spring Boot, żeby móc pozbyć się (prawie) wszystkich wersji z pom.xml’a i zaktualizować moje zależności
  • usunęła plik web.xml zastępując go klasą w Javie
  • poprawiła adnotacje tam, gdzie było to sensowne (np. @Transactional zmieniłam na Springowe)
  • zamieniła joda-time na API do czasu z Javy 8,

Oczywiście pełniejszy refaktoring powinien objąć nieco więcej, kilka pomysłów co można by jeszcze poprawić:

  • zmienić bibliotekę mapującą na nowszą (np. Orika)
  • dodać Lombok’a aby nie generować samodzielnie getterów i setterów
  • przenieść konfigurację Spring Security do JavaConfig
  • zaktualizować widoki i używane biblioteki JS

Było to dość ciekawe doświadczenie – to zaskakujące jak sporo długu technicznego aplikacja nabrała w ciągu 2 lat. Biorąc pod uwagę, że jest to stosunkowo prosty system, aż strach pomyśleć, co czai się w niektórych większych systemach, do których nikt nie zaglądał od lat ;)

Uwaga: ten refaktoring jest przykładem, w którym nie poprawialiśmy jakichś konkretnych problemów, a jedynie ‚unowocześniliśmy’ aplikację – tego rodzaju poprawki także są ważne, ponieważ ułatwiają korzystanie z nowych opcji oferowanych przez biblioteki w przyszłości i znacznie ułatwiają pracę z aplikacją w dłuższym terminie.

Pamiętaj, że nowe zadania będą się pojawiać codziennie o godzinie 11. Rozwiązania będziemy umieszczać pod zadaniami kolejnego dnia o godzinie 18. Nie zapomnij podzielić się swoimi odpowiedziami i przemyśleniami na wydarzeniu na facebooku, a jak masz ochotę to też w komentarzu ;)!

Linki do wszystkich zadań znajdziesz w innym wpisie na naszym blogu. Powodzenia!

  •  
  •  
  •  
  •  
  •  
  • Laghnarr

    Przepraszam, że zadaję pytanie nie związane z tematem, ale nie mogę znaleźć odpowiedzi na moje pytanie w angielskojęzycznej części internetu:

    Który wzorzec projektowy nadaje się do przesyłania referencji pomiędzy widokiem a kontrolerem?

    Czy da się jakoś związać (w MVC) widok i kontroler w sposób ogólny? To znaczy bez przekazywania specjalnego typu klasy reprezentującej widok… i przy zachowaniu niezależności tych dwóch klas? Mówiąc inaczej – tak aby kontroler mógł obsługiwać zdarzenia kliknięcia na dowolny komponent graficzny?
    Bo wydaje mi się to trochę… nieelastyczne. No bo zakładam, że ten kontroler może mi się jeszcze jakoś przydać… z innymi widokami?

    Pozdrawiam.

    • Cześć,
      nie jestem pewny czy do końca zrozumiałem problem, który opisujesz ;) Ale wydaje mi się, że rozwiązaniem może być wzorzec Observer, czy po prostu Data Binding – więcej o nich (i innych opcjach) poczytasz na http://martinfowler.com/eaaDev/uiArchs.html.
      Niestety nie do końca wpisują się one w architekturę MVC (nie do końca rozumiem dlaczego jest to wymaganie?). MVC zakłada właśnie separację widoku od kontrolera i niejako komunikację pomiędzy nimi (nie jest to stricte komunikacja pomiędzy nimi, ponieważ Model jest tutaj centralnym obiektem, który jest manipulowany/odczytywany przez kontrolery i widoki – przepływ informacji jest wiec w pewnym sensie skutkiem ubocznym) za pomocą Modelu. Bezpośrednie zależności pomiędzy widokiem i modelem w obie strony nie powinny mieć miejsca (w niektórych implementacjach faktycznie kontroler ma bezpośrednie odniesienie do widoku i manipuluje nim bezpośrednio).

      Innym wzorcem związanym z UI jest MVP – w tym wypadku związek pomiędzy widokiem a prezenterem (mniej więcej odpowiednik kontrolera w tym wzorcu) jest ściślejszy. Przykładem implementacji w Javie jest np. GWT (Google Web Toolkit).

      Czy to rzuciło trochę światła na problem? :)

      • Laghnarr

        Całkiem możliwe, że nie zrozumiałem do końca wzorca MVC. Spróbuję, może MVP trafi w moje potrzeby.
        Dziękuję za odpowiedź :)

      • Laghnarr

        Faktycznie MVP to jest właśnie to! Dodatkowo używam też Obserwatora.
        PS. Czy dobrą praktyką byłoby gdybym rozszerzał moje podstawowe interfejsy MVP (zawierające ogólne metody dla wszystkich możliwych przypadków) przez moje specyficzne interfejsy MVP (gdy potrzebuję specyficznego kontraktu pomiędzy widokiem i prezenterem)?

        Np. ViewResponsibilites -> TimerViewResponsibilites.

        Trochę potem nagromadziłoby się tych interfejsów…

        Pozdrawiam i przepraszam za głupie pytanie.

        • Pytanie jak najbardziej na miejscu ;)
          Tak, interfejsy dedykowane do poszczególnych widoków mają sens – pytanie czy powinny one być osobne do każdego widoku czy np. pogrupować je wg jakiejś logiki (w tym sensie, że jeden prezenter może ‚wspierać’ wiele widoków). Ale kierunek słuszny :)