No desenvolvimento de conhecimentos profundos de programação

136

Ocasionalmente, vejo perguntas sobre casos extremos e outras estranhezas no Stack Overflow que são facilmente respondidas por nomes como Jon Skeet e Eric Lippert, demonstrando um profundo conhecimento da linguagem e seus muitos meandros, como este:

Você pode pensar que, para usar um foreachloop, a coleção sobre a qual você está iterando deve implementar IEnumerableou IEnumerable<T>. Mas, como se vê, isso não é realmente um requisito. O que é necessário é que o tipo da coleção tenha um método público chamado GetEnumeratore que retorne algum tipo que tenha um getter de propriedade pública chamado Currente um método público MoveNextque retorne a bool. Se o compilador puder determinar que todos esses requisitos sejam atendidos, o código será gerado para usar esses métodos. Somente se esses requisitos não forem atendidos, verificamos se o objeto implementa IEnumerableou IEnumerable<T>.

Isso é legal de se saber. Eu posso entender por que Eric sabe disso; ele está na equipe do compilador, então ele tem que saber. Mas e aqueles que demonstram um conhecimento tão profundo que não são privilegiados?

Como meros mortais (que não fazem parte da equipe do compilador C #) descobrem coisas como essa?

Especificamente, existem métodos que essas pessoas usam para erradicar sistematicamente esse conhecimento, explorá-lo e internalizá-lo (torná-lo seu)?

Robert Harvey
fonte
10
Eu acho que é particularmente aqui que brilha o software de código aberto. É bom poder entrar na estrutura / sistema / bibliotecas até o fim. Eu costumava entender melhor os aspectos internos da estrutura quando trabalhava com o Qt do que quando estava trabalhando com o WinForms.
Vitor Py
2
Quando você precisaria conhecer esse exemplo específico, além de não parecer idiota diante de uma multidão especial? Eles foram à prova de idiotas. Fora isso, as séries Effective C #, Java, C ++ etc. podem ter algumas coisas interessantes. O blog de Eric Lippert também é uma boa fonte. Em geral, geralmente não sabemos o que não sabemos, então, como se costuma dizer: "viva por 100 anos, aprenda por 100 anos e morra de tolo".
26
Vale a pena o esforço? Sou bilíngue e estou tentando aprender algumas outras línguas faladas. Tomei algumas aulas de matemática, mas não o suficiente. Eu gostaria de aprender a jogar tênis meio decentemente e aprender a nadar usando o golpe de borboleta. Eu gostaria de viajar mais. Eu quero aprender um pouco de Clojure. O que eu não quero é ser especialista em um idioma, ter um doutorado em matemática, passar 30 horas por semana em uma piscina como Michael Phelps, etc. O conhecimento de Lippert e Skeet se deve ao fato de que eles colocam muito esforço em uma (ou algumas) coisas, perdendo outras experiências. Talvez mudar de emprego?
10
"Eu posso entender por que Eric sabe disso; ele está na equipe de compiladores, então ele precisa saber". - é provável que ele saiba disso porque pensou em primeiro lugar . Duvido que ele tinha de 'descobrir' que ele funciona como este :)
Alex ten Brink
10
@ Alex: Na verdade, só trabalhei em C # desde que começamos a criar a implementação do C # 3. A especificação "foreach" foi escrita mais de seis anos antes. Eu ainda descubro coisas históricas loucas sobre o idioma todos os dias. Por exemplo, eu aprendi hoje que para delegados, ((A + B) + C) - (A + C) = A + B + C, mas ((A + B) + C) - (B + C) = A . Esquisito!
Eric Lippert

Respostas:

167

Primeiro, obrigado pelas amáveis ​​palavras.

Se você deseja obter um conhecimento profundo de C #, é sem dúvida uma vantagem ter a especificação da linguagem, dez anos de anotações de design, o código fonte, o banco de dados de bugs e Anders, Mads, Scott e Peter no final do corredor. Eu certamente tenho sorte, não há dúvida sobre isso.

No entanto, mesmo sem essas vantagens, ainda é possível obter um conhecimento profundo do assunto.

Quando comecei na Microsoft, eu trabalhava no intérprete JScript que acompanha o Internet Explorer 3. Meu gerente na época me disse algo que era um dos melhores conselhos que já recebi. Ele disse que queria que eu me tornasse o especialista reconhecido na Microsoft na sintaxe e na semântica da linguagem JScript, e que eu deveria fazer isso procurando perguntas sobre esses aspectos do JScript e respondendo a eles. Respondendo particularmente às perguntas para as quais eu não sabia as respostas, porque essas são as que eu aprenderia.

Obviamente, o StackOverflow e outros fóruns públicos de perguntas e respostas são como beber de uma mangueira de incêndio para esse tipo de coisa. Naquela época, li comp.lang.javascript e nossos fóruns internos do "JS User" da Microsoft religiosamente e segui o conselho do meu gerente: quando vi uma pergunta sobre a semântica da linguagem que eu não sabia a resposta, eu a fiz meu negócio para descobrir.

Se você quiser fazer um "mergulho profundo" assim, terá que escolher com cuidado. Até hoje, sou extremamente ignorante sobre como o modelo de objetos do navegador funciona. Desde que tenho me concentrado em me tornar o especialista em linguagem C # nos últimos anos, sou notavelmente ignorante sobre como as várias classes nas bibliotecas de classes base funcionam. Tenho a sorte de ter um trabalho que preza profundo conhecimento específico; se seu trabalho ou seus talentos estão mais alinhados com a generalidade, aprofundar-se pode não funcionar para você.

Escrever um blog também é tremendamente útil; ao exigir que eu explique tópicos complexos para outras pessoas, sou forçado a enfrentar o meu próprio entendimento inadequado de vários tópicos o tempo todo.

Eric Lippert
fonte
14
Não para arrastar esse tópico fora do tópico, mas depois de ler esta resposta, estou curioso para saber por que você não fez nenhuma pergunta aqui ou no Stack Overflow. Seus colegas, blog etc. são suficientes para você neste momento? Existem recursos melhores do que o SO que devemos conhecer?
Matthew Leia
6
Talvez você tenha entendido errado o que ele está dizendo. Contra-intuitivamente, ele não estava fazendo perguntas para aprender coisas, ele estava respondendo perguntas.
Jhocking 01/11
65

Tendo estado do lado "guru" da conversa uma ou duas vezes, posso dizer-lhe que muitas vezes o que você percebe como "conhecimento profundo" de uma linguagem ou sistema de programação geralmente é o resultado do "guru" recentemente lutando por um mês para resolver exatamente o mesmo problema. Isso é especialmente verdade em um fórum onde as pessoas podem escolher quais perguntas responderão. Até nomes como Jon Skeet e Eric Lippert tiveram que aprender olá mundo em um ponto. Eles escolhem seu conhecimento um conceito de cada vez, o mesmo que qualquer outra pessoa.

Karl Bielefeldt
fonte
1
Um ponto muito bom. Muitas vezes, ao iniciar longos períodos de pesquisa, encontro perguntas que agora posso responder devido a coisas que aprendi no início do dia.
Matthew Leia
47

Parafraseando Yogi Bhajan:

"Se você quer aprender algo, leia sobre isso; se você quer entender algo, escreva sobre ele; se você quer dominar algo, programe -o."

A programação é como o desafio final do ensino. Ensinar computador a fazer alguma coisa exige que você conheça muito bem suas coisas - ou aprenderá a dominá-las.

Por exemplo, se você quiser aprender física, escreva um mecanismo de física. Se você quer aprender xadrez, programe um jogo de xadrez. Se você quiser aprender um profundo conhecimento de C #, escreva um compilador de C # (ou alguma outra ferramenta).

Maglob
fonte
2
Programar também é uma tentativa modesta de escrever (para ser lida pelas pessoas, é claro) da maneira mais inequívoca.
vpit3833
4
Essa citação soou muito profunda até eu ler o exemplo do xadrez. Infelizmente, programar uma IA de xadrez não o tornará um melhor jogador de xadrez (é basicamente uma pesquisa em uma árvore Min-Max). Ainda +1
bughi
1
@bughi Talvez você possa dominar as regras: D
Julio Rodrigues
@bughi, 'program it' é um termo muito amplo, nem sempre relacionado à escrita de código! Apenas pense um pouco fora da caixa.
Nitesh Verma
25

Tanto quanto eu sei, as maneiras de aprender isso são:

  • Leia sobre isso com alguém como Eric Lippert
  • Experimente e resolva os problemas em primeira mão.

A segunda maneira pode levar muito mais tempo, mas provavelmente resultará em um entendimento mais profundo (mas nem sempre).

FrustratedWithFormsDesigner
fonte
17
Ou ambos. [15 caracteres]
Michael K
23

Eu diria que faça o seguinte:

Depois de aprender uma pilha relativamente útil de idiomas (os necessários para um trabalho real) no nível em que você pode executar as tarefas mais comuns, pare de aprender mais idiomas até estudar pelo menos um em profundidade. Parte do problema em nosso setor agora, na minha opinião, é que as pessoas aprendem apenas os primeiros 5 a 10% do idioma antes de passarem para outro idioma. Depois de ter a capacidade de executar as tarefas mais comuns em um trabalho, comece a analisar uma coisa em profundidade. (Você pode voltar a obter amplitude depois de obter um pouco de profundidade e depois alternar entre as duas.)

Ofereça-se para as tarefas mais complexas e difíceis, aquelas que fazem você precisar se aprofundar para resolver os problemas. Se não houver um onde você trabalhe, procure tarefas de código aberto para executar ou comece a trabalhar em um projeto pessoal que fará com que você tenha que se aprofundar. Se o seu trabalho não tiver problemas interessantes, considere procurar um trabalho mais desafiador.

Leia os livros avançados em um idioma (para o SQl Server, por exemplo, isso incluiria a leitura sobre ajuste de desempenho e internos do banco de dados) em vez do tipo de livro Learn X in 30 days.

Leia as perguntas interessantes aqui e em outros lugares em que elas são feitas e tente resolver algumas. Se você quiser aprender, tente resolver algumas sem ler as outras respostas primeiro. Mesmo se a pergunta já tiver sido respondida, você aprenderá mais se encontrar a resposta. Você pode até encontrar uma resposta melhor do que a que a pergunta tinha.

Faça algumas das perguntas mais difíceis. Avalie as respostas que você recebeu, não as use apenas. Certifique-se de entender por que a resposta funcionaria ou não. Use essas respostas como ponto de partida para pesquisar.

Encontre bons blogs técnicos de especialistas conhecidos e leia-os.

Pare de jogar fora seu conhecimento depois de terminar com ele. Aprenda a reter. A maioria dos especialistas não precisa procurar a sintaxe comum. Eles não precisam reinventar a roda toda vez que enfrentam um problema, porque se lembram de como abordaram um problema semelhante antes. Eles podem conectar os pontos e ver como o problema X que eles fizeram há dois anos é semelhante ao problema Y que eles têm agora (me surpreende como poucas pessoas parecem capazes de fazer conexões como essa). Consequentemente, eles têm mais tempo disponível para pesquisar assuntos mais interessantes.

HLGEM
fonte
Uma boa resposta. Mas fico pensando: como melhorar a retenção de conhecimento e a conexão dos pontos?
Eu sugiro que você faça anotações do que aprender. Comecei a fazer isso no Evernote e, durante alguns anos, descobri que posso viver de minhas anotações. Lentamente, cheguei ao ponto em que minhas anotações podem ser transformadas em apresentações, as quais estou pronto para apresentar a qualquer momento.
Shivasubramanian A
9

Você pode começar estudando profundamente as especificações de idioma daqueles que procura ser um especialista. Por exemplo:

Marcelo
fonte
3
Boa resposta - por exemplo, a seção 15.8.4 da especificação C # vinculada cobre a implementação foreache detalha o comportamento descrito na postagem de blog de Eric Lippert citada. Se alguém se encontrar pensando em algo como "imagino como o foreach realmente funciona ...", esse seria um bom lugar para começar a procurar.
Carson63000
6

Obtenha o Reflector ou qualquer outro descompilador (já que está pagando agora) e comece a abrir algumas das bibliotecas .NET mais usadas para aprender como os internos funcionam. Combinado com um livro como CLR via C #, você ficará bem profundo (mais profundo do que a maioria de nós continuará no trabalho regular).

Bart
fonte
5
Na verdade, eu fiz isso com as BitConverterclasses e descobri o IsLittleEndiansinalizador específico do sistema.
Robert Harvey
RI MUITO. +1 para isLittleEndian
Rudy
4

Eu desenvolvi esse tipo de conhecimento em C ++ comp.lang.c++.moderated, permanecendo por alguns anos, mesmo que eu não estivesse realmente trabalhando tão duro para codificá-lo naquele momento. Não tenho certeza de como guru posso dizer que sou.

Eu acho que existem dois tipos de conhecimento que se pode captar sobre uma linguagem de programação:

  1. Conhecer curiosidades sobre o idioma e saber como evitar as armadilhas.
  2. Saber resolver problemas de forma eficaz.

O número 2 só pode ser alcançado através da programação no idioma e da observação do código de outras pessoas, mas o número 1 pode ser alcançado demorando muito tempo para ler sobre o idioma em seus fóruns de discussão, ver quais tipos de perguntas as pessoas fazem e quais são as respostas são. O StackOverflow também é um bom lugar para isso.

Ken Bloom
fonte
4

Profundo conhecimento e experiência em programação significa estar confortável em todos os níveis de abstração. Ou seja,

  • bibliotecas e APIs
  • semântica da linguagem
  • otimizações do compilador
  • componentes internos do compilador e geração de código
  • tempo de execução e comportamento do coletor de lixo
  • problemas de arquitetura e conjunto de instruções

Tudo o que vi nos últimos 15 anos mostrou que somente se você realmente puder entrar no compilador e no tempo de execução, terá a chance de se tornar proficiente. Você pode ter que se esforçar para dar o passo e começar a raciocinar (e criar) o software no próximo nível de abstração mais baixo na pilha , mas é a única maneira de obter conhecimento.

Tudo o que temos é linguagem para abstração. Você deve entender como as linguagens de programação são projetadas e construídas para realmente saber o que a máquina está fazendo.

Don Stewart
fonte
3

Leia o Manual Fino Este não é um conhecimento particularmente profundo. Ele foi publicado na seção 8.6.4 de especificação de linguagem C # . Você deve adquirir o hábito de, pelo menos, examinar as especificações dos idiomas que usa, bem como a documentação de todas as bibliotecas internas.

Enfim, essa não é minha idéia de conhecimento profundo; é apenas um detalhe de implementação desinteressante. Poderia ser mais interessante se o designer explicasse por que isso foi feito dessa maneira mais dinâmica, em vez de apenas verificar se o objeto implementa o Iterable.

Kevin Cline
fonte
1
Eu não acho que exista uma "desnatação" da especificação da linguagem C #.
Robert Harvey
@RobertHarvey: você pode percorrer a maior parte da linguagem formal, cobrindo coisas que você já conhece, como precedência do operador e sintaxe da declaração, e se concentrar em detalhes inesperados, mas úteis, como o comportamento exato dos construtores C # foreach ou Java enum.
Kevin cline
Você pode comprar uma versão anotada do padrão. É um pouco datado agora, mas os comentários ainda são muito interessantes para as partes do idioma abordadas.
Jørgen Fogh 30/03