Introdução à Arquitetura e Design de Software Uma visão sobre a plataforma Java
Paulo Silveira, Guilherme Silveira, Sérgio Lopes, Guilherme Moreira, Nico Steppat, Fabio KungArquitetura Java
"A nossa avó Céres"
"A minha esposa, meus pais e meu irmão"
"A meus pais e esposa"
"A meus amados pais"
"A minha amada esposa e família"
Agradecimentos
Depois de dois anos ministrando o curso de Arquitetura e Design na Caelum, além de cinco anos com um blog de mais de duzentos artigos técnicos, parecia fácil escrever sobre um assunto que faz parte do nosso dia a dia.
Terrível engano.
Em vez dos seis meses previstos, passaram-se dois anos. Dois anos trabalhando de forma a tornar acessível práticas e trade-offs que aparecem com frequência na plataforma. São problemas que os desenvolvedores passam a enfrentar rapidamente ao ganhar mais experiência e familiaridade com Java.
Juntar esse conhecimento não seria possível sem a existência do GUJ.com.br, criado em 2002, no qual os usuários já trocaram mais de um milhão de mensagens. Nós, autores, participamos ativamente do fórum, o qual não atingiria essa magnitude sem a ajuda do Rafael Steil.
Também não seria possível organizar essas ideias sem a colaboração de diversos amigos que as revisaram e discutiram os temas conosco: Lucas Cavalcanti, David Paniz, Cecilia Fernandes, Alberto Souza, Bruno de Oliveira, Fábio Pimentel, Vinicius Roberto e Adalberto Zanata.
Agradecemos aos que participaram e participam da elaboração do curso FJ-91 na Caelum: Adriano de Almeida, Anderson Leite, José Donizetti e Douglas Campos.
Uma especial menção ao Maurício Aniche, que, além de realizar uma minuciosa revisão, nos incentivou a todo momento a melhorar o texto e a cortar o que não fosse essencial para o livro.
Sobre os autores
Paulo Silveira é bacharel e mestre em ciência da computação pela USP e cofundador da Caelum. Possui experiência com desenvolvimento web na Alemanha, passando pelo IBOPE e por dois anos como instrutor da Sun Microsystems. É um dos fundadores do GUJ.com.br, editor técnico da revista MundoJ e criador do VRaptor.
Guilherme Silveira é líder técnico e cofundador da Caelum. Trabalhou com Java e Tibco na Alemanha, comitter do XStream e criador do Restfulie. Concentra seus estudos em serviços REST. Programador experiente, participou das finais mundiais de programação no Japão e no Canadá do ICPC pelo time da USP e é arquiteto Java certificado (SCEA5).
Sérgio Lopes é coordenador na unidade São Paulo da Caelum. Programa desde 2000 e desenvolve em Java desde 2003. É arquiteto Java certificado (SCEA5), moderador do GUJ e participante ativo da comunidade através de palestras, projetos, cursos e artigos.
Guilherme Moreira é instrutor e consultor pela Caelum, onde foca seu trabalho principalmente com Java desde 2005, com projetos internos e também diretamente nos clientes. Formado em Processamento de Dados pela FATEC-SP e arquiteto Java certificado (SCEA 5), escreve artigos para a revista MundoJ, além de ser responsável pela unidade de Brasília da Caelum.
Nico Steppat é engenheiro de computação aplicada pela Fachhochschule Brandenburg. É instrutor, consultor e desenvolvedor há sete anos com Java no Brasil e na Alemanha. Atua na unidade Rio de Janeiro da Caelum e é arquiteto Java certificado (SCEA 5).
Fabio Kung é engenheiro da computação pela Escola Politécnica da USP. Passou por web, Java, Ruby, experiência na Alemanha, instrutor na Caelum, responsável na Locaweb por Cloud Computing e no Heroku em São Francisco. É arquiteto Java certificado (SCEA 5).
Prefácio
Por Jim Webber.
O Arquiteto
Quando penso sobre o termo "arquiteto", é sempre com sentimentos confusos, como suspeito que seja o caso para muitos de nós que trabalham com desenvolvimento de software atualmente. Durante minha carreira, ouvi diversas opiniões diferentes para esse termo, mas, para mim, o que é principal para ser um bom arquiteto posso buscar dos meus primeiros dias como desenvolvedor profissional (ou tentando ser um profissional).
Meu primeiro emprego parecia ser intimidador - após diversos anos de pesquisa acadêmica dentro de um departamento de ciência de computação em uma universidade, entrei em uma empresa que havia comprado recentemente uma startup de middleware Java gerenciada por um grupo de amigos. Esses amigos trabalhavam no ramo de middleware por décadas e "hackeavam" em Java até mesmo antes de ele ter esse nome. Sair da zona de conforto da computação de alto desempenho, com tecnologias as quais eu estava acostumado, e pular para um domínio novo de processamento de transações distribuídas com foco em CORBA e J2EE era realmente intimidador. Apesar de ter um senso razoável de teoria de sistemas distribuídos, eu jamais havia escrito CORBA ou J2EE como usuário, muito menos como desenvolvedor de middleware. Foram tempos complicados.
No laboratório onde comecei a trabalhar, meus colegas ostentavam nomes de cargos baseados em suas capacidades (e, suspeito, longevidade!). Possuíamos engenheiros, engenheiros seniores e arquitetos, todos os quais trabalhavam arduamente em desenvolver um excelente middleware de transação, workflow e mensageria. Como um engenheiro sênior, eu era um pouco menos verde do que os apenas engenheiros, mas ambos recebíamos ordens dos arquitetos - um por time - que eram oráculos. Os arquitetos que lideravam nosso time conheciam o código de trás para a frente, mas também conheciam seus campos. Era sempre possível confiar que seriam capazes de explicar modelos de transação distribuída complexos e mostrar como diversos padrões e abstrações do código os suportavam. Eles também conheciam as armadilhas e conseguiam detectar cedo escolhas de design e implementação ruins, uma vez que eram capazes de ver à frente, ou pelo menos ver mais longe do que eu conseguia.
Não acho que disse algum dia para esses arquitetos - talvez por causa do meu orgulho juvenil - o quão importante eles foram em delinear meu pensamento e comportamento. Entretanto, sempre aspirei (e algumas vezes sucedi) ser como eles, conhecer a tecnologia profundamente, entender o contexto no qual ela está sendo empregada, guiar e ser guiado pelos colegas de meu time. Essa foi uma aspiração que levei para meu próximo emprego em uma empresa global muito conhecida e admirada no ramo de consultoria de TI.
Ao entrar em minha nova empresa, decidi que já havia visto bastante software e era bom o suficiente em escrever código, e então me declarei um arquiteto. Ao encontrar alguns de meus novos colegas pela primeira vez, fui calorosamente recebido e perguntado sobre qual seria meu papel. Respondi que eu era um arquiteto; algo que pensei que daria um sentido de competência no nível micro da pilha de tecnologias, e no nível macro ao redor da construção de sistemas. Fiquei atônito ao descobrir que fui repreendido por essa resposta e fiquei me perguntando o que acabara de acontecer, afinal, eu não havia entrado para trabalhar com essas pessoas devido a reputação que eles possuíam no desenvolvimento de software e Agile?
Não demorou muito para que eu entendesse o contexto. Meus colegas trabalhavam com consultoria há alguns anos e conheceram muitos "arquitetos experientes". Mas esses não eram o mesmo tipo de pessoa que eu admirava em meu primeiro trabalho; eram arquitetos perigosamente ultrapassados, com pouca habilidade em entregar software, e um talento sem fim para causar confusão e criar políticas corporativas. E eu, aparentemente, tinha me apresentado como um desses. Não era a melhor maneira de causar uma boa impressão aos meus novos colegas.
Ainda assim, durante os 6 anos e nos 10 países em que trabalhei, me descrevi como arquiteto. Eu estava em uma missão de recuperar o valor desse título, e com o passar do tempo obtive algum sucesso. Começamos a pensar em um arquiteto não só como o "melhor programador" ou um "peso morto", mas sim como um papel que considera os detalhes de nível macro em um time que entrega software - como a integração com outros sistemas funcionará, como falhas e recuperações serão trabalhadas, como a vazão será medida e garantida.
Nos melhores projetos em que trabalhei, o papel do arquiteto era complementar ao dos stakeholders. Enquanto o pessoal de negócios prioriza a entrega de funcionalidades, arquitetos priorizam os requisitos não funcionais e ajudam a ordenar a entrega de requerimentos funcionais que minimizam e mantêm características não funcionais. Nos melhores projetos que trabalhei, eu não era o melhor programador da equipe, nem na maior parte das vezes tinha o maior conhecimento das linguagens, ferramentas e frameworks comparado com outros dedicados programadores. Após um tempo engolindo o orgulho, comecei a ver as vantagens inerentes disso.
Como arquiteto, ainda sou alguém que também entende bastante de código, em um nível no qual consigo escrever código com outros programadores (possivelmente melhores do que eu) e ler seu código e testes. Acredito que isso seja fundamental para a arquitetura. Sem a habilidade de se envolver com o código, arquitetos não têm como determinar como sua arquitetura foi adotada por uma solução, nem como eles têm uma maneira direta de pegar feedback de sua arquitetura para melhorá-la. Sem habilidades de software, um arquiteto fica refém dos times de desenvolvimento, o que é um overhead, não um benefício.
Sentado aqui em minha mesa, em Londres, escrevendo esse prefácio, é claro que a noção do conceito de arquiteto continua cinzenta. Até mesmo hoje, arquitetos estão frequentemente no topo da torre de marfim, descrevendo visões grandiosas e impraticáveis através de slides e diagramas UML que não ajudam para tropas nas trincheiras obedecerem como escravos (como se eles fossem!). Mas não precisa ser assim. Aqueles de nós que se preocupam com a melhoria contínua do ramo e se preocupam em escrever código cada vez melhor com os efeitos colaterais positivos que isso pode resultar em nossa sociedade e comunidade têm o dever de tomar o termo "arquiteto" e reapropriar-se dele.
Este livro é um passo nessa direção. Ele trata arquitetos como profissionais do desenvolvimento de software e é fundamental que eles entendam as ferramentas comuns do ramo de desenvolvimento de software. Este livro provê insights nas ferramentas comuns, padrões de desenvolvimento e práticas de design que arquitetos contemporâneos trabalhando em aplicações corporativas possuem. Ele trata de uma gama de disciplinas de desenvolvimento desde código robusto, design de aplicação, dados e integração, que são os principais elementos da maior parte dos sistemas corporativos. Ele não apenas foca em importantes detalhes da linguagem e dos principais frameworks, mas também no nível macro, dando uma percepção mais completa - percepção esta que um arquiteto praticante precisa quando ajuda a guiar um time para o sucesso.
À medida que desenvolvedores procuram se tornar arquitetos, o livro mostra que o foco estreito na última linguagem ou framework da moda é necessário, mas não suficiente. À medida que arquitetos buscam reabilitação, este livro deixa óbvio que não há sucesso sem reaprender as (habilmente demonstradas) ferramentas de construção de software. Enquanto nenhum livro pode torná-lo um arquiteto da noite para o dia, este provê ao menos um modelo do tipo de arquiteto que eu tanto admirava, e espero que sua leitura o inspire a se tornar esse tipo de arquiteto também.
Jim Webber é formado em computação e possui doutorado pela University of Newcastle. Trabalhou por bastante tempo na ThoughtWorks, onde ficou conhecido pelo seu manifesto Guerrilla SOA. Hoje, é Chief Scientist na Neo Technology, empresa por trás do banco de dados orientado a grafos Neo4j
Introdução
Implementação, design ou arquitetura?
Desenhar sistemas é uma tarefa difícil. E, ainda fazer com que sejam escaláveis e performáticos, mantendo uma alta qualidade interna e externa, é um desafio.
No artigo "A importância de ser fechado", Craig Larman diz que "você deve enfrentar suas batalhas de design, sejam elas no nível macroarquitetural ou no humilde campo das instâncias" *. Essas batalhas devem ser contra decisões que atrapalham o crescimento e a futura modificação da sua aplicação, diminuindo o custo de manutenção a longo prazo.
Mas é difícil definir com precisão o que são instâncias ou nível macroarquitetural, as linhas que separam arquitetura, design e implementação são muito tênues. Martin Fowler fala o mesmo no âmbito de patterns logo na segunda página de seu livro"Patterns of Enterprise Application Architecture: "Alguns dos padrões neste livro podem ser chamados arquiteturais, já que representam decisões importantes sobre essas partes; outros são mais sobre design e o ajudam a implementar essa arquitetura. Não faço nenhuma forte tentativa de separar esses dois, uma vez que aquilo que é arquitetural ou não é subjetivo". * Fowler questiona inclusive o uso do termo arquiteto como papel. * A universidade de Carnegie Mellon possui diversas definições e também aborda a grande dificuldade que é definir a diferença exata entre implementação, design e arquitetura. *, *
Neste livro, em vez de encontrar respostas e soluções encaixotadas, apresentaremos perguntas e discussões relacionadas a alguns dos principais tópicos recorrentes em aplicações escritas para a plataforma Java, a fim de alimentar o espírito crítico do desenvolvedor. Ele deve ser capaz de enxergar ambas, as vantagens e as desvantagens; todo o trade-off presente em suas decisões.
Dominar uma plataforma, seus principais frameworks e seu funcionamento interno é essencial para que os responsáveis pelo desenvolvimento de uma aplicação conheçam não só as vantagens, mas também as desvantagens de suas decisões. O desenvolvedor que acredita não existir ou desconhece o lado negativo para determinada abordagem sofrerá as consequências de manutenção quando as mesmas surgirem dentro da aplicação.
Com o passar do tempo, a implementação ou o design ou a arquitetura deixará de atender às necessidades dos clientes. Nesse instante, é necessário evoluir esse aspecto defasado, para que volte a ser suficientemente adequado para aquela realidade do sistema.
Como Joel Spolsky afirma, "pessoas de todo o mundo estão constantemente criando aplicações Web usando .NET, Java e PHP. Nenhuma delas está falhando por causa da escolha da tecnologia". Mas ele vai além, ao dizer que "todos esses ambientes são grandes e complexos, e você realmente precisa de, no mínimo, uma pessoa com enorme experiência de desenvolvimento na plataforma escolhida, porque, caso contrário, você tomará decisões erradas e acabará com um código muito confuso que precisa ser reestruturado". Joel deixa explícita a necessidade de profundo conhecimento técnico da plataforma escolhida.
Fowler ainda complementa que, diferentemente da engenharia civil, onde há uma divisão clara de habilidades entre quem faz o design e quem faz a construção, com software é diferente. Qualquer desenvolvedor que venha a lidar com decisões de alto nível necessita de um forte conhecimento técnico. Este livro foi elaborado com essa visão: o sucesso da arquitetura de um sistema está fortemente ligado com o design e a implementação.
Levando em consideração essa visão, este livro destina-se àquele que aspira por um papel de arquiteto? Quem seria o arquiteto? O papel do arquiteto é amplamente discutido e, na nossa visão, o arquiteto precisa conhecer profundamente a plataforma, além de ser um excelente e experiente desenvolvedor.
Nas palavras de Martin Fowler, "o termo arquitetura envolve a noção dos principais elementos do sistema, as peças que são difíceis de mudar. Uma fundação na qual o resto precisa ser construído".
Podemos ir além e dizer que essa fundação que constitui a arquitetura, que envolve os principais elementos do sistema, pode sim ser evolutiva e sofrer modificações com o tempo, desde que seu design e implementação permitam, quebrando um pouco a ideia de que o trio arquitetura-design-implementação forme um modelo estritamente piramidal. Este livro abordará muitas questões de design e implementação com o intuito de demonstrar essa possibilidade evolutiva.
A imagem de um arquiteto distante do dia a dia do desenvolvimento da equipe, sem profundo conhecimento técnico e de implementação sobre a ferramenta, que apenas toma as grandes decisões e despacha ordens e diagramas, há muito tempo está defasada. Mais do que querer ser o isolado arquiteto que apenas despacha ordens, cada vez mais enxergamos que o caminho é ser o líder incentivador da tomada de decisão, além de um exímio desenvolvedor. Parafraseando mais uma vez Martin Fowler, "(...) o arquiteto deve ser como um guia (...) que é um experiente e capacitado membro da equipe que ensina aos outros se virar melhor, e ainda assim está sempre lá para as partes mais complicadas". * E Larman também não perdoa o arquiteto que não vê código: "um arquiteto que não está a par da evolução do código do produto, não está conectado com a realidade", chegando a considerar que o código é o verdadeiro design ou arquitetura do software.
É impossível "mudar" uma arquitetura ou um design diretamente, uma vez que ambos são interpretações do único bem existente: a implementação. Através da mudança na implementação, adquire-se as características arquiteturais ou de design desejadas. Arquitetura e design são interpretações, visões, leituras críticas de uma implementação (Figura *).
Design é uma forma de interpretar a implementação, analisando e compreendendo as interações entre determinadas partes do sistema, como possíveis impactos que uma mudança em um ponto causa em outro componente que o acessa direta ou indiretamente. Existem diversas interfaces de comunicação entre diversos componentes: o Apache se comunica com o Jetty através do mod_jk; uma aplicação Web se comunica com o Jetty através da Servlet API; já dentro do domínio da aplicação, outras interfaces conectam partes de uma implementação, como uma List
, um Calendar
, um DAO
ou uma Connection
. Todas elas são analisadas no aspecto de design (Figura *).
Implementação não significa somente o código escrito pelos desenvolvedores da equipe atual, mas também o conjunto de escolhas de ferramentas, versões que fazem parte dos ambientes de desenvolvimento, homologação e produção, linguagem utilizada, legibilidade do código, entre outras. Todas essas escolhas modelam a implementação de um sistema, assim como sua qualidade (Figura *).
Arquitetura é ainda uma outra maneira de ver a implementação, analisando e compreendendo como uma mudança em determinado ponto do sistema afeta o sistema inteiro, e de todas as maneiras possíveis. Por exemplo, caso um ponto qualquer da aplicação passe a ter acesso remoto ao invés de apenas local, isso pode afetar uma outra ponta da aplicação, deixando-a mais lenta. Esse tipo de análise não costuma ser feita quando se pensa no design, já que o design tem uma preocupação mais local. A essa visão mais global do sistema, é dado o nome de arquitetura (Figura *).
Com o passar do tempo, como design e arquitetura são diferentes maneiras de interpretar a implementação, é através de uma mudança na implementação que obtém-se as mudanças desejadas na visão de design ou na visão de arquitetura (Figura *).
Uma boa implementação, design ou arquitetura é aquela que permite modificações causando somente um impacto considerado justo a outras partes do sistema, e, ao mesmo tempo, diminuindo as ocorrências de tais situações, minimizando o custo de desenvolvimento e manutenção.
É essa visão de arquitetura e design que tentamos obter neste livro. A plataforma Java é vista com profundidade e suas peculiaridades, desde o campo das instâncias, interfaces e da JVM, até o nível macroarquitetural de layers, tiers e frameworks. A implementação terá papel fundamental aqui, e sua importância é realçada mesmo em discussões arquiteturais de alto nível.
Colhemos nossa experiência ao longo de nove anos de discussões nos fóruns do GUJ.com.br, cinco ministrando o curso de Arquitetura e Design Java na Caelum, além de diversos projetos, consultorias e experiências trocadas com os clientes e parceiros. Conhecer profundamente as ferramentas é o primeiro passo para poder fazer as perguntas corretas ao enfrentar o cenário de uma nova aplicação.
Sumário
- 1 - A plataforma Java
- 1.1 - Java como plataforma, além da linguagem
- 1.2 - Especificações ajudam ou atrapalham?
- 1.3 - Use a linguagem certa para cada problema
- 2 - Java Virtual Machine
- 2.1 - Princípios de garbage collection
- 2.2 - Não dependa do gerenciamento de memória
- 2.3 - JIT Compiler: compilação em tempo de execução
- 2.4 - Carregamento de classes e classloader hell
- 3 - Tópicos de Orientação a Objetos
- 3.1 - Programe voltado à interface, não à implementação
- 3.2 - Componha comportamentos
- 3.3 - Evite herança, favoreça composição
- 3.4 - Favoreça imutabilidade e simplicidade
- 3.5 - Cuidado com o modelo anêmico
- 3.6 - Considere Domain-Driven Design
- 4 - Separação de responsabilidades
- 4.1 - Obtenha baixo acoplamento e alta coesão
- 4.2 - Gerencie suas dependências através de injeção
- 4.3 - Considere usar um framework de Injeção de Dependências
- 4.4 - Fábricas e o mito do baixo acoplamento
- 4.5 - Proxies dinâmicas e geração de bytecodes
- 5 - Testes e automação
- 5.1 - Testes de sistema e aceitação
- 5.2 - Teste de unidade, TDD e design de código
- 5.3 - Testando a integração entre sistemas
- 5.4 - Feedback através de integração contínua
- 6 - Decisões arquiteturais
- 6.1 - Dividindo em camadas: tiers e layers
- 6.2 - Desenvolvimento Web MVC: Actions ou Componentes?
- 6.3 - Domine sua ferramenta de mapeamento objeto relacional
- 6.4 - Distribuição de objetos
- 6.5 - Comunicação assíncrona
- 6.6 - Arquitetura contemporânea e o Cloud
- 7 - Integração de sistemas na Web e REST
- 7.1 - Princípios de integração de sistemas na Web
- 7.2 - Padronizações, contratos rígidos e SOAP
- 7.3 - Evite quebrar compatibilidade em seus serviços
- 7.4 - Princípios do SOA
- 7.5 - REST: arquitetura distribuída baseada em hipermídia
Dados do produto
- Número de páginas:
- 355
- ISBN:
- 978-85-35250-29-9
- Data publicação:
- 01/2013