Diretrizes de Desenvolvimento
15. Qualidade de Código

15. Qualidade de Código

A qualidade do código é fundamental para a manutenibilidade, escalabilidade e eficiência de nossos projetos. Esta seção fornece diretrizes detalhadas para garantir a excelência em nosso código, com foco especial em Laravel, Node.js e TypeScript.

15.1. Métricas de qualidade

Para medir objetivamente a qualidade do nosso código, utilizamos as seguintes métricas:

  1. Complexidade Ciclomática: Mantenha abaixo de 10 por método.
  2. Profundidade de Herança: Não exceda 3 níveis.
  3. Acoplamento Aferente: Mantenha abaixo de 10 por classe.
  4. Coesão: Busque alta coesão em cada classe e módulo.
  5. Cobertura de Testes: Mantenha acima de 80% para código crítico.

15.2. Ferramentas de análise estática

Utilizamos as seguintes ferramentas para análise estática de código:

  • PHP/Laravel: PHPStan, PHP_CodeSniffer
  • Node.js/TypeScript: ESLint, TSLint
  • Geral: SonarQube

Exemplo de configuração do PHPStan para Laravel:

# phpstan.neon
parameters:
    level: 8
    paths:
        - app
    excludePaths:
        - vendor
    ignoreErrors:
        - '#PHPDoc tag @var#'
    checkMissingIterableValueType: false

Exemplo de configuração do ESLint para TypeScript:

// .eslintrc.json
{
  "parser": "@typescript-eslint/parser",
  "plugins": ["@typescript-eslint"],
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  "rules": {
    "@typescript-eslint/explicit-function-return-type": "error",
    "no-unused-vars": "off",
    "@typescript-eslint/no-unused-vars": ["error"]
  }
}

15.3. Refatoração e melhoria contínua

A refatoração deve ser uma prática constante. Algumas técnicas importantes:

  1. Extrair Método: Divida métodos longos em métodos menores e mais focados.
  2. Renomear: Use nomes claros e descritivos para variáveis, métodos e classes.
  3. Substituir Condicional por Polimorfismo: Use herança e interfaces para substituir condicionais complexos.

Exemplo de refatoração em TypeScript:

// Antes
function calculateTotal(items: Item[], discountType: string): number {
    let total = items.reduce((sum, item) => sum + item.price, 0);
    if (discountType === 'PREMIUM') {
        total *= 0.9;
    } else if (discountType === 'VIP') {
        total *= 0.8;
    }
    return total;
}
 
// Depois
interface DiscountStrategy {
    applyDiscount(total: number): number;
}
 
class PremiumDiscount implements DiscountStrategy {
    applyDiscount(total: number): number {
        return total * 0.9;
    }
}
 
class VIPDiscount implements DiscountStrategy {
    applyDiscount(total: number): number {
        return total * 0.8;
    }
}
 
class NoDiscount implements DiscountStrategy {
    applyDiscount(total: number): number {
        return total;
    }
}
 
function calculateTotal(items: Item[], discountStrategy: DiscountStrategy): number {
    const total = items.reduce((sum, item) => sum + item.price, 0);
    return discountStrategy.applyDiscount(total);
}

15.4. Code smells e como evitá-los

Alguns code smells comuns e como evitá-los:

  1. Duplicação de Código: Use o princípio DRY (Don't Repeat Yourself).
  2. Métodos Longos: Divida em métodos menores e mais focados.
  3. Classes Grandes: Aplique o princípio de Responsabilidade Única (SRP).
  4. Lista de Parâmetros Longa: Use objetos de parâmetros ou builder pattern.
  5. Mudança Divergente: Separe responsabilidades em classes diferentes.

15.5. Princípios SOLID

Aplique os princípios SOLID em todos os projetos:

  1. Single Responsibility Principle
  2. Open/Closed Principle
  3. Liskov Substitution Principle
  4. Interface Segregation Principle
  5. Dependency Inversion Principle

Exemplo de aplicação do Single Responsibility Principle em Laravel:

// Antes
class User extends Model
{
    public function createPost($title, $content)
    {
        // Lógica para criar um post
    }
 
    public function sendEmail($subject, $body)
    {
        // Lógica para enviar email
    }
}
 
// Depois
class User extends Model
{
    // Apenas métodos relacionados ao usuário
}
 
class PostService
{
    public function createPost(User $user, $title, $content)
    {
        // Lógica para criar um post
    }
}
 
class EmailService
{
    public function sendEmail(User $user, $subject, $body)
    {
        // Lógica para enviar email
    }
}