Piszę grę w Typescript i postanowiłem, że spróbuję zastosować się do idei „ programowania opartego na interfejsie ”, w którym piszesz kod oparty na interfejsie zamiast implementacji obiektu.
Napisałem sporo interfejsów i klas, które je implementują, a następnie cofnąłem się i zdałem sobie sprawę, że klasy były na tyle proste, że prawdopodobnie nigdy nie będę musiał zmieniać implementacji, ponieważ tak naprawdę jest tylko jeden sposób, aby zrobić to, co klasa robi (poruszając się Phaser.Sprite
w ograniczony sposób, aby zachowywać się jak czołg).
Potem pamiętam, jak przeczytałem kilka lat temu o idei YAGNI , która polega zasadniczo na tym, że nie powinieneś nadmiernie konstruować swojego kodu, aby zawierał rzeczy, których nigdy nie możesz użyć.
Czy zgodnie z najlepszymi praktykami każda klasa powinna implementować interfejs, czy też powinna ograniczyć się do klas, które mogą zostać w przyszłości zamienione?
źródło
Odpowiedzi:
Powodem posiadania interfejsów jest to, że upraszcza polimorfizm. Oznacza to, że możesz wysyłać instancje na podstawie umowy, zamiast znać ich faktyczną implementację. Na przykład, możesz wysłać „Reader” do metody, aby tak zwana metoda mogła użyć metody „read ()”. Deklarując interfejs „Czytnik”, możesz dostosować dowolny obiekt do niniejszej umowy, wdrażając określone przez niego metody. W ten sposób każdy dzwoniący może założyć, że istnieją pewne metody, nawet jeśli obiekty leżące u podstaw umowy mogą być zupełnie inne.
Oddziela polimorfizm od klasy bazowej i umożliwia także między granicami łańcucha klasowego, narzucając kontrakt.
Teraz ... Przydaje się to tylko wtedy, gdy potrzebujesz wielu łańcuchów dziedziczenia, aby działały w ten sam sposób lub jeśli masz wiele klas bazowych o wspólnych zachowaniach, które będziesz chciał przekazać innym użytkownikom.
Jeśli masz tylko JEDEN łańcuch dziedziczenia (klasa podstawowa-> podklasa) lub tylko podstawa, lub nie musisz faktycznie PRZEKAŻAĆ powiązanych obiektów komuś innemu lub używać ich ogólnie, wówczas nie dodawałbyś implementacji interfejsu, ponieważ takie pojęcie jest wtedy nieprzydatny.
źródło
Moves
iShoots
na swoim przykładzie zbiornika) dla jednej klasy.Jeśli nie jesteś pewien, czy rzeczywiście potrzebujesz interfejsów, prawdopodobnie nie. To jest sedno zasady YAGNI. Kiedy musisz być w stanie zamienić implementację, musisz wprowadzić interfejs.
źródło
Tworzenie interfejsu dla każdej klasy jest nieco przesadne. Z czysto obiektowego punktu widzenia każda klasa ma już interfejs . Interfejs jest niczym więcej niż publicznymi metodami i członkami danych klasy.
Zazwyczaj „interfejs” oznacza „klasę Java zdefiniowaną za pomocą
interface
słowa kluczowego” lub „klasę C ++ z tylko publicznymi, czysto wirtualnymi funkcjami”. Są to użyteczne abstrakcje, ponieważ oddzielają interfejs klasy od jej implementacji.Mając to na uwadze, w razie potrzeby używaj interfejsów.
Czy będzie wiele implementacji interfejsu? Jeśli tak, sytuacja ta może być kandydatem do wyodrębnienia powszechnych metod publicznych w interfejsie.
Czy przekażę implementacje potencjalnego interfejsu innym modułom, które nie powinny znać wewnętrznego funkcjonowania mojego modułu? Interfejs może być tu przydatny, ponieważ zmniejsza rozmiar punktu styku między modułami.
Zwróć uwagę na powyższe słowa łasicy: „może” być kandydatem, „może być” przydatny. Nie ma twardej i szybkiej reguły, która mówi „tak” lub „nie” w danej sytuacji.
Biorąc to pod uwagę, posiadanie interfejsu do wszystkiego jest prawdopodobnie przesadą. Jeśli zobaczysz ten wzór, to za daleko:
źródło
interface
, tak się składa, że wszystko w Javieinterface
jest także interfejsem publicznym (koncepcja OO).Dla nowszych programistów może być bardzo kuszące, aby myśleć o interfejsach jako o niedogodności, którą dodajesz tylko dlatego, że według ciebie jest to „najlepsza praktyka”. Jeśli robisz to na ślepo, pachnie to programowaniem kultu ładunku .
Istnieje wiele bardzo dobrych powodów, dla których warto rozważyć interfejsy dla większych zmian, a nie zestawiać razem zestaw klas.
Szydzące frameworki
Jeśli chcesz przetestować aplikację wielowarstwową bez konieczności tworzenia obiektów dla różnych warstw, niewątpliwie zechcesz użyć struktur próbnych do wyśmiewania warstw. Interfejsy są tutaj szeroko stosowane.
Zastrzyk zależności
Chociaż nieco popadli w niełaskę z powodu dodanego wzdęcia, pomysł jest zdrowy - możliwość po prostu zamiany konkrecji na podstawie interfejsu. Zasadę można również znaleźć w wielu wzorach projektowych, takich jak wzór fabryczny.
Te podejścia są podsumowane w D z zasad SOLID . Nacisk na to jest - używaj abstrakcji, a nie konkrecji.
Podobnie jak same wzorce projektowe, kiedy z nich korzystać, należy dokonać oceny. Chodzi o to, aby zrozumieć, w jaki sposób interfejsy są przydatne, a nie tylko przyklejać je do swoich zajęć, ponieważ czujesz, że musisz. Dobra dyskusja na temat różnych zalet DIP i YAGNI tutaj .
źródło