10 Boas Práticas de Programação
Olá pessoal, hoje vou falar de um tema importante boas práticas de programação, vou listar 10 itens básicos que podem ser uteis para os iniciantes, porém essa lista poderia ser muito maior.
No futuro pretendo escrever sobre boas práticas ligadas a programação orientada a objetos, será um pouco mais avançado.
Todos os itens de boas práticas de programação listados aqui, não tem relação com nenhuma linguagem de programação específica, mas nesse post estou escrevendo os exemplos em PHP.
Interessante citar que em grandes equipes de desenvolvimento podem ser definidos padrões para que o código se torne legível para todos programadores e facilitando também o entendimento do código para novos integrantes.
1 – Identar o código
Considero a identação de código um dos itens mais básicos e ao mesmo tempo importante para um programador, sendo ele iniciante ou avançado. O fato de identificarmos o escopo de condições IF, WHILE e etc., facilita muito entendimento do código, além de deixar mais bonito.
Tenho um defeito muito grave, por mais simples que seja o código mas se o mesmo estiver sem identação eu não consigo ler e muito menos entender nada, parece até “tique nervoso” mas já começo a colocar uns espaçamentos no código quase que involuntariamente.
Sem Identação:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
if ($_SESSION['logado'] == 'SIM'): $retorno = array('codigo' => 1, 'mensagem' => 'Mensagem A!'); echo json_encode($retorno); exit(); else: if ($_SESSION['tentativas'] == TENTATIVAS_ACEITAS): $retorno = array('codigo' => 0, 'mensagem' => 'Mensagem B!'); echo json_encode($retorno); exit(); else: $retorno = array('codigo' => '0', 'mensagem' => 'Mensagem C!'); echo json_encode($retorno); exit(); endif; endif; |
Com Identação:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
if ($_SESSION['logado'] == 'SIM'): $retorno = array('codigo' => 1, 'mensagem' => 'Mensagem A!'); echo json_encode($retorno); exit(); else: if ($_SESSION['tentativas'] == TENTATIVAS_ACEITAS): $retorno = array('codigo' => 0, 'mensagem' => 'Mensagem B!'); echo json_encode($retorno); exit(); else: $retorno = array('codigo' => '0', 'mensagem' => 'Mensagem C!'); echo json_encode($retorno); exit(); endif; endif; |
2 – Nomear variáveis de maneira intuitiva
Nomear variáveis pode parecer uma tarefa simples, basta seguir as restrições de cada linguagem e por causa disso os nomes acabam não possuindo sentido ao escopo do código.
É possível encontrar esse tipo de problema em loops usando laços de repetição “FOR” aninhados, onde é comum encontrarmos contadores com nome de x, y, z e etc., variáveis, até mesmo nome de estruturas como Arrays é possível encontrar nomes “bizarros”.
Nomes Aleatórios:
1 2 |
$array1 = array('Joana', 'Maria', 'Pedro'); $array2 = array('Porto Alegre', 'Indaiatuba', 'Belo Horizonte'); |
Nomes Intuitivos:
1 2 |
$arrayNome = array('Joana', 'Maria', 'Pedro'); $arrayCidade = array('Porto Alegre', 'Indaiatuba', 'Belo Horizonte'); |
3 – Evite chamar funções para testes em loops
Aproveitando o exemplo das 2 Arrays acima, vamos usar um “FOR” para percorrer os elementos das Arrays, mas o laço “FOR” precisa saber qual é o limite do loop, é nesse momento que geralmente chamamos funções nativas para efetuar a contagem de elementos.
No exemplo abaixo chamo a função “count()” para saber a quantidade de elementos na minha Array, temos que levar em consideração que caso nossa Array tenha 500 elementos, iremos chamar a função “count()” 500 vezes.
Chamando a função count() por iteração:
1 2 3 4 5 6 7 8 9 10 11 12 |
$arrayNome = array('Joana', 'Maria', 'Pedro'); $arrayCidade = array('Porto Alegre', 'Indaiatuba', 'Belo Horizonte'); for ($indiceNome = 0; $indiceNome < count($arrayNome); $indiceNome++) : for ($indiceCidade = 0; $indiceCidade < count($arrayCidade); $indiceCidade++) : echo $arrayNome[$indiceNome] . ' - ' . $arrayCidade[$indiceCidade] . '<br>'; endfor; endfor; |
Chamando apenas uma vez a função count():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$arrayNome = array('Joana', 'Maria', 'Pedro'); $arrayCidade = array('Porto Alegre', 'Indaiatuba', 'Belo Horizonte'); $quantidadeNomes = count($arrayNome); $quantidadeCidades = count($arrayCidade); for ($indiceNome = 0; $indiceNome < $quantidadeNomes; $indiceNome++) : for ($indiceCidade = 0; $indiceCidade < $quantidadeCidades; $indiceCidade++) : echo $arrayNome[$indiceNome] . ' - ' . $arrayCidade[$indiceCidade] . '<br>'; endfor; endfor; |
4 – Evitar condição de negação no IF
Praticamente não existe programação sem o controle de fluxo usando condições “IF”, a ideia é sempre avaliar se uma condição é verdadeira dentro da condição para executar determinado código.
Por esse motivo evite sempre que possível usar verificações de negação na condição, sempre que possível avalie primeiro a condição verdadeira e caso falso execute o código do “ELSE”, isso também torna o código mais legível e menos confuso quando temos “IFs” aninhados.
Avaliando a condição de Negação:
1 2 3 4 5 6 7 |
$valor = true; if(!$valor === true): echo 'Falso'; else: echo 'Verdadeiro'; endif; |
Avaliando a condição Verdadeira:
1 2 3 4 5 6 7 |
$valor = true; if($valor === true): echo 'Verdadeiro'; else: echo 'Falso'; endif; |
5 – Nomear funções da maneira intuitiva
Nomear funções é outra tarefa que aparentemente é simples, mas se soubermos escolher nomes mais intuitivos e ligados ao objetivo da função, também podemos tornar nosso código mais legível.
Por exemplo, nos meus scripts orientado a objetos ou não, tenho o costume de nomear funções que retornam valores do tipo BOOLEAN sempre iniciando com “is”, essa prática deixa a chamada da função dentro de um “IF” mais intuitivo.
No código abaixo coloquei uma função básica para validar e-mails “isEmailValid()”, quando chamo a função para válidar um e-mail o entendimento da condição “IF” fica algo semelhante “SE é um e-mail válido ENTÃO”:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
function isEmailValid($email){ $conta = "/[a-zA-Z0-9\._-]+@"; $domino = "[a-zA-Z0-9\._-]+."; $extensao = "([a-zA-Z]{2,4})$/"; $pattern = $conta.$domino.$extensao; if (preg_match($pattern, $email)) return true; else return false; } if (isEmailValid('wllfl@ig.com.br')): echo 'Válido'; else: echo 'Inválido'; endif; |
6 – Comentar o código
Existem algumas literaturas que criticam a prática de comentar o código, pois acaba aumentando a quantidade de linhas e enchendo o código com sujeira, no livro “Código Limpo” o autor defende que variáveis e métodos bem nomeados são as melhores documentações e tiram a necessidade dos comentários.
Pessoalmente discordo dessa opinião, acho que um comentário detalhando o objetivo do método ou função, seus parâmetros de entrada e de saída podem ajudar em manutenções futuras desse código, principalmente se a manutenção for de um profissional que não conhece o sistema.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* * Função para validar E-mail * @param $email - String contendo o Email * @return Booleano - Retorna TRUE para válido e FALSE para inválido */ function isEmailValid($email){ $conta = "/[a-zA-Z0-9\._-]+@"; $domino = "[a-zA-Z0-9\._-]+."; $extensao = "([a-zA-Z]{2,4})$/"; $pattern = $conta.$domino.$extensao; if (preg_match($pattern, $email)) return true; else return false; } |
7 – Padronizar nome das constantes
Constantes são valores que não podem ser alterados durante a execução de uma aplicação, por isso elas merecem um destaque em nossos sistemas.
Uma boa prática é definir um padrão para o nome das constantes sempre em caixa alta, isso ajuda a identifica-las no meio do código, claro que se o programador tiver o costume de nomear variáveis em caixa alta também aí não tem sentido essa prática das constantes.
Em vários posts no blog uso essa padronização das constantes!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
/* * Constantes de parâmetros para configuração da conexão */ define('HOST', 'localhost'); define('DBNAME', 'DB'); define('CHARSET', 'utf8'); define('USER', 'root'); define('PASSWORD', '123456'); class Conexao { /* * Atributo estático para instância do PDO */ private static $pdo; /* * Escondendo o construtor da classe */ private function __construct() { // } /* * Método estático para retornar uma conexão válida * Verifica se já existe uma instância da conexão, caso não, configura uma nova conexão */ public static function getInstance() { if (!isset(self::$pdo)) { try { $opcoes = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8', PDO::ATTR_PERSISTENT => TRUE); self::$pdo = new PDO("mysql:host=" . HOST . "; dbname=" . DBNAME . "; charset=" . CHARSET . ";", USER, PASSWORD, $opcoes); } catch (PDOException $e) { print "Erro: " . $e->getMessage(); } } return self::$pdo; } } |
8 – Utilizar blocos try..catch..
Trabalhar com códigos dentro de blocos try..catch é considerado até uma boa prática de segurança, por exemplo se ocorrer um erro no script PHP para conexão com o banco de dados onde não está sendo usando try..catch, existem situações que será impresso na página o nome do banco de dados.
Além disso controlando as EXCEPTIONS da sua aplicação você pode exibir mensagens mais intuitivas para o usuário, evitando aquelas mensagens em ‘inglês” que são padrão da maioria das linguagens de programação.
Em ambiente de desenvolvimento até poderíamos exibir a mensagem de erro gerada em PDOException e retornada por “$e->getMessage()”, mas em produção é necessário uma mensagem mais amigável como abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public static function getInstance() { if (!isset(self::$pdo)) { try { $opcoes = array(\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8'); switch (SGBD) : case 'mysql': self::$pdo = new \PDO("mysql:host=" . HOST . "; dbname=" . DBNAME . ";", USER, PASSWORD, $opcoes); break; case 'mssql':{ if(SERVER == 'linux'): self::$pdo = new \PDO("dblib:host=" . HOST . "; database=" . DBNAME . ";", USER, PASSWORD, $opcoes); else: self::$pdo = new \PDO("sqlsrv:server=" . HOST . "; database=" . DBNAME . ";", USER, PASSWORD, $opcoes); endif; break; } case 'postgre': self::$pdo = new \PDO("pgsql:host=" . HOST . "; dbname=" . DBNAME . ";", USER, PASSWORD, $opcoes); break; endswitch; self::$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { print "Houve um erro ao tentar conexão com o Banco de Dados!"; } } return self::$pdo; } |
9 – Não usar valor padrão em argumentos de funções
Quando escrevemos uma função que necessita receber argumentos de entrada as vezes sentimos a necessidade de deixar um valor padrão nesse argumento, mas garanto que nem mesmo quem escreveu a função vai lembrar desse valor padrão quando precisar debugar em erro, imagine outro programador.
De preferência em tratar um valor de argumento inválido do que usar um valor padrão,
1 2 3 4 5 6 7 8 |
function dataBrToEng($data){ if (empty($data)): throw new \InvalidArgumentException("Argumento inválido!"); else: $data = explode("/", $data); return $data[2].'-'.$data[1].'-'.$data[0]; endif; } |
10 – Percorrer loops somente o necessário
As vezes precisamos percorrer um loop procurando por apenas uma combinação e mesmo após encontrar essa combinação ainda deixamos o loop executando por uma infinidade de vezes.
No exemplo abaixo estou percorrendo a “$arrayNome” procurando pelo valor ‘William’, caso seja encontrado atribuo o valor TRUE para variável “$existe” e mesmo assim o loop contínua, uma boa prática seria encerrar a execução do loop usando “break”.
Percorrendo Array até o final mesmo tendo encontrado a combinação:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$arrayNome = array('Joana', 'William', 'Pedro', 'Mario', 'Jorge'); $existe = false; $quantidadeNomes = count($arrayNome); for ($indiceNome = 0; $indiceNome < $quantidadeNomes; $indiceNome++) : if ($arrayNome[$indiceNome] === 'William'): $existe = true; endif; endfor; |
Finalizando loop após encontrar combinação:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$arrayNome = array('Joana', 'William', 'Pedro', 'Mario', 'Jorge'); $existe = false; $quantidadeNomes = count($arrayNome); for ($indiceNome = 0; $indiceNome < $quantidadeNomes; $indiceNome++) : if ($arrayNome[$indiceNome] === 'William'): $existe = true; break; endif; endfor; |
Bom pessoal com isso chego ao final de mais um post, essas 10 boas práticas de programação que citei acima são apenas uma pequena parte do que realmente existe.
Uma breve pesquisa no Google usando o termo “boas práticas de programação” é possível encontrar diversos sites com material semelhante, mas procurei postar exemplos para os iniciantes deixando o post mais didático.
Apesar das dicas desse post poderem ser aplicadas em praticamente todas as linguagens de programação, deixo o link documentação oficial do PHP caso exista alguma dúvida nos exemplos.
Espero que tenham gostado e até próxima ….