Arquitectura orientada a Servicios¶
Gaphor tiene una arquitectura orientada a servicios. ¿Qué significa esto? Bueno, Gaphor está construido como un conjunto de pequeñas islas (servicios). Cada isla proporciona una funcionalidad específica. Por ejemplo, utilizamos servicios separados para cargar/guardar modelos, proporcionar la estructura del menú, y para manejar el sistema de deshacer.
Definimos los servicios como puntos de entrada en el pyproject.toml. Con los puntos de entrada, las aplicaciones pueden registrar funcionalidades para fines específicos. También agrupamos los puntos de entrada en grupos de puntos de entrada. Por ejemplo, utilizamos el grupo de puntos de entrada console_scripts para iniciar una aplicación desde la línea de comandos.
Servicios¶
Gaphor se modela en torno al concepto de servicios. Cada servicio puede ser registrado con la aplicación y luego puede ser utilizado por otros servicios u otros objetos que existen dentro de la aplicación.
Cada servicio debe implementar la interfaz Service. Esta interfaz define un método:
shutdown(self)
Que se llama cuando hay que limpiar un servicio.
Permitimos que cada servicio defina sus propios métodos, siempre y cuando el servicio también esté implementado.
Los servicios deben definirse como puntos de entrada en el archivo pyproject.toml.
Normalmente, un servicio realiza algún trabajo en segundo plano. Los servicios también pueden exponer acciones que pueden ser invocadas por los usuarios. Por ejemplo, la combinación de teclas Ctrl-z (deshacer) está implementada por el servicio UndoManager.
Un servicio también puede depender de otros servicios. La inicialización del servicio resuelve estas dependencias. Para definir una dependencia de servicio, basta con añadirla al constructor por su nombre definido en el punto de entrada:
class MyService(Service):
def __init__(self, event_manager, element_factory):
self.event_manager = event_manager
self.element_factory = element_factory
event_manager.subscribe(self._element_changed)
def shutdown(self):
self.event_manager.unsubscribe(self._element_changed)
@event_handler(ElementChanged)
def _element_changed(self, event):
Los servicios que exponen acciones también deben heredar de la interfaz ActionProvider. Esta interfaz no requiere la implementación de ningún método adicional. Los métodos de acción deben llevar la anotación @action.
Ejemplo: fábrica de elementos¶
A nice example of a service in use is the
ElementFactory. It is one of the core services.
When an
important events occurs, like an element is created or destroyed, that event is
emitted. We then use an event handler for ElementFactory that stores the
add/remove signals in the undo system. Another example of events that are
emitted are with Element’s. Those classes, or more specifically, the
properties, send notifications every time their state changes.
Puntos de entrada¶
Gaphor uses a main :refentry point <https://packaging.python.org/en/latest/specifications/entry-points/> group called gaphor.services.
Los servicios se utilizan para llevar a cabo la funcionalidad básica de la aplicación, dividiendo las funciones en componentes individuales. Por ejemplo, la fábrica de elementos y el gestor de deshacer son ambos servicios.
Plugins pueden ser creados también para extender Gaphor más allá de la funcionalidad de núcleo como un add-on. Por ejemplo, un plugin podría ser creado para conectar los datos del modelo a otras aplicaciones. Los plugins también son definidos como servicios. Por ejemplo, un nuevo plugin XMI de exportación sería definido como sigue en el pyproject.toml:
[tool.poetry.plugins."gaphor.services"]
"xmi_export" = "gaphor.plugins.xmiexport:XMIExport"
Interfaces¶
Cada servicio (y plugin) debe implementar la interfaz gaphor.abc.Service:
Otro servicio más especializado que también hereda de gaphor.abc.Service, es el servicio UI Component. Los servicios que utilizan esta interfaz se utilizan para definir las ventanas y la funcionalidad de la interfaz de usuario. Un componente de interfaz de usuario debe implementar la interfaz gaphor.ui.abc.UIComponent:
- class gaphor.ui.abc.UIComponent[fuente]¶
Un componente de la interfaz de usuario.
- abstractmethod close()[fuente]¶
Cierre el componente de la interfaz de usuario.
El componente puede decidir ocultar o destruir los componentes de la interfaz de usuario.
Typically, a service and UI component would like to present some actions
to the user, by means of menu entries. Every service and UI component
can advertise actions by implementing the gaphor.abc.ActionProvider
interface: