Escrever código é uma arte, e como toda arte, existem princípios que podem elevar a qualidade de sua obra. No mundo da programação, um desses princípios é o Clean Code. Mas o que exatamente significa “código limpo”?

Clean Code, como popularizado por Robert C. Martin (Uncle Bob), refere-se a um código que é fácil de ler, entender, manter e estender. Ele não apenas funciona, mas também é elegante e coeso, facilitando a vida de qualquer desenvolvedor que precise interagir com ele – incluindo você no futuro.

Por que o Clean Code é importante? Link para o cabeçalho

Imagine um cenário onde você precisa corrigir um bug ou adicionar uma nova funcionalidade em um sistema. Se o código for confuso, mal organizado e cheio de “atalhos”, essa tarefa se torna um pesadelo. Você gastará mais tempo decifrando o que foi feito do que realmente trabalhando na solução. Isso leva a:

  • Aumento de Custos: Mais tempo de desenvolvimento e manutenção.

  • Mais Bugs: Código difícil de entender é mais propenso a erros.

  • Desmotivação da Equipe: Ninguém gosta de trabalhar em um “legado” bagunçado.

  • Dificuldade de Escalabilidade: Adicionar novas funcionalidades se torna um quebra-cabeça.

Em contraste, um código limpo promove a colaboração, acelera o desenvolvimento e reduz a ocorrência de bugs, resultando em um produto final de maior qualidade.

Princípios do Clean Code (resumido): Link para o cabeçalho

  • Nomes Significativos: Variáveis, funções e classes devem ter nomes que revelem sua intenção.

  • Funções Pequenas: Cada função deve fazer apenas uma coisa e fazê-la bem.

  • Sem Duplicação: Evite repetir código. Use abstrações e funções para reutilização.

  • Comentários Justificados: Comentários são para explicar o “porquê”, não o “o quê”. Um bom código é autoexplicativo.

  • Tratamento de Erros: Lidar com erros de forma explícita e clara.

  • Consistência: Mantenha um estilo de codificação consistente em todo o projeto.

Exemplo Prático em PHP: Do “Bad Code” ao “Clean Code” Link para o cabeçalho

Vamos considerar um exemplo simples em PHP para gerenciar uma lista de produtos.

Cenário: Código Sem Clean Code (Bad Code) Link para o cabeçalho

<?php

function p($a, $b, $c) {
    if ($a == "ad") {
        // adicionar produto
        $sql = "INSERT INTO pr (n, p) VALUES ('" . $b . "', " . $c . ")";
        // executar sql
        echo "Produto adicionado!";
    } elseif ($a == "up") {
        // atualizar produto
        $sql = "UPDATE pr SET n = '" . $b . "', p = " . $c . " WHERE id = " . $_GET['id'];
        // executar sql
        echo "Produto atualizado!";
    } elseif ($a == "de") {
        // deletar produto
        $sql = "DELETE FROM pr WHERE id = " . $b;
        // executar sql
        echo "Produto deletado!";
    } else {
        echo "Operação inválida!";
    }
}

// Exemplo de uso
// p("ad", "Laptop", 1200);
// p("up", "Teclado", 150); // Supondo que $_GET['id'] esteja definido
// p("de", 5, 0); // Deletar produto com ID 5

?>

Problemas com este código: Link para o cabeçalho

  • Nomes Obscuros: p, a, b, c, pr, n são nomes que não revelam a intenção.

  • Multiplas Responsabilidades: A função p faz adição, atualização e exclusão, violando o princípio de “uma função, uma responsabilidade”.

  • Magic Strings: Usar "ad", "up", "de" sem contexto claro.

  • SQL Injection Vulnerável: Concatenação direta de strings para construir consultas SQL é uma falha de segurança grave.

  • Falta de Abstração: Operações de banco de dados misturadas com a lógica de negócios.

  • Dependência Externa: Usa $_GET['id'] diretamente dentro da função.

  • *Sem Retorno Claro: A função apenas imprime mensagens, dificultando o teste e a integração.

Cenário: Com Clean Code Link para o cabeçalho

Para transformar o código acima em um código limpo, vamos aplicar alguns princípios:

  1. Classes e Objetos: Encapsular a lógica relacionada a produtos em uma classe.

  2. Nomes Descritivos: Usar nomes claros para variáveis, funções e métodos.

  3. Responsabilidade Única: Cada método fará uma única coisa.

  4. Injeção de Dependência: Passar dependências (como a conexão com o banco de dados) em vez de criá-las internamente.

  5. Prevenção de SQL Injection: Usar Prepared Statements.

  6. Retornos Significativos: Retornar booleanos ou objetos para indicar o sucesso/falha da operação.

<?php

class ProductRepository
{
    private PDO $dbConnection;

    public function __construct(PDO $dbConnection)
    {
        $this->dbConnection = $dbConnection;
    }

    public function addProduct(string $name, float $price): bool
    {
        try {
            $stmt = $this->dbConnection->prepare("INSERT INTO products (name, price) VALUES (:name, :price)");
            $stmt->bindParam(':name', $name);
            $stmt->bindParam(':price', $price);
            return $stmt->execute();
        } catch (PDOException $e) {
            error_log("Error adding product: " . $e->getMessage());
            return false;
        }
    }

    public function updateProduct(int $id, string $name, float $price): bool
    {
        try {
            $stmt = $this->dbConnection->prepare("UPDATE products SET name = :name, price = :price WHERE id = :id");
            $stmt->bindParam(':id', $id);
            $stmt->bindParam(':name', $name);
            $stmt->bindParam(':price', $price);
            return $stmt->execute();
        } catch (PDOException $e) {
            error_log("Error updating product: " . $e->getMessage());
            return false;
        }
    }

    public function deleteProduct(int $id): bool
    {
        try {
            $stmt = $this->dbConnection->prepare("DELETE FROM products WHERE id = :id");
            $stmt->bindParam(':id', $id);
            return $stmt->execute();
        } catch (PDOException $e) {
            error_log("Error deleting product: " . $e->getMessage());
            return false;
        }
    }
}

// Exemplo de uso (assumindo uma conexão PDO válida)
$dsn = 'mysql:host=localhost;dbname=mydatabase;charset=utf8mb4';
$username = 'root';
$password = '';

try {
    $pdo = new PDO($dsn, $username, $password, [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES => false,
    ]);
} catch (PDOException $e) {
    die("Database connection failed: " . $e->getMessage());
}

$productRepository = new ProductRepository($pdo);

if ($productRepository->addProduct("Laptop", 1200.00)) {
    echo "Produto Laptop adicionado com sucesso!" . PHP_EOL;
} else {
    echo "Falha ao adicionar Laptop." . PHP_EOL;
}

// Supondo que você queira atualizar o produto com ID 1
$productIdToUpdate = 1;
if ($productRepository->updateProduct($productIdToUpdate, "Teclado Mecânico", 150.00)) {
    echo "Produto com ID {$productIdToUpdate} atualizado com sucesso!" . PHP_EOL;
} else {
    echo "Falha ao atualizar produto com ID {$productIdToUpdate}." . PHP_EOL;
}

// Supondo que você queira deletar o produto com ID 5
$productIdToDelete = 5;
if ($productRepository->deleteProduct($productIdToDelete)) {
    echo "Produto com ID {$productIdToDelete} deletado com sucesso!" . PHP_EOL;
} else {
    echo "Falha ao deletar produto com ID {$productIdToDelete}." . PHP_EOL;
}

?>

Conclusão Link para o cabeçalho

Embora o exemplo de “Clean Code” seja mais longo, ele é infinitamente mais legível, seguro e fácil de manter. Nomes claros, responsabilidades bem definidas e o uso de recursos de segurança (Prepared Statements) transformam um pedaço de código caótico em uma base sólida para um software robusto.

Investir tempo para escrever código limpo é um investimento no futuro do seu projeto e na sanidade da sua equipe. Comece a aplicar esses princípios hoje e veja a diferença!