Mostrando postagens com marcador QUALIDADE DE SISTEMAS. Mostrar todas as postagens

quinta-feira, 29 de setembro de 2016

Tipos de Code Smells

Fala galera que acompanha o blog...

Antes de continuar lendo esse post sobre os Tipos de Code Smells, eu sugiro que caso não saiba o que são Code Smells, leia o post que fizemos sobre o que são Code Smells.

Bom, com o paradigma de orientação a objetos existem duas categorias de code smells: Within Classes (dentro de classes) e Between Classes (Entre classes).



Tipos de Code Smells


Code Smells within classes



Comments:
     É evidenciado pelo excesso de comentários que não necessariamente precisariam ser escritos e, ao invés de auxiliar, acabam por prejudicar o entendimento do código-fonte. Sempre atentar para que as explicações deixadas nos comentários e ter em mente que o comentário está sendo escrito para as pessoas, e não para as máquinas.

Long Method:
    Não importa qual o paradigma escolhido, mas saiba-se que métodos, funções ou procedimentos extremamente longos são difíceis de entender. Quanto maiores eles são e quanto mais parâmetros e variáveis eles usam, os tornam mais propensos a fazer mais do que seu nome sugere. Métodos curtos são mais “entendíveis” em relação ao que o seu código-fonte faz, permite um maior reuso de código e mais flexibilidade. Claro que, com métodos mais curtos há mais elementos para cuidar, e ter mais chamadas aos métodos curtos significa mais vezes tendo que verificar o que o método chamado realmente faz. Entretanto, se é dado aos métodos bons nomes, que mostram quais os seus propósitos, elimina-se muito a necessidade de olhar para o corpo dos métodos e a necessidade de adicionar comentários para esclarecer o código-fonte.

Too many parameters (Long Parameter List):
     Em programação orientada por objetos, a maioria dos dados necessários a um método pode ser diretamente obtida a partir dos próprios objetos, caso eles sejam visíveis para o método, ou eles podem ser derivados através de um pedido de outro parâmetro. Portanto, as listas de parâmetros devem ser curtas, pois quanto mais extensas se tornam mais difíceis de ler, difícil de usar e elas mudam muito quando mais dados são necessários. Fazer uma mudança para uma lista de parâmetros significa mudar todas as referências ao método envolvido. E assim, mantê-lo curto.

Duplicated Code:
     É caracterizado quando um código idêntico ou muito semelhante existe em mais de um local. Deve-se atentar para eliminar toda e qualquer duplicação sempre que possível. Procurando sempre casos mais sutis de quase duplicação no código-fonte escrito.

Large Class:
    As classes grandes são caracterizadas por deterem muitas responsabilidades, com muitos dados e/ou métodos demais. O que torna isto um problema, porque essas classes são difíceis de manter e compreender devido ao seu tamanho. As classes grandes muitas vezes recai nas situações que exemplificam “Duplicated Code” ou “Shotgun Surgery”. A solução é encontrar partes de dados e métodos que parecem estar bem relacionados e refatorar utilizando Extract Class.

Type Embedded in Name:
     Situação onde se coloca nomes de tipos em nomes de métodos. Isto não é apenas redundante, mas o obriga a mudar o nome, se as mudanças de tipo se fizerem necessárias, ou numa opção pior ainda: nome “tipado” divergente do tipo definido permanece inalterado no código-fonte.

Uncommunicative Name:
     Ocorre quando se opta por colocar nomes em métodos que não descreve sucintamente o que ele faz. O ideal é que os métodos procurem sempre passar de forma simplista, a função que o mesmo detém, apenas no nome que lhe é dado. Fazendo isso, evita-se no futuro em uma refatoração ter que renomeá-lo ou reescrevê-lo.

Inconsistent Names:
     Comumente acontece quando não se atenta para o conjunto de nomes dados aos métodos, de uma forma mais ampla, e só se detém a uma escolha que descreve minimamente tal método, sem transparecer a correlação com que ele tem com os demais criados. Para resolver isso, basta na hora da escolha optar por um conjunto de terminologia padrão e cumpri-lo em todos os seus métodos. Por exemplo, se existe Open(), provavelmente deve ter Close().

Dead Code:
     Acontece quando o desenvolvedor não elimina trechos de código-fonte que não está sendo utilizado pelo sistema, pensando que o mesmo poderá ser preciso futuramente. A boa prática prega que se deve apagar tal código-fonte que não está sendo usado e, se necessário, obtê-lo a partir do controle de versão do projeto.

Speculative Generality:
     Fica explicito quando se escreve código-fonte que não atende nenhum propósito no momento e se pensa em expandi-lo para efetivamente representar algo no sistema apenas no futuro. Para isso deve-se manter o foco e apenas escrever código para resolver os problemas de hoje, não se preocupando com os problemas de amanhã, quando realmente se concretizar. Atenção para isso: Não quer dizer que a abordagem é escrever código-fonte sem pensar no uso futuro dele, pois certo é escrever o que precisa hoje de modo a ser expansível, e errado é criar “esqueletos” de código-fonte inacabados (ou até acabados mas sem ligação alguma) e que existe uma definição real de que o mesmo será utilizado um dia.

Conditional Complexity:
     Lógica condicional é relativamente fácil de ser compreendida quando bem aplicada e contida dentro de algumas linhas de código-fonte. Infelizmente, isso raramente acontece. Ocorre geralmente quando são implementados vários recursos novos e de repente a lógica condicional torna-se bastante complexa e confusa. Portanto deve-se ter cautela com os grandes blocos lógicos condicionais, particularmente blocos que tendem a crescer ou mudar significativamente ao longo do tempo.

Combinatorial Explosion:
     Trata de uma forma sutil de duplicação. Ela existe quando há vários trechos de código-fonte que fazem a mesma coisa usando diferentes tipos ou quantidades de dados ou objetos. Por exemplo: existem vários métodos em uma classe para executar consultas. Cada um destes métodos executa uma consulta usando condições específicas, podendo o desenvolvedor recair numa condição de explosão de métodos ao criar inúmeros deles para lidar com as muitas maneiras de realizar consultas.

Oddball Solution:
     É caracterizado quando um dado problema é resolvido de duas maneiras diferentes no mesmo sistema, uma das soluções é tida como a excêntrica ou solução inconsistente. A presença dessa constatação geralmente indica sutilmente código duplicado. Para remover essa duplicação, primeiro determine a maneira preferida, e depois pode se aplicar o “Substitute Algorithm” para produzir uma solução consistente em todo o sistema. Dada uma solução consistente, É possível mover todas as instâncias da solução para um lugar, eliminando assim a duplicação.

Temporary Field:
     É evidenciado quando a variável está no escopo da classe, quando deveria estar no escopo do método. Violando o princípio ocultação de informação. Por meio do Extract Class é possível sanar tal situação.

Code Smells between classes

Alternative Classes with Different Interfaces:
     Classes similares por dentro, mas diferente por fora. Elas podem ser modificadas para partilhar uma interface comum.

Primitive Obsession:
    Usar muitas variáveis primitivas para representar tipos complexos. Se o tipo de dados é bastante complexo, escreve-se uma classe para representá-lo.

Data Class:
     Usar classes só para conter dados. Classes com campos, getters e setters e nada mais.

Data Clumps (Aglomerados de dados):
    Os mesmos dados sendo manipulados em diferentes níveis podem estar relacionados. Considera-se colocar os dados relacionados acima em uma classe maior.

Refused Bequest:
     Herda mas não usa nada, então não se faz necessário a herança, pois está apenas contribuindo para o alto acoplamento.

Inappropriate Intimacy:
     Comportamento de uma classe influenciado por aspectos internos de outra classe. As classes deve saber o mínimo possível sobre de uma sobre a outra.

Indecent Exposure:
     Demasiado uso de public.

Feature Envy:
     Método que usa muito, mas muito mesmo, uma outra classe. Em geral, tenta-se colocar um método na classe que contém a maioria dos dados que o método necessita.

Lazy Class:
     Classe que não atende a si mesma e joga parte de sua responsabilidade para outras.

Message Chains:
     Métodos com muita execução ou variáveis temporárias para dados de rotina.

Middle Man:
     Classes delegando toda sua responsabilidade para outras.

Divergent Change:
     Uma alteração pontal afeta aspectos completamente diferentes.

Shotgun Surgery:
    Oposto da mudança divergente, pois para uma alteração pontal tem que mexer em várias classes.

Parallel Inheritance Hierarchies:
     Ao herdar uma classe tem que criar uma subclasse similar à subclasse presente na herdada.

Incomplete Library Class:
     Não é possível alterar a biblioteca e o método acaba indo para uma classe qualquer.

Solution Sprawl:
     Se precisar de 5 ou mais classes para fazer algo útil, precisa simplificar e consolidar.


Esta lista foi obtida a partir do arquivo  Smells to Refactorings PDF, e do Wiki Smells to Refactorings Wiki,, que também fornecem orientações adicionais sobre as refatorações específicas que podem ser úteis em cada caso.

Não fique encabulado com todos esses problemas que podem ser encontrados no código, é claro que um código limpo é sempre bem vindo, mas o mais importante é saber identificar esses mau cheiros do código e assim aplicar a refatoração adequada para cada caso.

É isso pessoal até a próxima!

Code Smells

Fala galera que acompanha o blog...

Você já sentiu um cheiro enquanto programava, refatorava ou reutilizava o código de alguém? Aquele cheiro, que na verdade é uma sensação de código ruim, aquele trecho que você olha e pensa "humm isso aqui pode dar m3#d@!", ou então, aquele comentário explicando o código e pior ainda aquele comentário "Se remover esse trecho o sistema para de funcionar", sabe?


Code Smells

Esses exemplos citados (e vários outros) são chamados de Code Smells, ou "Mau cheiro no código".

Na literatura é possível verificar que alguns autores preferem dividir a lista de code smells em duas partes, os que estão em uma classe e os que envolvem mais de uma classe. Veja esse post sobre os Tipos de Code Smells.

Hoje existem vários padrões já identificados e difundidos. A partir destes padrões você pode avaliar seu código e verificar se ele está "muito mau cheiroso".


A Industrial Logic disponibilizou uma lista dos padrões de code smells mais conhecidos e das possíveis técnicas de refatoração que você pode utilizar para eliminar estes problemas.

É uma lista muito interessante e bastante útil para ser consultado naquele momento em que queremos alterar o código fonte e tentar melhorá-lo.


No entanto antes de iniciar o processo de refatoração, lembre-se de criar testes unitários e/ou de integração para garantir que as alterações realizadas não "quebraram" a sua aplicação.
Sem dúvida, o exemplo de code smells mais simples e corriqueiro que acontece no código, são as linhas em branco dentro de um método. Muitas vezes achamos que a linha em branco esta sendo usado para melhorar a leitura do código, usamos como uma forma de indentação, mas que na verdade, ao analisar melhor o trecho, percebemos que essa linha em branco está separando duas atividades dentro de um mesmo método, ou seja, poderíamos converter tudo que está abaixo dessa linha em branco em um outro método.

A linha em branco não é o problema em si. Ela só indica que há um problema.

Não saia refatorando todo o seu código de uma só vez, na medida que for utilizando as classes e seus métodos vá fazendo as correções necessárias.
Você pode seguir os seguintes passos:


  1. Encontre um Método;
  2. Caso não exista testes que garantam a funcionalidade, crie-os;
  3. Verifique se há linhas em branco separando blocos;
  4. Para cada bloco, extraia o código criando um novo Método;
  5. Faça a chamada do novo Método no mesmo lugar que extraiu o código;
  6. Repita o processo enquanto for necessário.

Se você gostou do assunto e se interessou em saber mais em como manter seu código limpo, pode começar lendo um livro muito bacana do autor Robert C. Martin ou "Uncle Bob" ( Tio Bob ), que é uma grande personalidade na comunidade de desenvolvimento de software, métodos ágeis e vários outros ramos, até porque o Tio Bob ai, atua na área desde 1970, e seu livro se chama Clean Code (Código Limpo).

"O renomado especialista em software, Robert C. Martin, apresenta um paradigma revolucionário com Código limpo: Habilidades Práticas do Agile Software. Martin se reuniou com seus colegas do Mentor Object para destilar suas melhores e mais ágeis práticas de limpar códigos “dinamicamente” em um livro que introduzirá gradualmente dentro de você os valores da habilidade de um profissional de softwares e lhe tornar um programador melhor –mas só se você praticar.

Que tipo de trabalho você fará? Você lerá códigos aqui, muitos códigos. E você deverá descobrir o que está correto e errado nos códigos. E, o mais importante, você terá de reavaliar seus valores profissionais e seu comprometimento com o seu ofício."

Mais informações sobre o livro acesse o site AltaBooks:


Bom pessoal é isso... parece bobeira mas a verdade é que escrever código qualquer um faz, existem diversos tutoriais sobre programação e tudo mais, mas escrever um bom código, no entanto, não é pra qualquer um. Pense no longo prazo, no acoplamento, na coesão, no design, deixe as coisas simples.



Até a próxima!