Czy jest to najczystsza apka ever made, pet clinic?? (code review)

0

user image

Poczatkowo do napisania apki była idea:
http://docs.spring.io/docs/petclinic.html

jednak z czasem odjechałem z funkcjonalnoscami, anyway, bede wdzieczny za wszelkie uwagi dotyczące kodu,

  • funkcjonalnosci specjalnie duzo nie ma,
  • celowo uzylem JPA, a nie np spring data,
  • najbardziej ciekawi mnie Wasze zdanie na temat implementacji kontrolerow,
  • ocena 1-10? 1-> bardzo źle , 5 -> w miare ok, 10 -> jest ok.

https://github.com/filemonczyk/PetClinic

0

target w repo, tak samo .settings czy .project
0/10 dalej nawet nie zaglądam bez kubka melisy...
Rozumiem że nie chciałeś Spring Data ale czemu copypaste zamiast napisać GenericDao w takim razie?

0

Hej. Sam dopiero uczę się Springa i spojrzałem na ten kod i mam pare pytań do osób bardziej obeznanych.

  1. Shalom w jaki sposób można inaczej to zaimplementować przy użyciu Spring Data?
  2. Czemu najpierw tworzony jest bean z adnotacją Repository a potem niejako opakowywany w Service? Czy nie można Od razu wstrzyknąć tego oznaczonego jako Repository (dodając obsługę tranzakcji) do Controllera?
0
  1. Nie rozumiem pytania. Tutaj mozesz sobie zobaczyc przykład https://github.com/Pharisaeus/SpringScaffoldApplication/tree/master/src/main/java/scaffold/data/dao
  2. Bo ta aplikacja "nic nie robi". W prawdziwym życiu jednak tak nie jest i warstwa serwisów / logiki biznesowej stanowi większość kodu ;]
0

Mówiłeś żeby zwrócić uwagę na kontrolery, no to tak:

  1. W OwnerController metody do update i delete oba są przez POSTa (rozróżnia je 'params') -> zmień to w taki sposób, żeby były po prostu różne metody HTTP do tych metod (PUT/POST do update i DELETE do delete).
  2. W VisitController w ostatniej metodzie jest dość sporo logiki -> przenieś ją do serwisu
0

ok, przerobilem to na generyczne podejscie , jednak cos mi nie pasuje, a mianowicie:

zrobilem repository:

public interface GenericRepository<T> {
	public void add(T entity);
	public void update(T entity);
	public void remove(T entity);
	public T get(Class<T> entityClass,int id);
	public Collection<T> getAll(Class<T> entityClass);
}

pozniej napisalem service

public interface GenericService<T> {
	public void add(T entity);
	public void update(T entity);
	public void remove(T entity);
	public T get(Class<T> entityClass,int id);
	public Collection<T> getAll(Class<T> entityClass);
}

ale czy to nie jest zle podejsice? Tzn gdybym pozniej dodawal metody juz do konkretnych klass serwisów, na przyklad klasy Owner,to:

tworze

 public Interface OwnerService extends GenericService<Owner>
// jakies dodatkowe metody np. znajdz ownerow ktorzy maja psa o imieniu Burek

I wtedy

OwnerServiceImpl implements OwnerService
/////

czy jest to dobre rozwiazanie?

0
private static final String[] visitTime =
    {"09:00:00","09:30:00","10:00:00","10:30:00","11:00:00","11:30:00","12:00:00",
         "12:30:00","13:00:00","13:30:00","14:00:00","14:30:00","15:00:00","15:30:00","16:00:00","16:30:00"};
  1. Czas zapisywany w Stringu
  2. Czasy predefiniowane, a nie generowane w locie.

2/10, nie utrzymywałbym tego kodu

0
wartek01 napisał(a):
private static final String[] visitTime =
    {"09:00:00","09:30:00","10:00:00","10:30:00","11:00:00","11:30:00","12:00:00",
         "12:30:00","13:00:00","13:30:00","14:00:00","14:30:00","15:00:00","15:30:00","16:00:00","16:30:00"};
  1. Czas zapisywany w Stringu
  2. Czasy predefiniowane, a nie generowane w locie.

2/10, nie utrzymywałbym tego kodu

ok dzieki za odpowiedz, stringi wiem ze sa zle ale co masz na mysli "predefiniowane a nie generowane w locie"? moja intencja bylo to, że wizyty moga odbywać sie tylko w określonych godzinach, a dokladniej w w/w godzinach. Przerobie to na LocalTime

5

public interface GenericService<T> { :D :D :D taguj to jakimś #rakcontent
O ile generyczne repozytorium/dao ma sens bo wyciąganie obiektów zwykle wygląda tak samo o tyle generyczny serwis to jakiś mindfuck. Serwisy realizują logikę biznesową aplikacji więc trudno tu mówić o jakiejś generyczności. Mam wrażenie że nie bardzo rozumiesz po co w ogóle jest ta warstwa serwisów...

0

@Shalom Co widzisz złego w generycznym serwisie? Skoro aplikacja robi sporo CRUDa, to ja np w projekcie mam generyczne zarówno DAO jak i Service. I ten generyczny serwis ma takie metody jak find, create, update, delete i one wołają metody z generycznego DAO. Potem jak chcę nowy, dodatkowy serwis do zwykłęgo CRUDa, to jedynie extenduję ten generyczny i już jest. OCzywiście customowa logika dojdzie osobno w tym nowym serwisie.

0

@Pinek i umiesz wyjaśnić w takim razie po co w ogóle masz tą warstwę "serwisów"? :D Żeby była? Bo wygląda to troche jak https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition

0

@Shalom Oczywiście że umiem wyjaśnić - mam również generyczny kontroler, który ma przypięty generyczny serwis. Chcąc dodać nowy kontroler, wystarczy że extenduję ten generyczny (z konkretnym typem podanym) i już mam CRUDa. Poza tym pytasz o zupełne podstawy - chcąc na pewnym endpoincie wykonać jakiś np update, nie powinno się wołać metody z DAO. Metody z DAO powinny być wołane JEDYNIE przez serwisy.

0

W sumie w tych kategoriach (generic service) nigdy nie myślałem, ale być może w jakimś frameworku może mieć to zastosowanie :)

Sam robię aktualnie framework, gdzie teoretycznie mógłbym mocno uogólnić pewne kwestie. Nie zrobiłem tego, bo mi się nie chciało i nie wiedziałem, czy kiedykolwiek taka abstrakcja by mi się przydała (a więc: po co komplikować), ale gdybym z góry wiedział, co będę chciał osiągnąć, kto wie ;)

0

Oczywiście że umiem wyjaśnić - mam również generyczny kontroler, który ma przypięty generyczny serwis. Chcąc dodać nowy kontroler, wystarczy że extenduję ten generyczny (z konkretnym typem podanym) i już mam CRUDa

@Pinek no tylko ze taka aplikacja generalnie nie ma sensu. Taka sztuka dla sztuki. Zresztą zmarnowany czas bo jakimś SpringRoo można takiego generycznego CRUDa sobie wygenerować w 5 sekund. Nie widziałem jeszcze prawdziwej aplikacji gdzie takie coś miałoby sens i zastosowanie.

Poza tym pytasz o zupełne podstawy - chcąc na pewnym endpoincie wykonać jakiś np update, nie powinno się wołać metody z DAO. Metody z DAO powinny być wołane JEDYNIE przez serwisy.

O RLY? Czyli uważasz że ma sens wprowadzanie całej dodatkowej warstwy do aplikacji, tylko po to żeby delegowała wywołania do innej warstwy? o_O No chyba ze płacą ci od linijki kodu... Jedyny sensowny argument mógłby być taki że nie chcesz transakcji na repozytorium/dao i ten delegujacy serwis dorzuca transactional, ale w sytuacji którą opisujemy, gdzie te "serwisy" i tak tylko delegują wywołania to nie ma specjalnie zastosowania.

0
Shalom napisał(a):

O RLY? Czyli uważasz że ma sens wprowadzanie całej dodatkowej warstwy do aplikacji, tylko po to żeby delegowała wywołania do innej warstwy? o_O No chyba ze płacą ci od linijki kodu... Jedyny sensowny argument mógłby być taki że nie chcesz transakcji na repozytorium/dao i ten delegujacy serwis dorzuca transactional, ale w sytuacji którą opisujemy, gdzie te "serwisy" i tak tylko delegują wywołania to nie ma specjalnie zastosowania.

To się nazywa DDD

1 użytkowników online, w tym zalogowanych: 0, gości: 1