# Vue.js: injetando serviços em componentes de forma transparente

> # Você provavelmente já viu alguns exemplos de aplicações utilizando Vue e já deve ter percebido que (atualmente em meados de 2018) ele ainda passa por uma fase de fragmentação quanto ao uso da ferramenta onde vários grupos tem várias arquiteturas sendo aplicadas e testadas.

Esta situação é um pouco desconfortável para alguns, mas ela espelha um momento cada vez mais comum no desenvolvimento web: POSSIBILIDADES.

É muito provável que se você perguntar a cada arquiteto de cada estrutura visitada ele tenha partido de alguma experiência anterior pela qual passou e tenha organizado sua estrutura porque a que vinha usando o deixou na mão ou não escalou nesta ou naquela situação.
Conosco não é muito diferente. Nosso caso era realmente a preocupação com a flexibilidade e rapidez.
Precisávamos de estruturas que fossem criadas rapidamente e que fossem simples de serem atualizadas, sem ter que abrir centenas de arquivos para aplicar mudanças; esse era nosso desafio.
> Disclaimer: o conteúdo do artigo são apenas sugestões de coisas que usamos no nosso dia-a-dia, fique à vontade para concordar e/ou discordar, aproveitando as experiências da forma que melhor lhe convir.

## Serviços

Nos contextos de arquitetura de software o termo serviço refere-se a uma funcionalidade ou um conjunto de funcionalidades de software com um propósito que pode ser reutilizado em diferentes ocasiões. Geralmente associamos os acessos à recursos HTTP ao nome Service, mas nem sempre usamos uma estrutura dedicada à isso para cada domínio da nossa aplicação, o que, particularmente se tornou um problema.
> # Devemos ter cuidado ao usar recursos como `this.$http.get('/api/v1/products')` dentro da nossa aplicação, pois estamos pulverizando uma camada lógica importante por toda a aplicação.

Vou deixar um link abaixo como referência para construções de serviços, caso queira se aprofundar um pouco mais sobre o tema (e ainda não conheça):
[**Vue.js: Trabalhando com Serviços**
*Serviços são parte fundamental em aplicações elaboradas, não importa o ambiente. Veja como trabalhar com eles no Vue.js*blog.codecasts.com.br](https://blog.codecasts.com.br/vue-js-e-servicos-4d4439320a2)

## Mantendo Contratos

Para quem está acostumado com linguagens onde a **Orientação a Objeto** possui suporte à recursos como interfaces, métodos abstratos, enum, entre outros, o javascript se torna um pouco assustador por não entregar esse tipo de composição. Contudo, isso não é exatamente um problema quando você organiza a sua aplicação porque essa chamada falta de rigidez pode ser compensada de outras formas para forçar que alguns caminhos não sejam seguidos. Vou deixar o link abaixo com algumas dicas de composição de serviços:
[**Vue.js Brasil - *Artigos em Português sobre Vue.js***
Artigos em Português sobre Vue.jsvuejs-brasil.com.br](http://vuejs-brasil.com.br/vue-js-ajax-patterns/)

### Criando Serviços Extensíveis

Para poder seguir com este material apresentaremos uma solução simples para criar um ***Service*** que pode ser estendido e usado nos domínios das entidades com as quais estão lidando. A seguir será apresentada uma lista de documentos e a respectiva explicação sobre o que representa cada um deles.

### A estrutura


### src/main.js

Um pequeno exemplo de uso de como o serviço será usado. Ele importa o *service* de *Product* e constrói uma instância para poder executar o método `read` e imprimir a saída;


### src/domains/Product/Service/Product.js

A especialização do serviço *Api* para ser usado no escopo da entidade *Product*;


### src/service/Api.js

Serviço para consumo de API’s que entrega 4 métodos básicos para realizar o que é costumeiramente chamado de CRUD;


### src/service/Service.js

Contrato básico para a *factory* de instâncias do *Service*;


### src/service/helper.js

Apenas uma função `fake` para simular o delay da troca de contexto de da manipulação dos dados.


A saída exibida nesse caso é algo parecida com a imagem abaixo.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1617062665101/n8xVIdo1i.png)

Com o que fora apresentado até aqui não é difícil perceber que podemos usar essa estrutura para representar diversas estratégias de API’s porque não está fechado o que o nosso serviço consome. Essa deve ser a visão do componente acerca do *service*: conhecer o contrato e não a implementação.
> # Embora o Javascript não tenha estruturas “formais” para contratos, é possível criar padrões para que a codificação componha esses contratos de forma orgânica

Se quiser se aprofundar em abordagens de gestão de *services* pode dar uma olhada nessa dica de artigo (que recebi do [Vinicius Reis](https://twitter.com/LuizVinicius73)) onde é explorado a níveis bem profundos o uso do serviço como um modelo da entidade totalmente isolado da apresentação do componente.
[**How not to suffer with APIs**
*Rethinking Apicase and why I still never used axios*itnext.io](https://itnext.io/how-not-to-suffer-with-apis-8aa75f890fe6)

## Lidando com Componentes

Bom, se o serviço agora é uma estrutura totalmente segmentada do meu componente, como posso fazer uso desse recurso dentro do componente? A resposta dessa pergunta também é uma pergunta: quão flexível será seu componente e quão dinâmica será sua estrutura?

### Importando serviços para o meu componente

Essa estratégia é bem simples e consiste basicamente em usar os módulos javascript para usar o *service* dentro do escopo do seu componente.


Se precisar de uma estratégia mais eficiente de distribuir o service, pode usar um plugin para manipular o estado dele dentro do componente. Seguindo essa abordagem teríamos o ***ProductTable.vue***:


E teríamos uma modificação no protótipo do **Vue** através do **src/service/Plugin.js**:


Com esta segunda abordagem, mesmo que algum desenvolvedor sem querer faça algo como `this.$service = null`, a resposta do **Vue** será contundente:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1617062666681/ke1LYdbFr.png)

Com a implementação do *plugin* feita dessa forma o *service* é passado para o componente e o então ele “descobre” se este é um item das opções do construtor da instância do **Vue** ou se é uma *prop* do componente, entregando um elemento, que como vimos acima, é imutável; o que nos leva a próxima abordagem: passar os serviços via *props*.

### Utilizando serviços como props

No ecossistema do **Vue** (na verdade é um conceito um pouco mais abrangente que isso) uma *prop* é um estado que é passado para um componente. Se não estiver recordando muito bem como funcionam essas propriedades dos componentes recomendo fazer uma visita no link abaixo antes de continuar.
[**Props - Vue.js**
*This page assumes you've already read the Components Basics. Read that first if you are new to components. HTML…*vuejs.org](https://vuejs.org/v2/guide/components-props.html)

Com a leitura em dia será fácil compreender que usando *props* tenho a capacidade de passar parâmetros para meus componentes sem ter que deliberadamente deixar esse parâmetro “hard-coded” dentro dele.

Para receber uma *prop* dentro de um componente é preciso declarar essa necessidade. O resultado é semelhante ao exemplo a seguir:


O que implicaria em um caso de uso semelhante à `&lt;ProductTable v-bind:service="service"/&gt;`.

Embora essa abordagem não seja ruim, ela possui alguns pontos que devem ser observados. Entre as situações que não me deixam confortável temos a questão de usar um estado do componente (uma propriedade no data) para abrigar o serviço que será mapeado à *prop*, e a necessidade imperativa de ter que criar um arquivo `.vue` para cada rota implementada.

### Usando o Router para injetar dependência

Durante a construção de app’s mais robustos geralmente usamos um *router*. O **Vue Router** é uma ferramenta que faz parte do ecossistema do **Vue** e nos permite criar rotas para nossos componentes. Ele tem suporte à informar as *props* que serão usadas para montar o componente e isto é descrito no trecho abaixo da documentação.
[**Passing Props to Route Components · vue-router**
*const User = { props: ['id'], template: ' User {{ id }} ' } const router = new VueRouter({ routes: [ { path…*router.vuejs.org](https://router.vuejs.org/en/essentials/passing-props.html)

No caso do nosso exemplo, vamos explorar o [function mode](https://router.vuejs.org/en/essentials/passing-props.html#function-mode) onde as *props* serão geradas por uma função que recebe a rota carregada como parâmetro. Com o *service* sendo uma *prop* poderemos passá-lo por parâmetro através da rota onde seu componente será montado.

Como podemos ver no exemplo abaixo, será possível combinar as duas abordagens no seu projeto. Poderemos usar um mesmo componente recebendo o **service** por *props* ou através de *$options*, *template*, *render* ou *route* porque o acesso ao ***$service*** será transparente para o componente.


## Conclusão

O **Vue** é muito flexível e deixa à cargo da sua capacidade de manipulação do Javascript a criação do ecossistema em que o componente está inserido. Tenha sempre cuidado para escolher abordagens que te permitam escalar a sua aplicação de forma mais objetiva possível pesquisando e estudando o máximo que puder antes de começar a escrever seus códigos.
Ademais, você pode começar a fazer uso dessas metodologias para fazer seus *requests* sem que seu componente perceba que algo mudou.
> # Isolar o comportamento dos serviços é uma boa pedida em tempos onde estão surgindo opções interessantes para manipulação de dados, como o [GraphQL](https://graphql.org).

Fique à vontade para enviar suas dúvidas, sugestões e/ou elogios. Para falar mais sobre [**VueJS](https://vuejs.org)** fique ligado na comunidade e em todo o seu ecossistema : )
[**Vue.js Brasil - *Artigos em Português sobre Vue.js***
Artigos em Português sobre Vue.jsvuejs-brasil.com.br](http://vuejs-brasil.com.br)
[**vuejs-br/comunidades**
*comunidades - Comunidades Vue.js ao redor do Brasil*github.com](https://github.com/vuejs-br/comunidades)

Ah, já ia esquecendo, segue o link do repositório e fica a dica para seguir os commits que será possível ver a evolução da mesma forma que a estrutura foi evoluindo nos artigos.
[**wilcorrea/transparent-services**
*Contribute to transparent-services development by creating an account on GitHub.*github.com](https://github.com/wilcorrea/transparent-services)
