Originalmente eu criei isso como uma pequena lista to-do de tópicos de estudo para se tornar um engenheiro de software,
mas isso cresceu para a grande lista que você vê hoje. Após passar por esse plano de estudo, Eu fui contratado
como Engenheiro de Desenvolvimento de Software na Amazon!
Você provavelmente não vai precisar estudar tanto quanto eu. De qualquer maneira, tudo que você precisa está aqui.
Os itens listados aqui irão preparar você muito bem para uma entrevista em praticamente qualquer empresa de software,
incluindo as gigantes: Amazon, Facebook, Google ou Microsoft.
Esse é o meu plano de estudo mensal para ir de desenvolvedor web (autodidata, sem formação em Ciência da Computação) à engenheiro de software para uma grande empresa.
Essa longa lista foi extraída e expandida a partir das anotações de treinamento da Google, então essas são as coisas que você precisa saber.
Eu adicionei alguns itens extras no final que podem aparecer na entrevista ou serem úteis para resolver um problema. Muitos itens são da obra “Get that job at Google” (Consiga aquele trabalho na Google) de Steve Yegge's e às vezes são expressados palavra-por-palavra nas anotações de treinamento da Google.
Isso é direcionado à engenheiros de software novos ou àqueles que estão migrando de desenvolvimento de software/web para engenharia de software (onde conhecimento de ciência da computação é necessário). Se você tem vários anos de experiência e está alegando muitos anos de experiência com engenharia de software, pode esperar por uma entrevista mais difícil.
Se você tem vários anos de experiência com desenvolvimento de software/web, observe que grandes empresas como Google, Amazon, Facebook e Microsoft consideram engenharia de software como algo distinto de desenvolvimento de software/web e elas requerem conhecimento de ciência da computação.
Se você quer ser um engenheiro de confiabilidade ou engenheiro de sistemas, estude mais da lista opcional (rede, segurança).
Quando eu comecei esse projeto, eu não sabia diferenciar memória dinâmica de memória estática, não sabia notação Big-O, árvores, ou como percorrer um grafo. Se eu tivesse que escrever um algoritmo de ordenação, eu posso te dizer que ele não seria muito bom.
Todas as estruturas de dados que eu já usei eram construídas dentro da linguagem, e eu não sabia como elas funcionavam por debaixo dos panos. Eu nunca tive que gerenciar memória a não ser que um processo que eu estava rodando desse um erro de "memória insuficiente", nesse caso eu teria que dar um jeito. Eu já usei alguns arrays multidimensionais na minha vida e milhares de arrays associativos, mas eu nunca criei estruturas de dados do zero.
É um longo plano. Você vai levar meses. Se você já é familiarizado com muitas dessas coisas, você vai precisar de muito menos tempo.
Como usar
Tudo abaixo é um esboço, e você deve abordar os itens em ordem de cima para baixo.
Eu estou usando a sintaxe de markdown especial do Github, incluindo listas de tarefas para verificar o progresso.
Crie um novo branch para você verificar itens assim, apenas coloque um x entre os colchetes: [x]
Bifurque (fork) um branch e siga os comandos abaixo
Alguns vídeos estão disponíveis somente ao ingressar em um curso no Coursera, EdX, ou Lynda.com. Esses são chamados de MOOCs (Curso Online Aberto e Massivo).
Às vezes as aulas não estão em sessão, nesse caso você terá que esperar alguns meses, portanto não terá acesso até lá. Os cursos da Lynda.com não são gratuitos.
Eu agradeceria a ajuda de vocês em adicionar recursos públicos gratuitos que sempre estejam disponíveis, como vídeos do YouTube para acompanhar os vídeos de curso online.
Eu gosto de usar palestras de universidades;
Processo de Entrevista e Preparação Geral para a Entrevista
Um curso de preparação para entrevistas focado em Python, que cobre estrutura de dados, algoritmos, entrevistas simuladas e muito mais.
Escolha Uma Linguagem para a Entrevista
Você pode escolher uma linguagem com a qual você esteja confortável para fazer a parte de programação (parte prática) da entrevista, mas para grandes empresas, essas são ótimas opções:
C++
Java
Python
Você também poderia usar essas, mas dê uma lida por aí antes. Podem haver ressalvas:
JavaScript
Ruby
Você precisa estar confortável com a linguagem e ser bem informado.
O livro foi publicado em 2004, e está meio desatualizado, mas é um recurso incrível para se compreender um computador resumidamente.
O autor inventou HLA (High-level Assembly ou, no português, Assembly de alto nível), então considere as menções e exemplos em HLA com cautela. Não é usado amplamente, mas contém exemplos decentes de como o assembly funciona.
Esses capítulos valem a pena serem lidos para lhe dar uma boa base:
Se quiser uma versão mais rica e atualizada (2011), mas com um tratamento mais longo
Específico de Linguagem
Você precisa escolher uma linguagem para a entrevista (veja acima). Aqui estão minhas recomendações por linguagem. Eu não tenho recursos para todas as linguagens. Contribuições são bem-vindas.
Se você ler um desses, você deverá ter todo conhecimento de estrutura de dados e algoritmos que precisará para começar a resolver problemas de programação.
Você pode pular todas as aulas em vídeo nesse projeto, a não ser que você queira uma revisão.
Algumas pessoas recomendam esses, mas eu acho que está além do necessário, a não ser que você tenha muitos anos de experiência em engenharia de software e está esperando por uma entrevista muito mais difícil:
Importante: Ler esse livro só terá um valor limitado. Esse livro é ótimo para revisão de algoritmos e estrutura de dados, mas não irá te ensinar a escrever um bom código. Você deve ser capaz de codificar uma solução decente eficientemente.
Half.com é um ótimo recurso para livros com bons preços.
também conhecido como CLR, às vezes CLRS, porque Stein estava atrasado para o negócio
Os primeiros capítulos apresentam soluções inteligentes para problemas de programação (alguns bem velhos usando suporte magnético)
mas isso é só uma introdução. Esse é um guia sobre design e arquitetura de programa, parecido com Code Complete, mas muito mais curto.
"Algorithms and Programming: Problems and Solutions" by Shen ("Algoritmos e Programação: Problemas e Soluções" por Shen)
Um bom livro, mas depois de trabalhar nos problemas em várias páginas eu fiquei frustrado com o Pascal, loops do...while, arrays de 1 índice (index), e resultados de satisfação pós-condição pouco claros.
Prefiro gastar tempo em problemas de programação de outro livro ou problemas de programação online.
Antes de começar
Essa lista cresceu por longos meses, e sim, ela meio que saiu do controle.
Aqui estão alguns erros que eu cometi para que você tenha uma experiência melhor.
1. Você não se lembrará de tudo
Assisti a horas de vídeos e fiz anotações e meses depois havia muito que eu não lembrava. Eu passei 3 dias revisando minhas anotaçes e fazendo flashcards para que eu pudesse relembrar.
Por favor, leia para que você não cometa os meus erros:
Para solucionar o problema, eu fiz um pequeno site de flashcards onde eu poderia adicionar dois tipos de flashcards: genérico e código.
Cada cartão tem formatação diferente.
Eu fiz um website focado em mobile para que eu pudesse rever no meu celular, tablet, onde quer que eu esteja.
Tenha em mente que eu exagerei e tenho cartões abrangendo desde linguagem assembly e trivialidades de Python até aprendizado de máquina e estatísticas. É demais para o que é requerido.
Nota: A primeira vez que você reconhece que sabe a resposta, não a marque como conhecida. Você tem que ver o mesmo cartão e respondê-lo várias vezes corretamente antes de realmente conhecê-lo. A repetição colocará esse conhecimento mais aprodundado em seu cérebro.
Uma alternativa ao uso do meu site de flashcards é Anki, que me foi recomendado várias vezes. Ele usa um sistema de repetição para ajuda-lo a se lembrar.
É fácil de usar, está disponível em todas as plataformas e possui um sistema de sincronização em nuvem. Ele custa 25 dólares no iOS, mas é gratuito em outras plataformas.
Prática, prática, prática, até eu enjoar e poder implementar sem problemas (algumas tem muitos casos com valores de entrada extremos, ou seja, muito pequenos ou muito grandes, e também têm muitos detalhes de escrituração para lembrar)
Trabalhar dentro das restrições básicas (alocar/liberar memória sem ajuda de um coletor de lixo (com exceção de Python))
Fazer uso de types internos para que eu possa ter experiência em usar ferramentas internas para problemas do mundo real (não vou escrever minha própria implementação de lista ligada durante a etapa de produção)
Talvez eu não tenha tempo para fazer tudo isso para cada tema, mas eu vou tentar.
Você não precisa memorizar os detalhes intrínsecos de cada algoritmo.
Escreva código em um quadro branco ou papel, não em um computador. Teste com umas amostras de valores de entrada (input). Depois teste em um computador.
Conhecimento Prévio
[ ] Aprenda C
C está em todo lugar. Você vai ver exemplos em livros, aulas, vídeos, em todo lugar enquanto você estiver estudando.
Esse é um livro curto, mas vai te ajudar a ter um ótimo domínio da linguagem C e se você praticar um pouco
você irá se tornar proficiente rapidamente. Entender C te ajuda a entender como os programas e a memória funcionam.
Peguei vocês: você precisa de conhecimento de ponteiro para ponteiro:
(para quando você passar um ponteiro para uma funcção que poderá mudar o endereço para o qual o ponteiro aponta)
Essa página é só para ter uma noção sobre ponteiro para ponteiro. Eu não recomendo o estilo transversal dessa lista. Legibilidade e manutenção sofrem devido à engenhosidade.
Implementar usando lista ligada, com ponteiro de cauda (aponta para o último elemento de uma lista):
enqueue(valor) - adiciona "valor" na posição na cauda (final da lista)
dequeue() - retorna um valor e remove o elemento menos recentemente adicionado (início da lista))
empty()
Implementar usando arrays de tamanho-fixo:
enqueue(valor) - adiciona um item no final do armazenamento disponível
dequeue() - retorna um valor e remove um elemento menos recentemente adicionado
empty()
full()
Custo:
uma implementação ruim usando lista ligada na qual você coloca na fila (enqueue) no head (cabeça/início da lista) e tira da fila (dequeue) no tail (cauda/final da lista) seria O(n)
porque você precisaria do penúltimo elemento, causando uma transversal completa a cada dequeue
enqueue: O(1) (amortizado, lista ligada e array [sondagem])
anotações:
complexidade de tempo: O(n)
space complexity:
melhor: O(log n) - altura média da árvore
pior: O(n)
em-ordem ou ordem simétrica(na busca em profundidade (ou DFS): percorre subárvore esquerda em ordem simétrica (em-ordem), visita a raiz, percorre subárvore direita em ordem simétrica)
pós-ordem (na busca em profundidade (ou DFS): percorre subárvore esquerda em pós-ordem, percorre subárvore direita em pós-ordem, visita a raiz)
pré-ordem (na busca em profundidade (ou DFS): visita a raiz, percorre subárvore esquerda em pré-ordem, percorre subárvore direita em pré-ordem)
get_max - retorna o item max (maior item), sem removê-lo
get_size() - retorna o número de elementos armazenados
is_empty() - retorna "true" se o heap não contém elementos
extract_max - retorna o item max (maior item), removendo ele
sift_down - necessário para extract_max
remove(i) - remove o item no índice x
heapify - cria um heap a partir de um array de elementos, necessário para heap_sort
heap_sort() - pega um array não-ordenado e o transforma em um array ordenado "in-place" (sem gerar um novo array) usando uma heap máxima (max-heap)
nota: usando uma heap mínima (min-heap) ao invés de uma heap máxima (max-heap) poderia salvar operações, mas duplicar o espaço necessário (não é possível fazer "in-place")
Ordenação
[ ] Anotações:
Implementar ordenações e saber melhor/pior cenário, complexidade média de cada um:
sem ordenação por bolha - é terrível - O(n^2), exceto quando n <= 16
estabilidade em algoritmos de ordenação ("O algoritmo de ordenação quicksort é estável?")
Sorting Algorithm Stability (Artigo da Wikipédia em Inglês sobre Estabilidade de Algoritmo de Ordenação, infelizmente a versão em Português não é tão informativa)
Grafos podem ser usados para representar muitos problemas na Ciência da Computação, então essa seção é longa, assim como árvores e ordenação também foram.
Anotações:
Há 4 maneiras básicas de representar um grafo na memória:
objetos e apontadores
matriz de adjacência
lista de adjacência
mapa de adjacência
Famialirize-se com cada representação e seus prós e contras.
Busca em Largura (BFS) e Busca em Profundidade (DFS) - saiba a complexidade computacional deles, seus perde-e-ganhas (tradeoffs), e como implementar eles em código real.
Quando for perguntado uma questão, busque por uma solução baseada em grafos primeiro, depois se não houver nenhuma, siga em frente.
I - Interface segregation principle | clientes não devem ser forçados a implementar interfaces que eles não usam (Princípio da segregação de Interface)
Eu sei que o livro canônico é "Design Patterns: Elements of Reusable Object-Oriented Software (Padrões de Design: Elementos de Software Orientado a Objetos reutilizável), mas "Head First" é ótimo para iniciantes em POO.
Saiba sobre as classes mais famosas de problemas NP-completo, como o problema do vendedor viajante e o problema da mochila,
e seja capaz de reconhecê-los quando um entrevistador lhe perguntar disfarçado.
Necessidades de recurso de processos (memória: código, armazenamento estático, memória estática (stack), memória dinâmica (heap), e também descritores de arquivo, i/o
Necessidades de recurso de threads (o mesmo que acima (menos stack) com outras threads no mesmo processo, mas cada um tem seu próprio pc, contador de stack, registros, e stack)
Bifurcação nada mais é que COW (copy-on-write) (somente leitura) até que o novo processo escreva na memória, depois ela faz uma cópia completa.
Troca de contexto
Como a troca de contexto é iniciada pelo sistema operacional e componentes de hardware subjacentes
Ler tudo de ponta a ponta com total compreensão irá provavelmente levar mais tempo do que você tem. Eu recomendo ser seletivo com os artigos e suas seções.
TDD is dead. Long live testing. (Desenvolvimento Guiado Por Testes (ou a sigla TDD em Inglês, que significa Test-Driven Development) está morto. Longa vida aos testes.
Design de Sistema, Escalabilidade, Tratamento de Dados
Você pode presumir que façam perguntas à respeito de design de sistema se você tem mais de 4 anos de experiência.
Escalabilidade e Design de Sistema são temas bem grandes com muitos tópicos e recursos, já que
há muito a se considerar quando se projeta um sistema de software/hardware que pode escalar.
Se prepare para gastar um bom tempo nisso.
Considerações:
escalabilidade
Refinar grandes conjuntos de dados para valores únicos
System Design Interview (Entrevista de Design de Sistema) - Tem vários recursos nesse aqui. Olhe os artigos e exemplos. Eu coloquei alguns deles abaixo.
Veja a seção "Envio de Mensagens, Serialização, e Sistemas de Enfileiramento" bem abaixo para informações sobre algumas das tecnologias que podem "colar" serviços juntos
Para ainda mais informações, veja a série de vídeos "Minerando Conjuntos de Dados Massivos" na seção de Séries de Vídeos.
Praticando o processo de design de sistema: Aqui estão algumas ideias para tentar trabalhar no papel, cada uma com documentação sobre como ela foi tratada no mundo real:
Essa seção terá vídeos mais curtos que você pode assistir rapidamente para revisar a maioria dos conceitos importantes.
É legal se você quiser dar uma refrescada na memória.
Séries de vídeos curtos (2 - 3 minutos) sobre o assunto (23 vídeos)
Agora que você sabe todos os temas de Ciência da Computação acima, é hora de praticar respondendo problemas de programação.
Prática com Questõs de Programação não é sobre memorizar respostas para problemas de programação.
Por que você precisa praticar com problemas de programação:
reconhecimento de problemas, e onde as devidas estruturas de dados e algoritmos se encaixam
coleta de requerimentos para o problema
pensar alto (falar enquanto resolve o problema) assim como você irá fazer em uma entrevista
escrever código em um quadro branco ou papel, não no computador
encontrar complexidade de espaço e tempo para suas soluções
testar suas soluções
Tem uma introdução ótima para resolução de problema metódica e comunicativa em uma entrevista. Você vai adquirir isso dos livros de
entrevista de programação, também, mas eu acho isso aqui excelente:
Algorithm design canvas (Quadro de design de algoritmo)
Não tem quadro branco em casa? Faz sentido. Eu sou um estranho e tenho um grande quadro branco. Ao invés de um quadro branco, pegue um
grande caderno de desenho de uma loja de arte. Você pode sentar no sofá e praticar. Esse é o meu "sofá de quadro branco".
Eu adicionei a caneta na foto para comparação de dimensões. Se você usar uma caneta, você vai desejar que você pudesse apagar. Fica uma bagunça bem rápido.
Depois que você enche o cérebro com novos aprendizados, é hora de botar ele para trabalhar.
Faça desafios de programação todo dia, o máximo que você puder.
Veja itens sobre preparo de currículo em "Cracking The Coding Interview" (Decifrando A Entrevista De Programação) e atrás do livro "Programming Interviews Exposed" (Entrevistas de Programação Expostas)
Esteja pensando à respeito para quando a entrevista chegar
Pense em 20 questões da entrevista que você vai ter, seguindo a linha de raciocínio dos itens abaixo. Tenha 2-3 respostas para cada.
Tenha uma história, não apenas dados, sobre algo que você realizou.
Por que você quer esse trabalho?
Qual um problema difícil que você tenha resolvido?
Maiores desafios enfrentados?
Melhores/piores designs que você já viu?
Ideias para melhorar um produto existente.
Como você trabalha melhor, como um indivíduo e como parte de uma equipe?
Quais das suas habilidades ou experiências seriam recursos úteis na função e por quê?
O que você mais gostou no [trabalho x / projeto y]?
Qual foi o maior desafio que você enfrentou no [trabalho x / projeto y]?
Qual foi o bug mais difícil que você enfrentou no [trabalho x / projeto y]?
O que você aprendeu no [trabalho x / projeto y]?
O que você teria feito melhor no [trabalho x / projeto y]?
Tenha questões para o entrevistador
Algumas das minhas (eu posso já saber a resposta, mas o quero a opinião deles ou a perspectiva da equipe):
Quão grande é sua equipe?
Como é o seu ciclo de desenvolvimento? Você trabalha com modelo em cascata (waterfall)/sprints/método ágil (agile)?
Correrias por causa de prazos são comuns? Ou tem flexibilidade?
Como as decisões são tomadas na sua equipe?
Quantas reuniões você tem por semana?
Você sente que o seu ambiente de trabalho te ajuda a se concentrar?
No que você está trabalhando?
O que você gosta a respeito desse trabalho?
Como é o balanço vida-trabalho?
Quando Você Conseguir O Trabalho
Parabéns!
Continue aprendendo.
O aprendizado nunca para.
*****************************************************************************************************
*****************************************************************************************************
Tudo abaixo deste ponto é opcional.
Ao estudar o que vem a seguir, você vai ter maior exposição a mais conceitos de Ciência da Computação, e está mais bem preparado para
qualquer trabalho de engenharia de software. Você será um engenheiro de software muito mais completo.
*****************************************************************************************************
*****************************************************************************************************
Esses tópicos provavelmente não aparecerão em uma entrevista, mas eu adicionei eles para ajudar você a se tornar um engenheiro de software mais completo, e para você ficar ciente de certas tecnologias e algoritmos, assim você terá mais ferramentas a disposição.
Saiba pelo menos um tipo de árvore binária balanceada (e saiba como ela é implementada):
"Entre as Árvores de Busca Balanceadas, AVL e árvore 2/3 agora são passado, e árvores red-black (rubro-negras) parecem mais populares.
Uma estrutura de dados auto-organizada particularmente interessante é a árvore splay, a qual usa rotações
para mover qualquer chave acessada para a raiz."
Dessas, eu escolhi implementar a árvore splay. Com base no que eu li, você não vai implementar uma
árvore de busca balanceada na sua entrevista. Mas eu queria uma certa exposição à programação de uma dessas árvoes
e convenhamos, árvores splay são muito legais. Eu li muito código de árvores rubro-negras.
árvore splay: funções de inserir, buscar e deletar
Se você acabar implementando uma árvore rubro-negra, tente apenas essas:
funções de busca e inserção, pulando a função de deletar
Eu quero aprender mais sobre a Árvore B, já que ela é amplamente usada com enormes conjuntos de dados.
Ná prática:
Pelo que eu vejo, essas não são muito usadas na prática, mas eu consigo ver onde elas seriam usadas:
Á arvore AVL é outra estrutura que dá suporte a remoção, inserção e busca O(log n). Ela é mais rigidamente
balanceada que as árvores rubro-negras, levando à inserções e remoções mais lentas, mas uma recuperação mais rápida. Isso faz dela
um atrativo para estruturas de dados que podem ser construídas uma vez e carregadas sem reconstrução, assim como os dicionários de
linguagem (ou dicionários de programas, como os opcodes de um montador (assembler) ou interpretador).
Ná prática:
Árvores splay são normalmente usadas na implementação de caches, alocadores de memória, roteadores, coletores de lixo,
compressão de dados, cordas (ou "ropes" no Inglês, que é uma estrutura de dados) (substituição de string usada para longas strings de texto), no Windows NT (em código de memória virtual,
rede e sistema de arquivos) etc.
essas são uma tradução de uma árvore 2-3 (veja abaixo)
Ná prática:
Árvores rubro-negras oferecem garantias de pior-caso para tempo de inserção, tempo de exclusão e tempo de busca.
Isso não só faz elas serem úteis em aplicações que sejam sensíveis ao tempo como aplicações que funcionam em tempo real,
mas isso faz elas serem úteis também em construir blocos para outras estruturas de dados, o que proporciona garantias de pior-caso;
por exemplo, muitas estruturas de dados usadas em geometria computacional podem ser baseadas em árvores rubro-negras, e
o Agendador Completamente Justo (Completely Fair Scheduler - CFS) usado em kernels de Linux atuais, usa as árvores rubro-negras.. Na versão 8 do Java,,
a Coleção HashMap foi modificada para usar uma árvore rubro-negra ao invés de usar uma ListaLigada para
armazenar elementos idênticos com hashcodes fracos.
Ná prática:
árvores 2-3 tem inserções mais rápidas ao custo de buscas mais lentas (já que a altura é mais comparado às árvores AVL).
Você raramente usaria árvore 2-3 porque a sua implementação envolve diferentes tipos de nós (nodes). Ao invés da árvore 2-3, as pessoas usam as árvores rubro-negras.
[ ] Árvores 2-3-4 (também conhecidas como árvores 2-4)
Ná prática:
Para cada árvores 2-4, existem árvores rubro-negras correspondentes com elementos de dados na mesma ordem. As operações de inserção e
exclusão nas árvores 2-4 são também equivalentes ao color-flipping (numa tradução livre, troca-de-cor) e às rotações nas árvores rubro-negras. Isso torna as árvores 2-4 uma
ferramenta importante para compreender a lógica por trás das árvores rubro-negras, e é por isso que muitos textos de introdução a algoritmos introduzem
árvores 2-4 logo antes das árvores rubro-negras, mesmo que as árvores 2-4 não são usadas frequentemente na prática.
curuiosidade: é um mistério, mas o B pode se referir a Boeing, Balanceado ou Bayber (co-inventor)
Ná prática:
Árvores B são amplamente usadas em bancos de dados. A maioria dos sistemas de arquivos modernos usam árvores B (ou variantes). Além do
seu uso em bancos de dados, ás arvores B são também usadas em sistemas de arquivos para permitir acesso aleatório rápido para um bloco
arbitrário em um arquivo particular. O problema básico é tornar o endereço de bloco de arquivo em um endereço de bloco de disco
(ou talvez em um cilindro-cabeça-setor, do Inglês Cylinder-Head-Sector - CHS).
MIT 6.851 - Memory Hierarchy Models (video) (MIT 6.851 - Modelos de Hierarquia de Memória - vídeo)
- cobre Árvores B de cache-alheio (do Inglês, cache-oblivious), estruturas de dados muito interessantes
- os primeiros 37 minutos são bem técnicos, pode ser pulado (B é tamanho de bloco, tamanho de linha de cache)
Árvores k-D
ótimo para encontrar número de pontos em um retângulo ou objeto de maior dimensão
Eu adicionei esses detalhes para reforçar algumas ideias já apresentadas acima, mas não quis incluir elas
acima porque aí é simplesmente demais. É fácil exagerar em um tema.
Você quer ser contratado nesse século, certo?