De um tradutor : estamos publicando para você uma tradução de um artigo de Steve Merrit , um funcionário do Google que fala sobre como ele resolve problemas típicos de programação. A publicação será útil principalmente para programadores iniciantes.Neste artigo, falarei sobre minha estratégia para resolver problemas que surgem durante o trabalho em um projeto, do início ao fim. Eu o uso no fluxo de trabalho diário do Google, bem como ao trabalhar com codificadores de todos os níveis (colegas, graduados em bootcamps, estudantes universitários). Uma técnica estruturada minimiza o tempo gasto na depuração e, ao mesmo tempo, leva à criação de um código melhor.
A propósito, a mesma estratégia geralmente funciona durante entrevistas em grandes empresas de tecnologia. Há três anos, consegui um emprego no Google graças a ela.
Lembramos que: para todos os leitores de "Habr" - um desconto de 10.000 rublos ao se inscrever em qualquer curso Skillbox usando o código promocional "Habr".
A Skillbox recomenda: O curso educacional on-line "Profissão Java-developer" .
Passo a passo
Mostrarei exemplos na forma de problemas típicos para revelar o tópico.
Problema: “Dadas duas linhas, sourceString e searchString, você precisa retornar o primeiro índice quando sourceString aparecer no searchString. Se searchString não estiver em sourceString, retorne -1. "
1. Desenhe
Começar a escrever código imediatamente não é uma boa ideia. Primeiro, você precisa descrever uma maneira de resolver o problema. Comece formando uma hipótese e evidência de seu ponto de vista. E comece a trabalhar somente quando você já tiver um plano claro. Se isso não for feito, quando o trabalho já tiver começado, você poderá encontrar o fato de que partes individuais do código não corresponderão uma à outra.
A solução geralmente pode não ser trivial, mesmo que a tarefa pareça simples. O planejamento de papel ajuda a encontrar a abordagem correta e a garantir que ela funcione em outras situações. E você aprenderá tudo isso mesmo antes da primeira linha de código ser escrita.
Portanto, não comece a escrever código, nem pense nisso. Você terá muito tempo para trabalhar. Você é um computador humano e resolve o problema.
Coloque o algoritmo da solução no papel. Se algo o ajudar a visualizar seu plano, faça-o. A tarefa é resolver o problema com lápis e papel, sem teclado.
Crie uma entrada simples. Se a função "passa a string", então "abc" é o primeiro exemplo excelente. Tente entender qual deve ser o resultado correto. Em seguida, pense em como você entendeu o problema, que medidas foram tomadas.
Imagine que as strings tenham os seguintes valores:
sourceString: "abcdyesefgh"
searchString: "yes"
Então, podemos ver que o searchString está dentro do sourceString. Mas como chegamos a isso? Começamos do início do sourceString e lemos até o final, olhando para cada fragmento de três caracteres para ver se ele corresponde à palavra "yes". Por exemplo, "abc", "bcd", "cde" e assim por diante. Quando chegamos ao índice 4, encontramos “sim” e, portanto, decidimos que havia uma correspondência, e começa no índice 4.
Eu tive um professor no instituto que definiu a tarefa de apresentar instruções para criar um sanduíche de manteiga de amendoim. Para uma instrução detalhada e compreensível, eles nos prometeram a classificação mais alta.
Eu escrevi o seguinte:
“Abra a manteiga de amendoim, espalhe-a sobre o pão. Coloque outro pedaço de pão por cima e pronto.
Achei que consegui até a professora pegar a manteiga e espalhar sobre o pão, que ainda estava em um saco plástico.
Programas, como meu professor, exigem instruções muito detalhadas para tornar a tarefa possível. Portanto, quando criamos o algoritmo, garantimos tudo - todos os cenários possíveis. Retornar a resposta correta quando a partida é ENCONTRADA é excelente, mas é necessário retornar a resposta mesmo que a correspondência NÃO seja ENCONTRADA.
Vamos tentar novamente com outro par de linhas:
sourceString: "abcdyefg"
searchString: "yes"
Aqui, começamos do início do sourceString e o lemos até o final, analisando cada fragmento de três caracteres para ver se ele corresponde à palavra "yes". Quando chegamos ao índice 4, encontramos yef, o que foi quase uma coincidência, mas incompleto, porque o terceiro caractere era diferente. Assim, continuamos a ler até chegar ao final da linha e depois decidimos que não havia correspondência, e retornamos -1.
Criamos uma série de etapas (na programação, isso é chamado de algoritmo) que executamos para resolver o problema e tentamos executar vários cenários, cada vez obtendo o resultado correto. No momento, podemos ter certeza de que nosso algoritmo funciona e agora é hora de formalizá-lo, o que nos levará ao próximo passo.
2. Escrevemos o algoritmo em palavras
Isso torna as etapas reais, o que significa que podemos consultá-las posteriormente ao escrever o código.
- Comece no início da linha.
- Examinamos todas as combinações de três caracteres (ou quantos caracteres são indicados em searchString).
- Se algum deles for igual a searchString, retornamos o índice atual.
- Se chegarmos ao final da linha sem encontrar uma correspondência, retorne -1.
3. Escrevemos um pseudocódigo
O pseudocódigo não é realmente um código, mas finge ser um código. Um exemplo do que estou falando, dado o nosso algoritmo:
for each index in sourceString,
there are N characters in searchString
let N chars from index onward be called POSSIBLE_MATCH
if POSSIBLE_MATCH is equal to searchString, return index
at the end, if we haven't found a match yet, return -1.
Eu posso torná-lo ainda mais como um código real como este:
for each index in sourceString,
N = searchString.length
POSSIBLE_MATCH = sourceString[index to index+N]
if POSSIBLE_MATCH === searchString:
return index
return -1
4. Traduzimos tudo o que podemos para o código
Agora temos que cuidar da sintaxe, dos parâmetros de função e das regras de linguagem. Talvez você não possa escrever tudo, e isso é normal. Escreva no código o que você sabe com certeza!
function findFirstMatch (searchString, sourceString) { let length = searchString.length; for (let index = 0; index < sourceString.length; index++) { let possibleMatch = <the LENGTH chars starting at index i> if (possibleMatch === searchString) { return index; } } return -1; }
Observe que deixei parte deste pedaço de código em branco. Isso é intencional! Eu não tinha certeza da sintaxe para processar seqüências de caracteres em JavaScript, mas mais sobre isso mais tarde.
5. Não confie na sorte
Um erro bastante comum, especialmente para programadores iniciantes, é usar algo encontrado na rede com a esperança de que funcione. O fragmento encontrado é simplesmente inserido em seu próprio projeto sem teste. Quanto mais seções do seu programa você não entender, mais irrealista será a conclusão bem-sucedida do trabalho.
A probabilidade de um erro dobra quando você adiciona qualquer item que não tem certeza. Como resultado, o processo fica fora de controle.
Comentário: a probabilidade de um erro pode ser calculada usando a sequência de Mersenne: a (n) = (2 ^ n) - 1
Teste seu código. Encontrar algo online é legal, mas antes de adicionar um trecho ao seu programa, tente esta seção separadamente de tudo.
Na etapa anterior, eu disse que não sabia como selecionar uma determinada parte da string usando JavaScript. Vamos procurar no Google.
https://www.google.com/search?q=how+to+select+part+of+a+string+in+javascriptO primeiro resultado é de w3schools. Um pouco desatualizado, mas funcionará:
http://www.w3schools.com/jsref/jsref_substr.aspSuponho que devo usar substr (index, searchString.length) para destacar a parte sourceString de cada vez. Mas até agora isso é uma suposição e nada mais. Então, vou verificar primeiro.
let testStr = "abcdefghi"
let subStr = testStr.substr(3, 4); // simple, easy usage
console.log(subStr);
"defg"
subStr = testStr.substr(8, 5); // ask for more chars than exist
"i"
Agora eu sei exatamente como essa função funciona. Portanto, quando adiciono esse fragmento ao meu programa, já saberei que, se não funcionar, o problema não está na seção adicionada.
E, finalmente, adiciono a última parte do código.
function findFirstMatch(searchString, sourceString) { let length = searchString.length; for (let index = 0; index < sourceString.length; index++) { let possibleMatch = ( sourceString.substr(index, searchString.length)); if (possibleMatch === searchString) { return index; } } return -1; }
Conclusão
Se você leu até o fim, tente a dica. Encontre um problema que você não pode resolver. Eu garanto que tudo vai dar certo agora.
Boa sorte e feliz codificação!
A Skillbox recomenda: