Dziedziczenie interfejsów.

0

Cześć.

Mam pewną zagwozdkę. Zazwyczaj spotykałem się z potrzebą modelowania prostych struktur obiektowych, jednak teraz pojawiły się nieco bardziej skomplikowane modele i mam dwa sposoby, jak mogę je odzwierciedlić - zastanawiam, się który lepszy, co wy o nich sądzicie.

Mamy dwa interfejsy:

public interface IZwierzyniec<T>
{
   void Glaszcz(T zwierze);
   void Karm(T zwierze, Object karma);
}

public interface IStajnia<T>
{
   void Siodłaj(T zwierze, Siodło siodło);   
   T WyprowadzZeStajni(T zwierze);
}

Szukając analogii - w każdym zwierzyńcu można pogłaskać zwierzę. W zasadzie w stajni, też można głaskać zwierzę. Mam teraz potrzebę zaimplementować stajnie która dostosowuje się do koni, kuców, osłów, oraz klatkę w której można przechowywać króliki, norki, nutrie, zatem implementuje:

public class Stajnia<T> : IStajnia<T>
{
   public void Siodłaj(T zwierze, Siodło siodło)
   {
      throw new NotImplementedException(); 
   }
  
   ...
}

public class Klatka<T> :  IZwierzyniec<T>
{
   void Glaszcz(T zwierze)
   {
      throw new NotImplementedException();
   }
  
   void Karm(T zwierze, Object karma)
   {
      throw new NotImplementedException();
   }
   ...
}

Jednak w moim gospodarstwie agroturystycznym pojawia się potrzeba, żeby każde zwierzę można było pogłaskać czy nakarmić. Z drugiej strony trudno siodłać króliki czy nutrie, które przebywają w klatkach. Można zaimplementować zatem wiele interfejsów w przypadku stajni czyli:

public class Stajnia<T> : IStajnia<T>, IZwierzyniec<T>
{
   public void Siodłaj(T zwierze, Siodło siodło)
   {
      throw new NotImplementedException(); 
   }
  
   void Glaszcz(T zwierze)
   {
      throw new NotImplementedException();
   }
  
   void Karm(T zwierze, Object karma)
   {
      throw new NotImplementedException();
   }
}

Jednak od razu mi rzuca się obserwacja, że głaskać i karmić to będzie można zawsze, wiec czy nie lepiej zaproponować dziedziczoną hierarchię interfejsową i implementować pojedyncze interfejsy, albo bazowe, albo dziedziczone ? Podaje przykład który zastosuje dziedziczenie interfejsów, żeby osiągnąć co wyżej:

public interface IZwierzyniec<T>
{
   void Glaszcz(T zwierze);
   void Karm(T zwierze, Object karma);
}

public interface IStajnia<T> : IZwierzyniec<T>
{
   void Siodłaj(T zwierze, Siodło siodło);   
   T WyprowadzZeStajni(T zwierze);
}

public class Klatka<T> :  IZwierzyniec<T>
{
   void Glaszcz(T zwierze)
   {
      throw new NotImplementedException();
   }
  
   void Karm(T zwierze, Object karma)
   {
      throw new NotImplementedException();
   }
   ...
}

public class Stajnia<T> : IStajnia<T>
{
   public void Siodłaj(T zwierze, Siodło siodło)
   {
      throw new NotImplementedException(); 
   }
  
   void Glaszcz(T zwierze)
   {
      throw new NotImplementedException();
   }
  
   void Karm(T zwierze, Object karma)
   {
      throw new NotImplementedException();
   }
}

Ja osobiście jestem za rozwiązaniem 2. Moim zdaniem jest bardziej eleganckie, bardziej odzwierciedla rzeczywistość i sama konstrukcja interfejsu i dziedziczenia ogranicza programistę, który będzie zeń korzystał. Owszem, ciężko będzie zaimplementować np. stajnie gdzie nie można głaskać koni, ale taka jest filozofia mojego gospodarstwa, żeby zawsze sie dało. Co wy o tym sądzicie ? Widzicie jakieś inne zagrożenia poza zmniejszeniem elastyczności możliwości implementowania różnych interfejsów ?

1

ja bym raczej zrobila w ten sposob:
zwierzatka implementujace 'IGlaskalne', 'IUjezdzalne' czy 'IJedzaceGrzecznieZReki' ;)
budynki w stylu 'Stajnia' gdzie sa metody typu 'siodlaj' przyjmujace obiekty typu 'IUjezdzalne' i 'karm' przyjmujace obiekty typu 'IJedzaceGrzecznieZReki'
jesli juz mialby byc wspolny interfejs miedzy roznymi pojemnikami/budynkami na zwierzeta to raczej mialby on metody 'dodajZwierze', 'otworz', 'zamknij', 'ilezwierzat' etc

2

Skoro stajnie siodłają, a klatki głaszczą, to ludzie chyba nie są już do niczego potrzebni.

0

Powinieneś poprawić model danych, stajnia nie jest od siodłania itp.
Jeśli podejdziesz do problemu bez gwałcenia SRP to będzie ci łatwiej

0

Ok, nie gwałcę SRP tylko troszkę źle przedstawiłem problem. Klasyczny http://xyproblem.info/ a po prostu nie chciałem dawać dokładnie problemu jaki chciałem rozwiązać. Niemniej znalazłem materiał w którym jest częściowo odpowiedź. Podjąłem decyzję, o kolejnych stopniach dziedziczenia tychże interfejsów co w założeniach mojego projektu spełni swoje zadania. Ciekawy art co porusza istotę problemu ;) http://www.pzielinski.com/?p=281 . Stajnie i klatki były repozytoriami u mnie od początku, tylko zastanawiałem się nad konstrukcją interfejsów do nich - czy je dziedziczyć, czy mnożyć i implementować wiele.

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