ruby on rails - Ejemplo práctico de arquitectura usando EBC?
ruby-on-rails design (3)
Esto también debería ser de interés. Es el otro libro, no mencionado por su nombre en "Arquitectura: los años perdidos"
"Desarrollo ágil de software: principios, patrones y prácticas", por "Uncle Bob" Martin.
Tomado de esta SE pregunta y respuesta . Lea las otras respuestas también.
Estaba intrigado por la charla de Robert Martin sobre "Arquitectura: los años perdidos" . En él, analiza el patrón de diseño Entity, Boundary, Control en el que se basa MVC. Me encanta la idea de diferir las decisiones arquitectónicas. Describió diferir la decisión sobre cómo implementar la capa DB en su propia aplicación wiki FitNesse. He diferido orgánicamente decisiones como esta en mi propia codificación, aunque no hubo un diseño modular preconcebido que trajo esto.
Quiero entender mejor esta arquitectura EBC (que parece estrechamente relacionada con DCI) desde un punto de vista práctico, de modo que pueda comenzar a usarla en un proyecto pequeño. Quiero aprovechar las "decisiones diferidas" y la capacidad de cambiar aspectos del diseño como la IU.
Rails, por ejemplo, usa una forma de EBC (MVC), pero está tan recargada que no se puede sustituir fácilmente una IU alternativa, convirtiendo así una aplicación de Rails en una aplicación de consola o una aplicación de escritorio. Lo más intrigante del diseño para mí es la capacidad de transformar aplicaciones al intercambiar una cosa y conectarla a otra. Es decir, me sorprende la idea de diseñar una arquitectura para poder, como una forma de hablar, intercambiar la interfaz de usuario. o la capa de persistencia. Siento que si la arquitectura está bien diseñada, el acoplamiento será bajo, y tal hazaña estará al alcance.
He ordenado el libro de Ivar Jacobson que Bob mencionó en su charla. He buscado bastante en línea pero todos los ejemplos que he encontrado muestran diagramas simples. Digo el código Me beneficiaría más si miro algunas clases simples que demuestran el concepto y cómo se puede cambiar una capa (UI, DB) por alguna otra implementación mediante el uso de clases de límites.
Si alguien no puede indicarme un buen recurso que ilustre esto, ¿sería difícil de organizar? Tal vez podríamos usar el ejemplo standby utilizado en muchos libros de software: una tienda de alquiler de videos (casi una reliquia en estos días). Por favor, demuestre cómo se podría intercambiar la interfaz de usuario o la capa de BD. Una cosa que me confunde son las opiniones. No puedo decir a partir de los diagramas que he visto si las vistas son las clases de límites en sí mismas o si simplemente se comunican con ellas. Además, Bob mencionó que la intención original de EBC era que tendríamos muchas microvistas, no una sola macro-vista (como hacemos en MVC típico); Tengo curiosidad por cómo se vería esto. (Prefiero Ruby o JavaScript pero, como los mendigos no pueden elegir, cualquier ejemplo estaría bien).
Gracias.
Pedid y se os dará. Mantuve los ojos abiertos y descubrí este recurso de Avdi Grimm:
http://avdi.org/devblog/2011/11/15/early-access-beta-of-objects-on-rails-now-available-2/
En él, cubre algunas de las razones por las que los proyectos de Rails se acoplan tanto al framework como a ActiveRecord. Él usa TDD para asegurar un acoplamiento flexible con técnicas como
- Inyección de dependencia
- Presentadores
- Patrón de estrategia
- DCI
Proporciona un buen comienzo para responder a esta pregunta de una manera práctica. (Cuesta $ 5 para la versión beta inicial pero eventualmente será gratis.) De hecho, es el primer recurso que descubrí que lo hace. Por favor agregue cualquier otro que encuentre.
Aquí está la verdadera joya que aclara el corazón del problema:
Un día, después de años de presenciar y abordar la deuda técnica incurrida en varias bases de código de Rails en proceso de vencimiento como resultado del acoplamiento ajustado inspirado por ActiveRecord, tuve una epifanía. ¿Qué pasaría si dejamos de tratar a ActiveRecord como columna vertebral de nuestras clases modelo, y en su lugar, programamos como si ActiveRecord fuera simplemente un detalle de implementación privada?
Corey Haines lo dice de otra manera:
Extraigo el comportamiento de mis modelos en otros objetos que envuelven a los modelos. Prefiero hacer que los objetos AR sean envoltorios simples alrededor del material de acceso db en AR.
Tengo una regla bastante estricta de que las acciones del controlador no pueden usar buscadores de AR o, de hecho, interactuar con AR en absoluto. Debe accederse a AR dentro de los métodos api dentro de su modelo, no desde el exterior.
Por lo que entiendo el video de Uncle Bob usando "EBI" ( Entity , Boundary , and Interactor ) debe desacoplar por completo su comportamiento / estado comercial de los frameworks / SO y servicios.
Por lo tanto, en el caso de una aplicación de Rails, su comportamiento / estado comercial está completamente libre de dependencias con el framework de Rails y, por lo tanto, puede probarse como con rspec sin activar Rails.
Por lo que respecta al negocio, tiene clases de límite que interactúan con el lado de Rails utilizando modelos de solicitud y respuesta (los titulares de datos son muy simples, no se pueden intercambiar con los modelos habituales de Rails ). Solo las clases de límites interactúan con las clases de Interactor que implementan casos / escenarios de uso (de negocios). Y solo las clases interactivas interactúan con las clases de entidad que encapsulan el estado comercial.
En el lado de Rails , encontrará las clases de Controller interactuando con las clases de Boundary (utilizando los modelos de Request) y hacia atrás una clase de Boundary interactúa con un Presenter (utilizando un modelo de respuesta). Solo los presentadores / controladores interactúan con las vistas (con la ayuda de modelos (también simples titulares de datos). Tenga en cuenta que en el ámbito de los presentadores de rieles es muy probable que los controladores .
¿Dónde deja esto a AR? Bueno, AR solo proporciona el servicio persistente. En el mismo nivel que el nivel de Presentador / Controlador , encontrará clases de Servicio que brindan sus servicios a las clases de Límite . Por lo tanto, proporcionan todos los servicios necesarios que son framework / OS / technology dependiendo de la persistencia, seguridad, timing, notifaction, etc.
Con esta arquitectura, realmente puede reutilizar su lógica de negocio y reemplazar por completo la interfaz de usuario o la tecnología de base de datos. Por ejemplo, portar a dispositivos móviles (iOS, Android, Windows) debería ser bastante directo.
Con Rails , su carpeta de aplicaciones podría verse así:
app/
controllers/ Only these interact with Boundary classes
models/ simple data-holders, no AR here! (see services)
views/
services/ AR-stuff
boundaries/ To be tested without Rails
models/ Request & Response
interactors/ use cases / scenarios, to be tested without Rails
entities/ "the real business model without technical dependencies"
Con esta arquitectura, necesitas codificar un poco más, pero no olvides los beneficios de una buena arquitectura:
- Una buena arquitectura permite diferir los cambios importantes
- Una buena arquitectura maximiza los cambios (importantes) no realizados
Última nota: en comparación con el patrón MVC, es más como que M es reemplazado por EBI, C se puede dividir en CP / Resenter) y se agrega un S (servicio). Así que esto podría llamarse: VCPS / EBI pero eso me suena feo ;-) BEPVICS quizás?
@Seralize , gracias por sus comentarios.
Déjame intentar responder tus preguntas, hasta ahora las entiendo: las cosas en los servicios están acopladas a Rails. Proporcionan la implementación de la lógica en el lado EBI. En el caso de uso de la seguridad, debe tener claros los requisitos (cuantificados) que tiene, para saber qué lógica puede implementar en el lado EBI, por ejemplo reglas (comerciales) sobre cuándo un usuario (función) tiene acceso a qué contenido ( y necesita ser autenticado).
Esto significa que la implementación de la autenticación se implementará con Rails, este servicio será utilizado por EBI. Esta lógica relacionada con la seguridad en EBI es bastante fácil de reutilizar en su ejemplo de la GUI de Java. Allí solo tiene que volver a implementar el servicio de autenticación.
Para ser claro en el ejemplo de seguridad:
El lado EBI tiene la lógica: qué cosas necesitan qué tipo de seguridad y cuándo y cómo. The Rails no sabe nada al respecto, solicita qué hacer desde el lado EBI y el lado EBI solicita al lado Rails que actúe.
El lado de Rails solo implementa la forma de hacer seguridad, como pedirle al usuario que se autentique (cuando sea necesario) y pasar el resultado de esto a EBI para que la lógica pueda decidir lo que se debe hacer a continuación.
EBI exige que ambos lados estén desacoplados e independientes. Fue mientras desarrollaba el EBI como una biblioteca con una API definida.