Refatoração

 

O que é e como pode ser code "smell"?



Código pode "cheirar" porque indica potenciais problemas que podem levar a bugs, dificuldades de manutenção ou outros problemas. Os code smells são sinais de que o código pode não estar bem projetado ou implementado.

Alguns exemplos de code smells incluem:

  • Codigo duplicado: Código que é repetido em diferentes partes do programa. Isso pode dificultar a manutenção e aumentar o risco de bugs.
  • Codigo acoplado: Código que depende excessivamente de outros pedaços de código. Isso pode dificultar a mudança e a manutenção.
  • Codigo complexo: Código que é difícil de entender ou manter. Isso pode levar a erros e dificultar a evolução do programa.
  • A refatoração é o processo de melhorar o código sem alterar seu comportamento externo. Ela pode ser usada para corrigir code smells e melhorar a qualidade do código.

Aqui estão alguns exemplos de como a refatoração pode ser usada para corrigir code smells:

  • Codigo duplicado: O código duplicado pode ser combinado em uma única função ou classe.
  • Codigo acoplado: O código acoplado pode ser refatorado para usar interfaces ou abstrações.
  • Codigo complexo: O código complexo pode ser dividido em partes menores e mais fáceis de entender.

A refatoração é uma ferramenta importante para melhorar a qualidade do código. Ela pode ajudar a evitar bugs, facilitar a manutenção e melhorar a produtividade.


Em português, um code smell pode ser traduzido como "mau cheiro de código". O termo é usado para descrever código que pode indicar problemas.

Princípios de design e padrões de design com Robert Martins

 

O que é arquitetura de software? 

Segundo Robert C. Matins diz ,na  resposta que é multifacetada. 

No nível mais alto, existem os padrões de arquitetura que definem a forma e a estrutura gerais das aplicações de software [1]. 

Um nível abaixo está a arquitetura que está especificamente relacionada ao propósito da aplicação de software. 

Mais um nível abaixo reside a arquitetura dos módulos e suas interconexões. Este é o domínio dos padrões de design [2], pacotes, componentes e classes. 

É com este nível que nos preocuparemos neste artigo.

Nosso escopo neste capítulo é bastante limitado. Há muito mais a ser dito sobre os princípios e padrões que são expostos aqui. Os leitores interessados são encaminhados para [Martin99].

====================

Pelo meu entendimento que a arquitetura de software é de fato um assunto multifacetado e possui diferentes níveis de definição. No nível mais alto, temos os padrões de arquitetura que estabelecem a forma e a estrutura geral das aplicações de software. Estes padrões fornecem diretrizes abrangentes para a organização e interação dos componentes de um sistema.

Logo abaixo, temos a arquitetura específica da aplicação de software. Essa arquitetura está relacionada diretamente com o propósito e os requisitos da aplicação em questão. Ela define como os diferentes módulos e componentes se encaixam para cumprir os objetivos da aplicação.

Em um nível mais detalhado, encontramos a arquitetura dos módulos individuais e suas interconexões. Nesse nível, entram em jogo padrões de design, pacotes, componentes e classes. Esses elementos fornecem diretrizes mais específicas sobre a estrutura interna dos componentes de software, como eles se relacionam entre si e como podem ser reutilizados em diferentes contextos.

Neste artigo, focaremos principalmente nesse nível da arquitetura de software, explorando padrões de design, pacotes, componentes e classes em suas interconexões dentro de um sistema.

Os Dez Mandamentos da Programação OO


Jim Fleming


O que Jim Fleming tenta compor na Programação OO a reduzir 20 boas ideias  para 10 ao Robert Martins?

Estamos tentando compor Os Dez Mandamentos da Programação OO. Betrand Meyer disse em algum lugar que existem cerca de 20 boas ideias em OO, e é isso que a(s) linguagem(s) deve(m) suportar.
É possível reduzir tudo a 10? Se pudéssemos, poderíamos passar isso para estudantes e pessoas que estão começando no OO e isso poderia economizar algum tempo para todos.

Aqui está uma lista de exemplos, não necessariamente em ordem.

1. Os nomes das classes devem ser substantivos e os nomes dos métodos devem ser verbos.
2. Os comentários são tão importantes quanto o código e devem ser “classificados”.
3. A herança deve ajudar os novos desenvolvedores a “programar as diferenças”.
4. O encapsulamento de tudo, inclusive da fonte, é essencial.
5. Os verbos (métodos) devem ser escolhidos cuidadosamente para apoiar o polimorfismo.
6. A reutilização só pode ser alcançada quando as classes padrão são compreensíveis.
7. Novos desenvolvedores devem reutilizar as ferramentas CASE dos desenvolvedores experientes.
8. A portabilidade entre plataformas deve ter prioridade sobre outras questões de design.
9. Uma nova classe deve ser usada para cada nova interface de biblioteca legada.
10. Vários retornos devem ser usados ​​apenas para tratamento de erros e depuração.


--
Jim Fleming /|\ Unir Corporation Unir Technology, Inc.
%Techno Cat I / | \ One Naperville Plaza 184 Shuman Blvd. #100
Pouso de Penn / | \ Naperville, IL 60563 Naperville, IL 60563
East End, Tortola |____|___\ 1-708-505-5801 1-800-222-UNIR(8647)
Ilhas Virgens Britânicas__|______ 1-708-305-3277 (FAX) 1-708-305-0600
\__/-------\__/ e-mail: jim.f...@bytes.com
Navegação Suave no Cruzeiro C+@amarans
~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\______até o final da OuterNet

Linkedin: https://www.linkedin.com/in/jim-fleming-a324825/


Robert Martin


Se eu tivesse que escrever mandamentos, estes seriam candidatos.

1. As entidades de software (classes, módulos, etc.) devem estar abertas para
extensão, mas fechadas para modificação. (O princípio aberto/fechado - Bertrand Meyer)

2. As classes derivadas devem ser utilizáveis ​​por meio da interface da classe base sem a necessidade do usuário saber a diferença. (O Princípio da Substituição de Liskov)

3. Os detalhes devem depender das abstrações. As abstrações não devem depender de detalhes. (Princípio da Inversão de Dependência)

4. O grânulo de reaproveitamento é igual ao grânulo de liberação.
Somente os componentes liberados por meio de um sistema de rastreamento podem ser efetivamente reutilizados.

5. As classes dentro de um componente liberado devem compartilhar um encerramento comum.
Ou seja, se alguém precisa ser mudado, é provável que todos precisem ser mudados. O que afeta um, afeta todos.

6. As classes dentro de um componente lançado devem ser reutilizadas juntas.
Ou seja, é impossível separar os componentes uns dos outros para reaproveitar menos que o total.

7. A estrutura de dependência dos componentes lançados deve ser um DAG. Não pode haver ciclos.

8. As dependências entre os componentes liberados devem seguir na direção da estabilidade. O dependente deve ser mais estável que o depender.

9. Quanto mais estável for um componente lançado, mais ele deverá consistir em classes abstratas. Um componente completamente estável deve consistir apenas em classes abstratas.

10. Sempre que possível, utilize padrões comprovados para resolver problemas de projeto.

11. Ao cruzar dois paradigmas diferentes, construa uma camada de interface que separe os dois. Não polua um lado com o paradigma do outro.


--Roberto
Martin | Consultoria de Design | Cursos de formação oferecidos:
Object Mentor Assoc.| rma...@rcmcon.com | Análise Orientada a Objetos
2080 Cranbrook Rd. | Tel: (708) 918-1004 | Design Orientado a Objetos
Green Oaks IL 60048 | Fax: (708) 918-1023 | C++

Linkedin: https://www.linkedin.com/company/cleancoder/

Um framework para a descrição arquitetural de sistemas complexos. (IEEE 1471-2000)

 O IEEE 1471 é um padrão que define um framework para a descrição arquitetural de sistemas complexos. O título completo do padrão é "IEEE 1471-2000 Prática Recomendada para Descrição Arquitetural de Sistemas Intensivos em Software." Foi desenvolvido pelo Instituto de Engenheiros Eletricistas e Eletrônicos (IEEE) e publicado em 2000.

O objetivo do IEEE 1471 é fornecer um conjunto comum de termos e conceitos para descrever a arquitetura de sistemas intensivos em software. O padrão destina-se a ser utilizado por arquitetos de software e outros interessados envolvidos no projeto e desenvolvimento de sistemas de software complexos.

Características e conceitos-chave do IEEE 1471 incluem:

Descrição Arquitetural: Define o que constitui uma descrição arquitetural, que inclui visões, pontos de vista (viewpoints) e preocupações (concerns).

Visões e Pontos de Vista: O padrão incentiva o uso de múltiplas visões para capturar diferentes aspectos da arquitetura do sistema. As visões representam uma perspectiva sobre a arquitetura, enquanto os pontos de vista definem as convenções e regras para criar e interpretar essas visões.

Preocupações: As preocupações representam os principais interesses, objetivos ou requisitos das partes interessadas. As descrições arquiteturais são organizadas em torno dessas preocupações, e cada ponto de vista aborda uma ou mais preocupações.

Partes Interessadas: O padrão enfatiza a importância de compreender e atender às necessidades e preocupações de várias partes interessadas no sistema, incluindo usuários finais, desenvolvedores, gerentes e outros.

Abstração e Decomposição: O IEEE 1471 promove o uso de abstração e decomposição para gerenciar a complexidade e representar a arquitetura do sistema em diferentes níveis de detalhe.

Consistência e Coerência: As descrições arquiteturais devem manter consistência e coerência em diferentes visões e pontos de vista para garantir uma compreensão abrangente da arquitetura do sistema.

O IEEE 1471 é um padrão fundamental no campo da arquitetura de software e influenciou o desenvolvimento de outros frameworks e práticas arquiteturais. Ele fornece uma abordagem estruturada e sistemática para documentar e comunicar a arquitetura de sistemas intensivos em software, contribuindo para melhorar a compreensão e a qualidade desses sistemas ao longo de seu ciclo de vida.

Fontes:

- https://ieeexplore.ieee.org/document/875998/figures#figures

- https://pdfs.semanticscholar.org/e74f/0b588e95d5e3c5c5176617026f48a63655d5.pdf

- https://insights.sei.cmu.edu/documents/5445/2001_003_001_13778.pdf

O que é a arquitetura limpa na área de software?

Arquitetura apresentada pela primeira vez em 2012 por Robert Martin, em seu blog. Em 2018, Robert Martin lança o livro sobre a arquitetura limpa como solução para softwares frágeis a manutenção, ganhando atenção de muitos desenvolvedores e diretores.

A arquitetura limpa é composta por vários princípios. Alguns princípios foram criados por Robert Martin, outros foram de autoria de outros programadores experientes. Ao todo existem 11 princípios abordados:

  • Princípios SOLID (5 princípios)
    • Princípio de responsabilidade única
    • Princípio aberto fechado
    • Princípio de substituição de Liskov
    • Princípio de segregação de interfaces
    • Princípio da inversão de dependências
  • Princípios RCC (3 princípios)
    • Princípio equivalente de reuso/release (REP)
    • Princípio de fechamento comum (CCP)
    • Princípio de reuso comum (CRP)
  • Princípios ASS (3 princípios)
    • Princípio das dependências acíclicas (ADP)
    • Princípio das dependências estáveis (SDP)
    • Princípio das abstrações estáveis (SAP)

Além de abordar como o código deve ser escrito, a arquitetura limpa também fala como os componentes (conjunto de classes) devem ser agrupados, analisando a estrutura do nível de código e do nível arquitetural.

A regra de dependências é essencial na arquitetura limpa. Detalhes devem depender de abstrações, mas abstrações não devem depender de detalhes.

  O objetivo da arquitetura limpa é proteger os componentes de nível alto dos componentes de nível baixo

A proteção é feita usando a hierarquia de dependências em níveis, onde os componentes de nível baixo devem depender dos componentes de nível alto. 

Essa prática possibilita a reutilização de componentes e a substituição de detalhes por outros, uma vez que os componentes não sabem nada sobre os detalhes de nível baixo.

Imagem sobre arquitetura limpa:



Arquitetura limpa - Clean Architecture - Aplicada em softwares de grande porte.

 Eficiente quando aplicada em softwares de grande porte que necessitam de manutenção ao longo prazo. Criada em 2012 por Robert Martin.

A maioria dos softwares usam a arquitetura MVC (model view controller). O MVC tem as suas vantagens. Softwares de porte pequeno com necessidade de rápido desenvolvimento podem optar pelo MVC. Porém, essa arquitetura também tem as suas desvantagens. Projetos de grande porte que usam a arquitetura MVC, provavelmente vão ter alguns problemas ao longo prazo na realização da manutenção. O forte acoplamento entre as classes faz com que o software seja difícil de modificar ou adicionar novas funcionalidades. O termo “difícil” quer dizer mais demanda de tempo para realizar uma tarefa. Quanto mais tempo os desenvolvedores necessitam para implementar novas funcionalidades ou para fazer modificações, mais custos essa tarefa terá para a empresa que paga os seus funcionários.

Felizmente, existem outros tipos de arquitetura de software que são eficientes no quesito de manutenção. Quanto mais eficiente for a manutenção, menor serão os custos. A arquitetura limpa (clean architecture) é uma boa arquitetura para projetos de porte grande que irão demandar manutenções frequentes no futuro.

Design Modular conhecido como projeto na área de engenharia de softwares

 

Projeto Modular: O papel do projeto modular eficaz na engenharia de software

Qualquer software é composto por muitos sistemas que contêm vários subsistemas, e esses subsistemas contêm ainda seus subsistemas. Portanto, projetar um sistema completo de uma só vez, compreendendo todas as funcionalidades necessárias, é um trabalho árduo e o processo pode ter muitos erros devido ao seu grande tamanho.

Assim, para resolver este problema, a equipe de desenvolvimento divide todo o software em vários módulos. Um módulo é definido como os componentes exclusivos e endereçáveis do software que podem ser resolvidos e modificados independentemente, sem perturbar (ou afetar em uma quantidade muito pequena) outros módulos do software. Portanto, todo projeto de software deve seguir a modularidade.

O processo de dividir um software em vários módulos independentes, onde cada módulo é desenvolvido separadamente, é chamado de modularização.

Um projeto modular eficaz pode ser alcançado se os módulos particionados forem separadamente solucionáveis, modificáveis e compiláveis. Aqui, módulos compiláveis separadamente significa que, depois de fazer alterações em um módulo, não há necessidade de recompilar todo o sistema de software.

Para construir um software com projeto modular eficaz, existe um fator "Independência Funcional" que entra em jogo. O significado de Independência Funcional é que uma função é de natureza atômica, de modo que executa apenas uma única tarefa do software, sem ou com pouca interação com outros módulos. A Independência Funcional é considerada um sinal de crescimento na modularidade, ou seja, a presença de maior independência funcional resulta em um sistema de software de bom design, e o design afeta ainda mais a qualidade do software.

Benefícios de módulos/funções independentes em um projeto de software:

Uma vez que a funcionalidade do software foi decomposta em níveis atômicos, os desenvolvedores obtêm um requisito claro de cada função e, portanto, o projeto do software torna-se fácil e livre de erros.

Como os módulos são independentes, eles têm dependência limitada ou quase nenhuma em outros módulos. Portanto, fazer alterações em um módulo sem afetar todo o sistema é possível nesta abordagem.

A propagação de erros de um módulo para outro e ainda mais para todo o sistema pode ser negligenciada, o que economiza tempo durante o teste e a depuração.


Objeto de valor por Martin Fowler

  Ao programar, muitas vezes acho útil representar coisas como compostos. Uma coordenada 2D consiste em um valor x e um valor y. Uma quantia...