Metoda dla dwóch klas

0

Witam,

Mam sobie klasę Pracownik i klasę Pensja. Chciałbym w systemie oprogramować metodę, która będzie dawać pracownikowi pensję. W związku z tym mam coś takiego:

class System
{
public void AddSophisticatedPensja(Pracownik p, Pensja pe)
{
p.Pensje.Add(pe);
}
}

Pytanie: Czy ta metoda jest obiektowo poprawna? Czy może inaczej powinienem to oprogramować?

0

Tak po obiektowemu, to ta metoda powinna należeć do klasy Pracownik. Tzn. już należy (własność Pensje) więc to co napisałeś jest nie potrzebne w ogóle. Można by ewentualnie dorobić "AddPensja(Pensja pe) { Pensje.Add(pe); }" ale nie widzę większego sensu aby to robić.

0

Dlaczego musi należeć do klasy Pracownik?

0

Skoro tyczy się pracownika, to niech należy do pracownika.

0

No dobra. Może ten przykład nie oddaje dokładnie istoty problemu.
Powiedzmy że jest taki kod:

class FinanseFirmy
{
public decimal SumaWazonaPensjiPracownikaIPrzelozonego(Pracownik PracownikA, Pracownik Przelozony)
{
return PracownikA.Pensja + Przelozony.Pensja * 2;
}
}

To tak powinno być? Czy nie?

0

Wszystko zalezy. Jak suma wazona pensji pracownika i przelozonego, to pewnie wykorzystywana do jakiegos raportu. Wtedy nalezy do klasy takiego raportu ;) Tak z kosmosu to nie ma reguly, ze zawsze tu, czy zawsze gdzie indziej. To co Ty robisz czasem jest sensowne (wyciagniecie operacji poza obiekty obslugiwane), ale tylko w przypadkach uzasadnionych. Tak robi na przyklad wzorzec Visitor. Tyle, ze to lamie zasade enkapsulacji i trzeba miec mocny powod, zeby z niej rezygnowac.

0

johny_bravo,

Czyli uważasz że powinno się robić tak albo inaczej? :-D
Mnie naprawdę zależy na uzyskaniu jakichś argumentów, które by przeważały za jednym rozwiązaniem albo innym.

0

W OOP chodzi o to aby dana funkcjonalność była związana z obiektem, którego się tyczy. W pierwszym przypadku funkcjonalność tyczy się pracownika - to pracownikowi przydzielane są pensje, nie pensjom pracownicy. Pensja nie musi wiedzieć, że jest przydzielana pracownikowi, a trzecia klasa która ma jedynie oddzielać funkcjonalność pracownika od jego klasy no nie jest na miejscu.
W drugim przypadku funkcjonalność tyczy się klasy FinanseFirmy - to ona operuje jednocześnie na pensjach wielu pracowników. To jej jest potrzebna średnia ważona. Obiekt Pracownik nie musi wiedzieć, że ktoś oblicza średnią z jego pensji. Jednak jeśli z tej średniej miało by korzystać więcej klas niezwiązanych z FinanseFirmy to warto ją zawrzeć w klasie Pracownik.

0

Dodatkowym argumentem moze byc stwierdzenie, ze, jezeli w metodzie nie uzywasz pol czy innych metod obiektu danej klasy, to warto sie zastanowic, czy nie uczynic metody statyczna. Jezeli do tego dochodzi spostrzezenie, ze metoda przyjmuje inne obiekty jako argumenty, zamiast metody statycznej przydanym moze okazac sie przeniesienie metody do klasy jednego z tych obiektow, gdyz z biezacym obiektem czy klasa metoda moze nie miec nic wspolnego.

0
TomaszSmykowski napisał(a)

Czyli uważasz że powinno się robić tak albo inaczej? :-D

Dokladnie ;) Wszystko zalezy od tego gdzie logicznie ta funkcjonalnosc bedzie przynalezala. A to zalezy od projektu i kontekstu wlasnie.

0

No i kto teraz ma rację?

0
TomaszSmykowski napisał(a)

No i kto teraz ma rację?
Przecież nikt nie zajął sprzecznych stanowisk [???]

0

Myślę że problem i kontekst jest wyraźnie zarysowany. Napisałem dokładnie co robi metoda i jakie przyjmuje obiekty, już chyba bardziej dokładnego przykładu nie można podać!

Zebrałem Wasze pomysły i przedstawiłem je poniżej w postaci wypunktowanej. Proszę o odpowiedź które z tych rozwiązań wybrać i dlaczego:

  1. Zostawić metodę w klasie FinanseFirmy
  2. Zawrzeć metodę w klasie Pracownik
  3. Zostawić metodę w klasie FinanseFirmy w postaci statycznej
  4. Zawrzeć metodę w klasie Pracownik w postaci statycznej
  5. Użyć wzorca Visitor.

Jak widać są one między sobą sprzeczne. Przypominam że chodzi mi o rozwiązanie tego problemu zgodnie z metodologią OOP.

0

Na oko nr 3. Za mało informacji.

Kto (jakie klasy) korzystają z tej funkcji ?

0

Ale teraz chodzi Ci o pierwszy przyklad (dawanie pracownikowi pensji) czy drugi (SumaWazonaPensjiPracownikaIPrzelozonego)?

W pierwszym rozwiazanie nr 2, bo pensja jest przynalezna pracownikowi i jest mu podrzedna.
W drugim przypadku prawdopodobnie rozwiazanie nr 3, chociaz klasa FinanseFirmy jest prawdopodobnie zle zaprojektowana klasa. To znaczy w prawdziwym przypadku taka klasa zawieralaby z 500 metod, z czego polowa nie mialaby ze soba nic wspolnego. Wtedy to rozwiazanie (tworzenie takiej klasy) nie byloby w duchu OOP, bo zawieralaby kilka/wiele odpowiedzialnosci. Chyba, ze bylaby np. implementacja wzorca Fasady.

Rozwiazanie nr 5 z zalozenia odpada. Wzorzec Visitor podany byl jako przyklad sytuacji, kiedy lamanie zasad OOP ma sens. Stosuje sie go w przypadku, gdy model/struktura danych zmienia sie czesciej od operacji na nich wykonywanych. Wtedy warto wyciagnac operacje poza obiekty, zeby uniezaleznic ich implementacje od zmian struktury. W Twoim wypadku ten wzorzec w ogole nie ma zastosowania.

Podsumowujac: podajesz kilka szczegolow (nie za wiele) i zadasz uniwersalnego rozwiazania, ktorego nie ma. To czy jakiekolwiek z podanych rozwiazan ma sens zalezy od logiki biznesowej, podzialu na klasy, definicji samych klas i odwzorowania na logike biznesowa, projektu aplikacji, itp, itd, mozna wymieniac w nieskonczonosc. Przyklad tej zaleznosci masz podany powyzej w uzasadnieniu o wzorcu Visitor (dlaczego kompletnie nie pasuje).

0
johny_bravo napisał(a)

chociaz klasa FinanseFirmy jest prawdopodobnie zle zaprojektowana klasa. To znaczy w prawdziwym przypadku taka klasa zawieralaby z 500 metod, z czego polowa nie mialaby ze soba nic wspolnego.

Właśnie, czy to już jest ostateczny kształt tej metody ? Jeśli tak to nie dobrze, po co pisać metodę, która zaledwie 2 operacje arytmetyczne wykona. Miałem o tym pisać, ale w końcu założyłem, że ona ma się jakoś rozrosnąć, że może sposób obliczania tej średniej będzie zależeć od jakichś czynników. Tak więc jeśli to jest jej ostateczny kształt, to pozbądź się jej w ogóle.
Jeśli to nie jest jej ostateczny kształt, no to będą nowe zależności, które znowu mogą zaważyć na tym, aby umieścić ją gdzie indziej.

0

Chodzi o przykład 2, bo pierwszy był za mało precyzyjny.

Nie wiem jak będą wyglądać te klasy dalej. Na razie jestem na etapie ich projektowania.

Klasy będą mieć o wiele wiele więcej właściwości i metod. Ale chyba zgadzamy się co do tego,
że zanim klasa będzie miała 500 metod trzeba zdecydować gdzie umieścić pierwszą?

Czyli jak na razie 2 głosy za opcją 3?

0
TomaszSmykowski napisał(a)

Czyli jak na razie 2 głosy za opcją 3?
Nie, 0 głosów. Przypomnę:

johny_bravo napisał(a)

prawdopodobnie rozwiazanie nr 3, chociaz klasa FinanseFirmy jest prawdopodobnie zle zaprojektowana klasa. To znaczy w prawdziwym przypadku taka klasa zawieralaby z 500 metod, z czego polowa nie mialaby ze soba nic wspolnego. Wtedy to rozwiazanie (tworzenie takiej klasy) nie byloby w duchu OOP

adf88 napisał(a)

jeśli to jest jej ostateczny kształt, to pozbądź się jej w ogóle.
Jeśli to nie jest jej ostateczny kształt, no to będą nowe zależności, które znowu mogą zaważyć na tym, aby umieścić ją gdzie indziej.

Najpierw określ jakie będą klasy i czym się będą zajmować. Pisanie metod to nie projektowanie a już implementacja.

Czyli raz, że do kitu sama metoda (prawie nic nie robi) a dwa jest wiele czynników, które mogą zaważyć, a których nie przedstawiłeś.
Te czynniki składają się głownie na

  • miejsca w których metoda będzie używana i częstotliwość użycia (tego nie podałeś)
  • zasobach, z których metoda będzie korzystać (I tu jednoznaczności nie ma bo zasoby są publiczne i można z nich korzystać zarówno z wnętrza jak i z zewnątrz klasy. Jakby zasoby były prywatne to sprawa jest jasna. Jest taka tendencja, że tam się daje metodę, gdzie są zasoby, ale jest jeszcze wiele innych czynników.)
0

To jest pierwsza metoda to skąd mam wiedzieć gdzie i jak często będzie używana ?

To koło zamknięte. Bo jak napiszę całą aplikację i będę wiedział gdzie tą metodę będę używać i ile razy to już będę miał ją gdzieś umiejscowioną i porada gdzie powinna zostać ona umiejscowiona nie będzie już miała sensu. Czy może się mylę?

0

Podchodzisz do sprawy od drugiej strony, od końca. Najpierw rozplanuj klasy, co mają robić, czego będą potrzebować i od kogo, komu będą służyć.
Pisanie metod to już ostatni etap i jest tylko przełożeniem całego planu (już prawie stworzonej chodź jeszcze nie napisanej aplikacji) na kod. Najpierw musisz wymyślić całą aplikację, a nie najpierw pisać kod i później zastanawiać się gdzie go użyć.

Właśnie o to chodzi, że przed napisaniem kodu musisz wiedzieć gdzie i co będziesz używać.

0

Wydaje mi się, że zamiast skupić się na problemie, wymijamy go wymyślając czym innym można by się zająć.

Przykład z kodem dałem żeby ułatwić dyskusję. Wiadomo że chodzi o to że potrzebuję funkcjonalność polegającą na wyliczaniu sumy ważonej pensji z pensji pracownika i jego przełożonego. I gdzie tą funkcjonalność zawrzeć czy w klasie pracownika czy w innej.

Jeżeli to doprowadzi do odpowiedzi na pytanie, możemy zacząć rozważać to na poziomie dokumentacji. Nie ma problemu z tym.

W takim razie jak określić na podstawie dokumentacji gdzie powinna być umieszczona ta metoda tj:

Gdzie ją umieścić jeżeli jest wywoływana często, gdzie ją umieścić jeżeli jest wywoływana rzadko?
Gdzie umieścić ją kiedy jest używana z innych klas, a gdzie jeżeli nie jest wywoływana z innych klas.
Od czego zależy czy ma być ona statyczna czy nie?

0
TomaszSmykowski napisał(a)

Gdzie umieścić ją kiedy jest używana z innych klas

adf88 napisał(a)

Jednak jeśli z tej średniej miało by korzystać więcej klas niezwiązanych z FinanseFirmy to warto ją zawrzeć w klasie Pracownik.
odatkowo jeśli byłaby używana przez klasy związane z FinanseFirmy (np. przez jej klasy prywatne) to wtedy można ją umieścić w FinanseFirmy.

TomaszSmykowski napisał(a)

a gdzie jeżeli nie jest wywoływana z innych klas.

adf88 napisał(a)

W drugim przypadku funkcjonalność tyczy się klasy FinanseFirmy - to ona operuje jednocześnie na pensjach wielu pracowników. To jej jest potrzebna średnia ważona

TomaszSmykowski napisał(a)

Gdzie ją umieścić jeżeli jest wywoływana często, gdzie ją umieścić jeżeli jest wywoływana rzadko?
Często w sensie wielokrotnie pisana w kodzie, a nie wielokrotnie wywoływana (np. w pętli). Odpowiedź - tam gdzie częściej.

TomaszSmykowski napisał(a)

Od czego zależy czy ma być ona statyczna czy nie?

Szczawik napisał(a)

jezeli w metodzie nie uzywasz pol czy innych metod obiektu danej klasy, to warto sie zastanowic, czy nie uczynic metody statyczna
Dodatkowo jeśli np. umieściłbyś ją w klasie pracownik to tyczy się ona zarówno pracownika jak i przełożonego więc nie jest szczególnie związana z pierwszym czy z drugim a z obydwoma tak samo, więc wtedy statyczna.

Jest wile czynników, trzeba wyciągnąć średnią.

0

Dzięki

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