Estoy trabajando con AngularJS para mi último proyecto. En la documentación y tutoriales, todos los datos del modelo se colocan en el alcance del controlador. Entiendo que tiene que estar allí para estar disponible para el controlador y, por lo tanto, dentro de las vistas correspondientes.
Sin embargo, no creo que el modelo deba implementarse allí. Puede ser complejo y tener atributos privados, por ejemplo. Además, es posible que desee reutilizarlo en otro contexto / aplicación. Poner todo en el controlador rompe totalmente el patrón MVC.
Lo mismo es válido para el comportamiento de cualquier modelo. Si usara la arquitectura DCI y el comportamiento separado del modelo de datos, tendría que introducir objetos adicionales para mantener el comportamiento. Esto se haría introduciendo roles y contextos.
DCI == D ata C OLABORACIÓN I nteracciones
Por supuesto, los datos y el comportamiento del modelo podrían implementarse con objetos javascript simples o cualquier patrón de "clase". Pero, ¿cuál sería la forma AngularJS de hacerlo? ¿Utilizando servicios?
Entonces se trata de esta pregunta:
¿Cómo implementa modelos desacoplados del controlador, siguiendo las mejores prácticas de AngularJS?
fuente
Respuestas:
Debe usar los servicios si desea algo que puedan utilizar varios controladores. Aquí hay un simple ejemplo artificial:
fuente
Actualmente estoy probando este patrón, que, aunque no es DCI, proporciona un desacoplamiento clásico de servicio / modelo (con servicios para hablar con servicios web (también conocido como modelo CRUD) y un modelo que define las propiedades y métodos del objeto).
Tenga en cuenta que solo uso este patrón cuando el objeto modelo necesita métodos que funcionen por sí mismo propiedades, que probablemente usaré en todas partes (como getter / setters mejorados). Estoy no abogando haciendo esto para cada servicio de forma sistemática.
EDITAR: Solía pensar que este patrón iría en contra del mantra "El modelo angular es un simple objeto javascript antiguo", pero ahora me parece que este patrón está perfectamente bien.
EDITAR (2): para ser aún más claro, utilizo una clase de Modelo solo para factorizar getters / setters simples (por ejemplo: para usar en plantillas de vista). Para la lógica de las grandes empresas, recomiendo utilizar servicios separados que "conozcan" sobre el modelo, pero que se mantengan separados de ellos, y solo incluyan la lógica empresarial. Llámelo capa de servicio "experto en negocios" si lo desea
service / ElementServices.js (observe cómo se inyecta Element en la declaración)
model / Element.js (usando angularjs Factory, hecho para la creación de objetos)
fuente
La documentación de Angularjs establece claramente:
Entonces significa que depende de ti cómo declarar un modelo. Es un simple objeto Javascript.
Personalmente, no usaré Angular Services, ya que estaban destinados a comportarse como objetos únicos que puede usar, por ejemplo, para mantener estados globales en su aplicación.
fuente
DCI es un paradigma y, como tal, no hay una forma angular de hacerlo, ya sea que el lenguaje sea compatible con DCI o no. JS admite DCI bastante bien si está dispuesto a utilizar la transformación de origen y con algunos inconvenientes si no lo está. Una vez más, DCI no tiene más que ver con la inyección de dependencia de lo que dice una clase C # y definitivamente tampoco es un servicio. Entonces, la mejor manera de hacer DCI con angulusJS es hacer DCI a la manera de JS, que está bastante cerca de cómo se formula DCI en primer lugar. A menos que realice la transformación de origen, no podrá hacerlo por completo, ya que los métodos de rol formarán parte del objeto incluso fuera del contexto, pero ese es generalmente el problema con la DCI basada en inyección de métodos. Si miras fullOO.infoEn el sitio autorizado de DCI, puede echar un vistazo a las implementaciones de ruby que también usan el método de inyección o puede echar un vistazo aquí para obtener más información sobre DCI. Es principalmente con ejemplos de RUby, pero las cosas de DCI son agnósticas a eso. Una de las claves de DCI es que lo que hace el sistema está separado de lo que es el sistema. Por lo tanto, los objetos de datos son bastante tontos, pero una vez vinculados a un rol en un contexto, los métodos de rol ponen a disposición cierto comportamiento. Un rol es simplemente un identificador, nada más, y cuando se accede a un objeto a través de ese identificador, los métodos de rol están disponibles. No hay un objeto / clase de rol. Con la inyección de métodos, el alcance de los métodos de rol no es exactamente como se describe, sino cercano. Un ejemplo de un contexto en JS podría ser
fuente
Este artículo sobre modelos en AngularJS podría ayudar:
http://joelhooks.com/blog/2013/04/24/modeling-data-and-state-in-your-angularjs-application/
fuente
Como lo indican otros carteles, Angular no proporciona una clase base lista para usar para modelar, pero uno puede proporcionar varias funciones útiles:
Una biblioteca que hace todas estas cosas bien es ngActiveResource ( https://github.com/FacultyCreative/ngActiveResource ). Divulgación completa: escribí esta biblioteca y la he utilizado con éxito en la creación de varias aplicaciones a escala empresarial. Está bien probado y proporciona una API que debería ser familiar para los desarrolladores de Rails.
Mi equipo y yo seguimos desarrollando activamente esta biblioteca, y me encantaría ver que más desarrolladores de Angular contribuyan a ella y la prueben en batalla.
fuente
ngActiveResource
y el de Angular$resource
. Soy un poco nuevo en Angular, y rápidamente examiné ambos conjuntos de documentos, pero parecen ofrecer mucha superposición. ¿SengActiveResource
desarrolló antes de que el$resource
servicio estuviera disponible?Una pregunta anterior, pero creo que el tema es más relevante que nunca dada la nueva dirección de Angular 2.0. Yo diría que una mejor práctica es escribir código con la menor cantidad posible de dependencias en un marco particular. Solo use las partes específicas del marco donde agrega valor directo.
Actualmente parece que el servicio Angular es uno de los pocos conceptos que llegará a la próxima generación de Angular, por lo que probablemente sea inteligente seguir la directriz general de mover toda la lógica a los servicios. Sin embargo, diría que puede hacer modelos desacoplados incluso sin una dependencia directa de los servicios de Angular. Crear objetos autocontenidos con solo las dependencias y responsabilidades necesarias es probablemente el camino a seguir. También hace la vida mucho más fácil cuando se realizan pruebas automatizadas. La responsabilidad individual es un trabajo zumbido en estos días, ¡pero tiene mucho sentido!
Aquí hay un ejemplo de un patrón que considero bueno para desacoplar el modelo de objeto del dom.
http://www.syntaxsuccess.com/viewarticle/548ebac8ecdac75c8a09d58e
Un objetivo clave es estructurar su código de una manera que lo haga tan fácil de usar desde una prueba unitaria como desde una vista. Si logra eso, está bien posicionado para escribir pruebas realistas y útiles.
fuente
He tratado de abordar ese problema exacto en esta publicación de blog .
Básicamente, el mejor hogar para el modelado de datos es en servicios y fábricas. Sin embargo, dependiendo de cómo recupere sus datos y la complejidad de los comportamientos que necesita, hay muchas maneras diferentes de llevar a cabo la implementación. Angular actualmente no tiene una forma estándar o una mejor práctica.
La publicación cubre tres enfoques, usando $ http , $ resource y Restangular .
Aquí hay un código de ejemplo para cada uno, con un código personalizado
getResult()
método en el modelo de trabajo:Restangular (fácil de guisante):
$ resource (un poco más complicado):
$ http (hardcore):
La publicación del blog en sí entra en más detalles sobre el razonamiento detrás de por qué podría usar cada enfoque, así como ejemplos de código de cómo usar los modelos en sus controladores:
Modelos de datos AngularJS: $ http VS $ resource VS Restangular
Existe la posibilidad de que Angular 2.0 ofrezca una solución más sólida para el modelado de datos que haga que todos estén en la misma página.
fuente