Jak stworzyć elastyczną architekturę wtyczek?

Powtarzającym się tematem w mojej pracy programistycznej było użycie lub stworzenie własnej architektury wtyczek. Widziałem to na wiele sposobów - pliki konfiguracyjne (XML, .konf i tak dalej), frameworki dziedziczenia, informacje o bazach danych, biblioteki i inne. Z mojego doświadczenia:

  • baza danych nie jest dobrym miejscem do przechowywania informacji konfiguracyjnych, zwłaszcza współmieszanych z danymi
  • Próba tego z hierarchią dziedziczenia wymaga wiedzy o wtyczki mają być zakodowane, co oznacza, że architektura wtyczek nie jest aż tak dynamiczna
  • pliki konfiguracyjne działają dobrze do dostarczania prostych informacji, ale nie mogą obsługiwać bardziej złożonych zachowań
  • Biblioteki wydają się działać dobrze, ale zależności jednokierunkowe muszą być starannie tworzone.

Ponieważ staram się uczyć z różnych architektur, z którymi pracowałem, Szukam również sugestii dla społeczności. Jak zaimplementowałeś solidną architekturę wtyczek? Co było twoja najgorsza porażka (lub najgorsza porażka jaką widziałeś)? Co byś zrobił, gdybyś miał zaimplementować nową architekturę wtyczek? Jaki projekt SDK lub open source, z którym pracowałeś, ma najlepszy przykład dobrej architektury?

Kilka przykładów znalazłem na własną rękę:

Te przykłady zdają się odgrywać różne mocne strony językowe. Czy dobra architektura wtyczek musi być powiązana z językiem? Czy do tworzenia architektury wtyczek najlepiej użyć narzędzi, czy zrobić to na własnych modelach?

Author: justkt, 2010-05-04

8 answers

To nie jest Odpowiedź tylko kilka potencjalnie przydatnych uwag/przykładów.

  • Jednym ze skutecznych sposobów rozszerzenia aplikacji jest ujawnienie jej wewnętrznych elementów jako języka skryptowego i napisanie wszystkich rzeczy najwyższego poziomu w tym języku. To sprawia, że jest to dość modyfikowalne i praktycznie przyszłościowe (jeśli Twoje prymitywy są dobrze wybrane i wdrożone). Historia sukcesu tego typu rzeczy to Emacs. Wolę to od systemu wtyczek w stylu eclipse, ponieważ jeśli chcę rozszerzyć funkcjonalność, nie muszę uczyć się API i pisać / kompilować osobnego pluginu. Mogę napisać 3-liniowy fragment w samym bieżącym buforze, ocenić go i użyć. Bardzo płynna krzywa uczenia się i bardzo przyjemne wyniki.

  • Jedną z aplikacji, którą nieco rozszerzyłem, jest Trac. Posiada architekturę komponentów, co w tej sytuacji oznacza, że zadania są delegowane do modułów, które reklamują punkty rozszerzeń. Następnie można zaimplementować inne komponenty które zmieściłyby się w tych punktach i zmieniłyby przepływ. To trochę jak sugestia Kalkiego powyżej.

  • Innym dobrym jest py.test . Opiera się ona na filozofii" best API is no API " i opiera się wyłącznie na wywoływaniu hooków na każdym poziomie. Możesz nadpisać te Hooki w plikach / funkcjach nazwanych zgodnie z konwencją i zmienić ich zachowanie. Możesz zobaczyć listę wtyczek na stronie, aby zobaczyć, jak szybko/łatwo można je wdrożyć.

A kilka ogólnych punktów.

  • staraj się, aby twój rdzeń nie-rozszerzalny/nie-modyfikowany przez użytkownika był jak najmniejszy. Deleguj wszystko, co możesz, na wyższą warstwę, aby zwiększyć rozszerzalność. Mniej rzeczy do poprawienia w rdzeniu, a następnie w przypadku złych wyborów.
  • związane z powyższym punktem jest to, że nie powinieneś podejmować zbyt wielu decyzji o kierunku swojego projektu na samym początku. Zaimplementuj najmniejszy potrzebny podzbiór, a następnie zacznij pisać wtyczki.
  • Jeśli osadzasz język skryptowy, upewnij się, że jest to Pełny, w którym możesz pisać ogólne programy, a nie Język zabawek tylko dla Twojej aplikacji.
  • zredukuj płytkę kotła tak bardzo, jak możesz. Nie przejmuj się podklasowaniem, złożonymi interfejsami API, rejestracją wtyczek i tym podobne. Staraj się, aby było to proste, aby było Łatwe, a nie tylko możliwe do rozszerzenia. Pozwoli to na korzystanie z API wtyczek i zachęci użytkowników końcowych do pisania wtyczek. Nie tylko programiści wtyczek. py.test robi to dobrze. Eclipse o ile wiem, nie .
 73
Author: Noufal Ibrahim,
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
2015-05-05 15:41:05

Z mojego doświadczenia wynika, że istnieją naprawdę dwa rodzaje Architektur wtyczek.

  1. podąża się za Eclipse model, które ma pozwolić na wolność i jest otwarte.
  2. drugi zwykle wymaga wtyczek do podążania za narrow API, ponieważ wtyczka wypełni określoną funkcję.

Aby określić to w inny sposób, jeden pozwala wtyczkom uzyskać dostęp do aplikacji, podczas gdy drugi pozwala aplikacji uzyskać dostęp do wtyczek.

The rozróżnienie jest subtelne, a czasami nie ma dystykcji... chcesz oba do swojej aplikacji.

Nie mam dużego doświadczenia z Eclipse / otwieranie aplikacji na model wtyczek (artykuł w poście Kalkiego jest świetny). Czytałem trochę o tym, jak eclipse robi różne rzeczy, ale nic więcej.

Yegge ' s properties blog mówi trochę o tym, jak użycie wzorca właściwości pozwala na wtyczki i rozszerzalność.

Większość mojej pracy ma używałem architektury wtyczek, aby umożliwić mojej aplikacji dostęp do wtyczek, takich jak czas/wyświetlanie/DANE mapy itp.

Lata temu stworzyłbym fabryki, Menedżery wtyczek i pliki konfiguracyjne, aby zarządzać tym wszystkim i pozwolić mi określić, której wtyczki używać w czasie wykonywania.

    Teraz zwykle mam tylko DI frameworkwykonać większość tej pracy.

Nadal muszę pisać adaptery, aby korzystać z bibliotek innych firm, ale zazwyczaj nie są takie złe.

 23
Author: menjaraz,
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
2015-01-04 16:45:11

Jedna z najlepszych architektur wtyczek jakie widziałem jest zaimplementowana w Eclipse. Zamiast aplikacji z modelem wtyczki, wszystko jest wtyczką. Podstawową aplikacją jest framework plug-in.

Http://www.eclipse.org/articles/Article-Plug-in-architecture/plugin_architecture.html

 13
Author: Patrick,
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
2010-05-04 20:38:06

Pracowałem kiedyś nad projektem, który musiał być tak elastyczny, aby każdy klient mógł skonfigurować system, a jedynym dobrym projektem, który znaleźliśmy, było dostarczenie klientowi kompilatora C#!

Jeśli spec jest wypełniony słowami typu:

  • elastyczny
  • Plug-In
  • Możliwość dostosowania

Zadawaj wiele pytań o to, jak będziesz wspierać system (i jak wsparcie będzie naliczane za, ponieważ każdy klient będzie myślał, że jego sprawa jest normalnym przypadkiem i nie powinien potrzebować wszelkie wtyczki.), jak z mojego doświadczenia

Wsparcie klientów (lub fount-line support people) pisząc Wtyczki są o wiele trudniejsze niż Architektura

 8
Author: Ian Ringrose,
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
2010-05-10 12:42:36

Zazwyczaj używam MEF. Struktura zarządzanej rozszerzalności (w skrócie MEF) upraszcza tworzenie aplikacji rozszerzalnych. MEF oferuje możliwości wykrywania i kompozycji, które można wykorzystać do ładowania rozszerzeń aplikacji.

Jeśli jesteś zainteresowany przeczytaj więcej...

 7
Author: Muse VSExtensions,
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
2010-05-04 19:13:18

Opiszę dość prostą technikę, której używałem w przeszłości. To podejście wykorzystuje C# reflection, aby pomóc w procesie ładowania wtyczki. Technika ta może być zmodyfikowana tak, że ma zastosowanie do C++ , ale tracisz wygodę korzystania z reflection.

Interfejs IPlugin służy do identyfikacji klas implementujących wtyczki. Metody są dodawane do interfejsu, aby umożliwić aplikacji komunikację z wtyczką. Na przykład metoda Init, którą aplikacja użyje do instruowania wtyczki, aby zainicjować.

Aby znaleźć wtyczki, aplikacja skanuje folder wtyczek w poszukiwaniu zestawów. Net. Każdy zespół jest załadowany. Reflection jest używane do skanowania klas implementujących IPlugin. Instancja każdej klasy wtyczki jest tworzona.

(alternatywnie, plik Xml może zawierać listę zestawów i klas do załadowania. To może pomóc w wydajności, ale nigdy nie znalazłem problemu z wydajnością).

Metoda Init jest wywoływana dla każdego obiektu wtyczki. Przekazywana jest Referencja do obiektu, który implementuje interfejs aplikacji: IApplication (lub coś innego o nazwie specyficznej dla Twojej aplikacji, np.

IApplication zawiera metody, które pozwalają wtyczce komunikować się z aplikacją. Na przykład, jeśli piszesz edytor tekstu, interfejs ten miałby właściwość OpenDocuments, która pozwala wtyczkom wyliczyć zbiór aktualnie otwartych dokumentów.

Ten system wtyczek można rozszerzyć na języki skryptowe, np. Lua, tworząc pochodną klasę wtyczek, np. LuaPlugin, która przekazuje IPlugin funkcje i interfejs aplikacji do skryptu Lua.

Ta technika pozwala iteracyjnie zaimplementować Twoje IPlugin, IApplication i innych interfejsów specyficznych dla aplikacji podczas tworzenia. Kiedy aplikacja jest kompletna i ładnie refakturowana, możesz udokumentować swoje narażone interfejsy i powinieneś mieć ładny system, dla którego użytkownicy mogą pisać własne wtyczki.

 6
Author: Ashley Davis,
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
2010-05-13 12:45:41

Myślę, że najpierw musisz odpowiedzieć na pytanie: "jakie komponenty mają być wtyczkami?" Chcesz ograniczyć tę liczbę do absolutnego minimum lub liczbę kombinacji, które musisz przetestować. Spróbuj oddzielić swój podstawowy produkt (który nie powinien mieć zbyt dużej elastyczności) od funkcjonalności wtyczki.

Odkryłem, że IOC (Inversion of Control) principal (read springframework) działa dobrze dla zapewnienia elastycznej podstawy, do której można dodać specjalizację, aby prostsze tworzenie wtyczek.

  • Możesz zeskanować kontener w poszukiwaniu mechanizmu "interface as a plugin type advertising".
  • możesz użyć kontenera, aby wprowadzić typowe zależności, których mogą wymagać wtyczki(np. ResourceLoaderAware lub MessageSourceAware).
 3
Author: Justin,
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
2010-05-12 16:33:36

Z mojego doświadczenia wynika, że dwa najlepsze sposoby tworzenia elastycznej architektury wtyczek to języki skryptowe i biblioteki. Te dwa pojęcia są w moim umyśle ortogonalne; te dwa mogą być mieszane w dowolnej proporcji, raczej jak programowanie funkcjonalne i obiektowe, ale znajdują swoje największe atuty, gdy są zrównoważone. Biblioteka jest zazwyczaj odpowiedzialna za wypełnienie określonego interfejsu z dynamiczną funkcjonalnością, podczas gdy Skrypty mają tendencję do podkreślania funkcjonalności z dynamiczną interfejs.

Odkryłem, że architektura oparta na skryptach zarządzających bibliotekami wydaje się działać najlepiej. Język skryptowy pozwala na manipulację na wysokim poziomie bibliotek niższego poziomu, a Biblioteki te są w ten sposób wolne od określonego interfejsu, pozostawiając całą interakcję na poziomie aplikacji w bardziej elastycznych rękach systemu skryptowego.

Aby to zadziałało, system skryptowy musi mieć dość solidne API, z hookami do danych aplikacji, logiki i GUI, a także podstawowa funkcjonalność importowania i wykonywania kodu z bibliotek. Ponadto, skrypty są zwykle wymagane, aby były Bezpieczne w tym sensie, że aplikacja może z wdziękiem odzyskać ze źle napisanego skryptu. Korzystanie z systemu skryptowego jako warstwy indrection oznacza, że aplikacja może łatwiej się odłączyć w przypadku czegoś złego™.

Sposób pakowania wtyczek zależy w dużej mierze od osobistych preferencji, ale nigdy nie można się pomylić z skompresowanym Archiwizuj za pomocą prostego interfejsu, powiedzmy PluginName.ext w katalogu głównym.

 2
Author: Jon Purdy,
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
2010-05-12 16:54:44