Introdução
Sempre que reescrevemos nosso código enxergamos o código antigo como ruim e refatoramos. Isso é ótimo afinal significa que estamos avançando na qualidade do mesmo.
Porem, entretanto, todavia existem formas de melhor escrever seu código sendo estas as chamadas boas práticas. Que aprimoram tanto o nome quanto a capacidade do código de se autorresolver mais rápido e de forma mais eficiente.
Formas mais comuns:
- D.R.Y
- Early Return
- Guard Clauses
- Tratamento de erros
D.R.Y
D.r.y ou Dont Repeat Yourself é um conceito da programação que consiste em dizer que cada porção do conhecimento em um sistema deve possuir uma representação única de autoridade e livre de ambiguidade de forma mais geral.
Código sem D.R.Y
# Code without DRY
def calculate_rectangle_area(width, height)
area = width * height
puts "The area of the rectangle is: #{area}"
end
def calculate_square_area(side)
area = side * side
puts "The area of the square is: #{area}"
end
calculate_rectangle_area(5, 8)
calculate_square_area(4)
Código com D.R.Y
# Code with DRY
def calculate_area(shape, *dimensions)
area = case shape
when :rectangle
dimensions[0] * dimensions[1]
when :square
dimensions[0] * dimensions[0]
end
puts "The area of the #{shape} is: #{area}"
end
calculate_area(:rectangle, 5, 8)
calculate_area(:square, 4)
Isso também significa “Não crie funções e funções iguais um idiota”.
O uso do Dry é considerado uma boa prática na programação por vários motivos:
- 1-Manutenção simplificado
- 2-Legibilidade aprimorada
- 3-Reusabilidade de Código
- 4-Consistência no código
- 5-Facilitação de atualização
- 6-Redução de código inútil
- 7-Melhoria na escalabilidade
Alguns exemplos são:
- Exemplo 1: Se você tem uma função que realiza uma operação específica em diferentes partes do código, é mais eficiente criar uma função e reutiliza-la sempre que necessário. Isso evita a duplicação de código e a facilita a manutenção.
- Exemplo 2: Se você está lidando com configurações e parâmetros utilizados em várias partes do sistema, seria de bom-tom centraliza-las já que isso evita a necessidade de atualizações repetidas.
- Exemplo 3: Se a lógica de tratamento de erros é a mesma em várias partes do código, consolidar essa lógica em um bloco centralizado melhorando consistência.
- Exemplo 4: Em vez de criar funções especificas para cada caso é possível criar funções mais genéricas e parametrizadas.
Early Return
Outra forma de melhorar seu código é usando o Early Return ou retorno antecipado que da mesma forma serve para evitar execução desnecessária de um código caso ele não esteja no caso ideal de execução.
Essa prática melhora o desempenho e a legibilidade do código.
Código sem Early Return
# Code without Early Return
def calculate_factorial(n)
if n < 0
puts "Error: Negative numbers do not have a factorial."
else
result = 1
while n > 1
result *= n
n -= 1
end
puts "The factorial is: #{result}"
end
end
calculate_factorial(5)
calculate_factorial(-3)
Código com Early Return
# Code with Early Return
def calculate_factorial(n)
return puts "Error: Negative numbers do not have a factorial." if n < 0
result = 1
while n > 1
result *= n
n -= 1
end
puts "The factorial is: #{result}"
end
calculate_factorial(5)
calculate_factorial(-3)
Alguns benefícios que está pratica traz ao código:
- Legibilidade
- Redução da complexidade
- Desempenho
- Manutenibilidade
Alguns exemplos de benefícios:
- Ao verificar as condições e retornar imediatamente, o fluxo do código se torna mais claro para se entender.
- Evitar a necessidade de aninhar blocos de código em estruturas condicionalmente complexas, simplificando a estrutura.
- Ao evitar a execução desnecessária do código, especialmente em casos de erros ou condições especiais, o desempenho pode ser aprimorado.
- Códigos com early return são mais fáceis de manter, pois reduzem a quantidade de código que os desenvolvedores precisam revisar para entender a lógica
Guard Clauses
Outra forma de aprimorar o seu código é usando Guard Clauses que consiste na ideia de negar o if é melhor que usar o else lidando com isso no começo do método interrompendo o código se o mesmo não estiver atuando em sua condição ideal.
Pode parecer similar ao **Early Return, mas ambos ocorrem em escopos diferentes, por exemplo:
- Guard Clauses: Atua como guarda verificando o código inicialmente para proteger o código.
- Early Return: É uma prática mais ampla que envolve retornar imediatamente assim que uma condição específica for avaliada como verdadeira.
Resumidamente, ambos são uma forma de implementar **Early Return, porém Guard Clauses envolve mais a condição do que o retorno em si. Enquanto **Early Return** envolve mais o retorno que a condição
Código sem Guard Clauses
# Code without Guard Clauses
def calculate_discount(price, discount_rate)
if price <= 0
puts "Error: Price should be greater than zero."
else
discounted_price = price-(price * discount_rate / 100)
puts "Discounted price: #{discounted_price}"
end
end
calculate_discount(-50, 10)
calculate_discount(100, 20)
Código com Guard Clauses
# Code with Guard Clauses
def calculate_discount(price, discount_rate)
return puts "Error: Price should be greater than zero." if price <= 0
discounted_price = price-(price * discount_rate / 100)
puts "Discounted price: #{discounted_price}"
end
calculate_discount(-50, 10)
calculate_discount(100, 20)
Alguns benefícios do uso de Guard Clauses:
- Legibilidade
- Prevenção de Execução desnecessária
- Tratamento antecipado de erros
- Lógica simplificada
- Facilidade na manutenção
Exemplo:-Ao lidar com situações especiais no início da função, o fluxo principal do código se torna mais claro e fácil de entender-Evita a execução desnecessária de blocos de códigos melhorando eficiência-Simplifica a lógica do código, pois as condições são tratadas antecipadamente-Cria funções concisas e focadas, facilitando a manutenção e reduzindo a complexidade do código
Tratamento de erros
Além das boas práticas citadas anteriormente, o tratamento de erros é crucial para o desenvolvimento de um código robusto e confiável. Lidando com situações inesperadas e garantindo que o programa possa lidar com elas de maneira adequada, evitando falhas catastróficas.
Novamente, isso não significa criar tratamentos de erros, igual um idiota. Você precisa do tratamento de erro certo para o caso certo que pode ocorrer ou de um tratamento global para conseguir depurar quando um erro ocorrer após passar pelo guard clause
Código sem tratamento de erros
# Code without Error Handling
def divide_numbers(a, b)
result = a / b
puts "The result of the division is: #{result}"
end
divide_numbers(10, 0)
divide_numbers(20, 5)
Código com tratamento de erros
# Code with Error Handling
def divide_numbers(a, b)
begin
result = a / b
puts "The result of the division is: #{result}"
rescue ZeroDivisionError => e
puts "Error: #{e.message}"
end
end
divide_numbers(10, 0)
divide_numbers(20, 5)
Alguns dos benefícios tragos pelo tratamento de erros:
- Prevenção de falhas inesperadas
- Mensagens de erros significativas
- Manutenção facilitada
- Robustez do sistema
- Log de Erros
Exemplos:
- Lidar com exceções impede que o programa seja encerrado abruptamente em caso de erros, garantindo uma execução mais suave
- Fornecer mensagens de erro claras e informativas ajuda na identificação e resolução rápida de problemas
- Tratar erros de forma adequada contribui para a manutenção mais fácil do código, uma vez que problemas podem ser diagnosticados e corrigidos de maneira mais eficiente.
- Um código que lida bem com erros é mais robusto e menos propenso a falhas, proporcionando uma experiência mais confiável para os usuários.
- Implementar um sistema de log de erros ajuda a rastrear e registrar problemas, facilitando a identificação de padrões e a correção proativa de possíveis problemas.
Conclusão
Como dito inicialmente, se você está achando seu código anterior porco é uma boa notícia. Pois você está melhorando como programador e espero que com essas dicas você possa melhorar seu código a novos níveis.
Já que essas práticas elevam seu código a um novo patamar adicionando uma base sólida para o desenvolvimento futuro adjunto a mentalidade de melhoria contínua e a atenção aos detalhes são fundamentais para criar software resiliente e sustentável ao longo do tempo.