Skip to content

Instantly share code, notes, and snippets.

@douglasconstancio
Created April 30, 2019 10:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save douglasconstancio/bd40a478ad2f22c3a5e69dfb3ffd96a0 to your computer and use it in GitHub Desktop.
Save douglasconstancio/bd40a478ad2f22c3a5e69dfb3ffd96a0 to your computer and use it in GitHub Desktop.

Anti-patterns e código limpo


Conceitos

Quando se fala em desenvolvimento de software é comum ouvirmos sobre design patterns, ou padrão de projeto, que nada mais é do que uma solução geral para um problema que ocorre com frequência dentro de um determinado contexto no projeto de software. Assim, um anti-padrão é:

[...] um padrão de projeto de software que pode ser comumente usado, mas é ineficiente e/ou contra-produtivo em prática.

Anti-patterns

Desenvolver software legível, reutilizável, e refatorável é essencial para ter um código limpo. Desse modo:

Clean Code é um estilo de desenvolvimento que tem por foco a facilidade para escrever, ler e manter o código.

Anti-patterns conhecidos

  1. Organizacionais
  2. Gerência de projeto
  3. Análise
  4. Design
  5. Desenvolvimento
  6. Metodológicos

Organizacionais

  • Barraca de bicicleta: Dedicar grande esforço a questões triviais
    • Ex.: Indicadores, previsão do tempo
  • Vaca do dinheiro: Um produto legado que às vezes leva à complacência sobre novos produtos
    • Ex.: Repetir erros históricos
  • Projeto por submissão: O resultado de ter vários contribuintes para o projeto, mas nenhuma visão unificada
    • Ex.: Querys
  • Agravamento de compromisso: Falhar em revogar uma decisão quando provada errada
  • Pensar em grupo: Um estado coletivo onde membros de um grupo começam a (comumente sem saber) pensar semelhantemente e passam a rejeitar pontos de vista diferentes
  • Gerência por objetivos: Gestão por números, focando exclusivamente em critério de gerência quantitativo, quando estes não são essenciais ou custam muito para alcançar
    • Ex.: Escopo inicial do projeto (Árvore Lógica, Planta Gráfica, Indicadores)
  • 'Microgerência': Ineficácia da observação e supervisão excessivas, ou outros excessos do envolvimento da gerência na prática
    • Ex.: Envolvimento dos stakeholders com o time, UX
  • Risco moral: Isolar alguém das consequências da sua decisão
    • Ex.: O time não foi envolvido nas reuniões de definição do projeto
  • Gerência cogumelo: Manter funcionários desinformados e mal-informados
  • Gerência gaivota: Gerência onde os gerentes só interagem com os empregados quando um problema aparece, ocasião na qual eles "pousam, fazem muito barulho, culpam todos, não resolvem o problema e então voltam a voar"
    • Ex.: Aspectos levantados na reunião geral de retrospectiva

Gerência de projetos

  • Marcha da morte: Todos sabem que o software será um desastre - exceto o CEO - então a verdade é escondida
  • Fumaça e espelhos: Demonstrar funções não implementadas como se já tivessem sido implementadas

Análise

  • Apatia do espectador: Quando uma decisão de análise é errada, mas quem percebe não faz nada pois afeta um número maior de pessoas

Design

  • Gold plating: Continuar a trabalhar em uma tarefa ou projeto passando do ponto em que esforço extra adiciona valor
  • Sistema chaminé: Um sistema montado difícil de ser mantido pelos componentes mal-relacionados

Desenvolvimento

  • Complexidade acidental: Introdução de complexidade desnecessária em uma solução
  • Âncora do barco: Manter uma parte de um sistema que não tem mais uso
  • Culto de programação: Usar padrões sem saber o motivo
  • Fluxo de lava: Manter código indesejável (redundante ou de baixa qualidade) porque removê-lo é caro ou tem consequências imprevisíveis
  • Números mágicos: Incluir números inexplicados em algoritmos
    • Ex.: Acesso por índices
  • Strings mágicas: Incluir literais no código para comparações inexplicadas
  • Don't repeat yourself: Escrever código que contém padrões repetitivos, a serem evitados com o princípio da abstração
    • Ex.: For dentro de For
  • Código espaguete: Programas que têm a estrutura pouco compreensível, especialmente por mal uso das estruturas de código
    • Ex.: Classe de ordem de serviço

Metodológicos

  • Programação por copiar/colar: Copiar (e modificar) código existente ao invés de criar soluções genéricas
    • Ex.: O sistema inteiro?
  • Martelo de ouro: Assumir que uma solução favorita é aplicável universalmente
  • Fator de improbabilidade: Assumir que é improvável que um erro conhecido ocorra
  • Otimização prematura: Preocupar cedo com eficiência, sacrificando um bom desenho, manutenabilidade e, às vezes, até a eficiência
  • Reinventar a roda: Falhar em adotar uma solução adequada e existente
    • Ex.: Desenvolver uma funcionalidade quando seria possível utilizar uma lib estável
  • Reinventar a roda quadrada: Falhar em adotar uma solução existente e no lugar adotar uma customizada que é bem pior

Clean code: Por onde começar?

  1. Variáveis
  2. Funções
  3. Objetos e Estruturas de Dados
  4. Classes
  5. Tratamento de Erros
  6. Testes

Variáveis

  • Use nomes pronunciáveis e com significado

const mntv003 = await this.mntv003(equipmentCode)
const mntv002 = await this.mntv002(equipmentCode)

✔️

const mntv003 = await this.mntv003(equipmentCode)
const mntv002 = await this.mntv002(equipmentCode)
  • Seja consistente na nomenclatura

function getExistingEquipment(): IEquipment
...
const existentEquipment = getExistingEquipment()

✔️

function getExistingEquipment(): IEquipment
...
const existingEquipment = getExistingEquipment()
  • Evite mapas mentais

const u = getUser()
const s = getSubscription()
const t = charge(u, s)

✔️

const user = getUser()
const subscription = getSubscription()
const transaction = charge(user, subscription)
  • Não adicione contexto desnecessário

type Equipment = {
    equipmentCode: string
    equipmentDescription: string
    equipmentTag: string
}

✔️

type Equipment = {
    code: string
    description: string
    tag: string
}

Funções

  • Evite muitos argumentos

mountInputUpd(
    protheusBranch: string,
    serviceOrder: ServiceOrder,
    taskCode: string,
    input: ESTInputReturn | PTInputReturn,
    taskSequence: string
) {
    ...
}

✔️

async update(userId: string, fields: AreaInput) {
    ...
}
  • Use doc-comments
/**
 * Updates a branch for a given user id
 *
 * @param userId user id
 * @param fields fields to update, only `name` is allowed currently
 * @returns the updated branch
 * @throws {AuthorizationError} if the user is not an admin
 */
  • Funções devem fazer uma coisa (funções da classe de ordem de serviço)
  • Nomes das funções devem dizer o que fazem

async mntv003(equipment: string) {
    ...
}

✔️

async totalHoursToRepair(equipment: string) {
    ...
}
  • Funções devem ter apenas um nível de abstração (não faça for dentro de for)
  • Evite código duplicado
  • Evite flags em funções

getTreeQuery(isForeseen: boolean) {
    ...
}

✔️

getTreeQuery() {
    ...
}

getForeseenTreeQuery(isForeseen: boolean) {
    ...
}
  • Evite condicionais, no geral

Objetos e Estruturas de Dados

  • Configure a visibilidade dos membros

async update(...params) {
    ...
}

✔️

private async update(...params) {
    ...
}

Classes

  • Classes devem ser pequenas
    • Ex.: Classe de ordem de serviço
  • Alta coesão e baixo acoplamento
    • Coesão define o grau de relação entre uma classe e seus membros. Uma classe altamente coesa faz uso máximo de seus membros em todos os métodos.
    • Acoplamento define o relacionamento entre classes e entidades. Quanto mais independente ela for, menos acoplada se torna. Classes com baixo acoplamento podem ser refatoradas sem implicar problemas em outras partes do programa que não deveriam ser relacionadas.
  • Prefira composição a herança

Tratamento de Erros

  • Não ignore erros

async removeChecklistBySO(...params) {
    ...
    await repository.delete(query).catch(() => undefined)
}

✔️

async removeChecklistBySO(...params) {
    ...
    await repository.delete(query)
}

Testes

  • Testes devem ser determinísticos
  • Cada teste deve testar uma coisa

Referências

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment