Forum Coders' city Strona Główna Coders' city
Nasza pasja to programowanie!
 

 PomocPomoc   SzukajSzukaj   UżytkownicyUżytkownicy   GrupyGrupy  RejestracjaRejestracja 
Archiwum starego forum + teoria    RSS & Panel/SideBar
 ProfilProfil   Zaloguj się, by sprawdzić wiadomościZaloguj się, by sprawdzić wiadomości   ZalogujZaloguj 

Potrzebuję szybkiej odpowiedzi na moje pytanie... Zasady

Obiektowe modelowanie dziedziny



 
Odpowiedz do tematu    Forum Coders' city Strona Główna -> Java
Zobacz poprzedni temat :: Zobacz następny temat  
Autor Wiadomość
wowo098
Gość





PostWysłany: Pią Lis 03, 2017 10:45 pm  OP    Temat postu: Obiektowe modelowanie dziedziny Odpowiedz z cytatem Pisownia

Witam,
Wiem, że temat jest bardziej ogólny, ale umieściłem go tutaj, ponieważ programuje w javie i chciałbym, aby uwzględniono jej "ograniczenia" (np. brak możliwości wielodziedziczenia klas).
Zmagam się z pewnym problemem już dłuższą chwilę i nie mogę znaleźć rozwiązania, które by mnie satysfakcjonowało. Problem wygląda następująco, mam klasę Osoba. Po klasie Osoba dziedziczą klasy Wokalista i Gitarzysta. Możemy stworzyć obiekty klas Perkusista i Gitarzysta. Bardzo fajnie, ale co w przypadku gdy dana Osoba jest Wokalistą i Gitarzystą jednocześnie? Czy istnieje jakiś struktura klas, wzorzec projektowy, który by ładnie oddawał takie zależności?
Z góry dziękuję za jakiekolwiek sugestie i pomoc.
Powrót do góry
samolot



Dołączył: 26 Sty 2006
Posty: 8314
Skąd: Toruń

PostWysłany: Pią Lis 03, 2017 11:09 pm      Temat postu: Odpowiedz z cytatem Pisownia

Jeśli żle myślę to mnie poprawcie. Ja bym w klasie osoba dodał właściwość "Funkcja", której można by nadawać wartości takiego enumeratora, zdefiniowanego wcześniej:
1-Wokalista
2-Gitarzysta
4-Perkusista
8-Wiolączelista
16-Skrzypoek
Tworzysz nową klasę typu Osoba i nadajesz jej wartość właściwości Funkcja
Przykładowo:
- jeśli równą 3, co będzie oznaczało, że ta osoba jest zarówno Wokalista jak i Gitarzystą
- jeśli równą 6, co będzie oznaczało, że ta osoba jest zarówno Perkusistą jak i Gitarzystą

_________________
Nie zadawaj bezcelowych pytań / Windows 8.1 / Windows 10 / VB2008 / VB 2010 / VB 2012 / Pisz poprawnie
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość Wyślij email
wowo098
Gość





PostWysłany: Pią Lis 03, 2017 11:14 pm  OP(?)    Temat postu: Odpowiedz z cytatem Pisownia

Problem w tym, że sama identyfikacja nie wystarcza. Każda z klas pochodnych będzie miała oddzielny zestaw metod.
Powrót do góry
samolot



Dołączył: 26 Sty 2006
Posty: 8314
Skąd: Toruń

PostWysłany: Sob Lis 04, 2017 12:24 am      Temat postu: Odpowiedz z cytatem Pisownia

Klasa pochodna dziedziczy metody "ogólne" po klasie bazowej
A specyficzne metody klasy pochodnej implementujesz w klasie pochodnej.

_________________
Nie zadawaj bezcelowych pytań / Windows 8.1 / Windows 10 / VB2008 / VB 2010 / VB 2012 / Pisz poprawnie
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość Wyślij email
wowo098
Gość





PostWysłany: Sob Lis 04, 2017 12:59 pm  OP(?)    Temat postu: Odpowiedz z cytatem Pisownia

Dziękuję za pomoc!
Powrót do góry
marcin_an



Dołączył: 26 Maj 2005
Posty: 18822

PostWysłany: Pią Lis 10, 2017 2:06 am      Temat postu: Odpowiedz z cytatem Pisownia

Ehh... efekt nauczania obiektowości na przykładzie "postaci z gier" (tudzież podobnych) w połączeniu z podchodzeniem do tworzenia programu od strony literki "M" w MVC.

Zacznij od przemyślenia, jakie operacje możesz wykonać na członkach zespołu. Czyli jakie metody będziesz miał. Zestawy tych metod mają być w interfejsach, nie klasach. Konkretne klasy jedynie implementują te metody. Nic ponad to: nie dziedziczą po innych klasach, nie tworzą między sobą hierarchii. Od tego są interfejsy, które mogą dziedziczyć po sobie - także w postaci dziedziczenia po kilku interfejsach jednocześnie. Zatem nic nie stoi na przeszkodzie, byś miał interfejs WokalistaGitarzysta.

Nic oprócz... prawie na pewno braku potrzeby tworzenia takiego potworka. Na tej zasadzie mógłbyś iść dalej i tworzyć WokalistaGitarzystaBasista itd. Dla standardowego, 4-instrumentowego zespołu masz już 23 możliwości. Dla typowej kapeli folk-metalowej z 7 instrumentami masz z 5 tysięcy opcji i wartość ta rośnie bardzo szybko. Nie tędy droga - i to jest bolączka, o której napisałem na początku.

Nie próbuj robić kopii świata w swoim programie. Definicje powinny być zależne od tego, jakie metody będziesz musiał wywoływać na swoich obiektach. Czy jakikolwiek fragment twojego programu oczekuje, że istnieje obiekt, który będzie musiał być jednocześnie wokalistą i gitarzystą? Czy jest chociaż jedna metoda, która przyjmuje jako argument coś, co musi być wokalistą ORAZ gitarzystą i wywołuje metody obydwu*? Jeżeli nie, to znaczy, że nie potrzebujesz takiego interfejsu.

Możesz, oczywiście, mieć klasę implementującą obydwa interfejsy. Przykładowo:
Kod:
public final class AdamDarski implements Gitarzysta, Wokalista {
    /* ... */
}
Jeżeli istnieje potrzeba, by gdzieś tworzyć obiekt, który reprezentuje je obydwa - ok.

Lub "prawie ok". O ile bowiem jest to już całkowicie w porządku z punktu widzenia obiektowości, to z praktycznego punktu widzenia będzie to droga przez mękę. Niemniej, jeżeli potrzebujesz tego na studia i nauczyciel tak wymaga, to tak rób. Poniższy fragment dotyczy już kwetii praktycznych, nie uczelnianych. Zauważyłeś, że w grach nie implementuje się postaci, historii, zdarzeń, tekstów, przedmiotów i całej reszty w postaci oddzielnych klas? Tak napisana gra byłaby bardzo trudna do utrzymania, kompilowałaby się nie wiadomo ile, byłaby niewydajna z punktu widzenia używanej pamięci, wymagałaby umiejętności programowania przez osoby odpowiedzialne za tematy nieprogramistyczne i byłaby trudniejsza w aktualizacji. Rozdziela się faktyczne dane od kodu, a jeśli nawet już coś jest w kodzie, to postaraj się tego użyć wielokrotnie i umożliwić wykorzystanie w miejscach, których może nawet teraz jeszcze nie widzisz. W tym przypadku to, czego chcesz, to możliwość utworzenia obiektu, który dane będzie dostawał z zewnątrz (np. z jakiegoś pliku konfiguracjnego), a zachowanie będzie realizowane np. przez wzorzec dekoratora.

samolot:
Miało być obiektowe. To, co zaproponowałeś, jest sprzeczne z podstawami obiektowości i uniemożliwi wowo098-owi faktyczne wykorzystanie tak zbudowanych klas w środowisku obiektowym.
____
* Ewentualnie istnieje pole klasy, które odnosi się do takiego czegoś.

_________________
Nieaktywny od 2017-04-01
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
samolot



Dołączył: 26 Sty 2006
Posty: 8314
Skąd: Toruń

PostWysłany: Sob Lis 11, 2017 12:29 am      Temat postu: Odpowiedz z cytatem Pisownia

Samolot napisał:
Jeśli żle myślę to mnie poprawcie

I niestety, nie jestem "zawodowcem" w tej dziedzinie, może niepotrzebnie więc mieszam. Szkoda, że tak rzadko tu teraz zaglądasz, bo twoją wiedzę zawsze tu wszyscy wysoko cenili. Ja tu jeszcze trochę sprzątam, ale ciemność widzę.

_________________
Nie zadawaj bezcelowych pytań / Windows 8.1 / Windows 10 / VB2008 / VB 2010 / VB 2012 / Pisz poprawnie
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość Wyślij email
marcin_an



Dołączył: 26 Maj 2005
Posty: 18822

PostWysłany: Czw Lis 16, 2017 8:20 am      Temat postu: Odpowiedz z cytatem Pisownia

Przepraszam, nie miałem zamiaru cię zrugać. Może powinienembył bardziej rozwinąć tamtą wypowiedź, co też zrobię.

Pomijając na chwilę sensowność takiego podejścia (o tym dalej), zauważ jedną rzecz. W zaproponowanym rozwiązaniu faktycznie jesteś w stanie rozróżnić różnych muzyków: mieć wokalistę, perkusistę, skrzypko-wokalistę itp. Ale nie możesz w żaden sposób spożytkować tej informacji. Wszystkie obiekty będą miały bowiem dokładnie ten sam zestaw metod. Tutaj są dwie opcje: znaleźć najmniejszą część wspólną albo użyć sumy wszystkich możliwości. Pierwsze oznacza, że nie będzie żadnych metod "muzycznych", czyli obiekty będą bezużyteczne. Drugie jest jeszcze gorszą sytuacją: większość metod jest obecna, ale w rzeczywistości nie działają, bo dla danej osoby nie mają sensu.

Wracając teraz do obiektowości: jedną z głównych zalet podejścia obiektowego jest uniezależnienie od siebie elementów programu, swobodne zmienianie ich implementacji bez wpływu na resztę programu oraz możliwość nieograniczonego dodawania nowych implementacji. Użycie rozwiązania takie, jakie zaproponowałeś, stoi w sprzeczności z tymi tematami.

Nie możesz dodawać ile chcesz nowych implementacji, bo każda musi mieć przyporządkowany bit w zestawie flag, określającym jej typ. W zależności od sytuacji, języka i możliwości, liczba bitów jest zwykle ograniczona do czegoś pomiędzy 32 a 128. Typowo: 64. Można używać kilku zmiennych, ale chyba zaczynasz już czuć, że jest to tylko uciekanie od problemu, które nie jest też pozbawione kosztów. A jeśli dzisiaj nie widzisz możliwości utworzenia 64 różnych muzyków, to podpowiem, że w hitorii informatyki niedoszacowanie możliwej liczby opcji jest powszechne. Nie szukając daleko: w X11 (najpopularniejszy system okien) na układ klawiatury przeznaczono 2 bity, bo uznano, że 4 układy klawiatury wystarczą każdemu. Jeśli nawet mimo tego 64 wydaje się dużą liczbą dla czegoś opisującego zespół muzyczny, to przypomnę o dwóch innych rzeczach. Pierwsze: w inżynierii zachowuje się pewien zapas "na wszelki wypadek". Drugie: w czasie rozwoju programu na przestrzeni wielu lat powstaną alternatywne implementacje tych samych muzyków. Po uwzględnieniu powyższego okazuje się, że 64-bitowa ma dużo mniejszą "pojemność": może nawet rzędu 4-8 muzyków.

Żeby dodać taki nowy identyfikator, trzeba poprawić każdy fragment kodu, który będzie się do niego dotykał. Nie możesz po prostu dodać wartości 32 dla flecisty. Nie, cały program musi wiedzieć, co oznacza to 32. W przypadku identyfikatorów w postaci flag, takich jak zaproponowane przez ciebie, jest jeszcze o tyle dobrze, że w niektórych sytuacjach można zignorować nieznane wartości i program się nie posypie. Ale to tylko ograniczenie skutków problemu, a nie jego wyeliminowanie. A problem jest znaczący. W projekcie, nad którym pracuje cały zespół ludzi, zsynchronizowanie ich pracy i zagwarantowanie spójności takich rzeczy wymaga sporego wysiłku. Nawet jeżeli pracuje się samodzielnie, to nadal jest to kupa roboty, konieczność przekompilowania sporej części programu i przetestowania jej - w tym napisania testów, które nie będą służyły niczemu innemu oprócz sprawdzeniu właśnie działania tej jednej wartości. Porównując to do podejścia obiektowego, gdzie jeden programista po prostu dodaje sobie klasę i nie wpływa to na nic innego, jest to potworne marnowanie zasobów.

I, ostatnie, niezależność różnych części programu. Częściowo poruszyłem to już w poprzednim paragrafie, ale tutaj podejdę do tego od strony bardziej formalnej. Istnieje coś, co nazywa się Liskov substitution principle. Po polsku: "zasada podstawienia Liskov", ale nie polecam definicji zawartej na polskiej Wikipedii. W skrócie* mówi ona, że jeżeli mamy dwa typy T i U, gdzie U jest podtypem T, oraz mamy kod używający obiektów typu T, to kod ten musi działać - bez żadnych zmian - także dla obiektów typu U. Przykładowo: mamy typ Zwierzę oraz typy Pies, Kot, Koń i Wieloryb. Mamy kod, który robi coś na obiektach typu Zwierzę: np. maluje je całe pomarańczowo. Do kodu tego możemy podstawić Pies, Kot, Koń albo Wieloryb i dla tego kodu nie powinno mieć żadnego znaczenia, jakie zwierze faktycznie dostał: każde ma pomalować na pomarańczowo. I jeśli przyjdzie mi do głowy za rok, żeby stworzyć typ Biedronka, to kod ten powinien pomalować biedronkę na pomarańczowo bez zająknięcia. Jak sam zapewne zauważasz, używanie rozwiązania z flagami przeczy tej regule.

Niezależność różnych części programu jest też ograniczona faktem, że musi istnieć centralny "rejestr" tych wartości. Czy to będzie typ wyliczeniowy, jakaś lista, czy nawet kawałek papieru na biurku każdego programisty, jest to coś, co niepotrzebnie spina ze sobą rzeczy, które powinny być oddzielne.

____
* Formalna definicja jest bardziej precyzyjna i mniej zależna od konkretnego języka programowania. Tutaj przyjąłem formę uproszczoną, pasującą do praktycznego jej zastosowania w językach obiektowych w stylu C++, C# czy Javy.

_________________
Nieaktywny od 2017-04-01
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
samolot



Dołączył: 26 Sty 2006
Posty: 8314
Skąd: Toruń

PostWysłany: Czw Lis 16, 2017 10:55 pm      Temat postu: Odpowiedz z cytatem Pisownia

Z tą obiektowością jest tak, że właściwie ja ją rozumiem, ale trudno ją stosować "od razu", bo to wymaga dokładnej analizy problemu pod względem obiektowości. Widzę, że palnąłem głupstwo, ale liczyłem właśnie na taką wypowiedź jak twoja.
Poza tym uważam, że nigdy nie jest tak, że implementuje się dla problemu od razu gotowe, bezbłędne, niezależne obiekty, które są od razu w każdym względzie doskonałe. Tworzy się raczej coś zbliżonego, a później się to poprawia i udoskonala. Oczywiście dogłębne przemyślenie problemu na początku pomaga wystartować z lepszą jakością obiektów, ale zawsze jest to proces dochodzenia do pełnej obiektowości.


'

_________________
Nie zadawaj bezcelowych pytań / Windows 8.1 / Windows 10 / VB2008 / VB 2010 / VB 2012 / Pisz poprawnie
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość Wyślij email
Wyświetl posty z ostatnich:   
Odpowiedz do tematu    Forum Coders' city Strona Główna -> Java Wszystkie czasy w strefie CET (Europa)

Strona 1 z 1

 
Skocz do:  
Możesz pisać nowe tematy
Możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Możesz dodawać załączniki na tym forum
Możesz pobierać pliki z tego forum




Debug: strone wygenerowano w 0.14296 sekund, zapytan = 11
contact

| Darmowe programy i porady Jelcyna | Tansze zakupy w Helionie | MS Office Blog |