Sobre el desarrollo de profundos conocimientos de programación

136

De vez en cuando veo preguntas sobre casos extremos y otras rarezas en Stack Overflow que son respondidas fácilmente por personas como Jon Skeet y Eric Lippert, lo que demuestra un profundo conocimiento del lenguaje y sus muchas complejidades, como esta:

Puede pensar que para usar un foreachbucle, la colección sobre la que está iterando debe implementar IEnumerableo IEnumerable<T>. Pero resulta que eso no es realmente un requisito. Lo que se requiere es que el tipo de la colección debe tener un método público llamado GetEnumerator, y que debe devolver algún tipo que tenga un getter de propiedad pública llamado Currenty un método público MoveNextque devuelva a bool. Si el compilador puede determinar que se cumplen todos esos requisitos, el código se genera para usar esos métodos. Solo si no se cumplen esos requisitos, verificamos si el objeto se implementa IEnumerableo no IEnumerable<T>.

Eso es algo genial para saber. Puedo entender por qué Eric sabe esto; él está en el equipo compilador, así que tiene que saberlo. ¿Pero qué pasa con aquellos que demuestran un conocimiento tan profundo que no son expertos?

¿Cómo se enteran los simples mortales (que no están en el equipo del compilador de C #) sobre cosas como esta?

Específicamente, ¿existen métodos que estas personas usen para erradicar sistemáticamente dicho conocimiento, explorarlo e internalizarlo (hacerlo propio)?

Robert Harvey
fuente
10
Creo que esto es particularmente donde brilla el software de código abierto. Es bueno poder entrar en el marco / sistema / bibliotecas hasta el final. Solía ​​tener una mejor comprensión de los componentes internos del framework cuando trabajaba con Qt que cuando trabajaba con WinForms.
Vitor Py
2
¿Cuándo necesitarías conocer este ejemplo específico, aparte de no parecer tonto frente a una multitud especial? A prueba de idiotas esto. Aparte de eso, la serie Effective C #, Java, C ++, etc. podría tener algunas cosas interesantes. El blog de Eric Lippert también es una buena fuente. En general, a menudo no sabemos lo que no sabemos, así que como dicen "vive durante 100 años, aprende durante 100 años y muere como un tonto".
Trabajo
26
¿Vale la pena el esfuerzo? Soy bilingüe y estoy tratando de aprender algunos otros idiomas hablados. He tomado algunas clases de matemáticas pero no suficientes. Me gustaría aprender a jugar al tenis medio decente y aprender a nadar con mariposa. Me gustaría viajar más. Quiero aprender algo de Clojure. Lo que no quiero es ser experto en un idioma, tener un doctorado en matemáticas, pasar 30 horas por semana en un grupo como Michael Phelps, etc. El conocimiento de Lippert y Skeet se debe al hecho de que ponen mucho esfuerzo en una (o algunas) cosas sin perderse otras experiencias. Tal vez cambiar de trabajo?
Trabajo
10
"Puedo entender por qué Eric lo sabe; está en el equipo compilador, así que tiene que saberlo". - es probable que él sepa esto porque lo pensó en primer lugar . Dudo que tuviera que "descubrir" que funciona así :)
Alex ten Brink
10
@Alex: en realidad solo he trabajado en C # desde que comenzamos a construir la implementación de C # 3. La especificación "foreach" se escribió más de seis años antes. Todavía encuentro cosas históricas locas sobre el idioma todos los días. Por ejemplo, hoy aprendí que para los delegados, ((A + B) + C) - (A + C) = A + B + C, pero ((A + B) + C) - (B + C) = A . ¡Extraño!
Eric Lippert

Respuestas:

167

En primer lugar, gracias por las amables palabras.

Si desea obtener un conocimiento profundo de C #, sin duda es una ventaja tener la especificación del lenguaje, diez años de notas de diseño, el código fuente, la base de datos de errores y Anders, Mads, Scott y Peter justo al final del pasillo. Ciertamente soy afortunado, no hay duda al respecto.

Sin embargo, incluso sin esas ventajas, todavía es posible obtener un conocimiento profundo del tema.

Cuando comencé en Microsoft, estaba trabajando en el intérprete JScript que se incluía con Internet Explorer 3. Mi gerente en ese momento me dijo algo que fue uno de los mejores consejos que he recibido. Dijo que quería que me convirtiera en el experto reconocido de Microsoft en la sintaxis y la semántica del lenguaje JScript, y que debería hacerlo buscando preguntas sobre esos aspectos de JScript y respondiéndolas. Particularmente respondiendo las preguntas para las que no sabía las respuestas, porque esas son las que aprendería.

Obviamente, StackOverflow y otros foros públicos de preguntas y respuestas son como beber de una manguera de bomberos para ese tipo de cosas. En aquel entonces, leí religiosamente comp.lang.javascript y nuestros foros internos de "usuarios de JS" de Microsoft y seguí el consejo de mi gerente: cuando vi una pregunta sobre la semántica del idioma para la que no sabía la respuesta, lo hice. Mi negocio es averiguarlo.

Si quieres hacer una "inmersión profunda" como esa, debes elegir con cuidado. Hasta el día de hoy, soy notablemente ignorante de cómo funciona el modelo de objetos del navegador. Como me he concentrado en convertirme en el experto en lenguaje C # estos últimos años, soy notablemente ignorante de cómo funcionan las diversas clases en las bibliotecas de clases base. Soy afortunado porque tengo un trabajo que premia el conocimiento profundo específico; Si su trabajo o sus talentos están más en línea con ser un generalista, profundizar podría no funcionar para usted.

Escribir un blog también es tremendamente útil; Al exigirme que explique temas complejos a otras personas, me veo obligado a enfrentar mi propia comprensión inadecuada de varios temas todo el tiempo.

Eric Lippert
fuente
14
No para arrastrar esto fuera del tema, pero después de leer esta respuesta, tengo curiosidad por saber por qué no ha hecho ninguna pregunta aquí o en Stack Overflow. ¿Sus colegas, blog, etc. son suficientes para usted en este momento? ¿Hay mejores recursos que SO que deberíamos conocer?
Matthew leyó el
66
Quizás entendiste mal lo que está diciendo. Contraintuitivamente, no estaba haciendo preguntas para aprender cosas, estaba respondiendo preguntas.
jhocking
65

Después de haber estado en el lado del "gurú" de la conversación una o dos veces, puedo decirle que muchas veces lo que percibe como "conocimiento profundo" de un lenguaje o sistema de programación es a menudo el resultado del "gurú" que lucha recientemente por un mes para resolver exactamente el mismo problema. Eso es especialmente cierto en un foro donde las personas pueden elegir qué preguntas responderán. Incluso los gustos de Jon Skeet y Eric Lippert tuvieron que aprender hola mundo en un punto. Recogen su conocimiento un concepto a la vez, igual que cualquier otra persona.

Karl Bielefeldt
fuente
1
Un muy buen punto. A menudo, cuando me embarco en largos períodos de investigación, encuentro preguntas que ahora puedo responder debido a cosas que aprendí más temprano en el día.
Matthew Lee el
47

Parafraseando a Yogi Bhajan:

"Si quieres aprender algo, léelo; si quieres entender algo, escríbelo; si quieres dominar algo, prográmalo ".

La programación es como el último desafío de enseñanza. Enseñar a la computadora a hacer algo requiere que conozcas tus cosas realmente bien, o aprenderás a dominarlas.

Por ejemplo, si quieres aprender física, escribe un motor de física. Si quieres aprender ajedrez, programa un juego de ajedrez. Si desea aprender un profundo conocimiento de C #, escriba un compilador de C # (o alguna otra herramienta).

Maglob
fuente
2
La programación también es un intento modesto de escribir (para ser leído por la gente, por supuesto) de la manera más inequívoca.
vpit3833
44
Esa cita sonó muy profunda hasta que leí el ejemplo de ajedrez. Desafortunadamente, programar una IA de ajedrez no te hará un mejor jugador de ajedrez (es básicamente una búsqueda en un árbol Min-Max). Todavía +1
bughi
1
@bughi Quizás puedas dominar las reglas: D
Julio Rodrigues
@bughi, 'programarlo' es un término muy amplio que no siempre está relacionado con la escritura de código. Solo piense un poco fuera de la caja.
Nitesh Verma
25

Hasta donde yo sé, las formas de aprender esto son:

  • Lea sobre esto de alguien como Eric Lippert
  • Experimente y luego resuelva los problemas de primera mano.

La segunda forma puede llevar mucho más tiempo, pero probablemente resultará en una comprensión más profunda (pero no siempre).

FrustratedWithFormsDesigner
fuente
17
O ambos. [15 caracteres]
Michael K
23

Yo diría que hagas lo siguiente:

Después de aprender una pila relativamente útil de idiomas (los que necesita para un trabajo real) en el nivel en el que puede realizar las tareas más comunes, deje de aprender más idiomas hasta que haya estudiado al menos uno en profundidad. Parte del problema en nuestra industria en este momento, en mi opinión, es que las personas solo aprenden el primer 5-10% del idioma antes de pasar a otro idioma. Una vez que tenga la capacidad de realizar las tareas más comunes en un trabajo, comience a analizar una cosa en profundidad. (Puede volver a obtener amplitud después de obtener algo de profundidad, luego ir y venir entre los dos).

Voluntario para las tareas más complejas y difíciles, las que hacen que tengas que profundizar para resolver los problemas. Si no hay ninguno donde trabaje, busque tareas de código abierto para hacer o comience a trabajar en un proyecto personal que lo obligará a profundizar. Si su trabajo no tiene problemas interesantes, considere buscar un trabajo más desafiante.

Lea los libros avanzados en un idioma (para SQl Server, por ejemplo, esto incluiría leer sobre ajuste de rendimiento y aspectos internos de la base de datos) en lugar del tipo de libros de aprender X en 30 días.

Lea las preguntas interesantes aquí y en otros lugares donde se hacen y trate de resolverlas usted mismo. Si quieres aprender, intenta resolver algunas sin leer primero las otras respuestas. Incluso si la pregunta ya ha sido respondida, aprenderá más si encuentra la respuesta usted mismo. Incluso podría encontrar una mejor respuesta que la que tenía la pregunta.

Haga algunas de las preguntas más difíciles. Evalúa las respuestas que te dan, no las uses solo. Asegúrese de entender por qué la respuesta funcionaría o no. Use esas respuestas como punto de partida para investigar.

Encuentre algunos buenos blogs técnicos de expertos conocidos en el campo y léalos.

Deja de tirar tu conocimiento una vez que hayas terminado con él. Aprende a retener. La mayoría de los expertos no tienen que buscar la sintaxis común. No tienen que reinventar la rueda cada vez que enfrentan un problema porque recuerdan cómo abordaron un problema similar antes. Pueden conectar los puntos y ver cómo el problema X que hicieron hace dos años es similar al problema Y que tienen ahora (me sorprende cómo pocas personas parecen capaces de hacer conexiones como esa). En consecuencia, tienen más tiempo disponible para dedicar a la investigación de temas más interesantes.

HLGEM
fuente
Una buena respuesta Pero me pregunto, ¿cómo puedo mejorar en retener el conocimiento y conectar los puntos?
Le sugiero que tome notas de lo que aprenda. Comencé a hacer esto en mi Evernote, y durante unos años, descubrí que podía vivir de mis notas. Lentamente, también he llegado al punto en que mis notas pueden convertirse en presentaciones, que estoy listo para presentar en cualquier momento.
Shivasubramanian A
9

Puede comenzar estudiando a fondo las especificaciones de idioma de las que busca ser un experto. Por ejemplo:

Marcelo
fuente
3
Buena respuesta: por ejemplo, la sección 15.8.4 de la especificación de C # vinculada cubre la implementación foreachy detalla el comportamiento descrito en la publicación de blog citada de Eric Lippert. Si alguien alguna vez se encuentra pensando algo como "Me pregunto cómo funciona realmente foreach ...", este sería un buen lugar para comenzar a buscar.
Carson63000
6

Obtenga Reflector o cualquier otro descompilador (ya que está pagando ahora), y comience a abrir algunas de las bibliotecas .NET más utilizadas para aprender cómo funcionan las partes internas. En combinación con un libro como CLR a través de C #, se volverá bastante profundo (más profundo de lo que la mayoría de nosotros realizaremos su trabajo habitual).

Bart
fuente
55
Realmente hice esto con las BitConverterclases, y descubrí la IsLittleEndianbandera específica del sistema.
Robert Harvey
Jajaja +1 para isLittleEndian
Rudy
4

Desarrollé ese tipo de conocimiento en C ++ al pasar comp.lang.c++.moderatedun par de años, a pesar de que realmente no estaba trabajando tan duro para codificarlo en ese momento. Sin embargo, no estoy seguro de qué gurú puedo decir que soy.

Creo que hay dos tipos de conocimiento que uno puede aprender sobre un lenguaje de programación:

  1. Conocer curiosidades sobre el idioma y saber cómo evitar las trampas.
  2. Saber resolver problemas de manera efectiva.

El número 2 solo se puede lograr programando en el lenguaje y mirando el código de otras personas, pero el número 1 se puede lograr tomando mucho tiempo para leer sobre el idioma en sus foros de discusión, ver qué tipo de preguntas hacen las personas y cuáles son las respuestas son StackOverflow es un buen lugar para eso también.

Ken Bloom
fuente
4

El conocimiento profundo y la experiencia en programación significa sentirse cómodo en todos los niveles de abstracción. Es decir

  • bibliotecas y API
  • semántica del lenguaje
  • optimizaciones del compilador
  • compilación interna y generación de código
  • tiempo de ejecución y comportamiento del recolector de basura
  • problemas arquitectónicos y de instrucción

Todo lo que he visto en los últimos 15 años ha demostrado que solo si realmente puedes entrar en el compilador y el tiempo de ejecución, tienes la oportunidad de ser profundamente competente. Puede que tenga que obligarse a dar el paso y comenzar a razonar (y construir) software en el siguiente nivel de abstracción más bajo en la pila , pero es la única forma de experiencia.

Todo lo que tenemos es lenguaje para la abstracción. Debe comprender cómo se diseñan y construyen los lenguajes de programación para saber realmente lo que está haciendo la máquina.

Don Stewart
fuente
3

Lea el buen manual Esto no es un conocimiento particularmente profundo. Está publicado en la sección de especificación del lenguaje C # 8.6.4. Debería habituarse al menos a eliminar las especificaciones de los idiomas que utiliza, así como a eliminar la documentación de todas las bibliotecas integradas.

De todos modos, esta no es mi idea de conocimiento profundo; es solo un detalle de implementación poco interesante. Podría ser más interesante si el diseñador explicara por qué se hizo de esta manera más dinámica, en lugar de simplemente verificar que el objeto implemente Iterable.

Kevin Cline
fuente
1
No creo que exista una "especificación" de la especificación del lenguaje C #.
Robert Harvey
@RobertHarvey: puede hojear la mayor parte del lenguaje formal que cubre cosas que ya conoce, como la sintaxis de declaración y precedencia de operadores, y centrarse en los detalles inesperados pero útiles, como el comportamiento exacto de los constructores enum de Java o foreach de C #.
Kevin Cline
Puede comprar una versión anotada del estándar. Ahora está un poco anticuado, pero los comentarios siguen siendo muy interesantes para las partes del lenguaje que se tratan.
Jørgen Fogh