terça-feira, 5 de maio de 2015

Eu e Arquitetura e Design de Aplicações


A minha experiência como desenvolvedor Java começou em fevereiro de 2011 em uma empresa que tinha a simplicidade e qualidade como principal valor, devido a simplicidade raramente (ou quase nunca) se utilizava frameworks, a menos que fosse extremamente necessário. Assim desenvolvi aplicações utilizando Java EE e seus poucos recursos:
  • Não utilizávamos um Servidor Web robusto, preferia-se alguma opção mais “leve” como o Tomcat, apenas algumas implementações como Servlet era o suficiente;
  • Não utilizávamos nenhum framework MVC (Struts, JSF ou Spring MVC)  apenas Servlets e JSP;
  • Não utilizávamos ORM - Object Relational Mapping (Implementações do JPA como Hibernate ou EclipseLink). Pool de Conexão e JDBC era padrão;
  • Não utilizávamos Inversão de Controle através de Injeção de Dependência (muito menos um framework como o Spring para tal), alias, no meu ponto de vista evitar a utilização de new era um absurdo e não fazia o menor sentido;
  • Não utilizávamos ferramentas de build como Ant ou Maven, na verdade o trabalho da IDE era mais que suficiente. Build nem era uma questão de debatida.

Talvez esse modelo funcionasse bem pois os projetos não passavam de 4 desenvolvedores, na sua maioria não era crítico para a operação do cliente. Hoje, analisando estes projetos, percebo que acabamos criando uma estrutura particular, uma mistura de MVC, REST e AJAX. Não implementamos todas por completo, mas parte delas.
  • Criamos um Servlet que controlava requisições à serviços via Reflection;
  • Tínhamos nossas views em JSP (Java Server Pages), me pergunto porque não HTML, já que utilizávamos massivamente Javascript/AJAX e nada de taglibs ou temidos scriptlets;
  • Os serviços, que chamávamos de REST, não obedecia todos os seus princípios como granularidade fina e utilização dos métodos HTTP corretamente;
  • O modelo (Model Business) não existia, os serviços criavam query SQL utilizando JDBC e ali mesmo era implementado a nossa regra de negócio, acredito que esse seja o pior erro, por isso existiam muitos serviços de granularidade grossa que executavam milhares de tarefas.
  • Não conhecia outra maneira de deploy a não ser um “grande” WAR utilizando a ferramenta administradora disponibilizada pelo servidor de aplicação.
  • Não explorávamos os recursos do sistema de controle de versão, já que não existiam muitos projetos concorrentes, uma branch para cada aplicação satisfazia as necessidades
  • Havia tarefas repetitivas, explorávamos pouco a Orientação a Objetos, a Alta Coesão e o Baixa Acoplamento não recebia muita atenção, mas era feita implicitamente. Porém, o fato do código ser muito legível e ser uma equipe extremamente inteligente e participativa ajudava na manutenção dos sistemas.
Existiu uma lição fundamental e importantíssima que levei desta experiência: Como a empresa tinha poucos funcionários, tive uma multidisciplinaridade absurda, participava de todo o ciclo de desenvolvimento do projeto, com pouca experiência e mesmo sem saber escolher as suas melhores ferramentas. Levantava requisitos, documentava, fazia a arquitetura e design do sistemas, pinçava algumas ideias de metodologias ágeis, criava e controlava o banco de dados, controlava prazo e escopo do projeto e suportava novos desenvolvedores na medida em que ia criando maturidade. E a melhor, tomei como valores pessoais a simplicidade e qualidade, juntamente com um olhar analítico para novas ferramentas e tecnologias.
Eu, influenciado pelos valores simplicidade e qualidade, sempre era muito crítico com relação a utilização de frameworks, buscava sempre evitar a complexidade que eles traziam para o desenvolvimento e preparação de ambiente para um novo desenvolvedor com suas inúmeras bibliotecas, configurações e implementações desconhecidas. Porém, aguçado por tantas ferramentas utilizadas do Java EE no mercado como EJB, Hibernate, CDI, Spring, Spring MVC, Spring Batch, SOA e tantas outras, era obcecado por encontrar alguma razão plausível para usá-las. Com esse entusiasmo acabei estudando estas ferramentas e buscando oportunidades em outras empresas em que eu pudesse usá-las de maneira coerente, afim de descobrir sua real necessidade.
Desde Agosto de 2014 trabalho em um sistema (conjunto de aplicações) que foi construído em 2006 e se mantêm em produção, participo de projetos de grandes manutenções evolutivas para que ele se adeque ao modelo de negócio de uma nomeada empresa no ramo de seguros. Este sistema é extremamente crítico, não pode parar por NADA, afetando diretamente a receita da empresa e a satisfação dos clientes. Neste projeto utilizamos diversos frameworks, me esforcei para compreender o motivo real de cada framework utilizado.
Para começar utilizamos um Servidor de Aplicação com inúmeros recursos, o WebSphere Application Server da IBM, exploramos seu mecanismo de cluster, com sua cell e nodes para garantir a disponibilidade e escalabilidade da aplicação. Para atingir este objetivo de maneira transparente é utilizado EJB 2 (Enterprise Java Bean 2), realizamos lookup dos Stateless Session Bean no que estiver disponível, desta forma compreendi melhor o conceito de aplicação distribuída N-tiers, que antes era nebuloso na minha ótica (é importante saber a diferença de tier e layer, será abordado em algum próximo artigo). Também há a tentativa frustada do sistema controlar as transações com EJB, o que não acontece devido o não conhecimento de prévios desenvolvedores.
Utilizamos também o famoso Hibernate 3, ainda sem a especificação da JPA (Java Persistence API), como sou apaixonado por SQL, prefiro sua utilização em vez de Criteria ou HQL. Neste caso a justificativa é devido a existência de muitas integrações entre sistemas, sempre precisamos executar o SQL para garantir que a consulta em Criteria ou HQL está correta, ou seja, é obrigação do desenvolvedor dominar SQL. Neste cenário a única vantagem com Criteria é no sentido de refatoração, mas neste trade-off prefiro utilizar SQL. Ainda pretendo utilizar Hibernate com toda sua capacidade de transformar um ResultSet em um objeto, seu mecanismo de busca lazy (que é adquirido através do Design Pattern Proxy) e sua capacidade de controlar transações associados a outros contextos da aplicação.
Utilizamos o framework MVC Struts 2, com seus Actions e Forms para a view, que na minha opinião só torna o código view mais ilegível, difícil manutenção e não performático. Temos pouco acesso ao HTML puro, utilizando várias taglibs criadas pela equipe de arquitetura da empresa, que sequer conhecemos o código e toda a rotina é executada no servidor que fica em overhead.
O EJB com os Stateless Session Bean também tem papel interessante, utilizamos eles como serviços, com as especificações JAX-RPC nos serviços mais antigos e JAX-WS para os mais atuais.
Recentemente os projetos foram migrados para utilização do Apache Maven, assim controlamos melhor as versões, dependências, build e deploy. O sistema de controle de versão (em inglês, Version Control System) também foi migrado do CVS (Current Version System) para RTC (Rational Team Concert). Antes dessas alterações tínhamos que controlar o build do projeto, uma tarefa bem mecânica, já que as aplicações view, business e database model são separados em 3 Enterprise ARchive (EAR) diferentes, era preciso gerar os EJB Clients, adicionar nas aplicações e gerar os EARs utilizando o RAD (Rational Application Developer). Agora o Maven e o RTC fazem essas tarefas de maneira integrada.
Por fim, utilizamos mensageria com JMS (Java Message Services) e WebSphere MQ Series para integração com outros sistemas legados da empresa de maneira assíncrona e até mesmo síncrona.
Recentemente encontrei um artigo sobre SOFEA (www.smart-soft.com/downloads/articles/sofea.html) que me fez comparar minhas duas experiências de Arquitetura e Design. Com estas duas resumidas experiências, percebo que, sem saber, inicialmente eu estava no caminho certo, bastava mais maturidade para encaixar as peças e utilizar somente o que é necessário. Mais importante que a utilização de frameworks é preciso assumir os principais conceitos e boas práticas em uma programação orientada a objetos como alta coesão, baixo acoplamento, separação de responsabilidades, granularidade de métodos/serviços e legibilidade. Desta forma é possível utilizá-los de maneira correta, não apenas adicionando complexidade desnecessária ao desenvolvimento e manutenção.

Nenhum comentário:

Postar um comentário