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:
- Complexidade Ciclomática: Mantenha abaixo de 10 por método.
- Profundidade de Herança: Não exceda 3 níveis.
- Acoplamento Aferente: Mantenha abaixo de 10 por classe.
- Coesão: Busque alta coesão em cada classe e módulo.
- 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: falseExemplo 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:
- Extrair Método: Divida métodos longos em métodos menores e mais focados.
- Renomear: Use nomes claros e descritivos para variáveis, métodos e classes.
- 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:
- Duplicação de Código: Use o princípio DRY (Don't Repeat Yourself).
- Métodos Longos: Divida em métodos menores e mais focados.
- Classes Grandes: Aplique o princípio de Responsabilidade Única (SRP).
- Lista de Parâmetros Longa: Use objetos de parâmetros ou builder pattern.
- Mudança Divergente: Separe responsabilidades em classes diferentes.
15.5. Princípios SOLID
Aplique os princípios SOLID em todos os projetos:
- Single Responsibility Principle
- Open/Closed Principle
- Liskov Substitution Principle
- Interface Segregation Principle
- 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
}
}