Esnek Eklenti Mimarisi Nasıl Oluşturulur?


154

Geliştirme çalışmamda tekrarlanan bir tema, bir şirket içi eklenti mimarisinin kullanılması veya oluşturulmasıydı. Yapılandırma dosyaları (XML, .conf, vb.), Miras çerçeveleri, veritabanı bilgileri, kütüphaneler ve diğerleri gibi birçok yöne yaklaştığını gördüm. Tecrübelerime göre:

  • Bir veritabanı, yapılandırma verilerinizi saklamak için harika bir yer değildir, özellikle de verilerle karışır
  • Bunu bir miras hiyerarşisiyle denemek, eklentilerin kodlanabilmesi için bilgi gerektirir, yani eklenti mimarisi o kadar dinamik değildir
  • Yapılandırma dosyaları basit bilgi sağlamak için iyi çalışır, ancak daha karmaşık davranışları kaldıramaz
  • Kütüphaneler iyi çalışıyor gibi gözükse de, tek yönlü bağımlılıklar dikkatle oluşturulmalıdır.

Çalıştığım çeşitli mimarilerden öğrenmeye çalışırken, aynı zamanda öneriler için topluma bakıyorum. SOLID eklenti mimarisini nasıl uyguladınız? En kötü başarısızlığın neydi (ya da gördüğün en kötü başarısızlık)? Yeni bir eklenti mimarisi uygulayacak olsaydınız ne yapardınız? Hangi SDK ya da açık kaynaklı bir projede iyi bir mimariye en iyi örnek veriliyor?

Kendi başıma bulduğum birkaç örnek:

Bu örnekler çeşitli dil güçleri için geçerli gibi görünmektedir. İyi bir eklenti mimarisi mutlaka dile bağlı mı? Bir eklenti mimarisi oluşturmak veya kendi aşağıdaki modellerinde yapmak için araçlar kullanmak en iyisidir?


Eklenti mimarisinin neden ortak bir tema olduğunu söyleyebilir misiniz? Hangi sorunları çözüyor veya hedefleri ele alıyor mu? Birçok genişletilebilir sistem / uygulama bazı biçimlerde eklentiler kullanır, ancak biçim çözülmekte olan soruna bağlı olarak önemli ölçüde değişir.
Mdma

@mdma - bu harika bir soru. Genişletilebilir bir sistemde bazı ortak hedefler olduğunu söyleyebilirim. Belki de amaçların hepsi ortaktır ve en iyi çözüm, sistemin ne kadar genişletilebilir olması gerektiğine, sistemin hangi dilde yazıldığına bağlı olarak değişir. Bununla birlikte, IOC gibi desenlerin birçok dilde uygulandığını görüyorum ve benden tekrar tekrar benzer eklentiler (aynı işlevsellik isteklerine yanıt veren parçalarda düşüş için) yapmam istendi. Çeşitli eklenti türleri için en iyi uygulamalar hakkında genel bir fikir edinmenin iyi olduğunu düşünüyorum.
justkt

Yanıtlar:


89

Bu, potansiyel olarak faydalı açıklamalar / örnekler kadar bir cevap değildir .

  • Uygulamanızı genişletilebilir hale getirmenin etkili bir yolu, iç öğelerini bir komut dosyası dili olarak göstermek ve bu dilde en üst düzey tüm öğeleri yazmaktır. Bu, oldukça değiştirilebilir ve pratik olarak gelecekteki kanıtlar haline getirir (ilkelleriniz iyi seçilmiş ve uygulanmışsa). Bu tür bir şeyin başarı öyküsü Emacs. Eclipse tarzı eklenti sistemine tercih ederim, çünkü işlevselliği genişletmek istiyorsam, API'yi öğrenmek ve ayrı bir eklenti yazmak / derlemek zorunda değilim. Mevcut arabellek içine 3 satırlı bir snippet yazabilir, değerlendirebilir ve kullanabilirim. Çok düzgün öğrenme eğrisi ve çok hoş sonuçlar.

  • Biraz uzattığım bir uygulama Trac . Bu durumda, görevlerin uzantı noktalarının reklamını yapan modüllere devredildiği anlamına gelen bir bileşen mimarisi vardır. Daha sonra bu noktalara uyan ve akışı değiştiren diğer bileşenleri uygulayabilirsiniz. Kalkie'nin yukarıdaki önerisi gibi biraz.

  • İyi olan bir diğeri py.test . "En iyi API hiçbir API değildir" felsefesini izler ve her seviyede çağrılan kancalara dayanır. Bir kurala göre adlandırılan dosyalarda / işlevlerde bu kancaları geçersiz kılabilir ve davranışı değiştirebilirsiniz. Ne kadar hızlı / kolay uygulanabileceğini görmek için sitedeki eklentilerin listesini görebilirsiniz.

Birkaç genel nokta.

  • Genişletilemeyen / kullanıcı tarafından değiştirilemeyen çekirdeğinizi mümkün olduğunca küçük tutmaya çalışın. Genişletilebilirliğin artması için elinizden gelen her şeyi daha yüksek bir katmana devredin. Çekirdekte düzeltmek için daha az şey, daha sonra kötü seçimler durumunda.
  • Yukarıdaki nokta ile ilgili olarak, projenizin başlangıçta yönü hakkında çok fazla karar vermemelisiniz. Gereken en küçük altkümeyi uygulayın ve ardından eklentileri yazmaya başlayın.
  • Bir komut dosyası dili gömüyorsanız, yalnızca uygulamanız için bir oyuncak dili değil, genel programlar yazabildiğinizden emin olun .
  • Isıtıcı plakayı olabildiğince azaltın. Alt sınıflandırma, karmaşık API'ler, eklenti kaydı ve bunun gibi şeylerle uğraşmayın. Bir o kadar basit So tutmaya çalışın kolay sadece değil, mümkün uzatmak için. Bu, eklenti API'nizin daha fazla kullanılmasına izin verir ve son kullanıcıları eklenti yazmaya teşvik eder. Sadece eklenti geliştiricileri değil. py.test bunu iyi yapıyor. Eclipse bildiğim kadarıyla değil .

1
Komut dosyası dili noktasını, python veya perl gibi mevcut bir dili gömmeye değer olduğuna değinirdim
Rudi

Gerçek Rudi. Birçok dil, gömülmek üzere tasarlandı. Örneğin Guile, sadece gömmek için yapılır. Uygulamanızı komut dosyası haline getirebiliyorsanız zaman kazandırır. Bu dillerden birine girebilirsiniz.
Noufal İbrahim

24

Deneyimlerime göre gerçekten iki tür eklenti Mimarisi olduğunu gördüm.

  1. Bunlardan biri Eclipse modelözgürlüğe izin vermek ve açık uçlu olanı izler .
  2. Diğeri genellikle takip etmek için eklentiler gerektirir narrow APIçünkü eklenti belirli bir işlevi dolduracaktır.

Bunu farklı bir şekilde ifade etmek için, biri eklentilerin uygulamanıza erişmesine izin verirken diğeri uygulamanızın eklentilere erişmesine izin verir .

Ayrım çok incedir ve bazen hiçbir ayrım yoktur ... her ikiniz de uygulamanız için istersiniz.

Eclipse / Eklenti modeline uygulamanızı açma konusunda bir ton deneyimim yok (Kalkie'nin yazısındaki makale harika). Tutulmanın bazı şeyleri yapma yolunda biraz okudum, ama bundan başka bir şey yok.

Yegge'nin özellikler blogu , özellik deseninin kullanımının eklentilere ve genişletilebilirliğe nasıl izin verdiğinden biraz bahsediyor.

Yaptığım işlerin çoğu, uygulamamın eklentilere, zaman / görüntü / harita verileri gibi şeylere erişmesine izin vermek için bir eklenti mimarisi kullandı.

Yıllar önce hepsini yönetmek için fabrikalar, eklenti yöneticileri ve yapılandırma dosyaları oluşturacağım ve çalışma zamanında hangi eklentiyi kullanacağımı belirleyeceğim.

  • Şimdi genellikle DI frameworkbu işin çoğunu yapıyorum.

Hala üçüncü taraf kütüphanelerini kullanmak için adaptörler yazmam gerekiyor, ama genellikle o kadar da kötü değiller.


@ Justin evet, DI = bağımlılık enjeksiyonu.
türetme

14

Gördüğüm en iyi eklenti mimarilerinden biri Eclipse'de uygulandı. Eklenti modeli olan bir uygulamaya sahip olmak yerine, her şey bir eklentidir. Temel uygulamanın kendisi eklenti çerçevesidir.

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


Kesinlikle iyi bir örnek, ancak birçok uygulamanın gerektirdiğinden daha büyük ve daha karmaşık mı?
justkt

Evet, esnekliğin artması bir maliyetle birlikte olabilir. Ama bence farklı bir bakış açısı gösteriyor. Uygulamanızın menüsü neden bir eklenti veya ana görünüm olamaz?
Patrick

6
Aynı yaklaşım (her şey bir eklentidir) Symfony çerçevesinin yeni sürümünde kullanılır. Bunlara demetler denir, ancak prensip aynıdır. Mimarisi oldukça basit, belki de bir göz atmalısınız
Marijn Huizendveld

@Marjin Huizendveld - cevabı onaylayabilmek için bunu ayrı bir cevap olarak eklemelisiniz. İlginç bir çerçeve gibi görünüyor!
justkt

11

Geçmişte kullandığım oldukça basit bir tekniği anlatacağım. Bu yaklaşım, eklenti yükleme işlemine yardımcı olmak için C # yansımasını kullanır. Bu teknik C ++ için geçerli olacak şekilde değiştirilebilir, ancak yansıma kullanabilme kolaylığını kaybedersiniz.

IPluginEklentileri uygulayan sınıfları tanımlamak için bir arabirim kullanılır. Uygulamanın eklentiyle iletişim kurmasına izin vermek için arabirime yöntemler eklenir. Örneğin Init, uygulamanın eklentiyi başlatmasını bildirmek için kullanacağı yöntem.

Eklentileri bulmak için uygulama .Net derlemeleri için bir eklenti klasörü tarar. Her montaj yüklenir. Yansıma, uygulayan sınıfları taramak için kullanılır IPlugin. Her eklenti sınıfının bir örneği oluşturulur.

(Alternatif olarak, bir Xml dosyası yüklenecek derlemeleri ve sınıfları listeleyebilir. Bu performansa yardımcı olabilir, ancak performansla ilgili bir sorun bulamadım).

InitYöntem her eklenti nesne için çağrılır. Uygulama arabirimini uygulayan bir nesneye bir başvuru iletilir: IApplication(veya uygulamanıza özel olarak adlandırılmış başka bir şey, örneğin ITextEditorApplication).

IApplicationeklentinin uygulama ile iletişim kurmasını sağlayan yöntemler içerir. Örneğin, bir metin editörü yazıyorsanız, bu arayüz OpenDocumentseklentilerin o anda açık olan belgelerin toplanmasını numaralandırmasına izin veren bir özelliğe sahip olacaktır .

Bu eklenti sistemi, türetilmiş bir eklenti sınıfı oluşturarak, örneğin fonksiyonları ve uygulama arayüzünü bir Lua komut dosyasına LuaPluginileten türetilmiş bir eklenti sınıfı oluşturarak komut dosyası dillerine, örneğin Lua'ya genişletilebilir IPlugin.

Bu teknik iteratif sizin uygulamasına olanak tanır IPlugin, IApplicationgeliştirme sırasında ve diğer uygulamaya özgü arayüzleri. Uygulama tamamlandığında ve güzelce yeniden düzenlendiğinde, açıkta kalan arayüzlerinizi belgeleyebilirsiniz ve kullanıcıların kendi eklentilerini yazabilecekleri güzel bir sisteminiz olmalıdır.


7

Genellikle MEF kullanıyorum. Yönetilen Genişletilebilirlik Çerçevesi (veya kısaca MEF), genişletilebilir uygulamaların oluşturulmasını kolaylaştırır. MEF, uygulama uzantılarını yüklemek için kullanabileceğiniz keşif ve kompozisyon özellikleri sunar.

Eğer ilgileniyorsanız devamını oku ...


Teşekkürler, ilginç görünüyor. Benzer ilkeleri diğer dillere uygulamak ne kadar kolay?
justkt

Aslında MEF sadece .NET framework içindir Diğer çerçeveler hakkında hiçbir şey bilmiyorum
BALKANGraph

7

Bir keresinde, her müşterinin sistemi kurması için çok esnek olması gereken bir proje üzerinde çalıştım, bulduğumuz tek iyi tasarım müşteriye bir C # derleyicisi göndermekti!

Spesifikasyon aşağıdaki kelimelerle doluysa:

  • Esnek
  • Eklenti
  • kişiselleştirilebilir

Deneyimlerime göre, sistemi nasıl destekleyeceğiniz (ve her müşteri kendi durumunun normal durumda olduğunu ve herhangi bir eklentiye ihtiyaç duymaması gerektiğini düşündüğü için nasıl destek talep edileceği) hakkında birçok soru sorun.

Eklentileri yazan müşterilerin (veya giriş hattı destek personelinin) desteği, Mimari'den çok daha zor


5

Deneyimlerime göre, esnek bir eklenti mimarisi oluşturmanın en iyi iki yolu komut dilleri ve kütüphaneleridir. Bu iki kavram aklımda dik; ikisi işlevsel ve nesne yönelimli programlama gibi herhangi bir oranda karıştırılabilir, ancak dengelendiğinde en güçlü yönlerini bulurlar. Bir kütüphane genellikle dinamik işlevselliğe sahip belirli bir arabirimi yerine getirmekten sorumluyken , komut dosyaları dinamik bir arabirimle işlevselliği vurgulama eğilimindedir .

Kütüphaneleri yöneten betiklere dayalı bir mimarinin en iyi sonucu verdiğini gördüm . Komut dosyası dili, alt düzey kitaplıkların üst düzey manipülasyonuna izin verir ve böylece kitaplıklar, tüm uygulama düzeyi etkileşimini komut dosyası sisteminin daha esnek ellerinde bırakarak belirli bir arabirimden kurtarılır.

Bunun çalışması için, komut dosyası sisteminin uygulama verileri, mantık ve GUI'ye kancaları ve kütüphanelerden kod alma ve yürütmenin temel işlevselliği ile oldukça sağlam bir API'ya sahip olması gerekir. Ayrıca, uygulamanın kötü yazılmış bir komut dosyasından zarif bir şekilde kurtarılabilmesi açısından komut dosyalarının genellikle güvenli olması gerekir . Komut dosyası sistemini bir dolaylı katman olarak kullanmak, Something Bad ™ durumunda uygulamanın daha kolay ayrılabileceği anlamına gelir.

Paketleme eklentilerinin araçları büyük ölçüde kişisel tercihlere bağlıdır, ancak PluginName.extkök dizinde , basit bir arayüze sahip sıkıştırılmış bir arşivle asla yanlış gidemezsiniz .


3

İlk olarak şu soruyu cevaplamanız gerektiğini düşünüyorum: "Hangi bileşenlerin eklenti olması bekleniyor?" Bu sayıyı mutlak minimumda tutmak veya sınamanız gereken kombinasyon sayısını patlatmak istersiniz. Temel ürününüzü (çok fazla esnekliğe sahip olmamalıdır) eklenti işlevinden ayırmaya çalışın.

Eklenti geliştirmeyi daha basit hale getirmek için uzmanlık ekleyebileceğiniz esnek bir taban sağlamak için IOC (Inversion of Control) prensibinin (bahar çerçevesini okuyun) iyi çalıştığını gördüm.

  • "Eklenti türü reklam olarak arayüz" mekanizması için kapsayıcıyı tarayabilirsiniz.
  • Kapsayıcıyı, eklentilerin gerektirebileceği yaygın bağımlılıkları (ör: ResourceLoaderAware veya MessageSourceAware) enjekte etmek için kullanabilirsiniz.

1

Eklenti Deseni, sınıfın davranışını temiz bir arayüzle genişletmek için kullanılan bir yazılım modelidir. Sınıfların davranışı genellikle türetilmiş sınıfın sınıfın bazı sanal yöntemlerinin üzerine yazıldığı sınıf kalıtımıyla genişletilir. Bu çözümle ilgili bir sorun, uygulamanın gizlenmesi ile çakışmasıdır. Ayrıca türetilmiş sınıfın ilişkisiz davranış uzantılarının bir araya geldiği yerler haline gelir. Ayrıca, komut dosyası oluşturma, yukarıda anlatıldığı gibi bu kalıbı uygulamak için kullanılır. "İç metni bir komut dosyası dili olarak yap ve o dilde tüm üst düzey öğeleri yaz. Kütüphaneler, komut dosyası yönetim kütüphanelerini kullanır. Komut dosyası dili, alt düzey kitaplıkların üst düzey yönetimine izin verir. (Ayrıca yukarıda belirtildiği gibi)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.