Soy un programador autodidacta, en caso de que esta pregunta se responda en CS 101. Aprendí y usé muchos idiomas, principalmente para mi uso personal, pero ocasionalmente para cosas profesionales.
Parece que siempre me encuentro con el mismo muro cuando tengo problemas para programar. Por ejemplo, acabo de hacer una pregunta en otro foro sobre cómo manejar un puntero a matriz que fue devuelto por una función. Inicialmente estoy pensando que simplemente no conozco la técnica adecuada que los diseñadores de C ++ configuraron para manejar la situación. Pero de las respuestas y discusiones que siguen veo que realmente no entiendo lo que sucede cuando algo es "devuelto".
¿Qué nivel de comprensión del proceso de programación debe alcanzar un buen programador?
Respuestas:
No. Nadie entiende lo que está sucediendo a nivel de hardware.
Los sistemas informáticos son como las cebollas: hay muchas capas y cada una depende de la capa que se encuentra debajo para obtener soporte. Si eres el tipo que trabaja en una de las capas externas, no deberías preocuparte demasiado por lo que sucede en el medio de la cebolla. Y eso es bueno, porque la mitad de la cebolla siempre está cambiando. Mientras la capa o capas que soportan su capa en particular sigan pareciendo y soporten su capa, está bien.
Pero entonces de nuevo...
Sí. Quiero decir, no necesitas entender lo que realmente está sucediendo dentro de la cebolla, pero ayuda mucho tener un modelo mental de cómo se ve el interior de una cebolla típica. Tal vez no sea la parte más profunda, donde tienes compuertas compuestas de transistores y tal, o la siguiente capa o dos, donde tienes microcódigo, un reloj, unidades de decodificación de instrucciones, etc. Sin embargo, las siguientes capas son donde Tengo registros, la pila y el montón. Estas son las capas más profundas en las que tiene mucha influencia sobre lo que sucede: el compilador traduce su código en instrucciones que se ejecutan a este nivel, y si lo desea, generalmente puede seguir estas instrucciones y descubrir qué está sucediendo "realmente".
Los programadores más experimentados tienen una versión de cuento de hadas de estas capas en su cabeza. Le ayudan a comprender de qué está hablando el compilador cuando le dice que hubo una "excepción de dirección no válida" o un "error de desbordamiento de pila" o algo así.
Si está interesado, lea un libro sobre arquitectura de computadoras. Ni siquiera tiene que ser un libro particularmente nuevo: las computadoras digitales han estado trabajando aproximadamente de la misma manera durante mucho tiempo. ¡Cuanto más aprenda sobre el interior de la cebolla, más se sorprenderá de que cualquiera de estas cosas funcione en absoluto! Aprender (aproximadamente) lo que sucede en las capas inferiores hace que la programación sea menos misteriosa y, de alguna manera, más mágica. Y realmente, más divertido.
Otra cosa que podría considerar son las cebollas integradas. Er, me refiero a los sistemas embebidos. Hay varias plataformas integradas que son bastante fáciles de usar: Arduino y BASIC Stamp son dos ejemplos. Estos son básicamente microprocesadores pequeños con muchas características incorporadas. Puede pensar en ellas como cebollas con menos capas que una PC de escritorio típica, por lo que es posible obtener una comprensión bastante completa de lo que está sucediendo en todo el sistema, desde el hardware hasta el software.
fuente
No estás hablando del nivel de hardware, estás hablando de lo que realmente hace el compilador con lo que le dices que haga.
Sin duda, necesita este nivel de comprensión para descubrir qué salió mal cuando no es obvio, especialmente cuando se trata de una situación de pisoteo de memoria.
fuente
Understanding Program Memory! = Comprensión del hardware
Comprender la jerarquía de memoria == Comprender el hardware
Para responder a su pregunta genérica: depende. No está de más entender el hardware, pero comprenderlo no ayudará en todos los casos.
Según su ejemplo, solo necesita comprender más sobre cómo se divide la memoria y cómo se organiza cuando ejecuta un programa. Comprender el hardware no lo ayudará a este respecto, porque la memoria (como es visible para un programa) ni siquiera representa realmente el hardware gracias a la magia de la memoria virtual.
Si tuviera curiosidad acerca de los problemas de rendimiento en función del orden en el que accede a la memoria, AHORA se beneficiaría de la comprensión del hardware, la jerarquía de memoria, errores de caché, fallas de página y toda la gloriosa y maravillosa bondad que proviene del hardware.
fuente
Si no decide aprender un poco de ensamblador, probablemente debería aprender algo así como 6502 ensamblador en un Commodore 64 (emulado, por supuesto), o 68000 en un Amiga.
Puedes hacerte una idea del Commodore 64 aquí ...
http://thepiratebay.org/torrent/4609238/Tag3-Saal2-Slot16_00--ID2874-the_ultimate_commodore_64_talk-Main
El clásico libro de todo lo que necesitas saber es el que se describe aquí ...
http://reprog.wordpress.com/2010/03/12/programming-books-part-3-programming-the-commodore-64/
Probablemente pueda encontrar un escaneo PDF si mira a su alrededor.
OMI, 6502 es más fácil que Z80, y 68000 es más fácil que 8086: más conjuntos de instrucciones regulares, etc.
Pero la CPU es solo un aspecto del hardware. Además, una CPU moderna es una bestia enormemente diferente, y hace cosas que son transparentes incluso desde el punto de vista de los compiladores, como presentar un espacio de direcciones virtual.
Una ventaja particular del 6502 en el C64 es que no solo la CPU es simple, sino que también hay hardware muy sencillo de piratear. Solía divertirme mucho jugando con el chip de música SID.
Entonces, probablemente sea un ejercicio que valga la pena si no le dedica demasiado tiempo. Aprendí 6502 ensamblador como mi segundo idioma cuando tenía unos 14 años, justo después de Commodore Basic. Pero sobre todo está obteniendo ese modelo de trabajo muy simple para que pueda agregarle ideas más sofisticadas con un mínimo de malentendidos.
Algunas cosas útiles que puedes aprender trabajando en ensamblador ...
Una razón particular que recomendaría es tener una mejor intuición de la forma en que los pasos simples funcionan de manera totalmente determinista, mecánica y absoluta, sin inteligencia ni sentido común. Básicamente, acostumbrarse al modelo de ejecución imperativo en su forma más pura y obstinadamente ignorante.
Sin embargo, lo útil que es saber la mayoría de esas cosas ahora es una pregunta difícil.
Una cosa que no aprenderá es cómo jugar bien con una jerarquía de memoria. Esas máquinas antiguas en su mayoría tenían un modelo de memoria simple sin capas de caché y sin memoria virtual. Tampoco aprenderá mucho sobre la concurrencia: ciertamente fueron formas de manejar eso, pero en su mayoría significaron interrupciones. No tenía que preocuparse por mutexes, etc.
A veces, un modelo mental de cómo estas cosas una vez trabajado, o de cómo funciona la ensamblador, incluso puede inducir a error. Por ejemplo, pensar en un puntero C como una dirección puede conducir a problemas de comportamiento indefinidos. El puntero de CA normalmente se implementa como un entero que contiene una dirección, pero no hay garantía de que sea estrictamente cierto. Por ejemplo, en algunas plataformas extrañas, diferentes punteros pueden apuntar a diferentes espacios de direcciones. Esto se vuelve importante cuando quieres hacer aritmética o lógica bit a bit con dos punteros.
A menos que tenga una de esas plataformas extrañas, es posible que no piense que le importa, pero en la actualidad los compiladores son cada vez más propensos a explotar comportamientos indefinidos para la optimización.
Por lo tanto, un modelo mental de la arquitectura del sistema puede ser útil, pero sigue siendo importante codificar según las especificaciones del lenguaje, no según un modelo hipotético que su lenguaje y plataforma pueden no respetar.
Finalmente, muchas cosas útiles del modelo mental provienen de tener una idea de cómo los compiladores generan código, y la generación de código para lenguajes modernos es muy diferente de los compiladores bastante triviales disponibles en ese momento.
Este es un libro mío favorito para eso ...
http://dickgrune.com/Books/MCD_1st_Edition/
Junto con el material sobre análisis y AST, etc., cubre la generación de código para una variedad de paradigmas de lenguaje: imperativo, OOP, funcional, lógico, paralelo y distribuido, y también para la gestión de la memoria. Si desea saber cómo funcionan las llamadas a métodos polimórficos sin atascarse en los detalles del conjunto de instrucciones de la CPU, un libro como este es su amigo, y pronto saldrá una nueva edición.
fuente
Hace veinte años era importante, pero no tanto ahora: hay muchas más capas de abstracción entre el software y el hardware moderno.
Es útil saber cosas como necesitar múltiples subprocesos para aprovechar múltiples núcleos o que usar más memoria de la que existe en el sistema es algo malo, pero más allá de eso realmente no lo necesita a menos que sea su trabajo escribir esas abstracciones capas.
El resto de su pregunta sugiere que puede estar más preocupado con el compilador que con el hardware, que es un poco diferente. Puede encontrar casos en los que es importante, pero estos tienden a ser triviales (la recursión infinita no funciona muy bien) o el tipo de casos extremos en los que puede sentirse bien al resolverlo, pero probablemente nunca se encuentre con el mismo problema. otra vez.
fuente
Es de gran ayuda conocer y comprender la abstracción presentada por el hardware, y un poco de la idea general sobre cómo se crea esa ilusión, pero tratar de entender realmente cómo funciona realmente el hardware moderno es una gran cantidad de trabajo del cual usted ' Es probable que vea solo un retorno mínimo.
Si perdonas una distracción menor: esto me recuerda algo que noté hace unos años. Hace décadas (hasta fines de la década de 1970, más o menos), la mayoría de las personas pensaban que las computadoras eran mágicas, apenas afectadas por las leyes de la física, capaces de todo tipo de cosas que tenían poco sentido real, etc. En ese momento, pasé una buena cantidad de tiempo intentando (en su mayoría sin éxito) convencer a la gente de que no, que no eran mágicos. Eran máquinas realmente bastante ordinarias que hacían un número limitado de cosas de manera muy rápida y confiable, pero por lo demás eran extremadamente mundanas.
Hoy en día, la visión de la mayoría de las personas sobre las computadoras ha cambiado. Ahora son bastante comunes, hasta el punto de que algunas personas muy comunes tienen una comprensión práctica de ellos. Solo por ejemplo, hace un tiempo, mientras estaba cenando, vi / escuché a un mesero y una mesera en su descanso discutiendo lo que debería obtener en su nueva computadora. El consejo que estaba dando era completamente razonable y realista.
Sin embargo, mi visión de las computadoras también ha cambiado. He ido a Hot Chips, y antes de eso, el Foro de Microprocesadores se remonta a mediados de la década de 1990 más o menos. Probablemente sé más sobre el hardware de microprocesador que al menos el 99% de los programadores, y sabiendo lo que hago, diré esto: ya no son comunes. Ellos hacen casi rompen las leyes de la física. He realizado muchas pruebas de bajo nivel y puedo decirlo con certeza: superar la ilusión creada por la CPU y mostrar cómo funciona realmente el hardware a menudo es increíblemente difícil. Desearía poder publicar una imagen de una de nuestras configuraciones con una computadora enterrada bajo cables de no menos de 4 analizadores lógicos solo para medir adecuadamente uno aspecto de cómo funciona el almacenamiento en caché en una CPU moderna (sin mencionar una programación realmente fastidiosa para garantizar que lo que medimos era exactamente lo que estaba haciendo la CPU, y nada más).
fuente
Los diferentes idiomas funcionan en diferentes niveles de abstracción del hardware. C y C ++ son de muy bajo nivel. Los lenguajes de script, por otro lado, requieren que sepa menos sobre los detalles subyacentes.
Sin embargo, todavía diría que en todos los casos, cuanto más sepa, mejor será un programador. Parte de la programación es poder hacer malabarismos con múltiples niveles de abstracción al mismo tiempo.
Si está programando en C ++, debe comprender bastante bien cómo funciona una CPU moderna, al menos en el nivel de abstracción en el que funciona el compilador. (También están sucediendo cosas dentro de la CPU que son transparentes para el compilador).
fuente
Me gustaría agregar un punto sobre el diseño general de lenguajes de nivel superior como C.
En general, creo que es seguro decir que dichos lenguajes pueden verse como la implementación de una máquina abstracta, y de hecho así es como el propio Dennis Ritchie ha descrito cómo funciona C y cómo el diseño particular de la máquina abstracta de C lo ha convertido en un lenguaje más portátil. Como tal, tener cierta comprensión de la arquitectura de la computadora y el funcionamiento a nivel de máquina, puede ser extremadamente útil para comprender también la máquina abstracta de un lenguaje.
La Portabilidad en papel de DMR de los Programas C y el Sistema UNIX es la primera que recuerdo para discutir el modelo de máquina (abstracto) para C.
Creo que el artículo de DMR sobre la historia y el desarrollo de C también es extremadamente útil para mostrar cómo el hardware real afecta el diseño del lenguaje, y quizás también sea un ejemplo del diseño de lenguaje de programación inicial: El desarrollo del lenguaje C
fuente