Há um punhado de padrões e comportamentos que eu tenho visto consistentemente em todos os iniciantes.

E embora alguns desses comportamentos sejam equivocados e prejudiciais, muitos apresentam uma oportunidade de aprendizado para desenvolvedores seniores. Ao contrário da crença popular, há algumas lições que podem ser aprendidas com aqueles com menos experiência, pois têm uma perspectiva sem preconceitos (mente iniciante).

 

Inversão condicional

 

Um dos anti-padrões mais comuns que já vi com iniciantes é algo que gosto de chamar de “inversão condicional” (pode já existir com um nome melhor). A inversão condicional pode acontecer ao usar declarações de ramificação para controlar ou limitar o fluxo de código. Abaixo está um exemplo do código invertido:

 

function atleastOneOdd(potentialOdds) {

 

if (potentialOdds !== undefined) {

 

if (potentialOdds.length) {

 

return potentialOdds.some((num) = num 1);

 

}

 

}

 

return false;

 

}

 

exagerado para o efeito (mas eu definitivamente já vi pior)

 

Se você acha que o código acima parece muito complexo para uma tarefa tão simples, você não está sozinho. A complexidade percebida é resultado do aninhamento, pois o aninhamento contribui fortemente para a “complexidade percebida” do código. Aqui está uma implementação funcionalmente equivalente, mas muito mais legível:

 

function atLeastOneOdd(potentialOdds) {

 

if (potentialOdds === undefined) {

 

return false;

 

}

 

if (!potentialOdds.length) {

 

return false;

 

}

 

return potentialOdds.some((num) = num 1);

 

}

 

A lição:

 

Em geral, menos aninhamento torna o código mais fácil de ler e manter. Como em todas as regras, sempre há exceções, por isso certifique-se de entender o contexto antes de tomar uma decisão. Aqui está um ótimo tópico que cobre este cenário específico com mais profundidade:

 

Saber quando olhar

 

É importante lembrar que não é apenas que os iniciantes sabem “menos”, é também que eles ainda não desenvolveram um instinto para o que eles devem esperar. Depois de um certo número de horas gastas de codificação (não literalmente), você desenvolve um sentido aguçado para a granularidade da lógica que você pode esperar estar disponível a partir de bibliotecas e pacotes padrão. Um grande exemplo disso é uma situação que surgiu com minha namorada. Minha namorada é estudante de ciência da computação, e recentemente eu estava dando a ela algum feedback sobre o código que ela escreveu para uma tarefa C++. Como parte da tarefa, ela precisava verificar se um determinado char de entrada era uma carta. Esta foi mais ou menos a implementação dela:

 

 

 

bool isLetter(const char someChar) {

 

const char letters [] = {

 

‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’, ‘h’, ‘i’, ‘j’, ‘k’, ‘l’, ‘m’, ‘n’,

 

‘o’, ‘p’, ‘q’, ‘r’, ‘s’, ‘t’, ‘u’, ‘v’, ‘w’, ‘x’, ‘y’, ‘z’

 

};

 

 

 

int i = 0;

 

for (i = 0; i 26; ++i) {

 

if (letters[i] === someChar) {

 

return true;

 

}

 

}

 

return false;

 

}

 

Eu não podia nem estar bravo. É uma implementação tão direta e lógica. Mas como um desenvolvedor experiente, o instinto diz que tem que haver uma solução para um problema tão comum. Na verdade, meu instinto imediato era tirar vantagem da natureza numérica dos c chars e simplesmente verificar se um char de entrada está dentro de uma faixa ascii a-z específica. Mas devido à minha “intuição de programação” eu suspeitava que ainda era muito trabalho para um problema tão comum. Eu disse a ela para o Google se há uma maneira de verificar se Char é uma carta. Acontece que existe,isalphaque eu provavelmente usei cem vezes, mas não me lembro (algo que acontece com programação suficiente – você não consegue lembrar de tudo).

 

A lição:

 

Desenvolver uma intuição para saber se já existe algo que resolva seu problema é fundamental para ter sucesso como desenvolvedor. Para o bem e para o mal, a única maneira de fortalecer essa intuição é escrever mais códigos em um conjunto diversificado de linguagens e paradigmas.

 

Encontrar a solução mais direta para um problema

 

Iniciantes são absolutamente incríveis em encontrar soluções diretas ou literais para um problema. Basta pegar o exemplo isLetter da seção anterior. Embora a solução da minha namorada definitivamente não seja a mais eficiente (memória ou computação sábia), é muito limpa e faz o trabalho. Embora a tendência de gravitar para a solução de força mais bruta possa ser cara, na maioria das vezes não importa. Eu não estou dizendo que você deve jogar desempenho ao vento e apenas confiar em soluções de força bruta, mas há uma lição a ser aprendida aqui. Para entender essa lição, é importante olhar para uma das principais diferenças entre iniciantes e especialistas: o que eles estão tentando alcançar.

Um iniciante geralmente está programando para aprender a programar, enquanto um desenvolvedor experiente geralmente está programando como um meio de alcançar um fim (trabalho, projeto pessoal etc). Na faculdade, um professor de ciência da computação raramente dará uma tarefa que tenha um requisito de desempenho. Isso resulta em alunos aprendendo programação sem desempenho em mente. No início, isso pode parecer um enorme déficit na maneira como ensinamos a programação das pessoas, mas eu realmente acho que é uma das poucas coisas que a educação de nível superior faz corretamente. Preocupar-se com o desempenho é geralmente um sintoma de uma doença muito mortal conhecida como “otimização prematura”. Pelas minhas observações, uma vez que um programador começa a se preocupar com o desempenho, é muito difícil para eles pararem.

Isso n&atil