Início

Software Design

UA4 — Projetar a Solução

Projeto de software é o processo de traduzir requisitos em uma especificação técnica concreta. A primeira e mais importante decisão é a arquitetura — depois vem a decomposição modular e a documentação do que foi decidido.

Projeto de software vs. Arquitetura de software

São conceitos distintos mas complementares: arquitetura refere-se às estruturas de alto nível do sistema, às decisões estruturais fundamentais caras de mudar após implementadas (Bass; Clements; Kazman, 2012). Projeto de software é o processo mais amplo de criar a especificação de um artefato, incluindo componentes de baixo nível, algoritmos e a arquitetura como ponto de partida.

Cinco características da arquitetura de software

Atender stakeholders

Gerentes, usuários, operadores — cada parte interessada tem necessidades. A arquitetura equilibra e endereça todas essas preocupações.

Separação de necessidades

A complexidade é reduzida separando as necessidades em diferentes pontos de vista (vistas arquitetônicas), cada um descrevendo o sistema de um ângulo.

Orientada pela qualidade

A arquitetura é guiada por atributos de qualidade (RNFs): tolerância a falhas, extensibilidade, segurança, manutenibilidade, disponibilidade.

Estilos recorrentes

Padrões arquitetônicos são soluções reutilizáveis para necessidades recorrentes — evitam reinventar soluções já consolidadas.

Integridade conceitual

A arquitetura representa uma visão geral coerente. O arquiteto garante que adições ao sistema estejam alinhadas com essa visão.

Três tipos de projeto de software

TipoNível de abstraçãoFoco
EstruturalAlto — visão abstrataVisão geral do sistema como múltiplos componentes que interagem; domínio da solução proposta
Alto nívelMédio — menos abstratoQuebra em subsistemas e módulos; estrutura modular e interação entre subsistemas
DetalhadoBaixo — implementaçãoEstrutura lógica de cada módulo, interfaces para comunicação entre módulos, algoritmos

Modularização

Técnica para dividir o sistema em módulos independentes, capazes de executar tarefas de forma autônoma. Segue a estratégia “dividir e conquistar”. Vantagens da modularização:

  • Componentes pequenos são mais fáceis de manter
  • O sistema pode ser dividido com base em aspectos funcionais
  • Permite o nível de abstração desejado
  • Componentes com alta coesão podem ser reutilizados
  • Possibilidade de execução concorrente (paralela)
  • Maior segurança por isolamento

Coesão — o que é e seus 7 tipos

Coesão mede o grau de relacionamento entre os elementos dentro de um módulo. Quanto maior, melhor o design. Do mais fraco ao mais forte:

TipoDescriçãoQualidade
CoincidentalAgrupamento não planejado; resultado de modularização arbitráriaPior
LógicaElementos logicamente categorizados juntos, mas funcionalmente distintosFraca
TemporalElementos processados em um ponto de tempo similar (ex.: inicialização)Fraca
ProcessualElementos agrupados e executados sequencialmente para uma tarefaModerada
ComunicativaElementos sequenciais que operam sobre os mesmos dadosModerada
SequencialSaída de um elemento é entrada do próximoBoa
FuncionalTodos os elementos contribuem para uma única função bem definida; reutilizávelMelhor

Acoplamento — o que é e seus 5 níveis

Acoplamento mede o nível de interdependência entre módulos. Quanto menor, melhor o design. Do mais forte ao mais fraco:

NívelDescriçãoQualidade
ConteúdoUm módulo acessa ou modifica diretamente o conteúdo interno de outroPior
Comum (global)Vários módulos têm acesso de leitura e gravação a dados globais compartilhadosRuim
ControleUm módulo decide a função ou muda o fluxo de execução de outroModerado
SeloMódulos compartilham uma estrutura de dados comum e trabalham em partes diferentes delaModerado
DadosMódulos interagem apenas passando dados como parâmetros simplesMelhor

A relação entre coesão e acoplamento

São métricas opostas mas complementares: buscamos alta coesão (elementos relacionados ficam juntos) e baixo acoplamento (módulos independem uns dos outros). Um sistema com coesão funcional e acoplamento de dados é bem projetado — cada módulo faz uma coisa só e se comunica com outros apenas por parâmetros.

Princípios práticos de design

DRY

Don’t Repeat Yourself. Cada pedaço de conhecimento deve ter uma representação única no sistema.

KISS

Keep It Simple. A solução mais simples que funciona é preferível à elegante que ninguém entende.

YAGNI

You Aren’t Gonna Need It. Não implemente o que não é necessário agora.

SOLID

5 princípios de OO: SRP, Open/Closed, Liskov, Interface Segregation, Dependency Inversion.

SOLID — os 5 princípios

LetraPrincípioEm prática
SSingle ResponsibilityUma classe deve ter apenas um motivo para mudar
OOpen/ClosedAberta para extensão, fechada para modificação
LLiskov SubstitutionSubclasses substituem a superclasse sem quebrar o sistema
IInterface SegregationMuitas interfaces específicas são melhores que uma genérica
DDependency InversionDependa de abstrações, não de implementações concretas

Padrões arquitetônicos

Padrões são soluções reutilizáveis para necessidades recorrentes (Angelov; Grefen; Greefhorst, 2009). Os mais conhecidos:

Camadas / MVC

Separação em níveis horizontais; cada camada tem responsabilidade única.

Cliente-Servidor

Divisão entre quem solicita (cliente) e quem processa (servidor).

Orientado a Eventos

Componentes comunicam-se emitindo e consumindo eventos.

SOA / Microservices

Serviços autônomos com interfaces bem definidas.

Tubos e Filtros

Dados fluem por uma sequência de transformações (filtros) conectadas por tubos.

Peer-to-Peer (P2P)

Nós iguais — cada um pode ser cliente e servidor simultaneamente.

Documento de Especificação de Projeto

Toda decisão de projeto deve ser documentada. O Documento de Especificação de Projeto (padrão IEEE) contém:

SeçãoConteúdo
IntroduçãoProposta, escopo, visão geral, referencial teórico, definições/acrônimos
Visão geral do sistemaDescrição de alto nível do software
Arquitetura do SistemaProjeto arquitetural, decomposição, projeto racional
Projeto de DadosDescrição e dicionário de dados
Projeto de ComponenteEspecificação interna de cada módulo
Projeto de InterfaceVisão geral, telas, ações e objetos
Matriz de RequisitosRastreabilidade entre requisitos e componentes

Práticas Modernas — Projeto de Software

  • ADRs (Architecture Decision Records) documentam o “por quê” de cada decisão arquitetural em arquivos Markdown versionados no Git — substituem grandes documentos de especificação que ficam desatualizados.
  • Arquitetura Evolutiva (Rebecca Parsons) defende adiar decisões estruturais enquanto possível e construir “fitness functions” que verificam automaticamente se a arquitetura continua saudável.
  • Domain-Driven Design (DDD) é a abordagem moderna para projeto de software: o modelo do sistema reflete o domínio de negócio usando uma linguagem ubíqua compartilhada por desenvolvedores e especialistas de domínio.
  • Diagramas como código: Mermaid, PlantUML e Structurizr geram diagramas de arquitetura a partir de texto — versioning, diff e revisão em Pull Requests substituem arquivos .vsd e .drawio.

Dicas para a Prova

  • Sistema de RH corporativo com acesso interno, servidor central e terminais → Cliente-Servidor. O servidor centraliza dados críticos; os terminais apenas interagem.
  • Documento de Especificação de Projeto segue padrão IEEE: 7 seções incluindo Arquitetura, Projeto de Dados, Componente e Interface.
  • Coesão funcional = melhor nível (todos os elementos contribuem para uma única função). Coesão coincidental = pior nível.
  • Acoplamento de conteúdo = pior nível (um módulo acessa internamente outro). Acoplamento por mensagem = melhor.
  • Alta coesão + baixo acoplamento = design de qualidade.

Referências bibliográficas desta UA

  • BASS, L.; CLEMENTS, P.; KAZMAN, R. Software Architecture in Practice. 3. ed. Boston: Addison-Wesley, 2012.
  • ANGELOV, S.; GREFEN, P.; GREEFHORST, D. A Classification of Software Reference Architectures. In: IEEE/IFIP WICSA & ECSA, 2009.
  • SURYANARAYANA, G.; SAMARTHYAM, G.; SHARMA, T. Refactoring for Software Design Smells. Burlington: Morgan Kaufmann, 2015.
  • LEDUR, C. L. Análise e projeto de sistemas. Porto Alegre: SAGAH, 2017.