Tygodniowe zadanie

Nadszedł czas na wyznaczenie Ci kolejnego poważnego zadania na sam koniec trzeciego tygodnia.

Po ukończeniu trzech tygodni – gdzie poznałeś: podstawy Javy, programowania obiektowego, pisania testów i obsługę plików czas na kolejne zadanie. Zadanie jest oczywiście ściśle związane z tworzoną aplikacją podczas kursu – którą ciągle rozwijamy.

Stan

Póki co nasza aplikacja jest w takim stanie  – mamy stworzone modele oraz Product i User serwisy. Dodatkowo do serwisów mamy napisane testy.

Stan twojej aplikacji powinien wykonać podobnie – o ile wykonałeś zadanie, które pojawiło się na koniec lekcji o interfejsach, gdzie musiałeś zaimplementować ProductService. Tworzenie serwisu dla produktów omówie oczywiście na początku czwartego tygodnia.

Cel

Twoim zadaniem będzie stworzenie komunikacji między serwisami, a bazą danych – u nas póki co będą to pliki. W plikach będziemy przechowywać listę wszystkich produktów i póki co zarejestrowanych userów. W dalszej części kursu userów przeniesiemy do bazy danych – ale to tylko taka ciekawostka.

  1. Zdefiniować interfejs ProductDao dla klas odpowiedzialnych za relację produktów z bazą danych (będę pisał z bazą danych, jednak mam na myśli nadal pliki 😉 ), który będzie wymagał metod:
    1. saveProduct(Product product);
    2. saveProducts(List<Product> products);
    3. removeProductById(Long productId);
    4. removeProductByName(String productName);
    5. getAllProducts();
    6. getProductById(Long productId);
    7. getProductByProductName(String productName);
  2. Stworzyć klasę ProductDaoImpl w pakiecie dao (Data Access Object – czyli klasy odpowiedzialne za realację z żródłem danych: bazą danych lub plikiem)), która będzie implementować interfejs ProductDao. Mam kilka uwag i rad odnośnie tej klasy:
    1. W konstruktorze parametrowym inicjalizuj nazwę pliku i zapisz ją w polu klasy
    2. W każdej metodzie otwieraj na nowo plik i na koniec go zamykaj (!)
    3. Niech jeden produkt oznacza jedną linię
    4. Najlepiej w metodzie toString zdefiniuj format w jakim ma być zapisywany obiekt do pliku – wartości pół możesz oddzielać jakimś separatorem np. #
    5. Najlepiej, żebyś cały plik wczytywał do listy – najlepiej Produktów, a nie Stringów. Musisz wtedy odpowiednio wczytanego Stringa sparsować – np. pierwsza wartość do hasha to Id, kolejna do hasha to productName itd. Na wczytanej liście wykonuj odpowiednie operację w metodzie i ponownie zapisuj całą listę do pliku. Choć nie jest to zbyt optymalne rozwiązanie (pod względem czasu) to będzie wystarczająco bezpieczne.
  3. Zdefiniuj interfejs UserDao dla klas odpowiedzialnych za relację userów z bazą danych, który będzie wymagał metod:
    1. saveUser(User user);
    2. saveUsers(List<User> users);
    3. getAllUsers();
    4. getUserByLogin(String login);
    5. getUserById(Long userId);
    6. removeUserByLogin(String login);
    7. removeUserById(Long id);
  4. Stwórz klasę UserDaoImpl w pakiecie dao, która implementuje interfejs UserDao. Wszystkie rady odnośnie ProductServiceImpl możesz zastosować w przypadku UserDaoImpl. Trzymaj się tych samych zasad.

Do wczytywania i parsowania (czyli analizy) całej linii Stringa możesz użyc metody concat(separator) do zamienienia Stringa na tablicę wartości oddzielonych seperatorem np. String [] values = readLine.concat(“#”) – jeżeli w pliku wartości są oddzielone hashem. 😉

Na koniec dam Ci małą radę – w obu implementacjach zacznij od zaimplementowania metody getAllProducts, getAllUsers, saveUser, saveProduct, saveUsers, saveProducts – wtedy do wczytywania listy i jej zapisywania w innych metodach możesz wykorzystać te wcześniej napisane metody.

Git

Podczas rozwiązywania pamiętaj o wykorzystywaniu gita – możesz tworzyć commity po stworzeniu interfejsu, klasy – lub części funkcjonalności np. zaimplementowanie dodawania userów przy użyciu metod: saveUser i saveUsers.

Do dodania zmian do repozytorium możesz użyć:

git add *

Do stworzenia commita:

git commit -m "Wiadomosc"

A jak skończysz już swoje zadanie to wypchnij na zdalne repozytorium przy użyciu:

git push origin master

I pochwal się w komentarzu swoim repozytorium, a na pewno zerknę. 😉

Testy

Do klas odpowiedzialnych za relację z bazą danych nie ma raczej co pisać, mamy napisane póki co testy dla serwisów, które w czwartym tygodniu zaczną korzystać z klas DAO – jednak zintegrujemy już to razem. 😉

Podsumowanie

Spróbuj skorzystać z całych swoich sił, aby wykonać to zadanie chociażby po częsci – w kolejnym tygodniu wytłumaczę Ci jak można to zrobić. Jednak nie poddawaj się – wracaj do poprzednij lekcji, szukaj materiałów w internecie wpisując w google krótkie hasła np. read text file in java – i staraj się czytać stronę stackoverflow – tam zawsze jest odpowiedź na pytanie. 😉

Moje rozwiązanie możesz zobaczyć tutaj. Tak jak wspominałem, nasze serwisy będą korzystać z klas DAO jednak wspólnie je zintegrujemy w czwartym tygodniu. Możesz spróbować teraz, jednak musisz uważać – w końcu serwisy w testach są inicjalizowane listą wartości podanych przez nas.

I to na tyle w trzecim tygodniu – daj znać jak się podobało, o ile się coś podobało, a co byś zmienił? Pamiętaj, aby pisać do mnie lub na grupie facebook w przypadku, gdy czegoś nie rozumiesz. Nie zostawiaj w głowie zagadnień, których do końca nie rozumiesz – bądź głodny wiedzy!

 

Kamil Klimek

Od 2016 jestem programistą Java. Przez pierwsze 4 lata pracowałem jako Full Stack Java Developer. Później postanowiłem postawić nacisk na Javę, żeby jeszcze lepiej ją poznać.

Subscribe
Powiadom o
guest
8 komentarzy
najstarszy
najnowszy oceniany
Inline Feedbacks
View all comments
Paweł Dębiński
Paweł Dębiński
5 lat temu

Ok jakoś to zrobiłem, mam nadzieję że ok, bo nie jestem pewien czy wszystko dobrze zrozumiałem: https://github.com/PawelDebinski/project_1024kbpl.git .
Z tym że o ile udaje mi się zapisać do pliku obie podklasy(Boots i Cloth), to wczytując je wczytuję jako Product i tracą swoje właściwości.
Nie bardzo wiem jak to sensownie zrobić.

Poza tym kurs bardzo fajny, w przeciwieństwie do większości kursów w necie które traktują każdy temat jako osobną jednostkę, tutaj wszystko jest spójne w formie projektu, przy którym trzeba się samodzielnie napracować jest świetnym rozwiązaniem. Dzięki że Ci się chce, to dużo pracy wymaga.

Kamil Klimek
Kamil Klimek
5 lat temu

Super, że kurs Ci się podoba. Mam nadzieję, że z tej aplikacji wyjdzie nam coś sensownego w trakcie trwania kursu.

Co do Twojego rozwiązania, ze względu braku czasu w weekend dziś albo jutro wrzucę swoje rozwiązanie. Póki co mogę Ci podrzucić pomysł w kontekście parsowania wczytanego konkretnego produktu. To prawda, że wczytywanie mamy ugenerycznione do klasy Product, jednak do metody można przesyłać argument, mówiący o tym jaki obiekt będzie wczytywany. Może to być String, który później sprawdzisz, lub Enum jeżeli wiesz czym już on jest. My w dalszej części kursu poznamy również enum i projekt będzie refaktorowany, aby zastąpić Stringi enumami. 😉

Kamil Klimek
Kamil Klimek
5 lat temu

Możesz zerknąć już na moje rozwiązanie, jest na razie zrobione tak, aby były w nim zawarte zagadnienia z kursu. Oczywiście kod będzie refaktorowany w przyszłości, gdy będziemy poznawać nowe tematy. 😉

https://github.com/1024kb-pl/KJOP_Management/tree/4b3c877e541a72251237401cf4aa3c137f88c05c

Sekcję parsowania wczytanego Stringa wyrzuciłem sobie do osobnych klas zachowując Zasadę Jednej Odpowiedzialności. Klasa DAO niech będzie odpowiedzialna za samą relację, ale aby zmniejszyć jej skomplikowanie można moduł parsowania wydzielić do osobnych klas.

Dodatkowo dodałem klasę File do tworzenia pliku w przypadku, gdy nie istnieje. Więcej o tym napiszę w czwartym tygodniu. 😉

Paweł Dębiński
Paweł Dębiński
5 lat temu
Reply to  Kamil Klimek

Dzięki, przestudiuję Twoje rozwiązania a potem jakoś to przeniosę do siebie:)

Paweł Dębiński
Paweł Dębiński
5 lat temu
Reply to  Kamil Klimek

Mam pytania 🙂

– UserDaoImpl w metodzie getaAllUsers najpierw w pętli while sprawdzasz czy wczytana linia nie jest pusta, a potem to samo robisz z userem. Nie jest to zbędne? Skoro linia nie jest pusta to User też nie powinien być?
– W metodzie saveUsers ustawiasz w FileOutputStream drugi parametr jako true żeby dopisywać do pliku. W jaki sposób to będzie rozwiązane żeby nie powodowało nadpisywania do pliku powtórnie tych samych userów?

Kamil Klimek
Kamil Klimek
5 lat temu

– Masz rację jest to zbędnę. Z automatu zrobiłem to sprawdzanie, ponieważ ProductParser tego wymaga – zaś UserParser już nie. Po prostu się zagolopowałem. 😉
– Zauważyłem właśnie ten problem wczoraj. Dodałem metodę odpowiedzialną za czyszczenie pliku.

Nowe rozwiązanie możesz zobaczyć tutaj: https://github.com/1024kb-pl/KJOP_Management/tree/32719e015e47ae736d916abc4e92d492caa1b3c3 😉

Paweł Dębiński
Paweł Dębiński
5 lat temu
Reply to  Kamil Klimek

Dzięki:). Podoba mi się sposób w jaki piszesz kod – jest bardzo czytelny. Do tej pory miałem tendencje do pisania napuchniętych metody z wieloma if-ami i pętlami i nie wiadomo czym jeszcze:) co sprawiało że ten kod był później mega nieczytelny i bardzo ciężki do zmodyfikowania. Już raczej wolałbym go przepisać na nowo. A tutaj na pierwszy rzut oka wiadomo co i jak i łatwo coś zmienić jeśli potrzeba. Dużo wyciągam z Twojego kursu, najpierw piszę po swojemu, a potem studiuję Twój kod, zastanawiając się kto ma lepsze rozwiązania i potem poprawiam swoje 😀

Kamil Klimek
Kamil Klimek
5 lat temu

Dużo daje przeglądanie cudzego kodu, nie chodzi tu o przepisywanie go tylko wyciąganie jakiś dobryk praktyk, które pozwalają polepszyć swój kod. 😉

8
0
Would love your thoughts, please comment.x