Kiedy potrzebne są interfejsy?

(w kontekście. net na ile warto)

Zazwyczaj nie używam dziedziczenia i rzadko używam interfejsów. Natknąłem się na kogoś, kto uważa, że interfejsy są najlepszą rzeczą od czasu spit. Używa ich wszędzie. Nie rozumiem tego i stąd kolejne pytania. Chcę tylko sprawdzić moje rozumienie interfejsów.

Jeśli używasz interfejsów wszędzie, zakładam, że możesz przewidzieć przyszłość, twoje wymagania aplikacji są przybite i nic nigdy nie będzie zmiana w aplikacji. Dla mnie, szczególnie na wczesnym etapie rozwoju, interfejsy stają się przeszkodą. Aplikacja jest bardzo dynamiczna przez swoje życie. Jeśli chcesz odjąć lub dodać członków do interfejsu, wiele rzeczy się zepsuje. Facet powyżej mówi, że tworzy inny interfejs do obsługi nowych członków. Nic nie pęka.

Czy to nie jest kompozycja? Dlaczego nie używać kompozycji bez interfejsów? Bardziej elastyczny.

Jak załatwia sprawę, w której członek musi zostać odjęty od interfejs? Zasadniczo nie. rzeczy po prostu pękają i to jest świetne, ponieważ teraz Można zobaczyć wszystkie dotknięte obszary i je naprawić. Zamiast zastanawiać się bardziej elegancko, gdzie są wszystkie powiązane ścieżki kodu, powinniśmy po prostu wyrwać części klas za pomocą brutalnej siły?

Myślę o aplikacji jako grafie. Graf zupełny to najgorszy przypadek, mający n (n-1) / 2. Oznacza to, że każda klasa rozmawia z każdą klasą. Myląca pajęcza sieć. n-1 jest najlepszy, w którym ich jest ścisła hierarchia komunikacji. Dodanie innego interfejsu tylko w celu skompensowania nowego potrzebnego pręta dodaje wierzchołek do grafu, co oznacza więcej krawędzi i silniejszą realizację równania n(n-1)/2. Kompozycja bez interfejsów jest bardziej jak mixiny. Tylko wybrane klasy używają określonych metod. Dzięki interfejsowi wszystkie klasy są zmuszone do używania członków, nawet jeśli ich nie potrzebują. Podejście composition/mixin nie dodaje nowych niepotrzebnych krawędzi.

Author: 4thSpace, 2009-02-20

15 answers

Interfejsy nie zmuszają klas do używania metod . Zmuszają klasy implementujące do zaimplementowania wszystkich metod, ale to inna sprawa.

Podoba mi się sposób, w jaki interfejsy oddzielają API od implementacji. Co prawda robi się to również za pomocą modyfikatorów dostępu, ale interfejsy czynią to jaśniejszym. Co ważniejsze, interfejsy również ułatwiają wyśmiewanie - co oznacza, że możesz testować klasy, które zależą od interfejsu, nawet zanim kiedykolwiek zaimplementujesz to.

I tak, oznacza to, że często kończę z interfejsem, który ma tylko jedną implementację produkcyjną. Moim zdaniem nie jest to problem, ponieważ uzyskałem testowalność.

Z drugiej strony, nie piszę interfejsu dla każdej klasy. Lubię pisać interfejsy, w których obiekt zasadniczo dostarcza usługę - uwierzytelnianie, dostęp do danych itp. Zwykłe obiekty danych (nawet o znaczącym zachowaniu)nie są tak przydatne pod względem interfejsów, IME.

 40
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-20 16:54:03

Według Wikipedii ,

głównym zastosowaniem polimorfizmu w przemyśle (teoria programowania zorientowanego obiektowo) jest zdolność obiektów należących do różnych typów do reagowania na wywołania metod, pól lub właściwości o tej samej nazwie, każdy z nich zgodnie z odpowiednim zachowaniem specyficznym dla danego typu. Programista (i program) nie musi znać dokładnego typu obiektu z góry, więc dokładne zachowanie jest ustalane w czasie wykonywania (nazywa się to późnym wiązaniem lub dynamiczne Wiązanie).

To właśnie sprawia, że interfejsy są tak przydatne.

"facet powyżej mówi, że tworzy inny interfejs do obsługi nowych członków. Nic nie pęka."

Ja tylko zgaduję, ale wygląda na to, że ten facet pochodzi ze starej szkoły (mogę się mylić, oczywiście!). Skłania mnie do myślenia o całym kodzie, nad którym pracowałem, gdzie widziałem takie rzeczy jak to:

  • IWidgetManager
  • IWidgetManager2
  • IWidgetManager3

To nie jest dobry sposób pracy z interfejsami. Z mojego doświadczenia wynika, że widziałem obie skrajności: strach przed zmianą interfejsów do punktu, w którym nowe interfejsy są tworzone za każdym razem, gdy dodawane są nowe elementy, lub nieużywanie interfejsów w ogóle i posiadanie produktu, który cierpi na wysoki stopień sprzężenia . Musisz znaleźć dobrą równowagę. Nie zawsze jest koniec świata, aby zmienić interfejs.

Jaki jest rozmiar projektu, nad którym pracujesz? Może być trudno dostrzec korzyści z interfejsów, jeśli jest to stosunkowo mały projekt. Jeśli natomiast jest to projekt z kilkuset tysiącami linii kodu i składa się z wielu modułów, korzyści stają się o wiele bardziej widoczne.

 7
Author: Rob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-25 21:11:48

Interfejsy mają wiele przydatnych sytuacji. Gdy musisz dodać określone zachowanie do klasy, które można znaleźć w wielu różnych klasach, jest to idealny czas na interfejs. Dobrym przykładem jest interfejs IDisposable - masz jakiś zasób, który kiedy skończysz, musi zniknąć w odpowiednim czasie. Czy to połączenie z bazą danych? Czy to jakaś klamka okienna? Nieważne.

Innym przykładem może być sytuacja, gdy naprawdę nie wiesz, jak to powinno być zaimplementowane, takie jako interfejs do obiektu, który jeszcze nie istnieje. Być może obiekt powinien być dostarczony przez Klienta twojej Biblioteki lub musi być zaimplementowany przez zupełnie inny moduł, który nie jest pod twoją kontrolą. Możesz zasadniczo zaprojektować kontrakt dla metod dostępnych na zajęciach.

To powiedziawszy, używam ich tylko tam, gdzie są potrzebne. Jeśli Mogę to zrobić za pomocą zwykłej klasy, lub jeśli jest to coś nieodłącznego do konkretnego obiektu, zrobię z tego klasę. Istnieją pewne zalety korzystania z interfejsów dla każdej klasy, jak mówili inni, ale to tak dużo dodatkowych kosztów, że nie widzę na tym przyzwoitego zysku netto. Przez większość czasu projektowałem moje struktury klasowe tak, aby były płaskie i szerokie, z jak najmniejszą ilością zależności.

Podsumowując: jeśli masz wspólną funkcjonalność, która jest zaimplementowana diametralnie inaczej, interfejs jest właśnie tym, czego potrzebujesz.

 5
Author: Robert P,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-20 17:13:10

Interfejsy pomagają zachować zależności od abstrakcji.

Kod, który używa interfejsu zależy tylko od interfejsu, więc wiesz, że nie ma sztucznych zależności od szczegółów. Daje to dużą swobodę w zakresie zmiany kodu w przyszłości, ponieważ wiesz dokładnie, co powinno i nie powinno się zepsuć, gdy "naprawisz" błąd lub refaktor.

Moim zdaniem to esencja dobrego projektowania kodu.

 3
Author: Jim Carroll,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-23 20:51:46

" facet powyżej mówi, że tworzy inny interfejs do obsługi nowych członków. Nic nie pęka.

Czy to nie jest kompozycja? Dlaczego nie używać kompozycji bez interfejsów? Bardziej elastyczny."

Wydaje się, że myślisz o kompozycji w kategoriach dziedziczenia, jak w, " odziedziczę wszystkie te możliwości w tym jednym obiekcie, aby wykonać tę pracę."To zły sposób na pisanie kodu. To tak, jakby powiedzieć: "chcę zbudować wieżowiec, więc nauczę się każdej pracy, od tego, jak tworzyć plany dotyczące sposobu ubożenia fundamentu i instalacji oświetlenia..."

Pomyśl o kompozycji zamiast w kategoriach oddzielnych obiektów, z których każdy wykonuje jedno zadanie. Aby wykonać skomplikowaną pracę, mogę teraz polegać na tych oddzielnych obiektach do wykonywania swoich indywidualnych zadań. To jak wynajęcie architekta i ekipy budowlanej do budowy wieżowca. Nie muszę znać szczegółów, jak każdy z nich wykonuje swoją pracę, tylko to, że może to zrobić. W kodzie oznacza to wstrzykiwanie zależności do obiekt do wykonywania złożonych zadań zamiast dziedziczenia.

Więc gdzie się zmieścić? Są umową pomiędzy poszczególnymi obiektami. Pozwalają one nie przejmować się indywidualnymi, konkretnymi realizacjami. Pozwalają one mówić wspólnym językiem z wieloma obiektami, które dzielą tę samą odpowiedzialność, ale mogą mieć inną implementację. Interfejs staje się abstrakcją dla obiektu wykonującego zadanie. Nie muszę wiedzieć, jak każdy facet z młotkiem działa, tylko że wie jak trafić;).

Kiedy zaczynasz komponować złożony system kodu z mnóstwem małych klas, które mają pojedyncze obowiązki, szybko dowiadujesz się, że możesz napotkać poważne problemy, jeśli zbytnio polegasz na konkretnej implementacji danej klasy, A Ta klasa zaczyna się zmieniać... Zamiast więc polegać na konkretnej realizacji, tworzymy interfejs-abstrakcję. I mówimy: "nie obchodzi mnie, jak robisz JobX, tylko, że ty to zrób."

Istnieją inne zalety interfejsów, takie jak testowanie, wyśmiewanie itp... Ale to nie jest powód, aby kodować do interfejsu. Powodem jest stworzenie systemu kodu, który nie jest zależny od specyfiki, a tym samym wysoce sprzężony ze sobą. Dlatego z twoim mózgiem myślącym grafem powinieneś obawiać się łączenia ze sobą kilku konkretnych klas. Ponieważ zmiany w jednej z tych klas spowodują efekt falowania.

Kiedy połączysz się z abstrakcja zamiast konkretnej klasy, ograniczasz sprzężenie. Mówisz, że będę związany tylko z kontraktem, w którym oboje się zgadzamy, i nic więcej."A jeśli Klasa realizująca ten kontrakt zmieni swój wewnętrzny sposób wypełniania swojego zadania, nie obchodzi cię to, ponieważ nie polegasz na własności lub metodzie nieobjętej umową. Polegasz tylko na uzgodnionej umowie.

 2
Author: Chris Holmes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-20 17:48:35

Jeśli chcesz zrozumieć, kiedy używać interfejsów i jakie są ich zastosowania, myślę, że powinieneś rzucić okiem na książkę: Head First Desing Patterns .

To jest książka, która naprawdę pomogła mi zrozumieć, co jest takiego fajnego w interfejsach.

Przed przeczytaniem tej książki wiedziałem, co to jest interfejs, ale nie miałem absolutnie pojęcia, kiedy powinienem ich używać.

 2
Author: Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-20 17:54:29

Chodzi o zależności. Chcesz, aby Twój kod zależał od typów interfejsów, a nie konkretnych typów, w stosownych przypadkach. Na przykład możesz mieć wiele konkretnych typów, które wszystkie wykonują podobne zachowanie, ale implementują je w inny sposób. Czy chcesz, aby Twoja baza kodu miała zależności od tych wielu konkretnych typów lub jednego interfejsu? Jak elastyczna będzie twoja baza kodu, gdy będziesz musiał wprowadzić zmiany?

Do twojego punktu o tym, że nie chcesz wykorzystywać publicznych członków przez używając kompozycji, powiedziałbym, że po prostu zamykasz niepotrzebne zależności. Jeśli chcesz użyć kompozycji, znacznie zmniejszysz zależności, komponując typy interfejsów zamiast konkretnych typów.

Aby uzyskać lepsze wyjaśnienie, spróbuj spojrzeć na literaturę na temat inwersji sterowania .

 2
Author: Pragmatic Agilist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-23 19:01:23

Interfejsy mają dla mnie największy sens w kontekście Dependency injection i frameworków IoC. Podoba mi się pomysł, że można zdefiniować zestaw zachowań (metod) i "zagwarantować" te zachowania poprzez implementację interfejsu. Teraz możesz podłączyć zupełnie nowe funkcje do istniejącego systemu za pomocą jednego zestawu i aktualizacji pliku konfiguracyjnego.

Efektywne projektowanie interfejsów wymaga sporego planowania do przodu i uważam, że są one najbardziej przydatne w kontekście duże systemy i ramy. Kiedy są użyteczne, są naprawdę użyteczne. Kilka moich ulubionych:

  • IComparable (Ty decydujesz, jak twoje obiekty się ze sobą porównują)
  • IQueryable (LINQ anyone?)
  • IDisposable (trzymaj swoje using oświadczenie pod ręką)
 1
Author: Dave Swersky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-20 17:05:48

Myślę, że opisujesz tam top-down design metodę.
Nie musisz tego robić, ale czasami naprawdę pomaga.

 0
Author: Avram,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-20 17:20:26

Odwołałbym się do. Net design guidelines na ten temat: http://msdn.microsoft.com/en-us/library/ms229013.aspx

Istnieje wiele powodów, aby używać interfejsów, ale uważam również, że są one często nadużywane z niewłaściwych powodów. Interfejsy zapewniają znacznie większą elastyczność podczas pracy z typami wartości i są niezwykle przydatne podczas pracy z kolekcjami itp., ale podczas projektowania hierarchii klas dla własnych projektów zawsze staram się myśleć o prostocie, a Interfejsy często prowadzą do (niepotrzebnie) bardziej złożonych sytuacji.

Moją zasadą jest zaimplementowanie każdego interfejsu BCL, który ma sens, i dodawanie własnych interfejsów do moich projektów tylko wtedy, gdy faktycznie dostarcza coś bardzo cennego. Zamiast iwidgetmanager, IWidgetManager2, itd... Wolałbym mieć abstrakcyjną klasę WidgetManager i implementować konkretne metody w razie potrzeby.

 0
Author: Reed Copsey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-21 02:15:21

Ta osoba brzmi jakby źle rozumiała pojęcie programowania do interfejsu. Nie odnosi się do programowania przy użyciu tylko słowa kluczowego interface w. Net/Java lub klasy z niczym innym jak czystymi funkcjami wirtualnymi w C++, interfejs, o którym mowa w tej zasadzie, jest konstrukcją wysokiego poziomu, która hermetyzuje niskopoziomowe systemy. Podobnie jak w przypadku mnożenia, zawiera on ideę dodawania liczby do siebie określonej ilości powtórzeń. Ale kiedy mówimy 3 * 2, nie obchodzi mnie, czy to 3 + 3, 2 + 2 + 2 lub (2 + 2) + 2, gdzie część w nawiasach jest buforowana. Pod warunkiem, że otrzymamy z niego 6.

W rzeczywistości pojęcie interfejsów może być wypełnione interface lub abstract class lub ich kombinacją, jak ma to miejsce w przypadku wielu wzorców GoF. Chodzi o to, że słowo kluczowe interface obmywa wodę dwuznacznością.

To zabawne. Ten gość pewnie myśli, co zrodziło komentarze takie jak te skupiające się wokół StackOverflow odcinek # 38.
 0
Author: Thedric Walker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-23 20:36:28

Wygląda na to, że twój przyjaciel poważnie źle używał interfejsów.

Widziałem też aplikacje internetowe z interfejsami wszędzie. Niektórzy ludzie zdają się mieć pogląd, że interfejs jest w jakiś sposób lepszy niż zwykła sygnatura metody. Proste parametry dają nam już umowę-w większości przypadków uważam, że wystarczy i ułatwia kod.

Wydaje mi się, że interfejsy są najbardziej przydatne w przypadkach takich jak IDisposable lub Ikollection -- gdzie wskaż pewien zestaw funkcji, których można oczekiwać od obiektu. W takich przypadkach wydają się być odpowiednim narzędziem do tego zadania.

 0
Author: alchemical,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-27 06:54:18

W dużej mierze używamy interfejsów Na niestandardowych elementach UI, gdzie każdy z nich oczekuje istnienia określonej metody na innym (a interfejs wymusza to istnienie).

 0
Author: Beep beep,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-27 07:01:16

Głównym zastosowaniem interfejsu jest umożliwienie zmiany implementacji pozwalającej na przełączanie kodu w czasie wykonywania. Istnieje wiele powodów/przesłanek, aby to zrobić.

W przeszłości niektórzy twierdzili, że każda klasa w systemie powinna mieć interfejs, ale jest to powszechnie uznawane za przesadę. Obecnie używane są interfejsy, w których instancje klas mogą zmieniać się w ramach działania systemu (reprezentować stan): wzorce GoF takie jak strategia i polecenie przechwytują to użytkowania i / lub części systemu muszą być wymienione do testów(tj. dependency injection). Jeśli programiści postępują zgodnie z testowymi praktykami programistycznymi, kluczowe obiekty infrastruktury będą miały interfejsy. Pozwala to testom na tworzenie "moków" tych obiektów w celu przetestowania przepływu sterowania systemem. Istnieje zależność między tym użyciem interfejsu a zasadą substytucji Liskowa (jedną z zasad projektowania OO)

Kolejne zastosowanie dla interfejsów, które mniej zajmują się to, co jest dostępne dla dzwoniącego, to interfejs znacznika. Który jest sposobem kojarzenia metadanych z definicją klasy. Może to mieć wpływ na sposób, w jaki system wyświetla obiekt (na przykład pozwala na serializację) lub może po prostu służyć jako dokumentacja.

 0
Author: andygavin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-04 20:16:11

Jednym z najważniejszych powodów korzystania z interfejsu jest fakt, że pozwalają nam one pisać testy jednostkowe dla naszych klas i zdawać we własnych zależnościach. Umieszczając zależność za interfejsem otwieramy "szwy" w kodzie naszej aplikacji, gdzie testy jednostkowe mogą być łatwo napisane. Nie widzę tego kąta testowego wymienionego w wielu odpowiedziach, ale bardzo ważne jest, aby zrozumieć, że bez interfejsów te zależności (takie jak usługa sieciowa lub odniesienie do systemu plików) mogą stają się bardzo trudne do przetestowania lub w najlepszym razie są dość warunkowe. Napisałam tu posta: http://jeffronay.com/why-use-an-interface/ to idzie w znacznie bardziej szczegółowo z przykładami kodu pokazującymi klasę usług bez interfejsu, a następnie tę samą klasę napisaną ponownie za pomocą interfejsu, aby zademonstrować elastyczność testowania podczas korzystania z interfejsów.

 0
Author: Jeff Ronay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-27 00:12:52