Przykład architektury opartej o intefejsy

0

Witam

Zwracam się z takim oto pytaniem. Obecnie biorę udział w projekcie ,którego jednym z celów jest stworzenie w maire jednolitego mechanizmu , który będzie obsługiwał skrajne różne menu pewnego portalu.
Przykładowo pewna część nawigacji jest oparta na konfiguracji zapisanej w plikach xml , inna zaś, jest w wysokim stopniu powiązana ze strukturą produktów w bazie danych. Początkowo chciałem oprzeć ową konstrukcję na interfejsie MenuItem , co w skrócie miało zapewnić w miarę uniwersalny schemat generowania poszczególnych sekcji menu.
Tutaj pojawia się sedno problemu, aby w pełni obsłużyć daną sekcję muszę dodawać do owego interfejsu metody ,które są w zasadzie powiązane tylko z jednym typem menu ( co zaowocuje pustymi metodami w innych implementacjach), z drugiej zaś mogę cześć nieuniwersalnych metod do konkretnej implementacji , jednakże wtedy cześć kodu będzie musiała bazować na rzutowaniu interfejsu do określonej implementacji (często byłem uczulany aby opierać kod na interfejsach nie na implementacji).
Musze przyznać ,że doszedłem do pewnej sytuacji patowej i byłbym bardzo wdzięczny za wszelkie udzielone rady.

pzdr

0

Nie bardzo rozumiem czemu niektore metody musza byc powiazane z konkretna implementacja.

Ale nawet jesli tak to moze stworz klase, ktora opakowywc bedzie te szczegolne metody, tak jak to robi np. wzorzec Command.

Albo stworz Drivery do konkretnego rodzaju menu, tak by korzystaly sobie z roznych konkretnych implementacji podklas a by klasa wywolujaca dzialanie (np. dodanie nowego elementu menu) nie zaglebiala sie w szczegoly.

Moze podaj przyklad takich metod, ktore sa nieuniwersalne, a pasuje by byly wspolne z jakiegos powodu.

0

Zawsze możesz też użyć wzorca FrontControllera do generowania menu. Niech przyjmuje on żądania i wyrzuca już spójną odpowiedź. To co będzie działo się za nim niech będzie konfigurowane z xmla na zasadzie jeżeli żądanie jest A to użyj klasy A, jeżeli B to B itd. W ten sposób dostarczysz klientowi jednolitego interfejsu, za pomocą którego może opanować menu, a jednocześnie będziesz mógł dowolnie grzebać w jego bebechach.
Co zaś tyczy się samego problemu menu. Nie zapominaj, że możesz uprościć interfejs do poziomu jednej/dwóch metod publicznych, a różnice w poszczególnych przypadkach ukryć w metodach prywatnych. Należy dążyć do ujednolicenia różnych rodzajów menu przynajmniej w stopniu pozwalającym na jednolite pobieranie kolejnych elementów. To jak są wybierane to sprawa wtórna.

0

Cześć

Generalnie kwestia wygląda tak ,że projekt ma swój czas i budżet ,wiec zbytnich rewolucji tam robić nie mam możliwości. Jedna sekcja menu np. ma mieć mozliwość podziału danego poziomu podmenu na podgrupy aby przezentować tylko jedną z nich , wiec można np. zrobić metodę getMenuGroup(Id) czy cos w tym stylu , jakkolwiek druga sekcja menu(obslugujaca zupelnie inną czesc portalu) nie potrzebuje takiej funkcjonalnosci i w jej przypadku owa metoda bylaby pusta i wymagana jedynie do utrzymania zgodnosci z interfejsem.
Generalnie doszedlem do wzniosku ze jakkolwiek uniwersalny ten mechanizm by nie byl potrzebne będzie jakaś strategia dedykowana dla przekazywania do widoku danej sekcji menu obrobionych danych. Samą strategię łatwo można by podmienić w zależności od typu menu ,zaś w jej srodku można by korzystać z konkretnych implementacji.

Co sądzicie o takim rozwiązaniu.?

PS. Wiem ,że owy opis jest strasznie powierzchowny ale celowo nie chcę wgłębiać się w szczegóły gdyż to by tylko zaciemniło cały obraz.

pzdr

0
class Animal
{
  ...
  virtual ... = 0;
  virtual ... = 0;
  virtual ... = 0;
  ...
}

class Prosiak : public Animal 
{
  ...
}

class Wilk : public Animal
{
  ...
}

I juz masz architekture oparta o interfejsy.

0

?

0

egon mowi w jezyku C++. metody 'pure virtual', czyli np. virtual void metoda()=0; zachowuja sie jak definicje interfejsu - klasa staje sie abstrakcyjna i wszystkie klasy potomne musza je zaimplementowac lub staja sie abstrakcyjne. dzieki temu mozna napisac klase 'pure virtual', czyli zawierajaca asme metody pure virtual, ktora defacto bedzie sie zachowywac jak interfejs

0
quetzalcoatl napisał(a)

ktora defacto bedzie sie zachowywac jak interfejs

... bo to wlasnie jest interfejs, rownie dobrze mozemy dodac kolejny interfejs tym razem wymuszajacy implementacje narysowania zwierzaka

class Animal
{
  ...
  virtual ... = 0;
  virtual ... = 0;
  virtual ... = 0;
  ...
}

class DisplayAnimal
{
  virtual Draw() = 0;
}

class Prosiak : public Animal, public DisplayAnimal
{
  ...
}

class Wilk : public Animal, public DisplayAnimal
{
  ...
}
0

Czesc

Dzieki za odpowiedz jakkolwiek chodzilo mi o pewien przypadek projektowy a nie przyklad zastosowania interfejsow: >

Trzymając sie analogii do zwierząt powiedzmy(w bardzo wielkim uproszczeniu) ,że w pewnej apliakcji istniały zupełnie ze sobą niezwiązane fukcjonalności zarządzania świniakami i wilkami, obydwa typy zwierząt mogłyby być karmione ale do świniaków dodano funkcjonalność tuczenia i tarzania się w błocie zaś wilkom polowania i wycia.
Teraz przez kilka ładnych lat funkcjonlność otaczająca implementacjie obydwu zwierząt niezwykle się uzalezniła od konkretnych metod i nagle pojawia się koncepcja ujednoliccenia zarządzania wszystkimi zwierzakami w ramach calej aplikacji jednak budzet nie przewiduje żadnych rewolucyjnych zmian w obecnej funkcjonalności. Teraz powstaje pytanie czy wszędzie używać typu bazowego( interfejsu) i dokonać pewnej nadmiarowej implementacji metod czy też jednak dopuścić dla kiku komponentów wiedze z jaką implemetacją pracują. Ja wybrałem pewne dodatkowe rozwiązanie ,które ograniczyło do minimum liczbę komponentów rozwiazania B.

PS. W c++ już ładnych pare latek nic nie pisałem, metoda virtualna jest tożsama metodzie abstrakcyjnej tak?

0
PawelW napisał(a)

Teraz powstaje pytanie czy wszędzie używać typu bazowego( interfejsu) i dokonać pewnej nadmiarowej implementacji metod czy też jednak dopuścić dla kiku komponentów wiedze z jaką implemetacją pracują.

To zalezy od tego w jaki sposob zarzadzane sa zwierzaki, jezeli jest to jedna petla ktora tylko wywoluje metody zwierzakow to warto skorzystac z jednego interfejsu dla wszystkich rodzajow zwierzakow.

for(int i=0;i<AnimalCount;i++)
{
     pAnimalList[i]->Hunt(); // prosiak w tym momencie grzebie ryjkiem w ziemi a wilk szuka prosiakow
     pAnimalList[i]->Taunt(); // prosiak kwiczy, wilk wyje

     OR

     pAnimalList[i]->DoAction("HaveFun"); // w srodku tej metody okreslane jest jaka akcja ma byc wykonana, dla prosiaka bedzie to tarzanie sie w blocie, a dla wilka hasanie po kszakach...
}

Najlepiej zrobic jakis 'engine' do obslugi listy zwierzakow. Jesli wszystkie zwierzaki dziedzicza z jednej klasy abstrakcyjnej to dokladamy tylko kolejne zwierzaki a o obsluge ich zachowania nie musimy sie martwic bo wszystkie ich metody wywoluje engine. Tak wiec mozemy dodac dzikie prosiaki, wiewiorki itd itp.

edit:

Oczywiscie metody Hunt(); Taunt(); DoAction(); pochodza z interfejsu BehaviourAnimal, wiec:

class Prosiak : public Animal, public DisplayAnimal, public BehaviourAnimal
{
  ...
}

Interfejs jest klasa czysto abstrakcyjna (wszystkie metody = NULL), tak wiec interfejs nic nie robi tylko wymusza implementacje pewnych metod w klasach potomnych. I to jest cala filozofia.

0

Wiem że jest to już stary wątek, ciekawi mnie jakie rozwiązanie wybrałeś. Bo z tego co napisałeś wynika że chcesz czegoś co się nie da zrobić, masz dwie różne funkcjonalności i chcesz aby były jedną :|

0

Witam

Tu nie chodziło o to, jak piszesz, aby z dwóch funkcjonalności zrobić jedną ale o stworzenie dla nich wspólnego interfejsu. Koniec końców zdecydowałem się na rozwiązanie mechanizmu ,która działa w oparciu o strategie dedykowane dla konkretnej funkcjonalności ale sam korzysta jedynie ze wspólnego interfejsu. Nie chcę się tutaj rozpisywać o założeniach stawianych przed tym rozwiązaniem jakkolwiek projekt jest w fazie ostatecznej dlatego jeszcze nie wiem czy jest on prawidłowe i spełni oczekiwania. Jeśli wypłyną jakieś ciekawe informacje i wnioski oczywiście podzielę się nimi.

pozdrawiam

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