As empresas estão sempre buscando desenvolver novos produtos e serviços que possam atender as necessidades de seus clientes. Estamos vivendo em uma época de forte concorrência e mudanças constantes.

As tecnologias evoluem rapidamente permitindo que uma grande quantidade de produtos e serviços sejam disponibilizados diariamente no mercado. O consumidor final, diante de tantas possibilidades e ofertas, conta com diversas ferramentas para tomar a decisão de compra como, por exemplo, comparativos de preços e reviews na internet de outras pessoas que compraram ou utilizaram o serviço.

Para as empresas que criam, desenvolvem e implementam produtos e serviços esta evolução tecnológica gera um grande desafio: Quais caminhos seguir (metodologias, padrões e tecnologias) para que suas equipes possam desenvolver com qualidade, rapidez e com um menor custo gerando um produto/serviço que possa ser lançado no mercado antes que seus concorrentes o façam?

Seguindo nesta linha, este texto descreve de forma centralizada algumas tecnologias e padrões de desenvolvimento que podem ser utilizadas em conjunto no desenvolvimento de sistemas web buscando rapidez, qualidade, adaptação a mudanças e fácil manutenção.

Cada projeto requer uma análise criteriosa sobre quais tecnologias serão utilizadas no seu desenvolvimento, se você trabalha com sites pequenos, com algumas páginas, um pequeno blog com posts e comentários, por exemplo, utilizando apenas um framework MVC já seria o suficiente para um desenvolvimento rápido, porém se o seu sistema começar a crescer com a implementação de novos módulos e novas funcionalidades você certamente terá uma grande dor de cabeça para dar manutenção chegando ao ponto de se frustrar e desistir do projeto.

O que quero dizer é que sempre começamos projetos novos com entusiasmo, a utilização de um framework popular ou nosso próprio framework criado após anos de experiência. Tudo é pequeno e o desenvolvimento flui com rapidez onde vários CRUDs são implementados rapidamente. Com o passar do tempo por diversos motivos nosso sistema começar a ganhar corpo e de repente nos damos em conta de que temos vários trechos de códigos duplicados, misturamos a lógica do negócio com a interface do usuário e para cada correção geramos novos bugs.

Imagine que você precisa desenvolver um produto ou serviço. Alguns requisitos são apresentados e agora você sabe que o sistema deve:

  • Rodar em uma plataforma web;
  • Ser modular – os módulos possuem dependências e podem ser ativados/desativados a qualquer momento pelo cliente;
  • Atender diversos tipos de clientes;
  • Futuramente rodar em diversos aplicativos;
  • Futuramente pode se integrar a outros sistemas;
  • Ser integrado a um ERP que realiza a ativação, medição e cobrança dos clientes.

Pelo exemplo acima já podemos afirmar que não se trata de uma aplicação pequena, então definimos o nosso cenário. Temos um sistema complexo e que irá evoluir ao longo do tempo. Até este pondo já podemos descartar a utilização de um “simples MVC” como conhecemos, com os models que se comunicam com os controllers que por sua vez enviam informações para as views. Conforme já expliquei acima, com o tempo a manutenção seria desgastante e complexa.

Continuando com nosso exemplo, as tecnologias utilizadas para o desenvolvimento desta aplicação estão a seu critério. É sua responsabilidade definir como o sistema será desenvolvido.

Digamos que você é um programador ou analista de sistemas e com certeza (deveria) se preocupa com algumas características que a aplicação deveria ter antes de sair codificando. Citando alguns exemplos:

  • Deploy simples – controlar e subir novas versões para ambientes de testes e de produção deve ser simples sendo realizado com poucos comandos;
  • Facilidade de manutenção – correções e mudanças devem ser fáceis de realizar;
    • Base de código menor permitindo que novatos na equipe entendam o sistema rapidamente;
    • Reaproveitamento de código (de verdade) permitindo uma reutilização facilitando a manutenção e diminuindo duplicidade de código;
    • Implantação contínua e adaptável a mudanças;

Até este ponto temos em mente a complexidade do sistema e algumas características que queremos implementar no desenvolvimento. Antes de iniciarmos o projeto ou durante a análise já podemos definir algumas ferramentas que darão suporte ao desenvolvimento, seja por uma equipe ou apenas uma pessoa.

Controle de Versões

O controle de versões é essencial para manter todo histórico de desenvolvimento facilitando o trabalho em equipe e deploy em produção. No caso de falhas em produção, rapidamente é possível subir uma versão anterior do sistema para contornar a situação. Atualmente temos diversos repositórios gratuitos e pagos entre eles o Bitbucket, GitLab, GitHub, etc.

Para nosso projeto exemplo vamos utilizar o sistema de controle de versão GIT com as ferramentas disponíveis pela GitLab que possui uma versão free com repositórios ilimitados. Permite também repositórios privados onde o acesso é controlado e possui uma visualização gráfica dos branches muito útil quando se trabalha em equipe.

Bom de nada adianta utilizarmos um sistema de gerenciamento de versão se não utilizarmos boas práticas. O Git possui o Gitflow que é uma extensão do Git que permite uma maior agilidade e organização para trabalhar em equipes ou até mesmo sozinho. Para saber mais sobre isto acesse “Boas Práticas de Organização de Branches”.

Gitflow

Editor de Código

Existem vários editores de código disponíveis free e pagos, dentre eles podemos citar o Eclipse, NetBeans, Sublime, PhpStorm, etc.

Para o nosso exemplo vamos utilizar o editor eclipse que possui um plugin que integra com o Git onde podemos realizar todo o gerenciamento dos branches no próprio editor sem a necessidade de saber linhas de comando (o que às vezes pode fazer falta…).

Gitflow

Arquitetura de Sistemas

Até aqui já sabemos como vamos controlar o versionamento e qual ferramenta vamos utilizar para codificar.

Sobre a arquitetura de nosso exemplo poderíamos seguir dois caminhos. Criar um sistema com uma arquitetura monolítica ou baseado em microserviços.

Como ainda não temos nenhum cliente, não temos problemas de recursos e não temos a necessidade de enfrentar a complexidade de gerenciar microserviços, vamos seguir com uma arquitetura monolítica.

Frameworks

Para selecionarmos o framework sabemos que o sistema deve rodar na web, então vamos definir que a linguagem será PHP. Na “guerra” dos frameworks php podemos citar o Zend, Slim, CakePHP, yii2, CodeIgniter, Symfony, Laravel, etc.

Para seguir no nosso exemplo vamos utilizar o framework Laravel que possui como característica a simplicidade e principalmente uma curva de aprendizagem pequena (digamos que para se tornar um usuário avançado não é tão simples assim).

Com as informações que temos até o momento já podemos iniciar o desenvolvimento? Ainda não! Chegamos até a escolha do framework que vamos utilizar contando com todos os seus recursos, porém conforme apresentado no início deste texto falamos sobre os problemas de se desenvolver utilizando apenas os conceitos tradicionais do MVC. O “esqueleto“ do Laravel disponibilizado ao realizar a instalação via composer é uma sugestão de arquitetura. Este esqueleto nos condiciona a trabalhar com os tradicionais models, controllers e views. Conforme mencionei anteriormente para projetos pequenos sem perspectiva de crescimento isto não é um problema e provavelmente é o melhor caminho para se seguir no desenvolvimento. Mas este não é o nosso caso, pois já sabemos que nosso sistema é complexo e tende a crescer. Para atingir nosso objetivo precisamos aplicar Design Patterns que serão apresentados no próximo tópico.

DDD e Design Patterns

Podemos definir Design Patterns como técnicas e padrões para resolver problemas comuns no desenvolvimento de software com objetivo de facilitar e melhorar a comunicação entre os desenvolvedores. Estes padrões permitem o compartilhamento de conhecimentos sobre programação orientada a objetos. Por exemplo, temos um modelo que resolve um problema sendo que a solução proposta já foi utilizada e testada durante um tempo garantindo assim sua eficácia.

DDD – Domain-Driven Design significa Desenvolvimento Orientado a Domínio lançado por Erick Evans em 2003. Podemos conceituar DDD brevemente como uma série de técnicas e conceitos com foco no domínio do software, ou seja, foco nas regras de negócio. Existem diversos livros sobre DDD e artigos na internet que ajudam a entender melhor seus conceitos.

Para seguir no nosso exemplo, e não tornar o artigo mais extenso do que já está, vamos apenas citar padrões do DDD sem entrar em detalhes, conforme dito anteriormente a ideia deste artigo é centralizar conceitos de tecnologias, se você desejar se aprofundar pode buscar pelo Livro ou artigos mais específicos disponíveis na internet.

Vamos utilizar o DDD em partes e aplicar alguns de seus padrões a nossa equipe e ao nosso sistema.

  • Ubiquitous Language – Para se obter sucesso em um projeto DDD é necessário que todos os integrantes falem e entendam a mesma linguagem. Por exemplo, se o cliente chama pedido de venda de order, todos os envolvidos no projeto devem falar order quando se referem a pedidos de venda. Isto deve ser transmitido ao sistema onde uma função que retorna pedidos de venda deveria se chamar, por exemplo, getOrderByID.
  • Desenvolvimento em Camadas – seguindo os conceitos de DDD, o desenvolvimento de um sistema deverá ser desenvolvido em camadas conforme imagem abaixo:
Gitflow
  • Domain – representa o núcleo do negócio, as regras de negócio ficam na camada de domínio;
  • Infraestrutura – é responsável por fornecer suporte as demais camadas;
  • Application – é responsável pela comunicação entre o domínio e as camadas de entrada de dados;
  • User interface – é a camada responsável pela interface com o usuário, a entrada de dados.

Como mencionamos anteriormente não temos a pretensão de implantar o DDD por completo, então nossa sugestão de divisão de camadas utilizando laravel será um pouco diferente.

  • Domain
  • Support
  • Units (Aplicattion)

Esta estrutura foi proposta pelo codecasts no Laravel Conference Brazil e aborda diversos conceitos apresentados neste texto.

  • Repositórios – utilizando o conceito de repositórios separamos a comunicação com o banco de dados da lógica do sistema, desta forma controllers não acessam os models diretamente para recuperar dados e sim seus repositórios de forma desacoplada.
  • Factories – em alguns momentos criar instâncias de objetos se torna impossível sem a utilização de factories, para ir a fundo acesse “Factory Method in PHP”.

Fazendo um resumo do que foi apresentado nosso sistema teria uma arquitetura monolítica, seria desenvolvido em php utilizando framework Laravel com seu “esqueleto” alterado para se trabalhar com alguns conceitos de DDD, dentre eles linguagem ubíqua, desenvolvimento em camadas (proposto pelo codecasts), repositórios e factories.

Bom, se aplicarmos tudo isto teremos um sistema fácil de manter, com código reaproveitável e pronto para mudanças? A resposta é “depende” do quanto você vai se especializar e entender todos os padrões em envolvem o DDD ou até mesmo outros padrões. Quanto mais conhecimento você adquirir, mais “bagagem” você terá para escolher qual arquitetura vai usar, quais padrões e ferramentas. Realizar testes, entender como a estrutura do framework que você escolher funciona, refatorar seu projeto até que você perceba que todas estas ações estão gerando produtividade ao desenvolvimento. Infelizmente não existe uma receita pronta, cada projeto deve ser analisado com cautela. As tecnologias e design patterns estão aí para nos auxiliar no melhor caminho, cabe a você encontrá-lo!