Tema berulang dalam karya pengembangan saya adalah penggunaan atau pembuatan arsitektur plug-in in-house. Saya telah melihatnya mendekati banyak cara - file konfigurasi (XML, .conf, dan sebagainya), kerangka kerja pewarisan, informasi basis data, perpustakaan, dan lainnya. Dalam pengalaman saya:
- Basis data bukan tempat yang bagus untuk menyimpan informasi konfigurasi Anda, terutama yang digabungkan dengan data
- Mencoba ini dengan hierarki warisan membutuhkan pengetahuan tentang plug-in yang akan dikodekan, artinya arsitektur plug-in tidak terlalu dinamis
- File konfigurasi berfungsi dengan baik untuk memberikan informasi sederhana, tetapi tidak dapat menangani perilaku yang lebih kompleks
- Perpustakaan tampaknya berfungsi dengan baik, tetapi dependensi satu arah harus dibuat dengan cermat.
Ketika saya berusaha untuk belajar dari berbagai arsitektur yang telah saya kerjakan, saya juga mencari saran untuk komunitas. Bagaimana Anda menerapkan arsitektur plug-in SOLID? Apa kegagalan terburuk Anda (atau kegagalan terburuk yang pernah Anda lihat)? Apa yang akan Anda lakukan jika Anda akan mengimplementasikan arsitektur plug-in baru? SDK atau proyek sumber terbuka apa yang telah Anda kerjakan memiliki contoh terbaik arsitektur yang bagus?
Beberapa contoh yang saya temukan sendiri:
- Modul Perl :: Plugable dan IOC untuk injeksi ketergantungan pada Perl
- Berbagai kerangka kerja Spring (Java, .NET, Python) untuk injeksi ketergantungan.
- Sebuah pertanyaan SO dengan daftar untuk Java (termasuk antarmuka layanan Provider )
- Sebuah pertanyaan SO untuk C ++ menunjuk ke sebuah artikel Dr. Dobbs
- Sebuah pertanyaan SO mengenai ide tertentu plugin untuk ASP.NET MVC
Contoh-contoh ini tampaknya memainkan berbagai kekuatan bahasa. Apakah arsitektur plugin yang baik harus dikaitkan dengan bahasa? Apakah yang terbaik untuk menggunakan alat untuk membuat arsitektur plugin, atau melakukannya pada model berikut sendiri?
Jawaban:
Ini bukan jawaban sebanyak sekelompok komentar / contoh yang berpotensi berguna.
Salah satu cara efektif untuk membuat aplikasi Anda bisa dikembangkan adalah dengan mengekspos internalnya sebagai bahasa scripting dan menulis semua hal tingkat atas dalam bahasa itu. Ini membuatnya cukup dimodifikasi dan praktis menjadi bukti masa depan (jika primitif Anda dipilih dan diimplementasikan dengan baik). Kisah sukses dari hal semacam ini adalah Emacs. Saya lebih suka ini daripada sistem plugin gaya eclipse karena jika saya ingin memperluas fungsionalitas, saya tidak perlu mempelajari API dan menulis / kompilasi plugin terpisah. Saya dapat menulis cuplikan 3 baris di buffer saat ini, mengevaluasinya, dan menggunakannya. Kurva belajar yang sangat halus dan hasil yang sangat menyenangkan.
Salah satu aplikasi yang saya tambahkan sedikit adalah Trac . Ini memiliki arsitektur komponen yang dalam situasi ini berarti bahwa tugas didelegasikan ke modul yang mengiklankan poin ekstensi. Anda kemudian dapat mengimplementasikan komponen lain yang sesuai dengan poin-poin ini dan mengubah alurnya. Ini sedikit seperti saran Kalkie di atas.
Satu lagi yang bagus adalah py.test . Ini mengikuti filosofi "API terbaik bukan API" dan hanya mengandalkan kait yang dipanggil di setiap level. Anda dapat mengganti kait ini dalam file / fungsi yang dinamai sesuai dengan konvensi dan mengubah perilaku. Anda dapat melihat daftar plugin di situs untuk melihat seberapa cepat / mudah mereka dapat diimplementasikan.
Beberapa poin umum.
sumber
Dalam pengalaman saya, saya benar-benar menemukan dua jenis arsitektur plug-in.
Eclipse model
yang dimaksudkan untuk memungkinkan kebebasan dan terbuka.narrow API
karena plugin akan mengisi fungsi tertentu.Untuk menyatakan ini dengan cara yang berbeda, satu memungkinkan plugin untuk mengakses aplikasi Anda sementara yang lain memungkinkan aplikasi Anda untuk mengakses plugin .
Perbedaannya halus, dan kadang-kadang tidak ada gangguan ... Anda menginginkan keduanya untuk aplikasi Anda.
Saya tidak punya banyak pengalaman dengan Eclipse / Membuka model App to plugins Anda (artikel di posting Kalkie sangat bagus). Saya sudah membaca sedikit tentang cara gerhana melakukan sesuatu, tetapi tidak lebih dari itu.
Blog properti Yegge berbicara sedikit tentang bagaimana penggunaan pola properti memungkinkan plugin dan ekstensibilitas.
Sebagian besar pekerjaan yang saya lakukan telah menggunakan arsitektur plugin untuk memungkinkan aplikasi saya mengakses plugin, hal-hal seperti data waktu / tampilan / peta, dll.
Bertahun-tahun lalu saya akan membuat pabrik, pengelola plugin, dan file konfigurasi untuk mengelola semuanya dan biarkan saya menentukan plugin mana yang akan digunakan saat runtime.
DI framework
melakukan sebagian besar pekerjaan itu.Saya masih harus menulis adaptor untuk menggunakan perpustakaan pihak ketiga, tetapi mereka biasanya tidak terlalu buruk.
sumber
Salah satu arsitektur plug-in terbaik yang pernah saya lihat diimplementasikan di Eclipse. Alih-alih memiliki aplikasi dengan model plug-in, semuanya adalah plug-in. Aplikasi dasar itu sendiri adalah kerangka kerja plug-in.
http://www.eclipse.org/articles/Article-Plug-in-architecture/plugin_architecture.html
sumber
Saya akan menjelaskan teknik yang cukup sederhana yang saya gunakan di masa lalu. Pendekatan ini menggunakan refleksi C # untuk membantu dalam proses pemuatan plugin. Teknik ini dapat dimodifikasi sehingga berlaku untuk C ++ tetapi Anda kehilangan kenyamanan karena dapat menggunakan refleksi.
Sebuah
IPlugin
antarmuka digunakan untuk mengidentifikasi kelas yang mengimplementasikan plugin. Metode ditambahkan ke antarmuka untuk memungkinkan aplikasi berkomunikasi dengan plugin. MisalnyaInit
metode yang akan digunakan aplikasi untuk menginstruksikan plugin untuk menginisialisasi.Untuk menemukan plugin, aplikasi memindai folder plugin untuk .Net assemblies. Setiap unit dimuat. Refleksi digunakan untuk memindai kelas yang mengimplementasikan
IPlugin
. Sebuah instance dari setiap kelas plugin dibuat.(Atau, file Xml dapat mendaftar majelis dan kelas untuk memuat. Ini mungkin membantu kinerja tetapi saya tidak pernah menemukan masalah dengan kinerja).
The
Init
metode ini disebut untuk setiap objek Plugin. Itu diberikan referensi ke objek yang mengimplementasikan antarmuka aplikasi:IApplication
(atau sesuatu yang bernama khusus untuk aplikasi Anda, misalnya ITextEditorApplication).IApplication
berisi metode yang memungkinkan plugin untuk berkomunikasi dengan aplikasi. Misalnya jika Anda menulis editor teks antarmuka ini akan memilikiOpenDocuments
properti yang memungkinkan plugin untuk menyebutkan koleksi dokumen yang sedang terbuka.Sistem plugin ini dapat diperluas ke bahasa scripting, misalnya Lua, dengan membuat kelas plugin turunan, misalnya
LuaPlugin
yang meneruskanIPlugin
fungsi dan antarmuka aplikasi ke skrip Lua.Teknik ini memungkinkan Anda untuk secara iteratif mengimplementasikan antarmuka Anda
IPlugin
,IApplication
dan aplikasi khusus lainnya selama pengembangan. Ketika aplikasi selesai dan refactored dengan baik, Anda dapat mendokumentasikan antarmuka Anda yang terbuka dan Anda harus memiliki sistem yang bagus di mana pengguna dapat menulis plugin mereka sendiri.sumber
Biasanya saya menggunakan MEF. Kerangka Kerja Diperpanjang yang Dikelola (atau disingkat MEF) menyederhanakan pembuatan aplikasi yang dapat dikembangkan. MEF menawarkan kemampuan penemuan dan komposisi yang dapat Anda manfaatkan untuk memuat ekstensi aplikasi.
Jika Anda tertarik baca lebih lanjut ...
sumber
Saya pernah bekerja pada sebuah proyek yang harus sangat fleksibel dalam cara setiap pelanggan dapat mengatur sistem, yang satu-satunya desain bagus yang kami temukan adalah untuk mengirimkan kompiler C # kepada pelanggan!
Jika spec diisi dengan kata-kata seperti:
Ajukan banyak pertanyaan tentang bagaimana Anda akan mendukung sistem (dan bagaimana dukungan akan dikenakan biaya, karena setiap pelanggan akan berpikir kasus mereka adalah kasus normal dan seharusnya tidak memerlukan plug-in.), Seperti dalam pengalaman saya
sumber
Dalam pengalaman saya, dua cara terbaik untuk membuat arsitektur plugin yang fleksibel adalah bahasa scripting dan perpustakaan. Kedua konsep ini dalam ingatan saya ortogonal; keduanya dapat dicampur dalam proporsi apa pun, lebih suka pemrograman fungsional dan berorientasi objek, tetapi menemukan kekuatan terbesar mereka ketika seimbang. Pustaka biasanya bertanggung jawab untuk memenuhi antarmuka tertentu dengan fungsionalitas dinamis, sedangkan skrip cenderung menekankan fungsionalitas dengan antarmuka dinamis.
Saya telah menemukan bahwa arsitektur yang didasarkan pada skrip yang mengelola perpustakaan tampaknya berfungsi paling baik. Bahasa scripting memungkinkan manipulasi tingkat tinggi dari perpustakaan tingkat rendah, dan perpustakaan dengan demikian dibebaskan dari antarmuka tertentu, meninggalkan semua interaksi tingkat aplikasi di tangan yang lebih fleksibel dari sistem scripting.
Agar ini berfungsi, sistem skrip harus memiliki API yang cukup kuat, dengan kaitan ke data aplikasi, logika, dan GUI, serta fungsi dasar mengimpor dan mengeksekusi kode dari perpustakaan. Lebih lanjut, skrip biasanya diperlukan untuk aman dalam arti bahwa aplikasi dapat dengan anggun pulih dari skrip yang ditulis dengan buruk. Menggunakan sistem scripting sebagai lapisan tipuan berarti bahwa aplikasi dapat lebih mudah melepaskan diri dalam kasus Sesuatu Buruk ™.
Sarana pengemasan plugin sebagian besar tergantung pada preferensi pribadi, tetapi Anda tidak pernah bisa salah dengan arsip terkompresi dengan antarmuka yang sederhana, katakanlah
PluginName.ext
di direktori root.sumber
Saya pikir Anda harus terlebih dahulu menjawab pertanyaan: "Komponen apa yang diharapkan menjadi plugin?" Anda ingin menyimpan angka ini ke minimum absolut atau jumlah kombinasi yang harus Anda uji meledak. Cobalah untuk memisahkan produk inti Anda (yang seharusnya tidak memiliki terlalu banyak fleksibilitas) dari fungsionalitas plugin.
Saya telah menemukan bahwa kepala IOC (Inversion of Control) (baca springframework) bekerja dengan baik untuk memberikan basis yang fleksibel, yang dapat Anda tambahkan spesialisasi untuk membuat pengembangan plugin lebih sederhana.
sumber
Pola Plug-in adalah pola perangkat lunak untuk memperluas perilaku kelas dengan antarmuka yang bersih. Seringkali perilaku kelas diperluas dengan pewarisan kelas, di mana kelas turunan menimpa beberapa metode virtual kelas. Masalah dengan solusi ini adalah bahwa itu bertentangan dengan implementasi persembunyian. Ini juga mengarah pada situasi di mana kelas turunan menjadi tempat berkumpulnya ekstensi perilaku yang tidak terkait. Juga, scripting digunakan untuk menerapkan pola ini seperti yang disebutkan di atas "Jadikan internal sebagai bahasa scripting dan tulis semua hal tingkat atas dalam bahasa itu. Ini membuatnya cukup dapat dimodifikasi dan praktis menjadi bukti di masa depan". Perpustakaan menggunakan perpustakaan yang mengelola skrip. Bahasa scripting memungkinkan manipulasi tingkat tinggi dari perpustakaan tingkat bawah. (Juga seperti yang disebutkan di atas)
sumber