language agnostic - ¿Cómo diseñar software extensible(arquitectura de complementos)?
language-agnostic plugins (13)
Acabo de comenzar a desarrollar una aplicación de cliente inteligente. Estas son dos opciones que estoy considerando.
Usando el espacio de nombres System.AddIn de Microsoft. Parece muy prometedor, sin embargo puede ser un poco complejo para nuestra solución final.
O el Smart Client - Bloque de aplicación de interfaz de usuario compuesta de Microsoft
Recientemente, he considerado tomar componentes del bloque de aplicaciones de IU compuesto y del espacio de nombres System.AddIn para crear el mío propio. Como el código fuente está disponible para el CAB, es fácil de extender. Creo que nuestra solución final será una versión ligera del CAB, sin duda utilizando el bloque de aplicaciones de Unity
Necesito algunos recursos que hablan sobre cómo diseñar su software para que sea extensible, es decir, para que otras personas puedan escribir complementos / complementos que le agreguen funcionalidad.
¿Que recomiendas? ¿Hay algún libro que discuta el tema?
Preferiría algo que sea corto y directo; un poco de teoría y un montón de ejemplos concretos.
No estoy apuntando a un idioma específico, quiero ser capaz de comprender la idea central para poder implementarla en cualquier idioma.
Y por la misma razón, prefiero no hacerlo usando un marco que otro construyó (a menos que el marco no sea de muy alto nivel, es decir, no se esconda demasiado ), por el momento solo quiero educarme sobre el sujeto y experimentar con varias formas de implementarlo. Además, un marco usualmente asume el conocimiento del usuario sobre el tema.
ACTUALIZAR
No estoy preguntando sobre OOP o permitiendo que mis clases sean heredadas. Estoy hablando de diseñar una aplicación que se implementará en un sistema, de modo que pueda ser extendida por complementos de terceros DESPUÉS de su implementación.
Por ejemplo, Notepad ++ tiene una arquitectura de complemento en la que puede colocar un archivo .dll en la carpeta de complementos y agrega funcionalidad a la aplicación que no estaba allí, como la selección de colores o la inserción de fragmentos, u otras muchas cosas más. (una amplia gama de funcionalidades).
Bueno, depende del idioma.
- En C / C ++ estoy bastante seguro de que hay una función loadlibrary que le permite abrir una biblioteca en tiempo de ejecución e invocar sus funciones exportadas. Por lo general, así se hace en C / C ++.
- En .NET, hay Reflection, que ofrece ofertas similares (pero más amplias) a loadlibrary. También hay bibliotecas completas creadas en Reflection como Managed Extension Framework, o Mono.Addins que ya hace la mayor parte del trabajo pesado.
- En Java, también hay Reflexión. Y está el JPF (Java Plugin Framework) que se usa en cosas como Eclipse IIRC.
Dependiendo del idioma que use, podría recomendar algunos tutoriales / libros. Espero que esto haya sido útil.
Checkout "CAB" - Estructura de bloques de aplicaciones de Microsoft. Creo que también tienen una "versión web" de eso ...
Como no tengo suficientes puntos de repetición para dejar un comentario, lo estoy publicando como respuesta. SharpDevelop es un IDE para desarrollar aplicaciones en C # / VB.NET / Boo. Tiene una arquitectura bastante impresionante que permite extenderse de varias maneras, desde nuevos elementos de menú hasta soporte de desarrollo para lenguajes completamente nuevos.
Utiliza un poco de configuración XML para actuar como una capa de pegamento entre un núcleo del IDE y la implementación del complemento. Se encarga de localizar, cargar y versionar los complementos de fábrica. La implementación de nuevos complementos es una cuestión de simplemente copiar en el nuevo archivo de configuración xml y los ensamblados necesarios (DLL) y reiniciar la aplicación. Puede leer más sobre esto en el libro "Disección de una aplicación csharp" por el autor (es) original (es) - Christian Holm, Mike Krüger, Bernhard Spuida de la aplicación desde here . El libro no parece estar disponible en ese sitio, pero encontré una copia que todavía podría estar por here
También encontré una pregunta relacionada here
El artículo Writing Plugin-Based Applications explica claramente las responsabilidades de las diversas partes de la arquitectura usando un ejemplo muy simple; se proporciona el código fuente (VB.Net). Me pareció muy útil para comprender los conceptos básicos.
Implementa los principios SOLID en tu aplicación.
1. Principio de responsabilidad única: una clase debe tener una sola responsabilidad (es decir, solo un cambio potencial en la especificación del software debe poder afectar la especificación de la clase
2. Principio Open / closed: las entidades de software ... deberían estar abiertas para la extensión, pero cerradas por modificación
3. Principio de sustitución de Liskov: los objetos en un programa deberían ser reemplazables con instancias de sus subtipos sin alterar la corrección de ese programa.
4. Principio de segregación de la interfaz: muchas interfaces específicas del cliente son mejores que una interfaz de propósito general
5. Principio de inversión de dependencia: uno debe depender de las abstracciones . No dependas de concreciones
Preguntas :
Ejemplo del Principio de Responsabilidad Individual
¿Es el Principio Abierto / Cerrado una buena idea?
¿Cuál es el principio de sustitución de Liskov?
Principio de segregación de interfaz: Programa a una interfaz
¿Cuál es el Principio de Inversión de Dependencia y por qué es importante?
Intentas alcanzar dos objetivos competitivos:
- Los componentes de su software deben exponer mucho de sí mismos, para que puedan ser reutilizados
- Los componentes de su software deben exponer muy poco de sí mismos, por lo que pueden ser reutilizados
Explicación: Para alentar la reutilización del código, debería poder extender las clases existentes y llamar a sus métodos. Esto no es posible cuando los métodos se declaran "privados" y las clases son "finales" (y no se pueden extender). Para cumplir con este objetivo, todo debe ser público y accesible. No hay datos o métodos privados.
Cuando lanza la segunda versión de su software, encontrará que muchas de las ideas de la versión 1 eran completamente erróneas. Necesita cambiar muchas interfaces o su código, nombres de método, métodos de eliminación, romper la API. Si haces esto, muchas personas se alejarán. Por lo tanto, para poder evolucionar su software, los componentes no deben exponer nada que no sea absolutamente necesario, a costa de la reutilización del código.
Ejemplo: quería observar la posición del cursor (cursor) en un SWT StyledText. El cursor no debe extenderse. Si lo haces, verás que el código contiene comprobaciones como "esta clase está en el paquete org.eclipse.swt" y muchos métodos son privados y finales, y otras cosas. Tuve que copiar unas 28 clases de SWT en mi proyecto solo para implementar esta característica porque todo está bloqueado.
SWT es un buen marco de trabajo y un infierno para extender.
La arquitectura de los complementos se está volviendo muy popular por su extensibilidad y, por lo tanto, su flexibilidad.
Para c ++, el servidor httpd de Apache en realidad está basado en un complemento, pero en su lugar se usa un concepto de módulo. La mayoría de las características de Apache se implementan como módulos, como caché, reescritura, equilibrio de carga e incluso el modelo de subprocesamiento. Es un software muy modular que alguna vez vi.
Y para Java, Eclipse definitivamente está basado en un plugin. El núcleo de Eclipse es un sistema de módulo OSGI que gestiona paquetes, otro concepto para el complemento. Bundle puede proporcionar puntos de extensión en los que podemos construir módulos con menos esfuerzo. Lo más intrincado en OSGI es su característica dinámica, lo que significa que los paquetes se pueden instalar o desinstalar en tiempo de ejecución. ¡Ya no hay síndrome de parar el mundo!
Por supuesto, está el famoso Open Closed Principle - http://en.wikipedia.org/wiki/Open/closed_principle
Si hablamos de .NET, intente con las aplicaciones de Scripting .NET con VBScript en CodeProject. Muchos ejemplos concretos allí.
A continuación se muestran los sitios que implementan diversas técnicas de extensión de aplicaciones
- ClearScript: hace que V8, VBScript y JScript estén disponibles para las aplicaciones .NET
- CS-Script - El motor de script C #
- Arquitectura de complemento usando C #
- Arquitectura de complemento Opinio
- Notas sobre la arquitectura de plug-in de Eclipse
- Marco de arquitectura de plug-in para principiantes
- Gecko plugin architecture
- Arquitectura de plugin Fungimol
Si trabajas con .Net, nuestra investigación arrojó dos enfoques: creación de scripts y composición.
Scripting
Extiende la funcionalidad de lo que pueden hacer tus clases orquestando con scripts. Eso significa exponer lo que se compila en su lenguaje .Net favorito en un lenguaje dinámico.
Algunas opciones que encontramos vale la pena explorar:
- IronPython
- IronRuby
- JavaScript: Jint , Jurassic y JavaScript .Net son buenos puntos de partida.
- Script.Net -> este fue el primero en llamar nuestra atención.
Composición
Si comienza un proyecto con .Net 4 o superior, debe echar un vistazo al Framework de Extensibilidad Administrada (MEF). Le permite ampliar la funcionalidad de sus aplicaciones de forma complementaria.
Managed Extensibility Framework (MEF) es una capa de composición para .NET que mejora la flexibilidad, la capacidad de mantenimiento y la capacidad de prueba de las aplicaciones de gran tamaño. MEF se puede utilizar para la extensión de complementos de terceros, o puede aportar los beneficios de una arquitectura tipo plugin poco compactada a las aplicaciones normales.
Managed Add-in Framework también es una buena lectura.
OSGI es un buen ejemplo práctico de un marco técnico que permite hacer lo que está buscando.
La teoría está aquí .
El libro (¡gratis!) Está allí .
La extensibilidad y la capacidad de escribir el complemento deben tener en cuenta el ciclo de vida del servicio
- agregar / eliminar servicio / complemento en el acto
- gestionar dependencias entre servicios
- administrar estados de servicios (declarados, instalados, iniciados, detenidos, ...)
Una de las funciones principales de un módulo es como una unidad de implementación ... algo que podemos construir o descargar e instalar para extender la funcionalidad de nuestra aplicación.
Encontrará una buena introducción aquí , en la noción central de servicio (que se relaciona con su pregunta y que explica algunos problemas relacionados con los servicios, componente clave para la extensibilidad).
Extraer:
¿Por qué los servicios son entonces tan importantes si se pueden construir tantas aplicaciones sin ellos? Bueno, los servicios son la mejor manera conocida de desacoplar componentes de software entre sí.
Uno de los aspectos más importantes de los servicios es que minimizan significativamente los problemas de carga de clases porque funcionan con instancias de objetos, no con nombres de clase. Instancias creadas por el proveedor, no por el consumidor. La reducción de la complejidad es bastante sorprendente
Los servicios no solo minimizan la configuración, sino que también reducen significativamente la cantidad de paquetes compartidos.
En lugar de reinventar la rueda, use los marcos en la mano. Eclipse y Netbeans admiten extensiones basadas en complementos. Sin embargo, tienes que trabajar en Java.