Desenvolvimento

9 ago, 2017

Arquitetura de projetos Vue.js com DDD

Publicidade

Facilitando a manutenção, reuso e escala de projetos Vue.js com Domain Driven Design.

Arquitetura de projetos Vue.js com DDD

Muito se pergunta sobre quais as melhores práticas para criar projetos front-end, isso inclui projetos feitos com Vue.js. O assunto arquitetura por si só é bem extenso e complexo, decisões erradas podem ter consequências gigantescas durante o ciclo de desenvolvimento e manutenção.

Por que não MVC?

Antes muitos se apoiavam no modelo MVC, já que ele é (ou era) um sucesso no back-end, então nada mais lógico que importar para o front-end, certo?

Isso até funcionou por um tempo, em alguns projetos… porém ficou evidente que ele não é um bom modelo para o front-end.

Em 2012 começavam a surgir as primeiras especificações do Web Components. Muitas coisas aconteceram desde então. O propósito era criar “elementos reutilizáveis e intercambiáveis” , levando o reuso de código a novos patamares.

“O Advento React”

Com a popularização do React e ferramentas como Redux, o MVC perdeu muito espaço, dando origem a novas formas de criação de aplicações web. Porém, nenhuma nova arquitetura ou padrão foi estabelecido.

E quando falo arquitetura estou forçando um pouco o termo, pois estamos na verdade falando de estrutura de pastas. Não há, e talvez nunca haverá um consenso sobre como estruturar projetos com Web Components.

Abordagens diferentes para aplicações diferentes

Não importa o que digam, nenhum software é igual a outro, e muito menos existe um software que não quebre Design Patterns.

Vão existir aplicações que se contentam apenas com uma pasta components, outras que vão precisar mais do que isso. Acredito que quando há mais de um domínio, essa organização já não atenda mais.

O DOMÍNIO mencionado aqui vem de DDD (Domain-driven design ou Domain-driven development)

O básico de DDD

Existem vários artigos falando sobre DDD, nas mais diversas linguagens e aplicações, meu objetivo não é fazer você entender tudo sobre DDD, e sim sobre domínios.

Quem conhece o codecasts sabe que já abordamos esse assunto em uma série de vídeos gratuitos sobre modularização nativa com Laravel e na Laraconf Brasil 2016.

Um domínio, também pode ser conhecido como contexto ou assunto, ele não é necessariamente uma entidade, não cometa esse erro.

Entenda “domínios” como domínio de conhecimento de uma aplicação. Em uma aplicação de blog, teríamos Blog como um domínio, dentro dele teríamos as regras de negócio para interagir com posts, sejam repositórios, models, serviços… Post, comment e category são exemplos de models que estariam dentro de Blog.

Uma dica para identificar um domínio é quando há mais de uma entidade interagindo com ele.

No mesmo projeto também há o domínio Forum, com Question e Answer como models dele, porém Question interage com a entidade/model Category, logo Category também seria um domínio. Outro domínio do mesmo projeto seria Users, pois tanto Blog e Forum interagem com ele.

Um domínio pode depender de outros domínios, porém, domínios não representam “telas” ou rotas.

Espero poder me aprofundar mais nesse assunto em outro artigo.

I/O (Telas, Rotas…)

Domínio é onde ficam todas as regras de negócio da maneira mais agnóstica possível. Isso significa que um controller back-end ou um componente visual não podem ficar dentro dessa camada.

O código que fica presente no domínio não se importa com a origem dos argumentos ou comandos, o ideal é ele ser utilizável em qualquer ambiente. Como estamos falando de Vue.js, ou seja, estamos falando de JavaScript, o código que esta no domínio poderia ser executado tanto no node quanto no navegador.

Isso não é algo tão simples de se conseguir, nem sempre é possível, mas ter isso em mente garante uma boa manutenção e compatibilidade do código com futuras manutenções e atualizações.

A camada de I/O (Input/Output) fica separada dos domínios e totalmente dependente, podendo haver mais de uma dependência por tela. Justamente por isso é importante ela não se “misturar” com os domínios.

Support

O nome dessa camada já deixa claro seu objetivo. Nela ficam códigos de apoio (filters, mixins, plugins, componentes globais…). Em um projeto Vue.js quem mais depende dessa camada é a camada de I/O.

DDD em projetos com Vue.js

Essa explicação sobre DDD é bem rasa e superficial, porém é suficiente para entender a arquitetura que vou propor aqui. Muitos elementos do DDD foram ignorados, por não serem interessantes ou até mesmo viáveis em projetos front-end.

Como eu disse antes, cada projeto é um projeto diferente, o modelo que eu uso deve ser usado como ponto de partida para você criar um modelo que te atenda. O importante é se manter coeso na sua organização.

Em um projeto SPA completo com Vue.js você vai acabar usando Vue.js, Vue Router e Vuex, além de uma biblioteca de http, que provavelmente será o axios. Partiremos desse pré-suposto.

Overview

Abaixo segue um modelo da organização proposta. Este modelo se baseia no template webpack do vue-cli, a pasta components foi removida e as pastas app, domains e support foram criadas

src/
- app/ :: rotas e componentes das rotas, apenas lógica de exibição
-- home/
-- articles/ :: grupo de rotas, não expressa um domínio diretamente
--- components/ :: componentes das rotas
--- routes.js :: expõe um array de rotas
-- categories/
-- questions/
-- panel/
--- users/
-- routes.js :: importa as rotas de cada grupo, e expõe um array
-- index.js :: expõe um objeto com as rotas ({ routes: [] }) 
- domains/ :: Domínios da aplicação, regras de negócio, serviços...
-- auth/ 
--- services/ 
--- vuex-module/ :: Um domínio pode possuir um módulo do vuex
-- blog/
--- services/
-- forum/
--- services/
- support/ :: Camada de apoio, tanto app quanto domains podem usar
-- http/ 
--- resouces/ 
---- make.js
---- plugin.js
---- index.js
--- interceptors.js
--- client.js
--- index.js
-- c3/ :: Esta camada pode conter componentes, plugins, helpers...
--- chart.vue
--- index.js
-- common/
--- components/
- router/ 
-- routes.js :: Importa e expõe as rotas de src/app
-- index.js :: Expõe o router normalmente
- store/ :: cria o store baseado nos módulos e plugins da aplicação
- assets/
- static/
- root.vue :: Componente root da aplicação
- main.js :: Junta todas as peças e inicia a aplicação

Tirando proveito do template webpack do vue-cli é possível criar alias que apontam para app, domains e support, facilitando o uso em toda a aplicação.

Ponto de partida

Este é apenas um modelo genérico, criado como ponto de partida para que você pense no seu modelo, e em como resolver as necessidades do seu projeto.

Há vários detalhes de implementação que não puderam ser citados neste artigo, porém espero em breve criar um exemplo prático e comentado que sirva de start para novos projetos.

Ficou com alguma dúvida? Gostou do artigo? Não deixe de comentar, seu feedback é muito importante.