Czwarty dzień wyzwania oznacza, że jesteśmy w połowie drogi! Początkujących czeka dziś praca z bibliotekami i “cudzym” kodem, zaawansowanych krótka programistyczna wprawka z małą niespodzianką :) Gotowi?
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ą?
Software development to nie tylko tworzenie nowego kodu i rozwijanie go, ale też umiejętność zrozumienia rozwiązań innych i radzenie sobie z problemami jakie mogą się tam pojawić. Pewnie usłyszałaś już jakaś historię o kodzie, który przypomina wykopaliska i nikt nie chce go dotknąć ;) No cóż, czasem trzeba. Dlatego od samego początku warto nauczyć się rozumieć pracę innych. A jak to można zrobić? Ano czytając kod na głos. Więcej o samej metodzie znajdziecie, tradycyjnie w naszym wpisie. Czytanie kodu jest super ćwiczeniem, bo pozwala Ci zrozumieć logiczny ciąg przyczynowo-skutkowy zapisanego programu, a także może być świetnym sposobem na poznanie nowych bibliotek i wzorców ;)
Wyszukaj na GitHubie jakiś projekt open source/ popularną bibliotekę w Twoim języku programowania i zacznij go czytać. Znajdź jeden plik, najlepiej taki, który ma metody pomocnicze (np. SpringReflectionUtils albo IOUtils z biblioteki Apache Commons) i linijka po linijce opowiadaj sobie co w danym miejscu się dzieje.
Po 45 min takiego czytania odpowiedź na pytania:
- czego dotyczył czytany przeze mnie kod?
- jakie rozwiązania zastosowane w czytanym kodzie już znalałam?
- co było dla mnie nowością?
- co z tego mogę również zastosować w swoim kodzie?
Nasza odpowiedź
- W klasie możemy znaleźć metodę closeQuietly(), która od metody z javy.io różni się tym, że ignoruje IO Exception — tutaj warto zwrócić uwagę, na to, że taki pusty catch jest oznaczony komentarzem //ignore (czyli wiemy, czemu jest on pusty).
- rozróżnione zostało kopiowanie i kopiowane dużych Obiektów (metody copy() i copyLarge()),
- zastosowany został koncept overloadingu (przeciążania), czyli pod taką samą nazwą mamy takie metody, które przyjmują różny zestaw argumentów
Większość tego kodu przypomina to, co samemu musiałabyś napisać nie używając biblioteki. Dzięki jej zastosowaniu, kod staje się trochę czystszy i masz pewność, ze nie zapomnisz o żadnym szczególe.
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ą?
Code Kata, to sposób na ćwiczenie się w pisaniu kodu. I dzisiaj mamy dla Was takie właśnie ćwiczenie. Założenie jakie przyjmumjesz na początku: to zadanie, jest jak prawdziwe życie :), a wytyczne przyrastają z każdym rozwiązaniem. Czytaj je więc po kolei, nie przechodź do kolejnej części bez zaimplementowania poprzedniej, bo odbierzesz sobie całą zabawę!
Część 1: Pogoda
Napisz aplikację wyciągającą dane o pogodzie (np. z https://developer.yahoo.com/
Część 2: Sport
Napisz drugą aplikację przetwarząjącą dane o zawodnikach sportowych(np. z użyciem https://developer.yahoo.com/
«<Tutaj jest 3 część zadania, zaznacz, by przeczytać»>
Część 3: DRY
Połącz obie aplikacje ze sobą, korzystając z zasady DRY.
Podsumowanie:
- w jaki sposób decyzje, które podejmowałeś pisząc każdy z tych fragmentów wpływał na to, że połaczenie ich było później łatwiejsze/trudniejsze?
- czy sposób pisania drugiego programu był w jakimś stopniu dostosowany do pierwszej aplikacji?
- co osiągnąłeś poprzez wyciągnięcie wspólnych elementów? Co musiałeś poświęcić/w czym takie ;wspólne’ rozwiązanie jest gorsze? Które wersje byłyby łatwiejsze w utrzymaniu i rozwijaniu w przyszłości?
Zadanie pochodzi ze strony: http://codekata.com/kata/kata04-data-munging/
Nasza odpowiedź
Jako dwa źródła danych wybrałem nieco inne API niż w zadaniu — pierwsze to API serwisu Wikipedia, z którego odczytuję kiedy miała miejsce ostatnia zmiana strony głównej oraz jej opis. Drugie API dotyczy pogody, pobieram pogodę dla Wrocławia i wyświetlam jej opis na najbliższy dzień. Kod obu rozwiązań znajdziesz na GitHub’ie: https://gist.github.com/
Oczywiście pomijamy tutaj kwestię nieczytelnego kodu czy braku podziału na mniejsze bloki kodu — nie o clean code w tym zadaniu przede wszystkim chodziło ;)
Kwestia, która od razu rzuca się w oczy to fakt, że pomimo są to całkowicie odmienne API, większość kodu pozostaje taka sama — różni się adres URL, konkretna ‘ścieżka’ w odpowiedzi, którą chcemy pobrać z JSONa oraz (ewentualnie) rodzaj zwracanych danych.
Daje nam to trzy metody, które na pewno możemy wyłączyć jako abstrakcyjne i zależne od przypadku, niech będą to:
buildRequestURI — jej celem jest zbudowanie konkretnego URI, pod którym otrzymamy dane
readRawData — ma za zadanie zamienić odpowiedź z serwera na obiektową reprezentację
convert — ma za zadanie zamienić obiektową reprezentację odpowiedzi serwera na docelową odpowiedź
Całość jak zapewne zauważyłaś przypomina proces ETL (ang. Extract-Transform-Load; i nim w istocie jest) — najpierw pobieramy dane, konwertujemy je w sposób pozwalający na filtrowanie/obróbkę, wyciągamy interesujące nas informacje i zwracamy je. W praktyce moglibyśmy wykorzystać dowolne narzędzie przeznaczone do pracy z tego rodzaju procesami, i także by zadziałało :)
Jako że treść zadania była jasna — połączyć kod w sposób, który jak najbardziej eliminuje duplikacje, zaimplementowałem rozwiązanie z użyciem generyków i klas bazowych. Pozwala na implementacje logiki ETL dla dowolnego źródła danych opartego o protokół HTTP, niezależnie od formatu danych (wystarczy zaimplementować odpowiednią logikę konwertującą).
Oczywiście całość implementacji mogła wyglądać jeszcze lepiej, można było użyć interfejsów funkcyjnych itp, ale jak już wspomniałem idealny Clean code nie był celem tego zadania ;)
Oczywiście drugie rozwiązanie jest zdecydowanie łatwiejsze do utrzymania i rozwijania w przyszłości.
Kod rozwiązania po refaktorze znajdziesz na https://gist.github.com/
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!