Depois de uma primeira "vista de olhos" pelas resoluções
do Problema 3 queríamos alertá-los para alguns dos erros mais
comuns (ou mais graves).
1. Números mágicos! Em muitos casos aparecem pedaços de código tais como:
for(int i = 43; i != 83; i += 4) {
ecra << Posicao(3, i);
...
que seriam muito mais legíveis/úteis/bem programados/etc. se fossem rescritos usando constantes e variáveis com nomes sugestivos (ver mensagem do Prof. Manuel Menezes de Sequeira de quinta-feira, dia 18 de Janeiro de 2001) como por exemplo:
2. Procedimentos e funções muito longos(as). Uma regra de bom senso na programação é que quando uma função ou procedimento começa a ter muito mais do que uma página de código bem indentado, é uma boa candidata a ser modularizada em procedimentos e funções mais pequenas. É claro que esta regra tem excepções, mas é um bom hábito aprender desde o início a fazer pequenas funções e procedimentos e testar cada um deles separadamente. No Problema 3 há vários exemplos de procedimentos com 3 páginas que podiam ser modularizados adequadamente tornando o código mais claro e mais fácil de depurar.Dimensao const dimensao_do_tabuleiro(10, 10);
Posicao const origem_do_tabuleiro(2, 41);
Dimensao const dimensao_das_celulas(2, 4);
Posicao const centro_das_celulas(dimensao_das_celulas.linhas() / 2,
dimensao_das_celulas.colunas() / 2);
for(int coluna = 0; coluna != dimensao_do_tabuleiro.colunas(); ++coluna) {
ecra << (origem_do_tabuleiro + centro_das_celulas +
Dimensao(0, coluna * dimensao_das_celulas.colunas()));
...
3. Código repetido em ambos ramos de um if
else
ou em
todos os ramos de um switch
. Por exemplo
if(umaFuncaoBooleanaQualquer()) {pode (e deve) ser substituído por
fazQualquerCoisa1();
fazQualquerCoisa2();
fazQualquerCoisa3();
} else {
fazQualquerCoisa1();
fazQualquerCoisa4();
fazQualquerCoisa3();
}
EfazQualquerCoisa1();
if(umaFuncaoBooleanaQualquer())
fazQualquerCoisa2();
else
fazQualquerCoisa4();fazQualquerCoisa3();
switch(uma_expressão) {
case valor1:
fazQualquerCoisa1();
fazQualquerCoisa2();
fazQualquerCoisa3();
break;
case valor2:
fazQualquerCoisa1();
fazQualquerCoisa4();
fazQualquerCoisa3();
break;
case valor3:
fazQualquerCoisa1();
fazQualquerCoisa5();
fazQualquerCoisa3();
break;
}
pode ser substituído por
4. Paragem antecipada de ciclos. O seguinte códigofazQualquerCoisa1();
switch(uma_expressão) {
case valor1:
fazQualquerCoisa2();
break;
case valor2:
fazQualquerCoisa4();
break;
case valor3:
fazQualquerCoisa5();
break;
}fazQualquerCoisa3();
pode ser substituído pela versão mais eficientebool constaEm(int const n, vector<int> const& v){
bool consta = false;
for(vector<int>::size_type i = 0; i != v.size(); ++i)
if(v[i] == n)
consta = true;
return consta;
}
bool constaEm(int const n, vector<int> const& v){
bool consta = false;
for (vector<int>::size_type i = 0; i != v.size() and not consta; ++i)
if (v[i] == n)
consta = true;
return consta;
}
ou até por
Esta última versão é aceitável, apesar de não ter todas as condições de paragem na guarda do ciclo (uma está na condição da instrução condicional), uma que o corpo do ciclo é pequeno.bool constaEm(int const n, vector<int> const& v){
for (vector<int>::size_type i = 0; i != v.size(); ++i)
if (v[i] == n)
return true;
return false;
}
5. Testes de variáveis Booleanas. Não é necessário testar se uma variável Booleana é igual a true ou false, (embora funcione). Basta avaliar o seu valor, por exemplo:
bool aconteceu_qualquer_coisa = ...;
if(aconteceu_qualquer_coisa == true) // verboso!
...
if(aconteceu_qualquer_coisa) // simples e eficaz!
...
if(aconteceu_qualquer_coisa == false) // verboso!
...
if(not aconteceu_qualquer_coisa) // simples e eficaz!
...