Programing

유연한 플러그인 아키텍처를 만드는 방법?

lottogame 2020. 6. 13. 10:10
반응형

유연한 플러그인 아키텍처를 만드는 방법?


개발 작업에서 반복되는 주제는 사내 플러그인 아키텍처를 사용하거나 작성하는 것이 었습니다. 구성 파일 (XML, .conf 등), 상속 프레임 워크, 데이터베이스 정보, 라이브러리 등 여러 가지 방법으로 접근하는 것을 보았습니다. 내 경험상 :

  • 데이터베이스는 특히 데이터와 함께 구성 정보를 저장하기에 좋은 장소가 아닙니다.
  • 상속 계층 구조로 이것을 시도하려면 플러그인에 대한 지식이 필요합니다. 이는 플러그인 아키텍처가 그다지 역동적이지 않음을 의미합니다.
  • 구성 파일은 간단한 정보를 제공하는 데 효과적이지만 더 복잡한 동작을 처리 할 수 ​​없습니다
  • 라이브러리는 잘 작동하는 것처럼 보이지만 단방향 종속성은 신중하게 만들어야합니다.

함께 일한 다양한 아키텍처에서 배우려고 노력하면서 커뮤니티에 제안을 요청하고 있습니다. SOLID 플러그인 아키텍처를 어떻게 구현 했습니까? 최악의 고장은 무엇입니까? 새로운 플러그인 아키텍처를 구현하려는 경우 어떻게 하시겠습니까? 함께 작업 한 SDK 또는 오픈 소스 프로젝트 중 가장 좋은 아키텍처의 예는 무엇입니까?

내가 직접 찾은 몇 가지 예 :

이 예제는 다양한 언어 강점으로 재생되는 것 같습니다. 좋은 플러그인 아키텍처는 반드시 언어와 연결되어 있습니까? 플러그인 아키텍처를 만들거나 자신의 다음 모델에서 도구를 사용하는 것이 가장 좋습니까?


이것은 잠재적으로 유용한 발언 / 예만큼 대답 이 아닙니다 .

  • 응용 프로그램을 확장 가능하게 만드는 효과적인 방법 중 하나는 내부를 스크립팅 언어로 노출하고 해당 언어로 모든 최상위 항목을 작성하는 것입니다. 이를 통해 수정 가능하고 실질적으로 미래의 증거가 될 수 있습니다 (원본이 잘 선택되고 구현 된 경우). 이런 종류의 성공 사례는 Emacs입니다. 기능을 확장하려면 API를 배우고 별도의 플러그인을 작성 / 컴파일 할 필요가 없기 때문에 Eclipse 스타일 플러그인 시스템을 선호합니다. 현재 버퍼 자체에 3 줄 스 니펫을 작성하고 평가하여 사용할 수 있습니다. 매우 부드러운 학습 곡선과 매우 즐거운 결과.

  • 내가 조금 확장 한 응용 프로그램은 Trac 입니다. 이 상황에서 확장 아키텍처를 알리는 모듈에 작업이 위임됨을 의미하는 구성 요소 아키텍처가 있습니다. 그런 다음 이러한 지점에 맞는 다른 구성 요소를 구현하고 흐름을 변경할 수 있습니다. 위의 Kalkie의 제안과 약간 같습니다.

  • 또 다른 좋은 방법은 py.test 입니다. "최상의 API는 API가 아닙니다"라는 철학을 따르고 있으며 모든 수준에서 호출되는 후크에 전적으로 의존합니다. 규칙에 따라 명명 된 파일 / 함수에서 이러한 후크를 무시하고 동작을 변경할 수 있습니다. 사이트에서 플러그인 목록을보고 얼마나 빠르고 쉽게 구현할 수 있는지 확인할 수 있습니다.

몇 가지 일반적인 사항.

  • 확장 가능하지 않거나 사용자가 수정할 수없는 코어를 가능한 작게 유지하십시오. 확장 성을 높이려면 가능한 한 모든 것을 상위 계층에 위임하십시오. 잘못된 선택의 경우 코어에서 수정해야 할 사항이 적습니다.
  • 위의 요점과 관련하여 처음에 프로젝트 방향에 대해 너무 많은 결정을 내려서는 안된다는 것입니다. 가장 작은 필수 서브 세트를 구현 한 후 플러그인 작성을 시작하십시오.
  • 당신이 스크립트 언어를 내장하는 경우, 반드시 그 전체는 일반적으로 프로그램을 작성할 수있는 일이 아닌 장난감 언어의 수 있도록 단지 응용 프로그램에 대한.
  • 상용구를 최대한 줄이십시오. 서브 클래 싱, 복잡한 API, 플러그인 등록 및 이와 유사한 것들을 신경 쓰지 마십시오. 그것에게 그것의 간단하므로 유지하려고 쉽게 만이 아니라 가능한 확장 할 수 있습니다. 이를 통해 플러그인 API를 더 많이 사용할 수 있으며 최종 사용자가 플러그인을 작성할 수 있습니다. 플러그인 개발자 만이 아닙니다. py.test가 이것을 잘합니다. 내가 아는 한 이클립스는 그렇지 않다 .

필자의 경험에 따르면 실제로 두 가지 유형의 플러그인 아키텍처가 있습니다.

  1. 하나 Eclipse model는 자유를 허용하기위한 것이며 개방형입니다.
  2. 다른 하나 narrow API는 플러그인이 특정 기능 을 수행하기 때문에 일반적으로 플러그인을 따라야 합니다.

이를 다른 방식으로 설명 하기 위해 하나 는 플러그인이 애플리케이션에 액세스하도록 허용 하고 다른 하나 는 애플리케이션이 플러그인에 액세스하도록 허용합니다 .

구별은 미묘하고 때로는 혼란이 없습니다 ... 당신은 응용 프로그램을 위해 둘 다 원합니다.

Eclipse에 대한 경험이 많지 / 플러그인 모델로 앱 열기 (Kalkie의 게시물의 기사는 훌륭합니다). 나는 일식이하는 방식에 대해 조금 읽었지만 그 이상은 아닙니다.

Yegge의 속성 블로그 는 속성 패턴을 사용하여 플러그인 및 확장 성을 허용하는 방법에 대해 설명합니다.

내가 한 대부분의 작업은 플러그인 아키텍처를 사용하여 앱이 플러그인, 시간 / 디스플레이 / 맵 데이터 등과 같은 것들에 액세스 할 수 있도록했습니다.

몇 년 전에 팩토리, 플러그인 관리자 및 구성 파일을 만들어 모든 것을 관리하고 런타임에 사용할 플러그인을 결정할 수있었습니다.

  • 이제 저는 보통 DI framework그 일을 대부분합니다.

타사 라이브러리를 사용하려면 여전히 어댑터를 작성해야하지만 일반적으로 그렇게 나쁘지는 않습니다.


내가 본 최고의 플러그인 아키텍처 중 하나는 Eclipse에서 구현됩니다. 플러그인 모델이있는 애플리케이션을 사용하는 대신 모든 것이 플러그인입니다. 기본 애플리케이션 자체는 플러그인 프레임 워크입니다.

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


한 번은 각 고객이 시스템을 설정할 수있는 방식으로 매우 유연해야하는 프로젝트를 수행 한 결과, C # 컴파일러를 고객에게 제공하는 것이 가장 좋은 디자인이었습니다!

사양이 다음과 같은 단어로 채워져있는 경우 :

  • 융통성 있는
  • 플러그인
  • 맞춤형

Ask lots of questions about how you will support the system (and how support will be charged for, as each customer will think their case is the normal case and should not need any plug-ins.), as in my experience

The support of customers (or fount-line support people) writing Plug-Ins is a lot harder than the Architecture


I'll describe a fairly simple technique that I have use in the past. This approach uses C# reflection to help in the plugin loading process. This technique can be modified so it is applicable to C++ but you lose the convenience of being able to use reflection.

An IPlugin interface is used to identify classes that implement plugins. Methods are added to the interface to allow the application to communicate with the plugin. For example the Init method that the application will use to instruct the plugin to initialize.

To find plugins the application scans a plugin folder for .Net assemblies. Each assembly is loaded. Reflection is used to scan for classes that implement IPlugin. An instance of each plugin class is created.

(Alternatively, an Xml file might list the assemblies and classes to load. This might help performance but I never found an issue with performance).

The Init method is called for each plugin object. It is passed a reference to an object that implements the application interface: IApplication (or something else named specific to your app, eg ITextEditorApplication).

IApplication contains methods that allows the plugin to communicate with the application. For instance if you are writing a text editor this interface would have an OpenDocuments property that allows plugins to enumerate the collection of currently open documents.

This plugin system can be extended to scripting languages, eg Lua, by creating a derived plugin class, eg LuaPlugin that forwards IPlugin functions and the application interface to a Lua script.

This technique allows you to iteratively implement your IPlugin, IApplication and other application-specific interfaces during development. When the application is complete and nicely refactored you can document your exposed interfaces and you should have a nice system for which users can write their own plugins.


Usualy I use MEF. The Managed Extensibility Framework (or MEF for short) simplifies the creation of extensible applications. MEF offers discovery and composition capabilities that you can leverage to load application extensions.

If you are interested read more...


I think you need to first answer the question: "What components are expected to be plugins?" You want to keep this number to an absolute minimum or the number of combinations which you must test explodes. Try to separate your core product (which should not have too much flexibility) from plugin functionality.

I've found that the IOC (Inversion of Control) principal (read springframework) works well for providing a flexible base, which you can add specialization to to make plugin development simpler.

  • You can scan the container for the "interface as a plugin type advertisement" mechanism.
  • You can use the container to inject common dependencies which plugins may require (i.e. ResourceLoaderAware or MessageSourceAware).

In my experience, the two best ways to create a flexible plugin architecture are scripting languages and libraries. These two concepts are in my mind orthogonal; the two can be mixed in any proportion, rather like functional and object-oriented programming, but find their greatest strengths when balanced. A library is typically responsible for fulfilling a specific interface with dynamic functionality, whereas scripts tend to emphasise functionality with a dynamic interface.

I have found that an architecture based on scripts managing libraries seems to work the best. The scripting language allows high-level manipulation of lower-level libraries, and the libraries are thus freed from any specific interface, leaving all of the application-level interaction in the more flexible hands of the scripting system.

For this to work, the scripting system must have a fairly robust API, with hooks to the application data, logic, and GUI, as well as the base functionality of importing and executing code from libraries. Further, scripts are usually required to be safe in the sense that the application can gracefully recover from a poorly-written script. Using a scripting system as a layer of indirection means that the application can more easily detach itself in case of Something Bad™.

The means of packaging plugins depends largely on personal preference, but you can never go wrong with a compressed archive with a simple interface, say PluginName.ext in the root directory.

참고URL : https://stackoverflow.com/questions/2768104/how-to-create-a-flexible-plug-in-architecture

반응형