Jedna klasa, czy dwie ?

0

Cześć. Mam pytanie do bardziej doświadczonych ode mnie kolegów. Piszę pracę inżynierską na mobilki o nazwie "domowy budzet", która będzie dawała możliwość wprowadzania sobie wydatków, dochodów, wyliczała różne rzeczy itp. Jak Panowie by mi polecili, czy lepiej stworzyć dwie osobne klasy - Wydatek, oraz Dochód, a potem wykonywać operacje na obiektach tych klas, często jednocześnie na obu ( jak np wyświetlanie wydatku lub dochodu w zależności od daty utworzenia ), czy może lepiej jest stworzyć jedną klasę o nazwie Akcja, która rozróżniała by, czy to dochód, czy wydatek na podstawie typu wyliczeniowego enum, który zawierałby się w klasie ?

Pytanie z pogranicza czystego kodu, etyki programowania itp :D Jak na razie stworzylem dwie klasy, Wydatek i Dochód, ale zastanawiam się, czy sam sobie nie utrudniam tutaj rozbijając to na dwie osobne klasy, kiedy można by w zasadzie wrzucić to w jedną klasę, a obiekty odróżnić od siebie jakims enumem zwykłym.

1

Robisz w jednej + enum i implementujesz.
Przy 2-gim IFie wewnątrz metod klasy wspólnej, bazującym na enumie włącza Ci się lampka ostrzegawcza.
Przy 3-cim rozbijasz na dwie klasy.

Rozbijasz wtedy gdy masz znaczącą różnicę w zachowaniu albo zakresach atrybutów.

0

Wlasnie różnicy jakiejś wielkiej nie ma pomiędzy wydatkiem, a dochodem, w zasadzie sprowadza się głównie do kategorii wydatku/dochodu i znaku przy polu wartość ( + lub - ). Za to takie rozbicie rodzi sporo problemów przy sortowaniu. Dodatkowo RecyclerView w androidzie wyświeta obiekty tylko z jednej listy jednocześnie, a więc będę musiał wykminić stworzenie jakiejś trzeciej listy zawierającej w sobie oba obiekty

1

Sposób wyświetlania w ogóle nie ma znaczenia przy modelowaniu domeny. Zmiana modelu powinna mieć minimalny wpływ na kod zajmujący się prezentacją danych - to powinno bazować na "głupich" DTO-sach. Jeśli chodzi o sam model, czy 1 klasa czy 2, to popatrz na zachowania/api tych klas i zadecyduj czy warto to rozbijać - co na tym zyskasz?

0

Na pewno przejrzystość i eleganckie uporządkowanie. Ale czy coś więcej ? W aplikacji będę musiał wykonywać różne operacje na tych obiektach, co w przypadku dwóch list z dwoma różnymi obiektami nie jest takie proste, jak w przypadku jednej listy z jednym typem obiektu. Jednak bardziej zależy mi na elegancji i dążeniu do profesjonalizmu, dlatego ciekawi mnie, które rozwiązanie jest lepsze i które rozwiązanie jest lepiej widziane w programowaniu. Myślę, że to z dwiema klasami, ale chciałem zapytać bardziej doświadczone osoby, jak one na to patrzą.

1

Profesjonalizm nie polega na komplikowaniu prostych rzeczy, ale na umiejętności dostosowania rozwiązania do problemu. Popatrz jakie masz przypadki użycia, przy którym podejściu kod będzie bardziej elastyczny, przejrzysty i testowalny - to wg. mnie dobre guideliny. Popatrz czy nie łamiesz zasad SOLID, a jeśli łamiesz - czy robisz to świadomie? Nie ma czegoś takiego jak "najlepszy design".

0

Bardziej chodzi o to, by nie praktykować złego wzorca - o ile wzorzec z jedną klasą oczywiście jest zły z jakiś powodów.

Elastyczny będzie na pewno bardziej w przypadku jednej klasy, łatwiejsze sortowanie, łatwiejsze wyświetlanie, jeden IF i mam podział na wydatki i na dochody. Natomiast przejrzysty będzie pewnie w przypadku rozbicia tego na dwie klasy. Lepszy podział, jeśli interesują mnie tylko wydatki, to są w jednym miejscu, jeśli tylko dochody, to są w jednym miejscu. Sam nie wiem :P

0

Ja bym zrobił klasę Transfer i jakiś enum np Direction z instancjami typu IN/OUT.
Nie widzę żadnych zalet w rozbijaniu tego na osobne klasy

0

Próbowałbym nazywać po imieniu: Budzet agregujący PozycjaBudzetu (+- nazewnictwo angielskie)

budzet.ksiegujWydatek( new PozycjaBudzetu("KOKS",... ) );
budzet.dodajPrzychod(  ... );
budzet.wydatkiWOkresie(od,do);
...
0

No wlasnie mi ten typ wyliczeniowy tez nie wyglada elegancko. W dodatku wydatek i dochod beda mialy swoje, rozne kategorie, np dochod bedzie korzystal z kilku, takich jak - wyplata, odsetki, blabla, a wydatek bedzie korzystal z kategorii - rachunki, raty itp. Wiec musialbym przy ustalaniu kategorii sprawdzac typ "transakcji" i podsuwac inna tablice z kategoriami. Coraz bardziej mi to smierdzi :P

0

Wymyslilem, ze obie te klasy, jako, ze sa do siebie w wielu kwestiach podobne beda dziedziczyc po jednej klasie bazowej. Pozwoli mi to wrzucic je wszystkie do jednej ArrayListy i w przystepny sposob wyswietlac i sortowac ;) Pozdrawiam

0

Czyli klasycznie "encja na twarz i pchasz", gratuluję :)

0

Średnie rozwiązanie ? :D

2

Może po prostu odeślę to klasyka (to już 7 lat temu):

0

dzięki wielkie, obejrze na pewno ;)

1
RezyserKinaAkcji napisał(a):

Wymyslilem, ze obie te klasy, jako, ze sa do siebie w wielu kwestiach podobne beda dziedziczyc po jednej klasie bazowej. Pozwoli mi to wrzucic je wszystkie do jednej ArrayListy i w przystepny sposob wyswietlac i sortowac ;) Pozdrawiam

A słyszałeś o interfejsie? Możesz zrobić interfejs BudgetItem, i dwie klasy go implementujące typu Income, Outcome. Jak przyjdzie Ci do głowy rozróżniać wydatki i wpływy to dodasz następne klasy. A wtedy zrobisz te jedną listę typu List<BudgetItem>.

0

Tak, słyszałem słyszałem, tez fajna opcja, dzięki

1

Ja to robię tak: piszę sobie klasę Income i walę do niej testy sprawdzające logikę, która mnie interesuje. Np. sumowanie przychodu z danego miesiąca, danego użytkownika, w danej kategorii itp. Implementuję to cały czas i testuję. Kiedy wszystko działa to czyszczę kod, tzn. wyodrębniam małe metody, tak żeby się zajmowały jedną rzeczą, poprawiam ich nazwy, sprawdzam czy ta klasa jest odpowiednia czy może przenieść je do innej. Cały czas sprawdzam testami.
Potem potrzebuję klasy Outcome, a ona jest bardzo podobna do Income. Co robię? Kopiuj-wklej wszystko i testy! Poprawiam testy tak, żeby odpowiadały logice klasy Outcome. Kiedy już wszystko działa, testy przechodzą to wyciągam część wspólną do klasy abstrakcyjnej, np. wyżej wymienionej BudgetItem. Sprawdzam warunek JEST, Income jest BudgetItem, Outcome też. Cały czas odpalam testy, aby sprawdzić że logika dalej ok.
W tym przypadku myślę, że abstrakcyjna klasa bazowa i dwie klasy pochodne są w porządku rozwiązaniem.

0

Podziękował :) Jak na razie pozostaje przy interfejsie, który sprawuje się dobrze i spełnia moje wymagania, ale następnym razem poeksperymentuje z Twoim pomysłem

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