Engenharia de Software
A Engenharia de Software foi a disciplina de extrema importância no meu período de estágio na empresa. Logo abaixo descrevo os tópicos da área que foram maior utilidade.
Devido à alta competitividade do mercado, as empresas passaram a investir em TI como meio de diminuição de custos. Mas o maior investimento no desenvolvimento de programas na década de 90 resultou em percentuais muito significativos de projetos de software abandonados ou que não atendiam às necessidades do cliente. Isso foi denominado de 'crise do software'.
Esse problema se deve principalmente a falta de uso de uma metodologia que permitisse com maior chance de sucesso implementar sistemas funcionais e adequados ao cliente. Muitas vezes o conjunto de requisitos levantados para implementação do sistema não é bem compreendido, tornando-o ineficaz para seus usuários, e sua correção pode ser muito difícil e custosa. Além disso, a dinâmica do mercado exige que um bom sistema tenha novas características, tais como extensibilidade e escalabilidade, de tal modo a reduzir o custo para se adequar a novos requisitos.
A Engenharia de Software é uma disciplina relativamente recente com o objetivo de sanar problemas como estes e prover um produto com boa relação custo-benefício, e que formaliza as metodologias para o desenvolvimento de sistemas de software.
Um processo de software é um conjunto de atividades e resultados associados que levam a produção de um produto de software. Embora existam muitos processos de software, há atividades fundamentais comuns em todos eles:
Embora não sejam descrições definitivas de processos de software, temos alguns modelos genéricos que podem ser utilizados para explicar diferentes abordagens do desenvolvimento de software:
O modelo em cascata se caracteriza pela sua inflexível divisão do projeto em fases que a princípio envolvem a aprovação de um ou mais documentos, sendo que a fase seguinte não deve se iniciar até que a fase precedente tenha sido concluída. Na prática, esses estágios se sobrepõem e trocam informações entre si. Os principais estágios deste modelo são:
Devido aos custos de produção e aprovação de documentos, as iterações são onerosas e envolvem um retrabalho significativo. Portanto depois de um pequeno número de iterações é normal suspender partes do desenvolvimento e continuar com os estágios posteriores, o que pode acarretar em problemas no cumprimento de requisitos e a má estruturação do sistema. Além disso, a manutenção de software pode envolver a repetição de alguns ou de todos os estágios anteriores do processo.
Os acordos devem ser feitos em um estágio inicial do processo, e isso significa que é difícil responder aos requisitos do cliente. Portanto o modelo em cascata deve ser utilizado somente quando os requisitos forem bem compreendidos.
Por outro lado, este processo fornece um modelo simples de gerenciamento e sua separação de projeto e implementação devem levar a sistemas robustos, que são suscetíveis a mudanças.
O modelo evolucionário tem como base a idéia de desenvolver uma implementação inicial, e interagir ativamente com o cliente de modo a fazer seu aprimoramento por meio de muitas versões até que um sistema adequado tenha sido desenvolvido. As atividades de especificação, desenvolvimento e validação são realizados concorrentemente.
Temos dois tipos de desenvolvimento evolucionário:
A grande vantagem deste processo é a maior eficácia no cumprimento das necessidades imediatas do cliente, e a rapidez no desenvolvimento. Contudo existem alguns problemas: se o sistema é desenvolvido rapidamente, não é viável produzir documentos que reflitam cada versão do sistema e, portanto perde-se o controle sobre o gerenciamento do projeto, e devido a mudanças constantes, a estrutura do software tende a se degradar, e para o seu desenvolvimento podem ser exigidas técnicas e ferramentas especiais incompatíveis com outras ferramentas e ou que exigem conhecimento que poucas pessoas possuem.
Este modelo é recomendado para sistemas de pequeno e médio porte.
Este modelo tem como base a transformação matemática formal de uma especificação de sistema em um programa executável. A divisão de fases deste modelo se assemelha ao modelo em cascata, mas usando uma abordagem e linguagem formal e matemática nas atividades. Este é pouco utilizado pois requer de profissionais especializados, as atividades são lentas e trabalhosas, contudo oferece o maior grau de segurança ao atender os requisitos. Portanto é recomendável o seu uso somente em sistemas críticos, como por exemplo, no uso em aeronaves e na área da medicina.
O modelo orientado a reuso visa o desenvolvimento de sistemas tendo como base uma gama de componentes reutilizáveis e sistemas COTS* disponíveis no mercado. Partes do software que não puderem ser comprados são desenvolvidos e integrados a estes componentes.
* sistemas comerciais de prateleira
Este modelo se diferencia dos outros já citados por possuir atividades específicas:
Este modelo tem a vantagem de reduzir a quantidade software a ser desenvolvida e assim de reduzir custos e riscos, e geralmente propicia a entrega mais rápida do software. Porém as adequações nos requisitos são inevitáveis podendo resultar em um sistema que não atenda às reais necessidades dos usuários. Além disso, quando os componentes reutilizáveis não estão sob o controle da organização que os utiliza, perde-se o controle sobre o controle sobre a evolução do sistema.
Vimos que os modelos genéricos possuem várias vantagens e desvantagens, por isso, para a maioria dos grandes sistemas, existe a necessidade de utilizar diferentes abordagens para diferentes partes do sistema. Além disso, há também a necessidade de gerenciar o processo de iteração, em que partes do processo são repetidas, à medida que os requisitos do sistema evoluem. Para tanto temos alguns modelos híbridos bastante utilizados:
Em um processo de desenvolvimento incremental, os clientes identificam em um esboço as funções a serem fornecidas pelo sistema. Eles identificam quais funções são mais importantes e quais são menos importantes para eles. Em seguida é definida uma série de estágios de entrega, com cada estágio fornecendo um subconjunto das funcionalidades do sistema. A alocação de funções aos estágios depende da prioridade da função. As funções prioritárias são entregues primeiramente ao cliente.
Uma vez identificados os incrementos, os requisitos para as funções a serem entregues no primeiro incremento são definidos em detalhes, e esse incremento é desenvolvido utilizando-se o processo de desenvolvimento mais apropriado. Durante esse desenvolvimento outras análises de requisitos para os incrementos seguintes podem ocorrer, mas as mudanças nos requisitos para o incremental atual não são aceitas.
Os incrementos devem ser relativamente pequenos e cada incremento deve produzir alguma funcionalidade para o sistema.
Neste modelo o processo de software é representado como uma espiral. Cada loop na espiral representa uma fase do processo de software, por exemplo, o loop mais interno pode estar relacionado a viabilidade do sistema. Cada loop é dividido em 4 setores:
O grande diferencial neste processo de software é a explícita consideração dos riscos de projeto. Um bom modelo de gerenciamento de riscos é pró-ativo, isto é, ela deve antecipar e prevenir os problemas e se possível resolvê-los em sua origem. Para diminuir os riscos do projeto resolve-se primeiro os problemas mais graves, pois essas dificuldades podem inviabilizar o projeto e, portanto evita desperdícios, ou se resolvidos em outra ordem pode aumentar o custo do projeto, pois talvez seja necessário fazer alterações em partes já desenvolvidas devido a restrições que os problemas de maior gravidade impõem. Isto é chamado de Risk Driven Process.
Os problemas que os engenheiros de software têm para solucionar são, muitas vezes, imensamente complexos. É difícil estabelecer com exatidão o que o sistema deve fazer. O processo de descobrir, analisar, documentar e verificar a funções e restrições de um sistema é chamado de engenharia de requisitos. Por sua vez, estas descrições são os requisitos e podem ser classificados como:
No processo de engenharia de requisitos temos um estágio de extrema importância, o de levantamento e análise de requisitos. Este consiste na interação com os stakeholders* para descobrir informações sobre o domínio da aplicação, serviços que o sistema deve prover etc...O processo abrange as seguintes atividades:
*O termo stakeholder é utilizado para se referir a qualquer pessoa que terá alguma influência direta ou indireta sobre os requisitos do sistema.
É importante notar que fatores políticos podem influenciar os requisitos do sistema, e os requisitos e suas prioridades podem mudar ao longo de todo desenvolvimento, pois o ambiente econômico e de negócios no qual a análise de requisitos ocorre é dinâmico.
Temos algumas técnicas muito utilizadas para o levantamento e análise de requisitos:
Muitas vezes é mais fácil relacionar exemplos da vida real do que descrições abstratas. Para tanto, montamos um cenário composto por interações entre entidades (podem ser objetos ou usuários) e a partir destas informações traçar os requisitos reais do sistema. Este processo pode ocorrer mesmo informalmente na interação com os stakeholders, mas existem formas mais estruturadas, como os use-cases.
Basicamente um use-case identifica os agentes envolvidos em uma interação e especifica o tipo de interação. O use-case se tornou uma característica fundamental da notação em UML (Unified Modeling Language) para descrever modelos de sistemas orientados a objetos, e por isso este processo está sendo cada vez mais utilizado. Além disso, os diagramas de seqüência em UML podem ser utilizados para acrescentar informações a um use-case.
Um protótipo de sistema pode dar aos usuários finais uma impressão concreta das capacidades do sistema, permitindo ao usuário avaliar melhor os requisitos do sistema. Para tal objetivo normalmente utiliza-se de protótipos descartáveis. Para uso eficaz, o desenvolvimento do protótipo deve ser rápido e para tanto se pode utilizar de linguagens de nível mais alto. Mas existem limitações na técnica de prototipação, alguns requisitos não-funcionais não podem ser adequadamente testados, e o modo de utilização de um protótipo executável pode não corresponder à maneira como o sistema final entregue é utilizado.