Autor Wątek: Wzorzec projektowy  (Przeczytany 17366 razy)

Offline Karol

  • Użytkownik

  • +2
# Czerwiec 27, 2012, 11:43:23
Kurdę, coś w tym jest, sam teraz mam problemy z czymkolwiek co piszę sobie sam, bo co chwila kwestionuję swoje podejście i napisany kod, co skutecznie odciąga mnie od samego pisania. Szczególnie kiedy ubzdurałem sobie, że każda rasa oparta będzie na własnej klasie (dziedziczącej po jakiejś ogólnej), każdy typ ekwipunku także będzie miał swoją klasę z hierarchią dziedziczenia (np. klasa Item -> klasa Equipable -> klasa Weapon), w efekcie więcej było z tym problemów niż pomocy i to w każdym możliwym aspekcie.
A kiedyś, jak pisałem w QBasicu, nie wiedziałem jeszcze nawet co to tablice czy typy rekordów i dla każdego gracza tworzyłem oddzielne zmienne, ale mimo to grę ukończyłem (a był to klon Kolony z Atari :D ).

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline gmpro

  • Użytkownik

  • +1
# Czerwiec 27, 2012, 11:52:33
Nie znam tematu ale z tego co wyczytałem na wiki to ciekawym rozwiązaniem są domieszki
http://pl.wikipedia.org/wiki/Domieszka_%28programowanie_obiektowe%29

Offline Cocomide

  • Użytkownik

# Czerwiec 27, 2012, 12:12:04
każda rasa oparta będzie na własnej klasie (dziedziczącej po jakiejś ogólnej), każdy typ ekwipunku także będzie miał swoją klasę z hierarchią dziedziczenia (np. klasa Item -> klasa Equipable -> klasa Weapon), w efekcie więcej było z tym problemów niż pomocy i to w każdym możliwym aspekcie.

Tak z ciekawości, czym to zastąpiłeś? Przy projektowaniu nic mi innego nie przychodzi do głowy jak osobna klasa dla pojazdu, jednostki i budynku, trzymających interfejs "IPlayableObject" oraz dziedziczących po klasie "CGameObject". W takiej hierarchii używam każdej z tych klas a w listach obiektów trzymam albo interfejs albo "CGameObject". Zastanawia mnie jak to niby ma wyglądać schludniej/lepiej i ma ułatwić pisanie/skrócić kod.
« Ostatnia zmiana: Czerwiec 27, 2012, 12:13:57 wysłana przez Cocomide »

Offline Karol

  • Użytkownik

# Czerwiec 27, 2012, 12:14:47
@up tak jak to Krzysiek K. albo Kos przedstawił.

Offline Cocomide

  • Użytkownik

# Czerwiec 27, 2012, 12:31:16
I to jest ta alternatywa? Jak dla mnie klasa "Entity" to dokładnie to czego ja używam. Z taką różnicą, że jednostki grywalne mają dodatkowy interfejs. Ja to nazywam zwykłą hierarchią klas. Tą złą i niemoralną hierarchią OOPowców.

Offline Karol

  • Użytkownik

# Czerwiec 27, 2012, 12:40:18
Masz jedną klasę z interfejsem, więc gdzie tu owa hierarchia? Mówienie o hierarchii klas w tym momencie to jak używanie tablicy dla jednego elementu. IMHO lepiej sobie jakąś flagą oznaczyć czy to jednostka czy budynek czy grzybek, niż tworzyć dla nich nowe klasy dziedziczące po czymś tam.

Offline Cocomide

  • Użytkownik

# Czerwiec 27, 2012, 12:48:51
@up
No podawalem na szybko, w moich projektach tego trochę więcej było. Ale teraz wiem, że np. robienie osobnych klas dla dynamicznych i statycznych elementów było do uniknięcia.
Wyczuwam w tym wszystkim czasy Pascala z technikum. Czyli nauka teorii OOP teraz idzie w las? Zamiast klas robimy enumy i dołączamy zbędną funkcjonalność? To się tyczy tylko w rapid programming, czy w dużych projektach też wg Was powinno tak być? Pytam z czystej ciekawości.
« Ostatnia zmiana: Czerwiec 27, 2012, 13:06:35 wysłana przez Cocomide »

Offline Karol

  • Użytkownik

# Czerwiec 27, 2012, 13:11:10
Sam OOP jest fajny i jak dobrze się go rozplanuje to spisuje się świetnie, jednak (jak dla mnie) szybciej i wygodniej przetwarza się dane w grze bez tego (łatwiej też zapisać/wczytać dane i przesłać przez sieć o czym już wyżej wspomniano). Gry są na tyle specyficzne, że rzadko kiedy da się odseparować obiekty od siebie, aby ładnie pozamykać je w klasy, zawsze coś czegoś będzie wymagać nawzajem, zacznie się stosować jakieś brzydkie sztuczki typu "aby działało" (czyli "fuckfixy" :D spodobało mi się to określenie), które złamią całą ideę OOPu.

Offline hashedone

  • Użytkownik

  • +3
# Czerwiec 27, 2012, 13:20:52
A co ma teoria OOP do obszernych hierarchii dziedziczenia? Całkowicie nie powiązane rzeczy. Kod ma spełniać trzy zasady: DRY, KISS, YAGNI. Robienie rozległych drzew dziedziczenia na pewno się pod KISS nie wpisuje. Dalej - czy korzystasz z polimorfizmu? Hint: pisanie
DerrivedClass * dObject = dynamic_cast < DerrivedClass * >(object);
if(dObject)
{
//...
}
to nie jest dobrze pojmowany polimorfizm. Tam gdzie jesteśmy w stanie mieć zyski z wywołań wirtualnych, tam jest miejsce na dziedziczenie. W C++ tylko tam (przynajmniej tak długo, jak w C++ nie ma dobrego RTTI). Wszędzie indziej na dziedziczenie odpowiem tylko YAGNI. Kolejna rzecz - przy takim rozłożeniu klas o jakim mówisz bardzo często klasy mają powielane interfejsy. Z czym mi się to kojarzy? Oczywiście DRY!

Te trzy zasady które rozległe niepotrzebne dziedziczenie tworzy to nie jest wymysł lat '80 czy speców od programowania funkcyjnego. To są podstawowe akronimy OOP. OOP to nie jest paradygmat który mówi "wsadź nową klasę gdzie się da", tylko "niezależne od siebie komponenty zamknij w odseparowanych modułach". I to jest dobre. Przy czym można to zrobić bez jednej klasy w kodzie.

===EDIT===
Przypomniało mi się jak ktoś mi (chyba nawet na tym forum, wydaje mi się że konkretnie Kos - chociaż nie mam pewności) powiedział: OOP = Object Oriented Programming, nie Class Oriented Programming
« Ostatnia zmiana: Czerwiec 27, 2012, 13:23:54 wysłana przez hashedone »

Offline gmpro

  • Użytkownik

# Czerwiec 27, 2012, 13:36:54
Nawiązując do tego cytatu
Klasy w kodzie nie muszą być odzwierciedleniem świata w grze.. tzn. nie ma sensu tworzenie nowych klas, aby przedstawić postacie "różniące" się praktycznie tylko ilością hp.

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Czerwiec 27, 2012, 13:41:57
Cytuj
Czyli nauka teorii OOP teraz idzie w las?
Nie idzie. Po prostu masz dodatkowe narzędzie w skrzynce. Ale przecież gdy kupisz nowy śrubokręt to nie zaczynasz nim wbijać gwoździ twierdząc że młotek jest przestarzały.

Cytuj
To się tyczy tylko w rapid programming, czy w dużych projektach też wg Was powinno tak być?
Jak dla mnie głownie rapid. Przy założeniu, że każdy programista który w pojedynkę chce cokolwiek skończyć w sensownym czasie zyska na stosowaniu filozofii rapid.

Niestety przy podejściach i wzorcach z kategorii ekstremalnego agile zwiększa się mętlik w kodzie, który jest do ogarnięcia przez jedną osobę (i czasem mocnego zrefaktoryzowania), ale od dwóch osób zaczyna się problem z synchronizacją (kodu i wiedzy o nim). Im większy team, tym czytelniejszy musi być kod, więc powyżej pewnego progu albo musisz użyć OOP, albo wykształcić własny system i systematyczne podejście do jego programowania (np. dziedziczenie w systemie deklaracji encji).

Co do samych encji, to polecam zauważyć że nie wyklucza to koncepcji dziedziczenia - tyle że nie korzystamy tu z OOP, a sami robimy do tego system (albo styl programowania).

Ot na przykład taki kod skryptu:

void init_object(Entity e) { ... ustawia standardowe wartości pól encji ... }
void init_drawable(Entity e) { ... ustawia podstawowe właściwości pod renderowanie ... }
void init_physics(Entity e) { ... ustawia standardowe rzeczy pod fizykę ... }
void init_monster(Entity e) { init_object(e); init_drawable(e); init_physics(e); ... i przebija jeszcze parę właściwości potwora ... }
void init_zombie(Entity e) { init_monster(e); ... przebija wartości pól tak, żeby rzeczywiście to był zombie ... }

I co to jest innego, jak nie dziedziczenie? Tyle że bez konieczności rekompilacji całości, pisania dodatkowych deklaracji i zabawy z nagłówkami. :)

Offline Cocomide

  • Użytkownik

# Czerwiec 27, 2012, 13:49:39
@hashdone
rozumiem, że żeby uniknąć takiego rzutowania jak opisałeś stosuje się wzorzec "Fabryka" i się przechowuje tylko bazową klasę? I jest jeden element, którego nie rozumiem. W tej bazowej klasie typu "Entity" mają być przechowywane referencje do każdej właściwości wszystkich obiektów? Zgarnę wtedy do jednej klasy kilkadziesiąt zmiennych i tylko połowę z nich będę używać w jednym obiekcie. Jak się w tym nie pogubić potem, czy to czasami nie zaśmieca kodu?

@Krzysiek K.
Opiszesz dokładniej ten "kod skryptu"? To jest ta "Fabryka" na encajch?
Czyli używam funkcji do zapisywania w encji właściwości odpowiednich dla obiektu, który chcę stworzyć. To coś nowego do zapamiętania.


Wybaczcie głupie pytania. Specem nie jestem, a jak na razie to się nauczyłem z tej dyskusji jak wiele błędów popełniam dotąd. Będę pytał dalej, może komuś ta dyskusja się przyda tak jak mi.
« Ostatnia zmiana: Czerwiec 27, 2012, 13:51:17 wysłana przez Cocomide »

Offline gmpro

  • Użytkownik

# Czerwiec 27, 2012, 13:58:12
@Cocomide:
Jeśli sam coś piszesz to powinieneś się w tym połapać, gorzej jak z kimś.
Chociaż mnie to i tak przeraża :P lepiej posiedzieć i napisać racjonalną hierarchię

Offline Karol

  • Użytkownik

# Czerwiec 27, 2012, 14:00:38
OOP to nie jest paradygmat który mówi "wsadź nową klasę gdzie się da", tylko "niezależne od siebie komponenty zamknij w odseparowanych modułach". I to jest dobre. Przy czym można to zrobić bez jednej klasy w kodzie.

Przypomniało mi się jak ktoś mi (chyba nawet na tym forum, wydaje mi się że konkretnie Kos - chociaż nie mam pewności) powiedział: OOP = Object Oriented Programming, nie Class Oriented Programming
Więc jak chcesz programować obiektowo bez klas, bez których nie będzie obiektów? Podział na moduły to żadna obiektowość, bo te mogę mieć i programując strukturalnie.

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Czerwiec 27, 2012, 14:44:49
Cytuj
Czyli używam funkcji do zapisywania w encji właściwości odpowiednich dla obiektu, który chcę stworzyć. To coś nowego do zapamiętania.
To tylko przykład na to, jak w sensowny sposób reusować kod. :)