- Czy konieczny jest podział solucji na projekty, gdzie każdy projekt za coś odpowiada. Dlaczego nie można tego rozdzielić folderami w jednym projekcie?
W małym projekcie mozna. W dużym to robi się męczące, gdy w jednym projekcie masz setki/tysiące klas. Ciężko coś znaleźć, cieżko się korzysta z IDE, które podpowiadanie ma zaśmiecone wszystkim, co jest w projekcie. Dlatego w miarę z rozrostem projektu dobrze jest dzielić coraz bardziej.
- Czym się różnią serwisy od repozytoriów i dlaczego to nazewnictwo jest takie ważne?
Serwisem można nazwać właściwie wszystko realizujące jakąkolwiek logikę, a repozytoria to specyficzny element DDD.
- Co powinien zawierać kontroler? Dlaczego akcja kontrolera nie może zawierać logiki biznesowej?
Bo to wtedy nie jest już kontroler tylko jakiś god-object.
Kontroler powinien odebrać i zwalidować dane wejściowe, a następnie przekazać je do niższych warstw. A w drugą stronę powienien odebrać wyniki i przekazać je w prawidłowej formie na zewnątrz.
- Obsługa błędów, wyjątków, co wysyłać do klienta, co obsłużyć po stronie API?
Do klienta najlepiej prosty komunikat oraz unikalne ID błędu, po którym będziesz w stanie znaleźć zdarzenie w logach i je naprawić.
- Czy asynchroniczność jest konieczna w przypadku WebAPI?
Konieczna nie, po prostu pomaga serwerowi działać w niektórych sytuajach. Jeśli aplikacja ma raptem kilku użytkowników, to zysku nie będzie z niej wielkiego.
- Do czego "używa się" DTO?
To też szerokie pojecie. Ogólnie do przesyłania danych, np. między aplikacją a webservisem, można też między warstwami aplikacji, tylko to technicznie nie jest transfer, więc nazwa DTO nie brzmi najlepiej.
Pytania dodatkowe
- Czy to nie jest strata czasu?
Zależy od skali projektu.
- Czy jeśli jestem jedynym programistą w firmie to te wszystkie zasady mnie "obowiązują" lub powinny "obowiązywać"?
Nie, chociaż w takiej sytuacji większość z nich bym stosował będąc na Twoim miejscu. Ale ja juz taki jestem, że wolę sobie ułatwiać niz utrudniać.
Ok, argumentacja jest i dociera do mnie. Kilka osób wspomniało o testach. Moim zdaniem kolejna strata czasu.
Testy do systemu, którym zajmuję się obecnie wykonują się kilka minut. Gdybym chciał wszystko sprawdzić ręcznie zajęłoby to chyba z tydzień.
Generalnie inwestycja w pisanie testów to jedna z najszybciej zwracających się inwestycji. Generalnie w ciągu dnia można napisać testy pozwalające zaoszczędzić dziesiątki godzin w skali roku.
No chyba, że ktoś wali strony-wizytówki albo coś takiego, wtedy testowanie automatyczne nie ma sensu.
Rozumiem, że "dobre praktyki" robi się po to, aby się aplikację dobrze testowało?
Nie tylko testowało, ale też rozwijało i naprawiało. Jeśli w projekcie panuje porządek, to gdy coś się stanie, wiadomo gdzie szukać błędu i jak go naprawić. Gdy panuje bałagan nie jest to takie łatwe.
@Fuffu Chcesz powiedzieć, że używasz dobrych praktyk, aby cię "nie kusiło", żeby rozwiązać coś inaczej, szybciej, niezgodnie z dobrymi praktykami?
Pójście na skróty to często dołożenie sobie roboty w przyszłości. Trzeba umieć wybrać, co ma sens, a co nie w danej sytuacji.
Spróbuje to ogarnąć jakoś w sumie, odpowiedzi są bardzo podobne. Skoro repozytorium zapisuje i odczytuje dane to dlaczego nie mogę ich od razu "obrobić" w repozytorium i zapisać? Chcecie mi powiedzieć, że ze względu na "dobre praktyki" powinienem stworzyć interfejs (serwis), który mi te dane przerobi, tylko po to, aby repozytorium mogło zapisać w takiej formie w jakiej powinno być zapisane?
Nie, bo używanie repozytorium jeśli nie jest Ci potrzebne, to nie jest dobra praktyka. Podobnie jak robienie bezcelowych interfejsów.
W prostej aplikacji w zupełności wystarczy taki podział: Controller <-> Service <-> ORM <-> baza danych
, gdzie Service to tak naprawdę Transaction Script. Repozytoria są potrzebne w skomplikowanej domenie, tam gdzie stosuje się DDD, w każdym innym przypadku to jakiś antywzorcowy kult cargo.
PRZYKŁAD:
public bool CancelAgreement(int agreementId)
{
var agreement = _dbContext.Agreements.Find(agreementId);
//Te dwie linie poniżej powinny być w serwisie? Po co?
agreement.Canceled = true;
agreement.CancelDate = DateTime.Now;
_dbContext.Agreements.Update(agreement);
_dbContext.SaveChanges();
}
No to jest właśnie przykład skryptu transakcji. Nazywanie tego repozytorium to kompletne poplątanie pojęć.
Uważam, że więcej czasu spędza się na generowaniu tych wszystkich interfejsów do serwisów i repozytoriów niż na faktycznym programowaniu.
No tak, jeśli na siłę próbuje się używać repozytoriów tam, gdzie nie mają sensu, to masz rację.
Nazywasz kulty cargo dobrymi praktykami, a potem stwierdzasz, że nie mają sensu. Wnioski dobre tylko teza fałszywa.