Nesse artigo, iremos explicar o que é arquitetura de software e também como aplicar o padrão que utilizamos nos nossos projetos.
O que é arquitetura de software?
Você já deve ter pegado um projeto que não é intuitivo saber onde ele inicia e nem onde termina ou que o nome dos arquivos são simplesmente FONTE01, FONTE02, etc. Isso a longo prazo pode prejudicar e muito uma empresa, pois quando chegar o momento de fazer uma manutenção e/ou uma melhoria, demandará muito tempo para entender e melhorar esse projeto. Não precisa se assustar, pois a melhor forma de evitar esse possível problema é adaptar o seu projeto a uma arquitetura, seja ela própria ou comunitária (lembre-se de que há uma infinidade delas). Sendo assim, podemos definir a "Arquitetura de Software" como um conceito abstrato, que se refere à organização de um sistema. Ela é responsável por definir os componentes que farão parte de um projeto, suas características, funções e como devem interagir entre si e com outros softwares. Como já citamos anteriormente, não existe um funcionamento básico ou padrão de tecnologia. Há formas infinitas de aplicar e atender aos diversos problemas existentes.
Padrão G-Works
Algumas linguagens e frameworks possuem um padrão de projeto já definido que deve ser seguido, por exemplo, C# e Angular, que em sua essência já define um padrão de desenvolvimento, porém, na linguagem ADVPL não possuímos essa restrição. Até o surgimento do TLPP não existia outro caminho a não ser programação estruturada (Toda a lógica em um único arquivo) o que tornava comum fontes de 5 mil linhas e deixava a manutenção e o entendimento do projeto extremamente cansativo e maçante. Vendo esse cenário e visando a facilidade e a descomplicação de novos projetos, a Gworks começou a absorver o que tinha de melhor e mais simples em outras arquiteturas e construiu um padrão de projeto cujo objetivo é ser…
Simples
A organização e nomenclatura das pastas já indica a responsabilidade de cada contexto presente no projeto.
Autoexplicativa
Facilidade de aprendizado e de entendimento do projeto e contextos.
Estrutura bem organizada.
Escalabilidade
Fácil implementação de novos recursos e melhorias.
Facilidade na atualização de um service que se tornará legado.
Independência
A definição de responsabilidade facilita nos testes unitários e manutenção, já que podem ser chamados de qualquer lugar.
Baseando-se no que há de melhor
Absorvemos diversas características de outras arquiteturas e design de projeto para construir um único padrão de projeto simples e prático, dentre nossas inspirações, temos:
Design DDD
Cada contexto possui suas responsabilidades claramente definidas, que por sua vez podem ter sua própria linguagem ubíqua.
MVC (Model - View - Controller)
Divisão da aplicação em três camadas: camada de interação do usuário (View) camada de manipulação dos dados (Model) camada de controle (Controller).
Clean Architecture
Quanto mais ao centro, mais abstrata ela deve ser, ou seja, os códigos nas camadas internas não precisam ter conhecimento necessariamente das funções nas camadas externas. Os níveis mais internos não podem mencionar as variáveis, funções e classes que existem nas camadas externas.
Organização
Nossos projetos consistem na seguinte organização:
App
Inicio de toda aplicação.
Porta de entrada que o usuário tem para acessar os processos do projeto.
Não é recomendado ser chamado internamente por outro fonte.
O intuito dela é ser usada somente no Menu principal da aplicação, outras chamadas devem chamar diretamente o Controller.
Não possui regra de negócio, apenas chama o Controller.
Controller
Ponte entre o usuário/desenvolvedor e a camada de negócio (Service).
É por ele que todas as chamadas devem ser feitas, tornando assim fácil a troca de implementação de um determinado Service.
Service
Seguindo a regra do DDD, é a camada que vai cuidar das operações segmentadas, ou seja, nela vamos ter todas as receitas da nossa aplicação.
Camada responsável por cumprir o seu dever com o auxílio das camadas mais internas (Functions e DAO).
A service não pode ter uma função de job, o ideal é ela fazer um único processamento e o job separar os itens e enviar um por um para serem processados pelo Service.
Functions
Funções genéricas e diretas do projeto.
Aqui ficam funções que não podem ter muita regra de negócio, elas podem ou não receber um parâmetro, mas o processamento delas deve ser curto e direto e devem retornar algo.
Exemplos
Formatar data.
Montar JSON a partir de um registro no banco de dados.
Regras e validações sobre um determinado assunto.
Dao
Funções destinadas a consultas ao banco, queryes, posicionamento de várias tabelas ao mesmo tempo, e busca de registros.
Também utilizada para operações de criação, atualização ou remoção de um registro na tabela.
Job (Opcional)
Funções destinadas a processamentos automáticos, ou seja, o job vai juntar uma série de dados e enviar um por um para um service específico tratar (É por isso que os services devem ser feitos para serem chamados de qualquer lugar, apenas precisando de um ponto de partida).
Não é necessário um processamento de vários dados, pode ser somente um prepare environment e uma chamada ao service.
É semelhante à pasta APP, onde o JOB é a porta de entrada interna para o próprio sistema, enquanto a APP é a porta de entrada para o usuário.
Classes (Opcional)
Classes de mapeamento ou de uma série de operações que precisa estar em um único lugar (Objetos, métodos).
Pode, em alguns casos, substituir a pasta Service.
É importante ressaltar que as camadas internas não acessam as camadas superiores, ou seja, uma Function ou DAO não precisa saber quem está chamando ela ou o que vai acontecer depois, ela precisa receber uma tarefa, cumprir e encerrar seu processo, não tendo permissão para chamar um Service, Controller ou Job.
Regras de nomenclatura
Possuímos também uma série de regras que facilitam a leitura de variáveis e arquivos do projeto, por exemplo ao nomear um arquivo do nosso projeto, utilizamos a seguinte regra: NOME DO PROJETO + ASSUNTO ou VERBO + PASTA PERTENCENTE, sempre com as letras iniciais em caixa alta.
Exemplo: Possuímos um projeto chamado “Integração Nota Fiscal”, podemos supor alguns casos que podem existir.
Service
IntegracaoNotaFiscalEnviarNfService.tlpp
IntegracaoNotaFiscalEstornarNfService.tlpp
Functions
IntegracaoNotaFiscalGenericFunctions.tlpp
IntegracaoNotaFiscalMontarJsonFunctions.tlpp
Essas regras podem parecer desnecessárias e confusas, mas essa nomenclatura pode ajudar muito a análise em casos de bug ou novas implementações.
Também seguimos um padrão específico para nomear variáveis, qual desenvolvedor protheus nunca pegou aquela variável no meio do fonte e nunca descobriu de onde ela vem, ela está lá, mas não se sabe sua origem e se você definir ela como local… bye bye projeto, rsrs. Visando corrigir e evitar esse tipo de confusão, criamos o seguinte padrão:
Variaveis Locais
Segue o padrão normal
Local cMinhaVar
Variaveis Privadas
Nome da variavel seguida de 1 (um) underline
Private cMinhaVar_
Variaveis Estáticas
Nome da variavel seguida de 2 (dois) underlines__
Static cMinhaVar__
Variaveis Publicas
Nome da variavel seguida de 3 (três) underlines
Public cMinhaVar___
Outras recomendações
Sempre tente deixar seus services independentes, podendo chamar eles de qualquer lugar, assim, aproveitando ao máximo sua implementação e evitando duplicidade de código.
Os jobs não precisam se preocupar com muitas regras em si, precisam apenas filtrar o que vai ser processado e enviar essas informações para o service e deixar com que o ele cuide da tratativa desses itens.
Não sobrecarregue o seu service com muitas regras, ainda no exemplo de enviar o pedido de venda, não é prudente que no job de envio, seja realizado uma operação de estorno de pedido, geração de nota, etc. Ao invés disso pode-se segmentar essa operação em outros services e chamar-los quando necessário;
Não sobrecarregar uma function com regras de negócio, isso pode transformar ela em um service, então se sua Function tem a função de transformar uma data YYYYMMDD em DD-MM-YYYY HH: MM ela deve fazer somente isso e nada mais.
Finalização
Se as regras citadas aqui forem seguidas corretamente a manutenção, entendimento e evolução da sua aplicação vão se tornar algo natural, simples e descomplicado. Espero que esse artigo tenha te ajudado a organizar o teu projeto, lembre-se, qualquer dúvida ou recomendação será bem-vinda nos comentários e não esqueça de deixar sua curtida, isso nos ajuda a criar novos artigos.
Comments