Servicios vs. Fábricas en Angular

EDIT 2016. Tened en cuenta que este post, que es un repost de un post de 2015, es sobre Angular 1. Ya no hago frontend así que no hay garantías de que este post sea relevante para Angular 2 ;).

Uno de mis compañeros de Hack Reactor y yo construimos recientemente una calculadora de tratamiento de la presión arterial alta para Moxe Health, una emocionante empresa de Rock Health que está construyendo un sistema de integración de bases de datos y una API que permitirá a cualquier desarrollador acceder a los registros médicos electrónicos de cualquier hospital de la red de Moxe. Estoy emocionado de hablar sobre Moxe y el proyecto en otro post. Construimos el front-end de la aplicación en Angular, un potente framework de front-end con data binding y otras características impresionantes. Una cosa que fue confusa fue cuando usar servicios vs. fábricas. Stack Overflow tiene un buen hilo sobre la diferencia entre los dos, pero deja fuera algunas analogías que creo que son útiles para los desarrolladores que aún están consolidando sus conocimientos de Javascript.

En este post, vas a aprender la diferencia entre los dos.

TLDR – las fábricas y los servicios tienen más o menos la misma funcionalidad en términos de su capacidad para instanciar y encapsular métodos y propiedades, al igual que la instanciación funcional y los patrones de instanciación pseudoclásicos tienen habilidades similares. No hay preferencia en la comunidad de Angular por usar uno u otro. Las recetas de fábrica y servicio son sólo azúcar sintáctico sobre la receta de proveedor. Así que la pregunta que deberías hacerte no suele ser «¿debería usar fábricas o servicios?» es «¿debería usar instanciación funcional o instanciación pseudoclásica?»

Aparte de esa comprensión de alto nivel, la diferencia más significativa es que, como resultado de la diferencia en sus patrones de instanciación, las fábricas pueden devolver primitivas y funciones, pero los servicios no pueden.

Primitivas, funciones y objetos, ¡oh Dios!

Mira este JSFiddle. Crédito a Epokk para proporcionar la mayor parte del código. Hice un par de modificaciones que, de nuevo, realmente ayudan a los desarrolladores nuevos en Angular a profundizar en la diferencia aquí. Si eres nuevo en JSFiddle, es una herramienta que te permite probar fácilmente las interacciones entre tus archivos javascript, html y css. Así que puedes jugar con el código, y no sobrescribirá el código original en el enlace.

Tanto el servicio como la fábrica en este ejemplo tienen la misma funcionalidad de devolver la cadena «¡Hola Mundo!». La diferencia es cómo lo hacen.

El servicio instala un objeto y asigna la función que devuelve «¡Hola Mundo!» a la propiedad «sayHello» de ese objeto:

this.sayHello = function() { return "Hello, World!" };

El método se invoca entonces en el controlador: helloWorldFromService.sayHello().

La fábrica devuelve una función que retorna «¡Hola Mundo!»:

return function() { return "Hello, World!" };

La función es entonces invocada en el controlador: helloWorldFromFactory(). Observa cómo la referencia de la fábrica apunta a la función devuelta, en lugar de a la propiedad de un objeto cuyo valor es una función, como en el ejemplo del servicio. Un servicio nunca podría hacer esto, porque un servicio debe instanciar un objeto vacío cuya referencia dentro del cuerpo de la función de servicio es ‘this’. Los servicios siempre devuelven objetos.

Aquí está la parte de las fábricas que puede ser confusa. La fábrica también puede devolver un objeto que tiene un método ‘sayHello’, muy parecido al del servicio:

return { sayHello: function() { return "Hello, World!" } };

Que invocarías en el controlador exactamente como invocarías la función sayHello del servicio: helloWorldFromFactory.sayHello().

Este último formato de fábrica es útil cuando quieres tener múltiples métodos en una fábrica:

return { sayHello: function() { return "Hello, World!" }, sayGoodbye: function() { return "Goodbye, World!" } };

De nuevo, la clave aquí es no dejarse llevar por el hecho de que estás codificando en Angular, y recordar que las diferencias entre los servicios y las fábricas son en su mayor parte las mismas que las diferencias entre la instanciación pseudoclásica y la instanciación funcional.

Código fuente para los curiosos

Aquí está el código fuente de Angular, demostrando que las fábricas de servicios & se superponen a la función más general de proveedores:

//provider function provider(name, provider_) { assertNotHasOwnProperty(name, 'service'); if (isFunction(provider_) || isArray(provider_)) { provider_ = providerInjector.instantiate(provider_); } if (!provider_.$get) { throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name); } return providerCache = provider_; } //factory function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); } //service function service(name, constructor) { return factory(name, ); }

Tanto los servicios como las fábricas crean singletons. Patrones básicos de herencia funcional vs. pseudoclásica aquí. La fábrica devuelve lo que el factoryFn devuelve.

El servicio devuelve una instancia de una pseudoclase. El constructor de la pseudoclase se pasa al constructor de servicios de Angular service(). El hecho de que el constructor se pase al servicio del constructor de servicios (return $injector.instantiate(constructor)) puede ser confuso, pero piensa en ello como return new constructor().

¡Feliz codificación!

Leave a Reply