Você está na página 1de 25

See discussions, stats, and author profiles for this publication at: https://www.researchgate.

net/publication/324493041

Fundamentos de Engenharia de Software para o Desenvolvimento de Software


como Serviço através do uso de Metodologias Ágeis

Chapter · September 2012

CITATIONS READS

0 1,890

5 authors, including:

Regis Pires Magalhaes Francisco José Lins Magalhães


Universidade Federal do Ceará Universidade Federal do Ceará
29 PUBLICATIONS   71 CITATIONS    6 PUBLICATIONS   2 CITATIONS   

SEE PROFILE SEE PROFILE

Necio de Lima Veras Thalisson Oliveira


Instituto Federal de Educação, Ciência e Tecnologia do Ceará Universidade Federal do Ceará
10 PUBLICATIONS   6 CITATIONS    5 PUBLICATIONS   2 CITATIONS   

SEE PROFILE SEE PROFILE

Some of the authors of this publication are also working on these related projects:

SMA-Hermes View project

Graphast View project

All content following this page was uploaded by Regis Pires Magalhaes on 13 April 2018.

The user has requested enhancement of the downloaded file.


Capítulo

Fundamentos de Engenharia de Software para


o Desenvolvimento de Software como Serviço
através do uso de Metodologias Ágeis

Regis Pires Magalhães, Francisco José Lins Magalhães, Nécio de Lima


Veras, Thalisson Alves Oliveira e Polyanna Carvalho Moreira

Abstract
This chapter covers methodologies, languages, tools and artifacts carefully chosen
to motivate students to exercise best practices in software development, supported by
Software Engineering and Agile Methodologies to the construction of Software as a
Service (SaaS). Concepts related to software architecture, testing, modularity and reuse
are presented in theory and practice through analysis of a web application built for
teaching purposes using Java language and Play Framework.
Resumo
Este capítulo aborda metodologias, linguagens, ferramentas e artefatos
cuidadosamente selecionados para motivar os alunos a exercerem as melhores
práticas de desenvolvimento de software, apoiadas na Engenharia de Software e em
Metodologias Ágeis para a construção de Software como Serviço (SaaS). Conceitos
relacionados à arquitetura de software, testes, modularidade e reuso são apresentados
de forma teórica e prática através da análise de uma aplicação web construída para
fins didáticos usando a linguagem Java e o Play Framework.
1.1. Introdução

Sistemas computacionais estão presentes em toda parte no nosso cotidiano, desde


nossos telefones até quando estamos em um voo entre continentes. Por meio do uso
da internet, podemos complementar que os sistemas computacionais são acessíveis de
qualquer lugar. Observando esse cenário é imperativo que esses sistemas possuam a
qualidade intrínseca à sua importância. Nesse contexto, podemos fomentar a Engenharia
de Software, que é uma disciplina da engenharia, cuja meta é o desenvolvimento de
sistemas de software com boa relação custo benefício [Sommerville 2003].

A Engenharia de Software incorpora o conceito de Processos de Softwares, que


está relacionado com práticas e artefatos para nortear o desenvolvimento de software
com qualidade. Mas, geralmente esses processos (e. g. modelo em cascata e RUP) são
muito onerosos, podendo elevar muito o tempo de finalização de um sistema. Esse
fato abre lugar para as metodologias ágeis de desenvolvimento de software, pois estas
pregam o desenvolvimento e entrega de pequenas partes do sistema com o incremento
gradual das funcionalidades. O SCRUM representa uma dessas metodologias.

Retornando ao fato dos sistemas serem acessíveis de todo lugar, desde a


popularização da internet, existe uma convergência do desenvolvimento de software
para este ambiente. Em meio a esse panorama, surge a computação em nuvem
(Cloud Computing). Algumas empresas possuem uma poderosa infraestrutura de
servidores e disponibilizam alguns serviços acessíveis através da internet. As principais
classificações de serviços em nuvem são IaaS, PaaS e SaaS (Infrastructure as a Service,
Plataform as a Service e Software as a Service, respectivamente).

Na indústria de software moderna demanda-se o desenvolvimento de sistemas


em menos tempo e com qualidade superior. Vislumbrando atender essas exigências
podemos utilizar métodos ágeis para liberar versões de um software em menor tempo,
focando em testes automatizados para ajudar na garantia da qualidade. Podemos
também fazer uso de um leque de ferramentas que podem ajudar na execução do
método ágil (e.g. ferramentas para controle de versão, IDE’s1 e frameworks de
desenvolvimento). No âmbito dos sistemas web, temos a oportunidade de utilizar
arquiteturas maduras como MVC (Model-View-Controller) e fazer implantação
(deployment) das aplicações diretamente na nuvem.

Nas seções posteriores serão detalhados alguns pontos acima citados, como
processos de desenvolvimento, testes de software, SaaS, arquitetura MVC e computação
em nuvem. Além disso, serão abordados conteúdos relativos à utilização de sistemas de
controle de versão no processo de desenvolvimento de software e também implantação
na infraestrutura de nuvem.

1.2. Processos de Desenvolvimento


Qualquer projeto é formado por processos e estes são constituídos de atividades que,
fazendo uso de ferramentas, técnicas e artefatos, são executados de forma organizada
e/ou sincronizada. Um projeto é caracterizado por um tempo de vida finito e pela

1 Integrated Development Environment. Uma IDE facilita o desenvolvimento de um projeto de software.


produção de um produto ou serviço. Existem produtos que são facilmente visualizados
antes mesmo de sua construção, pois são quantificáveis, de escopo exato e incertezas
mínimas como, por exemplo, construções prediais. Essa definição não representa o
desenvolvimento de um software. É exatamente o contrário, pois este tipo de produto é
intangível, de escopo com altas taxas de variações e incertezas constantes. Assim, um
software por surgir de ideias conceituais, reajustáveis e não possuir recursos físicos, seu
escopo pode variar, provocando mudanças sérias durante sua construção e dificultando
sua visualização final. Esse fato de poder existir um grande número de possíveis estados
torna o software um produto extremamente complexo, dificultando a elaboração de seu
projeto de forma a atender todos os requisitos de qualidade e de controle total sobre os
possíveis erros. Mas como obter um produto de software com qualidade diante de todas
estas peculiaridades?
Percebeu-se a necessidade de inclusão da disciplina de engenharia no
desenvolvimento de software, pois com ela é possível que um gerente fortaleça práticas
de gerenciamento para obtenção de um produto com alta qualidade. A Engenharia de
Software aborda as formas de desenvolvimento e engloba três elementos fundamentais:
métodos, ferramentas e procedimentos. Os métodos estão relacionados a um conjunto
de tarefas que incluem planejamento, estimativas, projeto, codificação, testes e
manutenção de sistemas. As ferramentas oferecem apoio aos envolvidos nos projeto e
os procedimentos constituem a ligação entre os outros dois. Com isso, esses conjuntos
de etapas são compreendidos como paradigmas da engenharia de software [Pressman
2005].
Um processo geral é um conjunto de passos parcialmente ordenados,
constituídos por atividades, métodos, práticas e transformações com o objetivo de
atingir alguma meta, detalhando: produto, etapas, agentes, insumos e resultados. Em
processos que envolvem desenvolvimento de software podem ser definidas as seguintes
atividades: desenvolvimento, manutenção, aquisição e contratação de software, além
de também poderem existir subprocessos para cada um destes. Por exemplo, um
processo de desenvolvimento abrange determinação dos requisitos, análise, desenho,
implementação e testes [Paula Filho 2006].
Dessa forma, os processos para construção de um software são como conjunto
de passos que irão trabalhar de forma ampla definições, desenvolvimento e manutenção.
Existem diversos destes conjuntos que formam diferentes estratégias de abordagem e
são denominados também de Modelos de Ciclo de Vida de Software [Pressman 2005].
Com isso abordaremos neste contexto os ciclos de vida de Waterfall, Espiral e Ágil.
O modelo de Waterfall também conhecido como ciclo de vida clássico ou, ainda,
modelo cascata, prega uma filosofia de sequência onde uma fase deve ser completa
antes do início da próxima removendo assim muitos erros o mais cedo possível.
É esperado nesta abordagem uma extensa documentação em cada fase para que
informações importantes não sejam perdidas, caso um membro do projeto desmembre
a equipe. Assim como também se uma nova pessoa for adicionada ao time, então esta
poderá rapidamente participar de forma efetiva.
Figura 1. Visão geral do modelo Waterfall [Pressman 2005].
O fluxo ilustrado pela figura 1 mostra as fases sequenciais previstas pelo modelo
Waterfall. A longevidade do software é reconhecida pela fase de manutenção que repara
os erros na medida em que são descobertos. Futuras versões do software são feitas
usando as mesmas fases e consomem normalmente um prazo entre seis e dezoito meses.
Este modelo pode funcionar bem quando usado com tarefas bem definidas como, por
exemplo, voos espaciais da NASA, mas se torna problemático quando os clientes não
possuem uma definição clara do que eles precisam [Fox e Patterson 2012].
Observou-se que esse problema é minimizado quando os clientes conseguem
entender o que eles querem por meio da visualização de um protótipo e, ao mesmo
tempo, os engenheiros entendem melhor como construir, uma vez que eles fizeram
isso com a primeira interação com o cliente. Essa observação combinou protótipos de
software com o modelo Waterfall e a ideia foi repetir uma sequência de quatro fases,
onde cada uma resultaria em um protótipo mais aprimorado em relação à versão anterior
[Boehm 1986 apud Fox e Patterson 2012]. Este modelo de ciclo de vida ganhou a
denominação de Modelo Espiral.
O Modelo Espiral é composto por quatro fases. A figura 2 ilustra como este
ciclo de vida combina os modelos Waterfall e Prototipação. O processo se inicia no
centro, com cada iteração ao redor da espiral executando as quatro fases e gerando
como resultado um protótipo revisado. Isso se repete até que o produto esteja pronto
para ser liberado ou lançado.
Figura 2. Modelo Espiral [Fox e Patterson 2012].
Este modelo ao invés de produzir um documento com toda a documentação do
projeto, constrói os documentos de requisitos, fundamentais para a evolução do projeto,
por meio de cada iteração conforme as necessidades. Vale ressaltar que uma iteração
envolve o cliente antes do produto ser finalizado, e isso reduz consideravelmente
as chances de erros na concepção do sistema. Como as iterações demoram
presumidamente entre seis e vinte e quatro meses, o cliente tem tempo hábil para pensar
em novas ideias e isso seria um problema sério, pois os planejamentos deveriam ser
revisados para transformar as novas sugestões em recursos do sistema.
Ambos os modelos foram elencados porque envolvem um longo período de
tempo e um volume muito grande de documentação e planejamento, bem como, fases
maiores ainda emergindo o termo Big Design Up Front (BDUF). O desenvolvimento
de software com a abordagem BDUF reflete que o planejamento é completado e
aperfeiçoado antes mesmo de iniciar a codificação, o que praticamente inviabiliza uma
mudança brusca de escopo [Fox e Patterson 2012].
Um grupo de desenvolvedores de software em fevereiro de 2001, chamado de
Agile Alliance, começou a descobrir maneiras melhores e mais leves de desenvolver
software, valorizando principalmente, pessoas e interações ao invés de processos
e ferramentas, softwares funcionando no lugar de documentações abrangentes,
colaborações com clientes do que negociações de contratos e respostas à mudanças por
planos fechados. Esses valores deram origem ao Manifesto Ágil e possui ainda doze
princípios que regem a filosofia de criar softwares com agilidade [Beck 2001].
Este modelo alternativo de desenvolvimento é baseado em mudanças
abrangentes, como por exemplo um fato da vida. O desenvolvedor deve melhorar
continuamente um protótipo incompleto, até que o cliente fique feliz com o resultado
e, como o cliente oferecerá feedback a cada iteração, então a possibilidade de mal
entendidos é consideravelmente reduzida. O modelo enfatiza algumas práticas para
reduzir erros e aumentar a produtividade, tais como: Test-Driven Development (TDD),
User Stories e Velocity. Contrastando com os outros dois modelo citados, o ciclo de
vida Ágil é tão rápido que novas versões são disponibilizadas ao cliente a cada duas
semanas e novos recursos são adicionados continuamente ao mesmo protótipo até que o
cliente esteja satisfeito [Fox e Patterson 2012].
1.3. Arquitetura Orientada a Serviço (SOA – Service Oriented Architecture)
SOA é uma arquitetura de software onde todos os componentes são projetados para
virarem serviços. Atualmente significa que os componentes de uma aplicação devem
atuar como serviços interoperáveis e podem ser usados de forma independente e/ou
recombinados com outras aplicações. Uma implementação que contrasta com isso é
considerada um “software silo” e raramente possui uma API (Application Programming
Interface) para seus componentes internos. Uma consequência do uso destes tipos de
softwares são os custos para correção de erros, pois estes são muito menores em um
aplicativo com SOA do que em um “software silo” [Fox e Patterson 2012].
Formada por componentes disponibilizados por meio de interfaces genéricas e
protocolos padronizados, a SOA deve ser o mais independente possível dos sistemas
que a consomem e de seu núcleo técnico de desenvolvimento, promovendo assim
a reutilização e o aproveitamento de suas funcionalidades já existentes. Contudo,
devemos ter muito cuidado para não confundir esta arquitetura com outras ideias que
possuem certa semelhança, como por exemplo web services e padrões abertos para
protocolos de comunicação e documentação [Serman 2010].
A Amazon iniciou em 1995 um site de varejo online como um software silo. Em
meados de 2002 foi divulgado um e-mail enviado na época à todos os funcionários com
as seguintes observações:
● Todos os times deverão expor seus dados e funcionalidades através de interfaces
de serviços.
● Os times devem obrigatoriamente comunicar-se uns com os outros por meio
desta interface.
● Lá não será permitido outra forma de comunicação. A única permitida é serviço
de chamada de interface sob a rede.
● Não importa qual tecnologia será usada: HTTP, CORBA, PUBSUC, Protocolos
personalizados, etc.
● Todos os serviços de interface, sem exceção, devem ser projetos para um
ambiente externalizável. Isso quer dizer que o time deve planejar e projetar de
forma que seja possível expor as interfaces para desenvolvedores do outro lado
do mundo. Sem exceções.
● Quem não fizer isso será demitido.
● Obrigado. Tenham um ótimo dia!
Este texto evidencia a necessidade da empresa em criar e usar serviços de rede
para trocar informações. Em 2007, três anos depois da empresa colocar o produto
online, surgiu um revolucionário software similar, o Facebook Plataform. Apoiado na
SOA esta plataforma permite aos desenvolvedores criar aplicativos que interajam com
o núcleo de funcionalidades do Facebook e extrair informações tais como: o que as
pessoas gostam, quem são os seus amigos, quem está marcando suas fotos, entre outras.
No mesmo contexto de redes sociais e, um exemplo contrastante, o Google+ usando um
software silo foi lançado sem o uso de uma API própria. No entanto, três meses depois
o produto foi atualizado com uma API bem mais poderosa, harmonizando com o que os
usuários da marca Google estão habituados a usarem [Fox e Patterson 2012].
Objetivando um entendimento mais apurado sobre SOA, imagine um exemplo
no qual iremos construir um serviço de uma livraria que irá conter três subsistemas:
comentários (reviews), perfil de usuário (user profile) e, obviamente, compras (buying).
A figura 3 mostra a arquitetura para um software silo.

Figura 3. Modelo de software silo para serviços de uma livraria [Fox e Patterson 2012].
O silo forma internamente subsistemas que podem compartilhar acessos a
dados diretamente nos diferentes subsistemas. Perceba que todos os subsistemas
estão contidos em uma API externa única. Com isso, o subsistema de comentários
pode acessar informações fora do seu contexto de forma direta, como por exemplo no
subsistema de perfis de usuários.
Já a figura 4 exibe o mesmo sistema, mas agora com a versão SOA, onde todos
os subsistemas são separadas e independentes.

Figura 4. Modelo SOA para serviços de uma livraria [Fox e Patterson 2012].
Notamos agora que se o subsistema de comentários necessitar de informações de
um usuário, então ele não poderá recuperá-la diretamente na base de dados dos usuários
e para isso ele deverá usar o serviço da API. Essa é exatamente a diferença crítica
entre os dois modos. Notamos com isso que a SOA possibilita várias fatias verticais
com diversas camadas e cada uma das fatias está conectada por meio de serviços,
proporcionando bastante reusabilidade.

1.4. Computação em Nuvem


SOA está nos fundamentos dos serviços providos através de computação em nuvem e é
importante ter isso sempre em mente durante a implementação desses serviços, a fim de
maximizar o aproveitamento dos seus benefícios.
A computação em nuvem provê a infra-estrutura computacional escalável e
confiável de hardware e de armazenamento, que deve necessariamente ser constituída
de: (i) Comunicação realizada através da Internet para permitir que os clientes interajam
com os serviços; (ii) Escalabilidade para lidar com flutuações na demanda, atendendo
rapidamente ao crescimento do número de usuários; (iii) Confiabilidade para que o
serviço e a comunicação estejam continuamente disponíveis.
Inicialmente os serviços eram providos por servidores de custo elevado por
serem mais confiáveis e por ser mais fácil lidar com poucos servidores do que com
muitos computadores com menos recursos. No entanto, o advento dos clusters permitiu
que computadores de baixo custo fossem interligados para oferecer as seguintes
vantagens em relação ao uso de servidores de custo elevado: (i) clusters são mais
escaláveis, podendo atualmente interligar até centenas de milhares de computadores;
(ii) a distribuição de software em um cluster é facilitada pelo uso de máquinas virtuais
que imitam um computador real, ao ponto de possibilitar a execução de outras instâncias
de sistemas operacionais dentro do sistema hospedeiro. [Hoelzle e Barroso 2009]
demonstraram que o custo de processadores, memória e armazenamento em clusters é
cerca de 20 vezes menor que a quantidade equivalente em servidores de custo elevado.
(iii) Embora os componentes de cluster sejam individualmente menos confiáveis que
servidores e dispositivos de armazenamento de alto custo, a infra-estrutura de cluster
torna o sistema mais confiável, devido ao uso extensivo de redundância. O custo total
de cluster também é comparativamente menor devido ao baixo custo do hardware.
Além disso, os serviços estão espalhados por datacenters distribuídos geograficamente
para que até mesmo a ocorrência de um desastre natural não venha a tornar o serviço
totalmente indisponível.
Os custos por máquina e de pessoal dos grandes datacenters são
substancialmente menores que os custos de pequenos datacenters, devido à economia
de escala pela compra, operação e gerenciamento de centenas de milhares de
computadores. O nível de aproveitamento do poder computacional de cada máquina
também é superior, graças ao melhor compartilhamento dos recursos. [Hoelzle e
Barroso 2009] apontam que pequenos datacenters utilizam somente cerca de 10% a
20% do total de seus recursos computacionais. Para melhorar esse cenário, os
provedores passaram a disponibilizar recursos pagos pelo uso (pay-as-you-go). Assim,
os usuários dos serviços pagam apenas pelos recursos que recebem, à semelhança do
que ocorre com os serviços de distribuição de água, energia e telefonia que usamos em
nosso dia a dia. Esse serviço de nuvem pública capaz de oferecer poder de
processamento, armazenamento e comunicação a centavos por hora passou a ser
chamado de Utility Computing [Armbrust et al. 2010]. O objetivo da Utility Computing
é fornecer os componentes básicos como armazenamento, CPUs e largura de banda de
uma rede como uma “mercadoria”, através de provedores especializados com um baixo
custo por unidade utilizada [Sousa et al. 2010]. Usuários de serviços baseados em
Utility Computing não precisam se preocupar com escalabilidade, pois a capacidade de
armazenamento fornecido é praticamente infinita. A Utility Computing propõe fornecer
disponibilidade total, isto é, os usuários podem ler e gravar dados a qualquer momento,
sem serem bloqueados; os tempos de resposta são praticamente constantes e não
dependem do número de usuários simultâneos, do volume de dados utilizado ou de
parâmetros do sistema. Os usuários não precisam se preocupar com backups. Se os
componentes falharem, é de responsabilidade do provedor substituí-los e tornar os
dados disponíveis em tempo hábil através de réplicas [Brantner et al. 2008]. Desse
modo, qualquer pessoa com uma boa ideia e algum conhecimento pode iniciar uma
empresa de desenvolvimento de serviços em nuvem que podem atender bem milhões de
clientes sem a mínima necessidade de construir ou mesmo operar um datacenter. O
jogo social FarmVille2 obteve um milhão de jogadores em seus primeiros quatro dias e
75 milhões de jogadores mensais após 9 meses. Isso foi possível graças ao uso de
Utility Computing provido pelo serviço Amazon Elastic Compute Cloud (EC2)3. Google
App Engine4 e Microsoft Azure5 também se destacam como serviços populares de
Utility Computing.
Ambientes de computação em nuvem são tipicamente compostos por três
modelos de serviços que definem um padrão arquitetural para soluções de computação
em nuvem. Os modelos de serviços estão representados na figura 5 e são os seguintes:
Software como Serviço (SaaS – Software as a Service), Plataforma como Serviço
(PaaS – Platform as a Service) e Infra-estrutura como Serviço (IaaS – Infrastructure
as a Service). Como este capítulo trata especificamente sobre o desenvolvimento de
Software como Serviço, vamos explicar esse modelo de forma mais detalhada na
próxima seção. Antes disso, porém, abordaremos resumidamente os modelos de PaaS e
IaaS conforme descrito em [Sousa et. al. 2010].

Figura 5. Modelos de Serviços.

2 http://www.farmville.com/
3 http://aws.amazon.com/ec2/
4 http://developers.google.com/appengine/
5 http://www.windowsazure.com/
O modelo de PaaS fornece um sistema operacional, linguagens de programação
e ambientes de desenvolvimento para as aplicações, auxiliando a implementação
de softwares, já que contém ferramentas de desenvolvimento e colaboração entre
desenvolvedores. O usuário não administra ou controla a infraestrutura subjacente, mas
tem controle sobre as aplicações implantadas e, possivelmente, sobre as configurações
de aplicações hospedadas nesta infra-estrutura. Heroku6, Google App Engine7 e Aneka8
são exemplos de PaaS.
O modelo de IaaS torna mais fácil e acessível o fornecimento de recursos, tais
como servidores, rede, armazenamento e outros recursos de computação fundamentais
para construir um ambiente de aplicação sob demanda, que podem incluir sistemas
operacionais e aplicativos. Em geral, o usuário não administra ou controla a infra-
estrutura da nuvem, mas tem controle sobre os sistemas operacionais, armazenamento
e aplicativos implantados. Os recursos disponibilizados pela IaaS são geralmente
virtualizados. O Amazon Elastic Cloud Computing (EC2)9 e o Elastic Utility Computing
Architecture Linking Your Programs To Useful Systems (Eucalyptus)10 [Liu et al. 2007]
são exemplos de IaaS.

1.5. Software como Serviço (SaaS)


O modelo de SaaS fornece aos usuários softwares e dados com propósitos específicos
através da Internet. Tais softwares são acessíveis a partir de vários dispositivos por meio
de uma interface leve que normalmente é um navegador Web executado localmente
no dispositivo cliente. Esse modelo diferencia-se da abordagem tradicional que
exige a instalação e execução completa de um código binário na máquina cliente. No
modelo de SaaS o usuário não administra ou controla a infra-estrutura subjacente que
inclui rede, servidores, sistemas operacionais e dispositivos de armazenamento. Isso
possibilita que os desenvolvedores foquem em inovação e não na infra-estrutura, o que
melhora a produtividade e agiliza o desenvolvimento [Sousa et. al. 2009]. O software
disponibilizado como serviço através da Web pode ser acessado pelos usuários de
qualquer lugar e a qualquer momento. Além disso, suas atualizações podem ocorrer de
forma transparente para os usuários, sem a necessidade de realizar download, instalação
e execução de novas versões na máquina cliente. Como exemplos de SaaS, podemos
citar aplicações Web relacionadas a busca, redes sociais e vídeos.
A seguir são listadas algumas vantagens do uso de SaaS para usuários e
desenvolvedores [Fox e Patterson 2012]:
● Desde que os usuários não precisam instalar a aplicação, eles não precisam se
preocupar com requisitos específicos de hardware ou de sistema operacional;
● Os dados relacionados a determinado serviço são armazenamentos e gerenciados
pelo próprio serviço. Assim, os usuários não precisam fazer backup dos dados
ou correr o risco de perda de dados por problemas com o hardware ou mesmo
devido ao roubo do dispositivo.

6 http://www.heroku.com/
7 https://developers.google.com/appengine/
8 http://www.manjrasoft.com/products.html
9 http://aws.amazon.com/ec2/
10 http://www.eucalyptus.com/
● SaaS naturalmente fornece um ambiente propício ao compartilhamento, edição e
manipulação coletiva dos dados.
● O software servidor é executado em um ambiente com hardware e sistema
operacional controlados e selecionados pelo desenvolvedor, evitando problemas
de compatibilidade relacionadas à instalação de software em uma grande
variedade de computadores e sistemas operacionais. Além disso, é possível
disponibilizar novas versões da aplicação apenas para um grupo restrito de
usuários que podem testá-la para descobrir potenciais problemas antes de uma
disponibilização mais ampla que afetaria a maioria dos usuários.
● O uso de um ambiente controlado para execução de SaaS possibilita a realização
de atualizações mais frequentes de software e hardware. A possibilidade de
atualizações frequentes alinha-se perfeitamente ao ciclo de vida de softwares
desenvolvidos através de metodologias ágeis. Assim, novos recursos podem ser
disponibilizados regularmente para evitar que os usuários migrem para serviços
concorrentes. Além disso, evita a pirataria ou cópia ilegal do software, já que o
usuário usa a aplicação remotamente e não tem acesso ao código que está sendo
executado.
● Possibilidade de cobrar um valor periódico ou baseado na demanda de uso do
software.
Essas vantagens explicam o motivo do rápido crescimento de SaaS e
também porque estão sendo desenvolvidas versões SaaS para softwares tradicionais.
Um exemplo disso é a versão SaaS dos populares aplicativos de escritório Word,
Excel e PowerPoint da Microsoft (Microsoft Office 365)11. No entanto, aplicações
desenvolvidas como SaaS requerem acesso à Internet, o que pode restringir seu uso
em determinadas situações. Para atenuar esse problema, algumas aplicações SaaS
têm possibilitado a alternativa de permitir sua execução offline, o que, por outro lado,
aumenta a complexidade do desenvolvimento, por exigir um certo controle sobre o
que está sendo manipulado na máquina cliente e que precisará ser posteriormente
sincronizado com a versão online, assim que isso for possível.
Vários frameworks voltados para programação Web permitem o
desenvolvimento de SaaS. Neste capítulo ilustramos os conceitos abordados através de
exemplos implementados usando o Play Framework12, que foi concebido no intuito de
facilitar o desenvolvimento através do uso de metodologias Ágeis. Isso ocorre porque
ele se alinha ao ciclo de vida ágil. Além disso, o framework permite que a codificação
seja realizada na amplamente difundida linguagem Java, tendo como pré-requisito para
criação das primeiras aplicações Web, apenas o conhecimento do Java SE (Standard
Edition) e da arquitetura Modelo-Visão-Controlador (MVC). A baixa curva de
aprendizagem torna o framework propício para ilustrar os conceitos de engenharia de
software para o desenvolvimento de SaaS. Além disso, as aplicações implementadas a
partir deste framework podem ser facilmente disponibilizadas em modelos de
Plataforma como Serviço (PaaS), como o Google App Engine13 e o Heroku14. Também
é possível disponibilizá-las no modelo de Infra-estrutura como Serviço (IaaS), usando o
serviço Amazon Elastic Cloud Computing (EC2), por exemplo.

11 http://www.office365.com/
12 http://www.playframework.org/
13 http://appengine.google.com/
14 http://www.heroku.com/
Esta seção mostrou como SaaS tem causado alterações substanciais em relação
ao desenvolvimento tradicional de software. A seção a seguir trata da arquitetura
Modelo-Visão-Controlador que é amplamente difundida em aplicações de SaaS.

1.6. Arquitetura Modelo-Visão-Controlador (MVC – Model-View-Controller)


O padrão de arquitetura MVC – Modelo-Visão-Controlador – é amplamente difundido
em aplicações Web. A ideia original dessa arquitetura surgiu em 1978 durante a visita
de Trygve Reenskaug a uma equipe de desenvolvimento da Xerox, que terminou
implementando o MVC na linguagem Smalltalk [Liu 1996]. A arquitetura MVC divide
os componentes necessários para construir uma aplicação em três tipos, garantindo uma
clara separação de papéis:
● um modelo de dados (model) ou objeto de aplicação que não contém código de
apresentação;
● um objeto de visão (view), responsável pela exibição do modelo de dados;
● um objeto de controle (controller) que reage às entradas do usuário, atualizando
o modelo de dados.
Algumas razões para o sucesso da arquitetura MVC estão ligados a legibilidade,
modularidade e separação de papéis. Sistemas construídos com uso da abordagem MVC
tendem a ser flexíveis e extensíveis. A separação de papéis permite um
desenvolvimento mais organizado da aplicação, onde alterações na apresentação dos
dados não implicam em mudanças na forma como os dados são manipulados e vice-
versa. Desde que a apresentação fica separada da lógica, alterações significativas na
apresentação não afetam seu comportamento, sendo inclusive possível substituir uma
tecnologia de visão por outra. Desse modo, é possível desenvolver, editar e testar cada
parte da aplicação separadamente e com mais eficiência.

1.6.1. Modelo
A camada de modelo contem a lógica da aplicação e representa especificamente as
informações que serão apresentadas em formulários da camada de visão com que a
aplicação trabalha. A maioria das aplicações usa um mecanismo de armazenamento de
dados permanente, como um banco de dados, para guardar e recuperar as informações
necessárias à camada de modelo, apresentando também as anotações JPA para a
manipulação desses mesmos dados. A Figura 6 apresenta um modelo chamado Pessoa,
que permite o acesso a dados de uma tabela de nome pessoas.

package models;

import java.util.Date;
import javax.persistence.*;
import play.data.validation.Required;
import play.db.jpa.*;

@Entity(name="pessoas")
public class Pessoa extends Model {
@Column(length=50)
@Required
public String nome;

@Column(length=10)
public String fone;

@Temporal(TemporalType.DATE)
@Column(name="dt_nasc")
public Date dtNasc;

@Override
public String toString() {
return nome + " - " + fone + " - " + dtNasc;
}
}
Figura 6. Modelo Pessoa (app/models/Pessoa.java)
Essa camada é responsável pelo acesso a banco de dados, deixando as
informações prontas, o controlador requisita essas informações levando-as para a
camada de visão, onde serão exibidas na template correta. O modelo não possui
conhecimento de quais serão as interfaces com usuário que serão utilizadas.
Recomenda-se como boa prática de programação relativa à arquitetura MVC,
que os controladores possuam pouco código e que os modelos possam ter códigos
maiores [Chelimsky et al. 2010]. A responsabilidade do controlador é somente a de
receber entradas e fazer chamadas ao modelo para obter os dados que preencherão a
visão. Assim, o controlador basicamente fica responsável apenas por instanciar algumas
classes, obter dados dos modelos e enviá-los à visão adequada. Por outro lado, os
modelos realizam manipulação, validação e filtragem de dados.

1.6.2. Rotas, Controladores e REST


De acordo com a arquitetura MVC, modelos e visões não devem se comunicar
diretamente. Os controladores funcionam como intermediários ou elos de ligação entre
modelos e visões. Um controlador recebe as requisições HTTP endereçadas a ele,
obtém e/ou manipula os dados de um ou mais modelos, preenche uma determinada
visão com os dados obtidos e retorna uma resposta para o cliente, resultante da visão
preenchida. No Play Framework, o controlador corresponde a uma classe, onde cada
método geralmente é a uma ação responsável pela interação entre modelos e visões.
A Figura 7 apresenta um controlador de nome Application, constituído por duas ações
(index e show). Cada uma das ações obtém dados do modelo Pessoa e usa esse dados
para preencher as visões index e show, respectivamente.

package controllers;

import play.*;
import play.data.validation.Valid;
import play.mvc.*;
import java.util.*;
import models.*;

public class Application extends Controller {


public static void index(String nome) {
List<Pessoa> pessoas = Pessoa.findAll();
render(pessoas);
}

public static void show(long id) {


Pessoa p = Pessoa.findById(id);
render(p);
}
}

Figura 7. Controlador Application (app/controllers/Application.java)


Cada requisição HTTP enviada ao servidor Web possui uma URI que é usada
para identificar o servidor Web, o controlador e a ação a ser executada pelo controlador.
Além disso, a URI ainda pode possuir parâmetros a serem usados pelo controlador.
As relações entre URIs e quais são os controladores e as ações que estão associados a
elas são determinadas por um mecanismo de roteamento. Esse roteamento baseia-se
em um conjunto de regras que são chamadas de rotas. No Play Framework é possível
consultar e modificar as rotas através do arquivo conf/routes. Cada rota inicia com
um método HTTP, seguido por um padrão de URI e pela definição da chamada de um
método (action) do controlador. A Figura 8 apresenta um arquivo de rotas usado no Play
Framework.

# Routes
# Home page
GET / Application.index
GET /pessoa/{id} Application.show({id})

# Map static resources from the /app/public folder to the /public path
GET /public/ staticDir:public

# Catch all
* /{controller}/{action} {controller}.{action}
Figura 8. Arquivo conf/routes

A seguir, mostramos um exemplo de URI para exibir informações sobre a pessoa cujo
id é 1: http://localhost:9000/pessoa/1. O número 1 da URI corresponde ao {id} da
regra “GET /pessoa/{id} Application.show({id})”
Ainda sobre a figura 8, podemos notar que cada rota consiste em três blocos de
informações: O método HTTP; Padrão URI; Definição de chamada.
● O método HTTP pode ser qualquer método válido e suportado pelo protocolo
HTTP, como por exemplo: GET, POST, PUT e DELETE;
● Uma URI define o endereço de solicitação da rota, podendo ter ou não
parâmetros passados pela URL. Essas partes dinâmicas são variáveis provindas
do controlador, onde cada parte dinâmica deve ser escrita entre chaves {...}
● As definições de chamadas constituem a última parte da rota, sendo compostas
pelo nome do controlador e da ação a ser executada.
Em última instância, há o REST (Representational State Transfer) [Fielding
2000], ou em português, Transferência de Estado Representacional, que descreve uma
arquitetura de software para aplicações WEB que requisitam e manipulam recursos
WEB, usando os métodos do protocolo HTTP já citados acima. Cada recurso REST é
uma entidade acessível a partir de uma URL que oferece interação via HTTP, onde os
recursos podem ser apresentados em diferentes formatos, como HTML, RSS, XML,
PDF, etc. Dependendo exclusivamente da URL requisitada pelo cliente.
REST afirma alguns princípios chave de desenvolvimento:
● A funcionalidade da aplicação é divida em recursos.
● Cada recurso é endereçado unicamente usando URIs.
● Todos os recursos partilham uma interface uniforme para a transferência de
estado entre cliente e recurso.
Se uma aplicação segue os princípios de desenvolvimento REST, a aplicação é
denominada RESTful e passa a possuir URLs limpas, desde que a simples identificação
do recurso na URI, juntamente com o método HTTP usado na requisição, são
suficientes para determinar que ação deve ser tomada sobre o recurso. Twitter,
Facebook, Foursquare e muitos outros serviços utilizam REST. Webservices têm
ganhado cada vez mais atenção, não apenas pelo seu grande uso na criação de APIs,
mas também por causa da simplicidade de consumir e publicar um serviço RESTful
[Pautasso et al. 2008].

1.6.3. Visões
Uma visão é um componente usado para exibir dados de um modelo. Uma visão não
deveria realizar lógica de negócio ou obter dados além dos disponíveis no modelo.
Assim, múltiplas visões podem representar o mesmo modelo, sem interferir no
comportamento da aplicação. Um exemplo disso seria a existência de duas visões
para os mesmos dados: uma delas apresentando-os de forma tabular e a outra visão
mostrando uma representação gráfica dos mesmos dados.
A visão não deve fazer manipulação ou recuperação de dados, como por
exemplo interações com o Banco de Dados. Ao invés disso, deve meramente exibir
dados de um ou mais modelos. Por outro lado, a visão realiza a lógica de apresentação,
que é bem diferente de lógica de controle e de negócio. Um exemplo de lógica de
apresentação é o uso da cor vermelha para visualização de valores numéricos, caso eles
sejam negativos.
A visão é constituída por alguma tecnologia que permita a geração ou
visualização da interface com o usuário. Uma dessas tecnologias consiste no uso de
templates, associado a uma linguagem simples para manipulação e preenchimento
adequado das templates. Diversos frameworks voltados para o desenvolvimento Web,
inclusive o Play Framework, usam templates para a construção de visões.
Uma template é um arquivo texto, onde são escritos os códigos em HTML que
irão constituir o corpo da página na WEB, como também os elementos dinâmicos da
template. Esss elementos normalmente são parâmetros ou variáveis fornecidos pelo
controlador.
Exemplo de um uma visão em que é possível fazer uma listagem:

#{extends 'main.html' /}
#{set title:'Contatos - Listagem' /}

<table>
<tr>
<th>Nome</th>
<th>Telefone</th>
<th>Data de Nascimento</th>
</tr>
#{list pessoas, as:'p'}
<tr>
<td>${p.nome}</td>
<td>${p.fone}</td>
<td>${p.dtNasc}</td>
</tr>
#{/list}
</table>
Figura 9. Visão app/views/Application/index.html
Perceba que na figura 9, a lógica da aplicação não se encontra na visão,
encontramos na visão apenas o manuseio dos dados de forma a facilitar uma
visualização. No início da visão é colocado o layout em que essa visão se encontra,
é possível também colocarmos o título para a página. É importante ressaltar que as
visões devem ser implementadas de modo a possibilitar boa visualização em diferentes
dispositivos.

#{extends 'main.html' /}
#{set title:'Contatos - Visualização' /}

<p>Nome: ${p.nome}</p>
<p>Telefone: ${p.fone}</p>
<p>Data de Nascimento: ${p.dtNasc}</p>
Figura 10. Visão app/views/Application/show.html
Na figura 10, temos uma visualização simples de um contato, nesta visão temos
que o id do contato foi passado como parâmetro pela URL e então temos o objeto
Contato na variável p e então seus dados podem ser acessados como no exemplo.

1.7. Testes
A grande maioria das pessoas já teve alguma experiência com um
software que não funcionou como esperado. Softwares que não funcionam
corretamente podem levar a muitos problemas, incluindo financeiro, tempo
e reputação das empresas. Podendo, inclusive, chegar a influenciar na
integridade das pessoas [ISTQB 2011].

Dado esse fato, podemos associar a qualidade de um software à quantidade


de falhas percebidas no mesmo. O teste de software ajuda a medir essa qualidade no
momento em que julgamos que as funcionalidades testadas estão funcionando como
requisitadas.
Assim, podemos dividir os testes em quatro níveis [ISTQB 2011]:
● Teste de Componente (ou de unidade)
○ Teste de componentes ou unidades do código que podem ser testados
separadamente (e. g. métodos de uma classe).
● Teste de Integração
○ Teste de interface entre componentes (e. g. interações de diferentes
partes do sistema, como cadastro e financeiro).
● Teste de Sistema
○ Teste do comportamento de todo o sistema.
● Teste de Aceite
○ Normalmente verifica se o sistema está apropriado para o uso por um
usuário com perfil de negócio.
Para testar um software podemos fazê-lo de dois modos: manual, como
por exemplo usar o sistema e analisar se as funcionalidades atendem aos requisitos,
inspecionar visualmente o código para avaliar se ele faz o que se propõe a fazer; ou
automático, como realizar asserções nas funções do código, inserindo uma entrada
conhecida e verificando se a saída esperada ocorre, como mostra a Figura 11.
Atualmente podemos contar com ferramentas e APIs que ajudam na automação de
testes como JUnit15 e Selenium16.

Figura 11. Estrutura de uma classe de teste usando o framework JUnit (http://
www.devmedia.com.br/imagens/javamagazine/mpjuiiujfig10.jpg)
É importante ressaltar que pesquisas revelam que 58% de bugs em software
resultam de problemas com infra-estrutura de testes e processos, e não de falhas de
projeto. Elas apontam também que ambientes em que os testes são completamente
automatizados ainda são raros e, inclusive, existem locais em que a totalidade dos testes
é feita de maneira manual [Fox e Patterson 2012]. Estimamos que isso ocorra pelo
simples fato de que testar é muito caro em relação ao tempo, podendo tomar mais de
50% do prazo do projeto.
Para incentivar a cultura de testes automatizados de software e garantia de
qualidade, nasceram abordagens como o TDD (Testing-Driven Development) e BDD
(Behavior-Driven Design). Em uma tradução livre, TDD seria Desenvolvimento
dirigido por testes e BDD Projeto guiado por comportamento.
O TDD é caracterizado pelos seguintes passos:
● Os testes relativos à determinadas características são escritos antes mesmo da
funcionalidade estar codificada. Neste momento os testes irão falhar.
● O código é construído de modo a fazer todos os testes executarem com sucesso,
mesmo que não seja feito da maneira mais correta e completa.
● Feito isso, objetivando transformar o código em algo mais legível, padronizado
e completo, é feita uma refatoração e os testes devem continuar executando sem
erros.

15 http://junit.org/
16 http://seleniumhq.org/
● Todo o processo é repetido com outra funcionalidade ou, simplesmente,
adicionam-se mais testes.
Para exemplificar o TDD, imaginemos a implementação de uma funcionalidade
que receba dois números e retorne a soma deles. Seguindo os passos acima, criaríamos
a classe CalculoTest e também o método de teste testExecutaCalculo, que invoca
a funcionalidade executaCalculo da classe Calculo. Passaríamos como parâmetro
os números 10 e 5 e esperaríamos que o retorno fosse 15. Passaríamos também os
parâmetros 11 e 10 para esperarmos o número 21 como resposta. Como inicialmente
este método retornaria sempre zero, então ao executarmos o teste, este falharia. O
próximo passo é implementar o código de forma que esses testes não falhem. Após isso
podemos refatorar o método executaCalculo para que fique o mais legível possível.
Os testes devem continuar funcionando e, por fim, ou adicionaríamos mais testes
com outros parâmetros, ou criaríamos uma nova funcionalidade. Vale frisar que todo
o processo é repetido até que todas as unidades de código sejam consideradas como
testadas.
Direcionando agora para o BDD podemos fazer as seguintes considerações [Fox
e Patterson 2012]:
● BDD faz perguntas sobre comportamentos antes e durante o desenvolvimento,
visando reduzir falhas na comunicação dentro do projeto.
● Requisitos são escritos como estórias de usuários. São criadas descrições
simples de como a aplicação deve ser utilizada.
● BDD se concentra no comportamento da aplicação versus a implementação da
aplicação e os testes são conduzidos utilizando TDD.

Conforme considerado acima, as estórias de usuário passam a ser representadas


como cenários e compõem um texto atendendo a tripla “Dado que, Quando e Então”.
Desse modo, as máquinas também podem compreender esse texto que se aproxima da
linguagem natural. Um exemplo simples: suponha que você tenha escolhido uma estória
que determinado programa deve receber dois números e somá-los. Assim, você pode
representar essa funcionalidade gerando a tripla:
● Dado que: eu recebo dois números.
● Quando: eu executar o programa.
● Então: os números são somados e retorna o resultado.

Com isso, podemos representar as estórias de usuário obedecendo a prescrição


acima e usamos essa informação para homologar as funcionalidades frente ao cliente.
Além disso, os testes ainda serão automatizados, pois essa informação será lida e
verificada automaticamente com os resultados.

1.8. Implantação (Deploy) da Aplicação


Ao trabalhar com desenvolvimento de software, é importante dividir as etapas de
trabalho. Mesmo em processos ágeis, algumas etapas podem ser reconhecidas,
como a etapa de desenvolvimento, que é momento em que o software está sendo
construído. Outra etapa é a de testes. Finalmente, também há um momento em que,
após implmentadas as funcionalidades da iteração, a aplicação é posta em produção e o
cliente pode usá-las e avaliá-las. Esse momento pode ser chamado de implantação do
software, que ocorre após a aplicação ter sido diversas vezes testada e, depois, colocada
em um ambiente no qual o stakeholder poderá utilizar.
O processo de implantação (deploy em inglês) é todo o conjunto de atividades
necessárias para que o software esteja disponível para o cliente. O momento para a
realização desse processo, vai depender dos acordos feitos entre o desenvolvedor e o
cliente.
Há basicamente três ambientes utilizados pela comunidade: homologação
(teste), desenvolvimento e produção, conforme descrito a seguir.
Desenvolvimento: ambiente onde a aplicação é desenvolvida. Podendo ser
executado localmente na máquina do desenvolvedor, por exemplo.
Homologação: é o ambiente em que a aplicação pode ser testada. O
desenvolvedor irá produzir o software no ambiente de desenvolvimento, e depois irá
testá-lo no ambiente de homologação.
Produção: Local em que o cliente pode ver o sistema funcionando, neste
ambiente tudo que está nele já deve ter sido desenvolvido e testado. É o ambiente em
que o usuário irá poder utilizar a aplicação.
O ideal é que os ambientes devam ser semelhantes quanto à configuração
das máquinas, pois a aplicação será executada em todos eles. A execução em
cada um desses ambientes no momento oportuno poderá ser feita por uma pessoa
responsável, pois os ambientes podem possuir um certo grau de complexidade quanto às
configurações, requerendo um profissional devidamente capacitado para operá-los.
Convém que os ambientes sejam fisicamente separados, pois as atividades
de desenvolvimento podem ocasionar problemas operacionais no sistema. Deve-se
cuidar também para evitar que códigos não testados sejam colocados em ambientes de
produção.
Uma das características de grande parte dos frameworks Web é possuir
ambientes de desenvolvimento distintos para possibilitar a personalização ou
configuração de cada um deles. No que diz respeito ao Play framework, pode-se
configurar cada um desses ambientes de desenvolvimento. A implantação de uma
aplicação de SaaS implementada no Play poderia ser realizada na PaaS Heroku, por
exemplo. A utilização de serviços como esse possibilita a implantação e execução da
aplicação em nuvem, além de manter um registro (log) do que está acontecendo e outras
funcionalidades.
Também é uma boa prática a utilização de serviços de integração contínua. Com
eles, cada commit no servidor de integração contínua realiza um build da aplicação e
executa todos os testes, tendo como grande vantagem o feedback instantâneo. Desse
modo, erros introduzidos por diferentes desenvolvedores ao longo do processo podem
ser corrigidos rapidamente pela equipe. Não é preciso ter o trabalho de configurar
banco de dados e refazer configurações a cada vez que for necessário executar a
aplicação. Mas por que não executar todos os testes no servidor de desenvolvimento?
Um dos motivos é que todos os testes da aplicação podem demorar muito para serem
executados. Além disso, também é necessário criar builds completos da aplicação para
que a cada commit seja disponibilizada uma versão funcional e pronta para execução.
A versão da aplicação após o processo bem sucedido de integração contínua está pronta
para implantação no servidor de produção. Portanto, além dos ambientes já citados,
recomenda-se também o uso de um ambiente de integração contínua para melhor
acompanhamento e auxílio durante o desenvolvimento.
Há algumas diferenças na implantação entre o a versão 2 do Play e a versão
que estamos trabalhando neste minicurso, na versão 1.2.x esse processo pode ser
considerado ate mais fácil.Uma aplicação desenvolvida no Play Framework pode ser
executada a partir do terminal através do comando play run. É possível a geração de um
arquivo WAR(Web Application Archive) com o objetivo da implantação em servidores
JEE, como por exemplo o Tomcat.
Heroku é uma plataforma nas nuvens que atua como um serviço (PaaS) em
que é possível fazer o deploy de várias aplicações em várias linguagens, inclusive
Java. Especificamente o Heroku já possui alguns serviços em que é possível fazer
deploy de aplicações de SaaS baseadas no Play Framework. Serviços de PaaS, como
o Heroku, simplificam o trabalho do desenvolvedor, conforme explicado na seção 1.4
(Computação em Nuvem). Também é possível armazenar a aplicação em um repositório
GIT, o qual será explicado adiante, e a partir dele, enviar a aplicação para o Heroku ou
outro serviço de PaaS. Neste capítulo abordamos o uso do Heroku, pela facilidade de
uso e por permitir a implantação e a execução gratuitas de aplicações que atendam a
determinados limites definidos pelo serviço. A ausência de custo torna-se atrativa no
contexto acadêmico de uso do serviço para fins de aprendizagem. No entanto, outros
bons serviços poderiam ter sido usados.
Para realizar a implantação é necessário criar uma conta no Heroku e configurar
o GIT na máquina local, pois o Heroku atualiza os arquivos da aplicação a partir de
um repositório GIT. A seguir são descritos os passos necessários para publicação da
aplicação nas nuvens através do Heroku.
1. Crie a aplicação no Heroku
heroku create
2. Faça a implantação do código da aplicação
git push heroku master
Os passos acima são suficientes para disponibilizar a aplicação nas nuvens.
Pode-se acessá-la através de um link gerado pelo Heroku e que aparecerá no terminal
após a publicação da aplicação.
É possível ver registros (logs) da aplicação através do comando heroku logs. O
gerencimanento da aplicação, quantidade de espaço utilizado, endereço da aplicação,
entre outras coisas, pode ser realizado através da interface administrativa do Heroku.
Esta seção destacou a importância do uso de ambientes fisicamente separados
para a execução da aplicação durante as diversas etapas do desenvolvimento do
software, desde a sua modelagem até a visualização e utilização do software pelo
cliente. Servidores de integração contínua são úteis para teste da aplicação, após o
recebimento de variadas contribuições dos membros da equipe, fornecendo uma visão
clara e geral de possíveis erros.
1.9. Uso de sistemas de controle de versão e modelos de fluxo de trabalho
A ideia de usar sistemas de controle de versão é muito importante, especialmente,
quando o desenvolvimento ocorre em equipe. Eles possibilitam um controle e
gerenciamento mais efetivo sobre os detalhes das diversas modificações ocorridas no
software ao longo do tempo, além de facilitar bastante o trabalho colaborativo durante
o desenvolvimento do software. É possível, por exemplo, recuperar uma versão
anterior de uma determinada classe ou mesmo resolver conflitos decorrentes de dois
desenvolvedores alterarem simultaneamente um mesmo trecho de código.
GIT é um sistema que permite o controle de versão e o gerenciamento de código
fonte de forma rápida e eficiente. Ele foi inicialmente desenvolvido por Linus Torvalds,
também criador do Linux, para servir como sistema de versionamento do núcleo do
Linux. Por sua rapidez e facilidade, ele tem sido bastante utilizado na comunidade que
trabalha com desenvolvimento Ágil. O uso do GIT permite a aplicação de algumas
técnicas de fluxo de trabalho relacionadas à forma de utilização de repositórios locais e
remotos.
A criação de um repositório com o GIT, ocasiona a criação, por padrão, de
um repositório local denominado master. A adição de um repositório remoto, por
padrão gera um repositório denominado origin. Com esses dois repositórios, é possível
fazer com que o fluxo de trabalho seja uma transferência das alterações locais para as
remotas, de forma que ao fazer alterações localmente, pode-se enviar essas alterações
ao repositório remoto. Essa é a forma mais comumente usada para lidar com GIT.
Contudo, apresentaremos uma forma semelhante a essa, porém capaz de simplificar
ainda mais o controle de versões.
O fluxo de trabalho que apresentaremos foi inicialmente utilizado pela
HashRocket17, uma empresa americana de desenvolvimento ágil. O fluxo foi chamado
Hack-Sink-Ship por seus próprios criadores e seu objetivo principal é poupar tempo ao
fazer com que o processo de enviar e sincronizar alterações seja mais rápido. Scripts
simples podem implementar o fluxo, usando apenas alguns comandos GIT. Não há uma
tradução para o termo em português, entretanto, podemos tecer alguns comentários
sobre cada um deles. Hack pode ser traduzido do inglês como picar ou como sinônimo
de cortar, dando uma ideia de recorte de uma certa funcionalidade, de forma que o
desenvolvedor possa trabalhar apenas nela. Com relação ao sink, temos a noção de
sincronização. Assim, caso alguma nova modificação no repositório remoto ocorra,
deve-se sincronizar com as novas alterações realizadas localmente. Por último, o termo
ship em uma tradução praticamente literal do inglês, significa “deixar pronto para uso”.
Desse modo, executar um ship significa deixar a feature pronta para uso.
Hack-sink-ship baseia-se no fato de que com o GIT devemos sempre leva em
conta a sincronização entre dois repositórios. Inicialmente tínhamos um repositório
local e outro remoto e, então, havia uma sincronização entre os mesmos. Em seguida,
passamos a ter um repositório para cada funcionalidade implementada. Assim, temos:
o repositório master, o origin, além de um repositório para cada funcionalidade.
Geralmente em equipes ágeis, a funcionalidade a ser implementada possui um número

17 http://hashrocket.com/
identificador. Então, pode-se usar esse número para representar o branch onde ficará
a implementação da nova funcionalidade. No exemplo a seguir, a variável ATUAL
contém o valor numérico do identificador da funcionalidade.
Basicamente as operações funcionam como scripts contendo uma pequena
sequência de comandos GIT:
● Hack: cria o branch que terá apenas as alterações referentes a uma determinada
funcionalidade.
git checkout master
git pull origin master
git checkout -b $ATUAL master
● Sink: Sincroniza o repositório atual da funcionalidade com o repositório origin.
Com isso, antes do envio das alterações, checa-se se o código será bem aceito,
isto é, se ele não gerará erros ao ser integrado com as demais funcionalidades
existentes. Isso pode ocorrer quando algum desenvolvedor efetua alterações
antes de outro, em um mesmo trecho de código.
git checkout master
git pull origin master
git checkout $ATUAL
git rebase master $ATUAL
● Ship: Faz um merge do branch atual da funcionalidade com o master, e envia as
alterações para o repositório origin.
git checkout master
git merge --squash $ATUAL
git commit -a -v
git push origin master

Agora serão descritos os momentos ideais para cada uma dessas operações.
Inicialmente, quando uma funcionalidade é atribuída ao desenvolvedor, deve-se evitar
que as alterações necessárias para implementá-la não causem problemas ao código
anterior. Assim, executa-se o hack, fazendo um branch somente para a funcionalidade.
Para testar, sincroniza-se executando o sink. Se todos os testes passarem, a
funcionalidade foi integrada com sucesso ao código anterior da aplicação e, então, ela
pode ser integrada juntamente com o restante da aplicação, que se encontra remota.
Depois disso, faz-se um ship para que o código seja enviado.
O fluxo Hack-Sink-Ship é muito simples de ser implementado e pode simplificar
bastante o desenvolvimento em equipe. Aliando esse fluxo de trabalho a serviços de
integração contínua, pode-se monitorar e obter total controle sobre o código. Ressalta-se
ainda que a adoção desse fluxo permite que o desenvolvedor se dedique mais a outras
tarefas, como testes, por exemplo. Além disso, após a execução bem sucedida do fluxo,
pode-se realizar os testes para ter a certeza de que a aplicação funciona com a novas
contribuições dos demais membros da equipe de desenvolvimento.
A seguir, sugerimos um fluxo de trabalho mais completo, que se integra às
práticas supracitadas de uso do hack-sink-ship:
1. Inicie a funcionalidade a ser implementada.
2. Faça um hack, criando um branch para sua funcionalidade.
3. Escreva os testes.
4. Valide a implementação com os testes escritos.
5. Repita os passos 3 e 4 até que a funcionalidade esteja completa.
6. Faça um sink, sincronizando com alguma eventual alteração feita no origin,
posterior a sua versão do sistema.
7. Envie suas alterações através da execução do ship.
Portanto, vimos que a utilização desse fluxo de trabalho para o desenvolvimento
ágil de uma forma geral pode ser bem empregado, facilitando a forma de enviar
alterações, assim como a sincronização das mesmas. Essa é apenas uma proposta que
achamos conveniente utilizar, podendo ocorrer variações da mesma.

1.10. Conclusão
A forma como o mercado de software desenvolveu-se e a presença de sistemas
computacionais em quase todos os dispositivos de nosso cotidiano, desde alguns dos
mais simples aparelhos celulares até o mais complexo controlador de tráfego aéreo,
fez com que a indústria de desenvolvimento de software focasse cada vez mais na
qualidade e eficiência de seus produtos. Uma das maneiras de se garantir a qualidade
de um produto de software é a utilização da Engenharia de Software. Contudo, além da
qualidade, os clientes buscam rapidez na entrega dos produtos e a evolução da internet
como um meio de serviço leva os desenvolvedores ao uso de Metodologias Ágeis para a
construção de software robusto e com garantias de boa qualidade.
Diante da necessidade de um desenvolvimento de software mais dinâmico e
eficiente, este capítulo apresentou uma proposta de uso da arquitetura MVC e do
modelo de Software como Serviço (SaaS), uma vez que ambos viabilizam agilidade no
desenvolvimento e melhor interação do usuário com o sistema. O grande crescimento
da Internet e os custos cada vez mais baixos de serviços de computação em nuvem
viabilizam um enorme crescimento do número de aplicações que seguem o modelo de
SaaS. Apenas o uso de metodologias não garante a qualidade do produto final. Manter a
cultura dos testes de software é tão importante quanto o correto uso da Engenharia de
Software durante a construção da aplicação para garantir que o dinamismo das
exigências dos usuários sejam satisfatoriamente atendidas.
O capítulo abordou algumas das principais técnicas da Engenharia de Software
vinculadas ao desenvolvimento ágil como um incentivo aos novos desenvolvedores a
perpetuarem as melhores práticas de desenvolvimento de software, garantindo sempre
eficiência na entrega e qualidade no produto final.

Referências
Armbrust, M., Fox, A., Griffith, R., Joseph, A. D., Katz, R., Konwinski, A., Lee, G.,
Patterson, D., Rabkin, A., Stoica, I., and Zaharia, M. (2010). “A view of cloud
computing”. Commun. ACM, 53(4):50–58.
Beck, K., et al. (2001). "Manifesto for Agile Software Development". Agile Alliance.
http://agilemanifesto.org/. Acessado em 18 de agosto de 2012.
Brantner, M., Florescu, D., Graf, D., Kossmann, D., and Kraska, T. (2008). “Building a
database on s3”. In Proceedings of the 2008 ACM SIGMOD international conference
on Management of data - SIGMOD ’08, page 251, New York. ACM Press.
Chelimsky, D., Astels, D., Helmkamp, B., North, D., Dennis, Z., and Hellesoy, A.
(2010). “The RSpec Book: Behaviour Driven Development with Rspec, Cucumber,
and Friends”. Pragmatic Bookshelf Series. Pragmatic Bookshelf.
David C., Dave A., Zach D., Aslak H., Bryan H., Dan N. (2010) “The RSpec Book:
Behaviour Driven Development with RSpec, Cucumber, and Friends”, Pragmatic
Bookshelf, 2010.
Fielding, R. (2000). “Architectural Styles and the Design of Network-based Software
Architectures”. PhD thesis, University of California, Irvine.
Fox, A., Patterson, D. (2012). “Engineering Long-Lasting Software: An Agile Approach
Using SaaS and Cloud Computing”, Alpha Edition. Strawberry Canyon LLC, 2012.
Hoelzle, U. and Barroso, L. A. (2009). “The Datacenter as a Computer: An Introduction
to the Design of Warehouse-Scale Machines”. Morgan and Claypool Publishers, 1st
edition.
ISTQB. (2011). Certified Tester Foundation Level Syllabus, version 2011.
Liu, C. (1996). “Smalltalk, objects, and design”. Prentice-Hall, Inc., Upper Saddle
River, NJ, USA.
Liu, S., Liang, Y., and Brooks, M. (2007). Eucalyptus: a web service-enabled e-
infrastructure. In CASCON ’07: Proceedings of the 2007 conference of the center
for advanced studies on Collaborative research, pages 1–11, New York, NY, USA.
ACM.
Paula Filho, W. P. (2006). “Engenharia de Software: fundamentos, métodos e padrões”,
3 ed. Rio de Janeiro: LTC, 2006.
Pautasso, C., Zimmermann, O., and Leymann, F. (2008). “Restful web services
vs. "big"’ web services: making the right architectural decision”. In Proceedings of
the 17th international conference on World Wide Web, WWW ’08, pages 805–814,
New York, NY, USA. ACM.
Pressman, R. S. (2005). “Software engineering: a practitioner’s approach”, 6 ed. New
York: MacGraw-Hill, 2005.
Serman, D. V. (2010). “Orientação a projetos: uma proposta de desenvolvimento de
uma arquitetura orientada a serviços”. JISTEM: Journal of Information Systems and
Technology Management, Sin mes, 619-638.
Sousa, F. R. C., Moreira, L. O. e Machado, J. C. (2009). “Computação em Nuvem:
Conceitos, Tecnologias, Aplicações e Desafios”. In: Santos Neto, P. (Org.). III
Escola Regional de Computação Ceará - Maranhão - Piauí, ERCEMAPI 2009, 1 ed.
SBC, Piauí.
Sousa, F. R. C., Moreira, L. O., Macedo, J. A. F. e Machado, J. C.
(2010). “Gerenciamento de Dados em Nuvem: Conceitos, Sistemas e Desafios”. In:
XXV Simpósio Brasileiro de Banco de Dados, 2010, Belo Horizonte. SBBD 2010.

View publication stats

Você também pode gostar