¿Cómo ha afectado un aumento en la complejidad de los sistemas a las sucesivas generaciones de programadores?

127

Como programador "nuevo" (escribí por primera vez una línea de código en 2009), he notado que es relativamente fácil crear un programa que exhiba elementos bastante complejos hoy en día con cosas como .NET framework, por ejemplo. Crear una interfaz visual u ordenar una lista se puede hacer con muy pocos comandos ahora.

Cuando estaba aprendiendo a programar, también estaba aprendiendo teoría de la computación en paralelo. Cosas como algoritmos de clasificación, principios de cómo el hardware funciona en conjunto, álgebra booleana y máquinas de estado finito. Pero noté que si alguna vez quería probar algún principio muy básico que había aprendido en teoría, siempre era mucho más difícil comenzar porque mucha tecnología está oscurecida por cosas como bibliotecas, marcos y el sistema operativo.

Hace 40/50 años se requería hacer un programa con uso eficiente de la memoria porque no había suficiente memoria y era costoso, por lo que la mayoría de los programadores prestaron mucha atención a los tipos de datos y a cómo el procesador manejaría las instrucciones. Hoy en día, algunos podrían argumentar que debido a la mayor potencia de procesamiento y la memoria disponible, esas preocupaciones no son una prioridad.

Mi pregunta es si los programadores mayores ven innovaciones como estas como un regalo del cielo o una capa adicional para abstraer, y ¿por qué podrían pensar eso? ¿Y los programadores más jóvenes se benefician de más aprendizaje de programación de bajo nivel ANTES de explorar los reinos de las bibliotecas expansivas? Si es así, ¿por qué?

Adán
fuente
24
El artículo de Joel Spolsky de 2002 es relevante: joelonsoftware.com/articles/LeakyAbstraction.html Como frase / formulada, sin embargo, esta pregunta podría terminar siendo considerada principalmente basada en la opinión.
BrianH
Lamento la falta de opciones más simples para explorar técnicas de programación muy básicas.
GrandmasterB
1
Esto es relevante Algo así como. (Quiero decir, espero que esa imagen sea una broma, pero con algo de lo que pasa con StackOverflow ...)
Izkata
1
Tiene sus pros y sus contras. Abre el mundo de la programación a muchos programadores nuevos, que no necesitan tanta habilidad para tener éxito; al contrario de lo que algunas personas podrían decir, eso es algo bueno. Y todavía estamos escribiendo programas eficientes, que nunca cambiaron, es solo que los objetivos han cambiado. Guardar un byte en un año ya no es bueno: la diferencia de memoria es poco probable que marque la diferencia, y usar, por ejemplo. dos bytes es más flexible y a prueba de futuro. El costo de los programadores versus el costo de SW y HW también es un factor significativo. La demanda de nuevo software es enorme. Los codificadores son pocos.
Luaan
1
La escala de tiempo de 40/50 años está mal. La programación eficiente de la memoria todavía era de importancia crítica en Windows de 16 bits (hace menos de 20 años) y (desafortunadamente) en la mayoría de los embebidos / robótica actuales.
david.pfx

Respuestas:

174

simplemente no es necesario debido a la mayor cantidad de potencia de procesamiento y memoria disponible.

Tener memoria barata, discos enormes y procesadores rápidos no es lo único que ha liberado a las personas de la necesidad de obsesionarse con cada byte y ciclo. Los compiladores ahora son mucho, mucho mejores que los humanos para producir código altamente optimizado cuando es importante.

Además, no olvidemos para qué estamos tratando de optimizar, que es el valor producido por un costo dado. Los programadores son mucho más caros que las máquinas. Cualquier cosa que hagamos que haga que los programadores produzcan programas que funcionen, sean correctos, robustos y con todas las funciones de manera más rápida y económica conduce a la creación de más valor en el mundo.

Sin embargo, mi pregunta es cómo se siente la gente acerca de este "ocultamiento" de elementos de nivel inferior. ¿Los programadores más viejos lo ven como un regalo del cielo o una capa innecesaria para atravesar?

Es absolutamente necesario realizar cualquier trabajo. Escribo analizadores de código para vivir; si tuviera que preocuparme por la asignación de registros o la programación del procesador o cualquiera de esos millones de otros detalles, entonces no pasaría mi tiempo reparando errores, revisando informes de rendimiento, agregando características, etc.

Toda la programación se trata de abstraer la capa debajo de ti para hacer una capa más valiosa encima. Si hace un "diagrama de capas" que muestra todos los subsistemas y cómo se construyen entre sí, encontrará que hay literalmente docenas de capas entre el hardware y la experiencia del usuario. Creo que en el diagrama de pastel de capas de Windows hay algo así como 60 niveles de subsistemas necesarios entre el hardware en bruto y la capacidad de ejecutar "hello world" en C #.

¿Crees que los programadores más jóvenes se beneficiarían más aprendiendo programación de bajo nivel ANTES de explorar los reinos de las bibliotecas expansivas?

Pones énfasis en ANTES, así que debo responder tu pregunta en forma negativa. Estoy ayudando a un amigo de 12 años a aprender a programar en este momento y es mejor que creas que los estoy iniciando en Processing.js y no en el ensamblador x86. Si comienzas un programador joven en algo así Processing.js, estará escribiendo sus propios juegos shoot-em-up en aproximadamente ocho horas. Si los comienzas en ensamblador, multiplicarán tres números juntos en aproximadamente ocho horas. ¿Cuál crees que es más probable que atraiga el interés de un programador más joven?

Ahora, si la pregunta es "¿se benefician los programadores que entienden la capa n del pastel al comprender la capa n - 1?" la respuesta es sí, pero eso es independiente de la edad o la experiencia; siempre es posible mejorar su programación de nivel superior al comprender mejor las abstracciones subyacentes.

Eric Lippert
fuente
12
Cita divertida +1: Dunbars Number es un buen ejemplo (hay otros) de cocientes de capacidad cognitiva estudiados que se pueden ver en muchas personas que muestran que tenemos un espacio mental fijo. La abstracción de múltiples cosas en generalizaciones singulares es la única forma en que podemos aumentar de manera coherente el número de cosas en nuestro espacio mental, y eso es lo que la programación de nivel superior busca aprovechar.
Jimmy Hoffa
18
@Euphoric: Su pregunta tiene sentido, pero ¿dónde se detiene? Supongamos que digo "bueno, en lugar de aprender Processing.js, aprendamos a escribir videojuegos en C ++ usando DirectX". Está bien. Ahora, ¿qué te impide decir "no va a crear problemas si quieren hacer algo menos abstracto?" y quizás queremos comenzar con cómo escribir un controlador de tarjeta gráfica. Pero luego haces la pregunta nuevamente, y antes de que te des cuenta, estamos ingresando el código de la máquina en un Altair con interruptores de palanca. ¡Tienes que elegir un nivel de abstracción en alguna parte !
Eric Lippert
35
@Euphoric: ¿Harías el mismo argumento para, digamos, contabilidad? No necesitamos más personas que puedan mantener los libros simples para una nueva pequeña empresa; necesitamos grandes contadores de clase mundial. Si los cursos introductorios de contabilidad son tan difíciles que ahuyentan a las personas que simplemente aspiran a ser contadores productivos y trabajadores, BUENO. ¡No necesitamos a esas personas en la industria contable! ¿Qué hay de los pianistas? Si las lecciones introductorias de piano ahuyentan a las personas que no van a ser GRANDES pianistas, eso es bueno; solo queremos grandes pianistas en el mundo. ¿Algo parece estar mal con este argumento?
Eric Lippert
25
@Euphoric: La respuesta corta es BUENOS CIELOS ¡SÍ, necesitamos programadores más decentes! Necesitamos más programadores en todos los niveles de habilidad y experiencia. El mundo funciona con software . Cuantas más personas que tienen alguna comprensión de cómo hacen su trabajo mundo, el mejor.
Eric Lippert
66
@Euphoric (y otros): estamos llegando al límite con respecto a la constructividad de los comentarios. Únase a nosotros en el chat de ingeniería de software si desea continuar esta conversación.
50

Tenía ideas sobre este tema y las puse en un libro hace 20 años . Ya no se imprime, pero aún puede obtener copias usadas en Amazon .

Una respuesta simple a su pregunta es tan antigua como Aristóteles: la naturaleza aborrece el vacío . Tanto como las máquinas se han vuelto más rápidas y más grandes, el software se ha vuelto más lento y más grande.

Para ser más constructivo, lo que propuse fue que la teoría de la información, y su relevancia directa para el software, sea parte de la educación en informática. Ahora solo se enseña, si es que lo hace, de una manera muy tangencial.

Por ejemplo, el comportamiento big-O de los algoritmos se puede entender de manera muy clara e intuitiva si se piensa en un programa como un canal de información de tipo Shannon, con símbolos de entrada, símbolos de salida, ruido, redundancia y ancho de banda.

Por otro lado, la productividad de un programador puede entenderse en términos similares utilizando la teoría de la información de Kolmogorov. La entrada es una estructura conceptual simbólica en su cabeza, y la salida es el texto del programa que sale de la punta de sus dedos. El proceso de programación es el canal entre los dos. Cuando el ruido ingresa al proceso, crea programas inconsistentes (errores). Si el texto del programa de salida tiene suficiente redundancia, puede permitir que los errores sean detectados y corregidos (detección y corrección de errores). Sin embargo, si es demasiado redundante, es demasiado grande y su tamaño, combinado con la tasa de error, provoca la introducción de errores. Como resultado de este razonamiento, pasé buena parte del libro mostrando cómo tratar la programación como un proceso de diseño del lenguaje., con el objetivo de poder definir los lenguajes específicos de dominio apropiados para una necesidad. Hacemos un buen servicio a los lenguajes específicos de dominio en educación CS pero, de nuevo, es tangencial.

Construir idiomas es fácil. Cada vez que define una función, clase o variable, agrega vocabulario al idioma con el que comenzó, creando un nuevo idioma con el que trabajar. Lo que generalmente no se aprecia es que el objetivo debe ser hacer que el nuevo lenguaje coincida más con la estructura conceptual del problema. Si se hace esto, entonces tiene el efecto de acortar el código y hacerlo menos problemático simplemente porque, idealmente, hay un mapeo 1-1 entre los conceptos y el código. Si el mapeo es 1-1, puede cometer un error y codificar un concepto incorrectamente como un concepto diferente, pero el programa nunca se bloqueará, que es lo que sucede cuando no codifica ningún requisito consistente .

No estamos entendiendo esto. A pesar de todos nuestros comentarios valientes sobre el diseño de sistemas de software, la relación entre el código y los requisitos es cada vez mayor, mucho mayor.

Es cierto, tenemos bibliotecas muy útiles. Sin embargo, creo que deberíamos ser muy circunspectos sobre la abstracción. No debemos suponer que si B se basa en A y eso es bueno, que si C se basa en B es aún mejor. Yo lo llamo el fenómeno "princesa y guisante". Apilar capas encima de algo problemático no necesariamente lo arregla.

Para finalizar una publicación larga, he desarrollado un estilo de programación (que a veces me mete en problemas) donde

  • La invención no es algo malo. Es algo bueno, como lo es en otras ramas de la ingeniería. Seguro que puede estar creando una curva de aprendizaje para otros, pero si el resultado general es una mejor productividad, vale la pena.
  • Código minimalista estilo Haiku. Eso va especialmente para el diseño de la estructura de datos. En mi experiencia, el mayor problema en el software en estos días es la estructura de datos hinchada.
Mike Dunlavey
fuente
99
Esto suena mucho a lo que Chuck Moore (inventor de Forth ) siempre ha abogado. Por ejemplo, de los comentarios de Chuck Moore sobre Forth , "No creo que sea intrínseco en la naturaleza del software que tenga que ser grande, voluminoso, con errores. Está en la naturaleza de nuestra sociedad ... Hay tanto motivación económica para producir este ... bloatware, que me siento irresponsable al levantarme y decir que el emperador no tiene ropa ".
Peter Mortensen
3
@PeterMortensen: De acuerdo. Es solitario. Hay una palabra para eso: el complejo Cassandra .
Mike Dunlavey
2
Si bien escribir artefactos de código para "extender" lenguajes no es una tarea difícil, es una buena API que refleje de manera precisa e intuitiva el dominio del problema .
Robert Harvey
3
@MikeDunlavey: BTW: También eres el tipo "sin perfil" (esto se entiende de manera positiva). Hace unos meses, volví a usar su técnica en el mundo real para reducir rápidamente el tiempo de carga de un archivo de documento de 25 segundos a 1 segundo (un tiempo de carga que el usuario experimenta directamente). Tomó algunas iteraciones, y 10-20 muestras en todas las iteraciones fueron más que suficientes. Los problemas de rendimiento fueron, por supuesto, en lugares inesperados.
Peter Mortensen
2
@Izkata y Peter: Sí, soy un bicho raro. FWIW, publiqué un par de videos (extremadamente aficionados), con la esperanza de que sea más fácil de entender. Pausa aleatoria Ejecución diferencial. Salud.
Mike Dunlavey
35

La abstracción de alto nivel es esencial para lograr el progreso continuo en la informática.

¿Por qué? Porque los humanos solo pueden tener tanto conocimiento en sus cabezas en un momento dado. Los sistemas modernos a gran escala solo son posibles hoy en día porque puede aprovechar tales abstracciones. Sin esas abstracciones, los sistemas de software simplemente colapsarían bajo su propio peso.

Cada vez que escribes un método, estás creando una abstracción. Estás creando un poco de funcionalidad que está oculta detrás de una llamada al método. ¿Por qué los escribes? Debido a que puede probar el método, probar que funciona y luego invocar esa funcionalidad en cualquier momento que desee simplemente haciendo la llamada al método, y ya no tiene que pensar más en el código que está dentro de ese método.

En los primeros días de la informática, usábamos lenguaje máquina. Escribimos programas muy pequeños y básicos con un conocimiento profundo del hardware para el que los escribíamos. Fue un proceso minucioso. No hubo depuradores; su programa generalmente funcionó o se bloqueó. No había GUI; todo era línea de comandos o proceso por lotes. El código que escribió solo funcionaría en esa máquina en particular; no funcionaría en una máquina con un procesador o sistema operativo diferente.

Así que escribimos lenguajes de alto nivel para abstraer todos esos detalles. Creamos máquinas virtuales para que nuestros programas puedan ser portátiles a otras máquinas. Creamos la recolección de basura para que los programadores no tuvieran que ser tan diligentes sobre la administración de la memoria, lo que eliminó toda una clase de errores difíciles. Agregamos verificación de límites a nuestros idiomas para que los hackers no puedan explotarlos con desbordamientos de búfer. Inventamos la programación funcional para poder razonar sobre nuestros programas de una manera diferente, y la redescubrimos recientemente para aprovechar mejor la concurrencia.

¿Toda esta abstracción te aísla del hardware? Claro que si. ¿Vivir en una casa en lugar de armar una tienda de campaña te aísla de la naturaleza? Absolutamente. Pero todos saben por qué viven en una casa en lugar de una tienda de campaña, y construir una casa es un juego de pelota completamente diferente a lanzar una tienda de campaña.

Sin embargo, aún puede lanzar una tienda de campaña cuando sea necesario y, en la programación, puede (si así lo desea) seguir bajando a un nivel más cercano al hardware para obtener beneficios de rendimiento o memoria que tal vez no de lo contrario lograr en su lenguaje de alto nivel.


¿Puedes abstraer demasiado? "Superar las tuberías", como diría Scotty ? Por supuesto que puede. Escribir buenas API's es difícil. Escribir buenas API que incorporen de manera correcta e integral el dominio del problema, de una manera intuitiva y reconocible, es aún más difícil. Acumular nuevas capas de software no siempre es la mejor solución. Los patrones de diseño de software han empeorado, hasta cierto punto, esta situación, porque los desarrolladores inexpertos a veces recurren a ellos cuando una herramienta más precisa y ágil es más apropiada.

Robert Harvey
fuente
1
+1, aunque creo que tienes el historial de la programación funcional al revés (el cálculo lambda es anterior a las computadoras electrónicas, y muchos lenguajes funcionales son anteriores a la programación concurrente).
amon
1
Agregué una pequeña aclaración.
Robert Harvey
2
"En los primeros días de la informática, usábamos lenguaje de máquina. Escribimos programas muy pequeños y básicos con un conocimiento íntimo del hardware para el que los estábamos escribiendo". Algunos de nosotros en la programación integrada todavía lo hacemos de vez en cuando, en microcontroladores de 8 pero que tienen menos de 1K de memoria de programa, 64 bytes de RAM y cuestan alrededor de una cuarta parte. No hay compilador de C allí. (Pero generalmente trabajo con microcontroladores de 32 bits con típicamente 1/2 MB de espacio de programa).
tcrosley
9

Un entrenamiento realmente bueno involucra ambos extremos, así como un puente entre ellos.

En el lado de bajo nivel: cómo una computadora ejecuta el código desde cero *, incluido el conocimiento del lenguaje ensamblador y lo que está haciendo un compilador.

En el lado de alto nivel: conceptos generales, por ejemplo, el uso de matrices asociativas, cierres, etc. sin tener que perder el tiempo preocupándose por cómo funciona bajo el capó.

En mi humilde opinión, todos deberían tener experiencia con ambos, incluidos sus inconvenientes, y una muestra de cómo pasar de conceptos de bajo nivel a conceptos de alto nivel. ¿Te encantan las matrices asociativas? Genial, ahora intenta usarlos en un procesador integrado de 50 centavos con 1kB de RAM. ¿Te gusta escribir código rápido usando C? Genial, ahora tienes tres semanas para escribir una aplicación web; puede pasar su tiempo lidiando con estructuras de datos y administración de memoria usando C, o puede pasar su tiempo aprendiendo un nuevo marco web y luego implementar la aplicación web en unos días.

En cuanto al aspecto de la complejidad: creo que en estos días es demasiado fácil crear sistemas complejos sin una comprensión clara del costo de hacerlo . Como resultado, como sociedad, hemos acumulado una gran cantidad de deuda técnica que nos muerde de vez en cuando. Es como los terremotos (solo el costo de vida cerca de una falla geológica, ¿verdad?), Solo que gradualmente empeora. Y no sé qué hacer al respecto. Idealmente, aprenderíamos y mejoraríamos en el manejo de la complejidad, pero no creo que eso vaya a suceder. Una educación de ingeniería responsable debe incluir mucha más discusión sobre las consecuencias de la complejidad que la mayoría de nuestras universidades están proporcionando actualmente.


* y, de todos modos, ¿dónde está la "base" en cómo una computadora ejecuta el código? ¿Es lenguaje ensamblador? O arquitectura de la computadora? O la lógica digital? O transistores? ¿O la física del dispositivo?

Jason S
fuente
7

Siento que la programación de alto nivel tiene muchas ventajas y es una parte esencial de un lenguaje de programación. Una de las razones por las cuales Java se convirtió en exitoso fue que tiene una biblioteca completa. Logra más con menos código: solo llama a una función predefinida.

Ahora podemos distinguir a los usuarios del lenguaje de programación de los escritores de lenguaje de programación (escritores de compiladores). Dejamos las optimizaciones a los escritores del compilador. Nos centramos más en la mantenibilidad, reutilización, etc.

Ali
fuente
7

El aumento en la complejidad de los sistemas es implacable, opresivo y, en última instancia, paralizante. Para mí, como programador de una generación anterior, también es muy decepcionante.

He estado programando durante más de 40 años, he escrito código en 50-100 idiomas o dialectos diferentes, y me he convertido en experto en 5-10. La razón por la que puedo reclamar tantos es que en su mayoría son del mismo idioma, con ajustes. Los ajustes agregan complejidad, haciendo que cada idioma sea un poco diferente.

He implementado los mismos algoritmos innumerables veces: colecciones, conversiones, ordenar y buscar, codificar / decodificar, formatear / analizar, buffers y cadenas, aritmética, memoria, E / S. Cada nueva implementación agrega complejidad, porque cada una es un poco diferente.

Me pregunto por la magia forjada por los trapecistas voladores de los marcos web y las aplicaciones móviles, cómo pueden producir algo tan hermoso en tan poco tiempo. Entonces me doy cuenta de cuánto no saben, cuánto necesitarán aprender sobre datos o comunicaciones o pruebas o hilos o lo que sea antes de que lo que hagan sea útil.

Aprendí mi oficio en la era de los idiomas de cuarta generación, donde realmente creíamos que produciríamos una sucesión de idiomas cada vez más altos para capturar progresivamente más y más partes repetitivas del software de escritura. Entonces, ¿cómo resultó eso exactamente?

Microsoft e IBM mataron esa idea al regresar a C para escribir aplicaciones para Windows y OS / 2, mientras que dBase / Foxpro e incluso Delphi languidecieron. Luego, la web lo hizo nuevamente con su último trío de lenguajes de ensamblaje: HTML, CSS y JavaScript / DOM. Ha sido todo cuesta abajo desde allí. Siempre más idiomas y más bibliotecas y más marcos y más complejidad.

Sabemos que deberíamos hacerlo de manera diferente. Sabemos sobre CoffeeScript y Dart, sobre Less y Sass, sobre plantillas para evitar tener que escribir HTML. Lo sabemos y lo hacemos de todos modos. Tenemos nuestros marcos, llenos de abstracciones permeables, y vemos qué maravillas pueden hacer aquellos pocos elegidos que aprenden los encantamientos arcanos, pero nosotros y nuestros programas estamos atrapados por las decisiones tomadas en el pasado. Es demasiado complicado cambiar o comenzar de nuevo.

El resultado es que las cosas que deberían ser fáciles no son fáciles, y las cosas que deberían ser posibles son casi imposibles, debido a la complejidad. Puedo estimar el costo de hacer cambios para implementar una nueva característica en una base de código establecida y estar seguro de que estaré en lo cierto. Puedo estimar, pero no puedo justificarlo ni explicarlo. Es demasiado complicado.

En respuesta a su pregunta final, recomendaría encarecidamente a los programadores más jóvenes que comiencen lo más alto posible en el pastel de capas, y solo se sumerjan en las capas inferiores, ya que la necesidad y el deseo proporcionan el impulso. Prefiero los idiomas sin bucles, con poca o ninguna ramificación y estado explícito. Lisp y Haskell vienen a la mente. En la práctica siempre termino con C # / Java, Ruby, Javascript, Python y SQL porque ahí es donde están las comunidades.

Palabras finales: ¡la complejidad es el enemigo supremo! Supera eso y la vida se vuelve simple.

david.pfx
fuente
Mis más de 30 años de programación me han enseñado a usar el lenguaje de más alto nivel disponible que hará lo que se necesita hacer y aún permitirá el uso de idiomas de nivel inferior cuando sea necesario. El entorno más fácil para eso es el script de shell que puede invocar módulos escritos en cualquier idioma. La parte difícil es romper la mentalidad dominante de que todas las funcionalidades de un proyecto deben implementarse en el mismo idioma.
DocSalvager
@dicsalvage: Estoy de acuerdo, y mi gran decepción es la falta de niveles cada vez más altos. Lo que awk podía hacer en 10 líneas en la década de 1980 ahora toma 15 líneas en Ruby o Python, pero busco algo para hacerlo en 3. Y los entornos bloqueados en los teléfonos significan que lo mismo toma 50 en Java u Objective C. No guiones de shell allí!
david.pfx
Google "bash for android" muestra a mucha gente trabajando en puertos. También hay versiones de Python como Kivy
DocSalvager
@DocSalvage: Tarde o temprano, el entorno del teléfono se unirá a la civilización (tal como la conocemos). Mi queja es el tiempo necesario para hacer una y otra vez las cosas que parecen haber terminado. Seguimos teniendo que volver a poner cimientos, ladrillos, drenaje y chozas cuando quiero construir rascacielos.
david.pfx
4

Sin embargo, mi pregunta es cómo se siente la gente acerca de este "ocultamiento" de elementos de nivel inferior. ¿Los programadores más viejos lo ven como un regalo del cielo o una capa innecesaria para atravesar?

Ninguno de los dos.

La estratificación es necesaria porque sin ella, llegas a un punto donde tu sistema se convierte en espagueti imposible de mantener. También es uno de los principios de la reutilización: si el desarrollador de una biblioteca hizo un buen trabajo, las personas que la utilizan no deberían preocuparse por los detalles de la implementación. La cantidad de código enlatado que usamos en nuestros sistemas ha crecido por orden de manía de lo que era cuando escribí mi primer programa hace 35 años. Ese crecimiento significa que podemos hacer cosas más poderosas a medida que pasa el tiempo. Esto es bueno.

El lugar donde ha sido un problema para mí es completamente cultural. Mi mitad pragmática comprende que ya no es posible comprender mi mente hasta el último detalle y poder terminar las cosas que quiero hacer. (Envejecer tampoco ayuda). A mi medio barbudo de barba gris le costó mucho dejar ir muchos años de tener una comprensión tan precisa de todo lo que trabajé.

¿Crees que los programadores más jóvenes se beneficiarían más aprendiendo programación de bajo nivel ANTES de explorar los reinos de las bibliotecas expansivas?

Como se ha señalado en otras respuestas, hay que lograr un equilibrio entre atraer y mantener la atención de los neófitos y brindarles una educación ideal de abajo hacia arriba. Si no puede hacer lo primero, lo último no puede suceder.

Veo cosas en nuestra industria que son paralelas al resto de la sociedad. Solía ​​ser que casi todos cultivaban su propia comida y pasaban mucho tiempo haciendo eso. Desde entonces, hemos brotado especialistas llamados agricultores que hacen ese trabajo, liberando a otros para que hagan otras cosas que contribuyen a la sociedad. Compro mi comida en una tienda de comestibles y sería incapaz de producirla por mi cuenta si tuviera que hacerlo. Tenemos algo similar, aunque en una escala de tiempo mucho más comprimida. Los programadores se especializan en un conjunto de capas y no en otros. El tipo promedio que escribe GUI puede saber que existe el espacio de intercambio, pero probablemente no sabe ni le importa mucho cómo lo está administrando el sistema operativo.

El resultado de todo esto es que ya no se trata solo del desarrollo. La especialización continua significa que los desarrolladores deberán continuar mejorando sus habilidades de comunicación e integración.

Blrfl
fuente
3

Como con todo, un poco te hace bien, pero duele demasiado. El problema es que muchos sistemas no saben cuándo detenerse: solo 1 abstracción más, para ayudarlo a programar más rápido ... pero luego termina codificando en el mundo real donde las cosas nunca son tan simples como desea, y usted Pase más tiempo trabajando en los bordes de lo que hubiera pasado con una abstracción menos destacada.

Es hábilmente descrito aquí

o aquí : "con una sola línea de código, podría agregar 500 usuarios al dominio" ...

Sus abstracciones intentan ocultarle la complejidad, pero en realidad todo lo que hacen es ocultar esa complejidad. La complejidad sigue ahí, es solo que tienes mucho menos control sobre ella, y es por eso que terminas con este tipo de situación.

gbjbaanb
fuente
2

¿Los programadores más jóvenes se benefician de más aprendizaje de programación de bajo nivel ANTES de explorar los reinos de las bibliotecas expansivas? Si es así, ¿por qué?

No lo creo. Todavía hay muchas situaciones en las que es beneficioso tener en cuenta el nivel bajo de la 'capa inferior', por ejemplo,

  • Al depurar un problema en la capa n, a menudo se puede explicar considerando lo que sucede en la capa n-1(es decir, la capa a continuación). Supongo que la capa 0 sería "transistores", pero si quieres explicar un problema con los transistores, probablemente hablarías de física (por ejemplo, calor), por lo que tal vez la física esté realmente en el nivel 0.

  • Al optimizar el código, (desafortunadamente) ayuda a veces a reducir el nivel de abstracción, es decir, implementar un algoritmo en términos de una capa de nivel inferior. Sin embargo, los compiladores se volvieron realmente buenos para hacerlo si realmente ven todo el código involucrado. Esta razón se hizo más popular recientemente con el auge de los dispositivos móviles e integrados, que tienden a tener procesadores más débiles y donde el "rendimiento por vatio" es mucho más relevante que, por ejemplo, en los sistemas de escritorio.

Sin embargo, en general, se hizo mucho más fácil hacer que las computadoras hicieran cosas (incluso de maneras poco eficientes), lo que significa que hay muchos más programadores de lo que solían ser. Esto a su vez hizo que el factor "humano" fuera mucho más importante: la respuesta de Robert Harvey ya mencionó que "los humanos solo pueden tener tanto conocimiento en sus cabezas en un momento dado", y creo que ese es un aspecto muy relevante hoy en día.

Una motivación importante en el lenguaje de programación y el diseño de bibliotecas (es decir, API) es facilitar las cosas en el cerebro humano. Hasta el día de hoy, todo aún se compila en código máquina. Sin embargo, esto no solo es propenso a errores, también es notoriamente difícil de entender. Entonces es muy deseable

  • Haga que la computadora lo ayude a encontrar errores lógicos en los programas que escribe. Cosas como los sistemas de tipo estático o los analizadores de código fuente (escuché que Eric Lippert trabaja en uno bastante popular en estos días) ayudan con eso.

  • Tenga un lenguaje que pueda ser procesado eficientemente por un compilador y que comunique la intención del programador a otros programadores para facilitar el trabajo en el programa. Como un extremo absurdo, imagine que escribir programas en inglés simple fuera posible. Los programadores pueden tener un tiempo más fácil para imaginar lo que está sucediendo, pero aún así, la descripción sería muy difícil de compilar en instructores de máquina, y es notoriamente ambigua. Por lo tanto, necesita un lenguaje que un compilador pueda entender pero que también sea comprensible.

Dado que muchos de los compiladores (¿la mayoría?) Siguen siendo de uso general, cuentan con un conjunto de instrucciones muy genérico. No hay instrucciones de "dibujar un botón" o "reproducir esta película". Por lo tanto, moverse hacia abajo en la jerarquía de abstracción te hace terminar con programas que son muy difíciles de comprender y mantener (aunque triviales para compilar). La única alternativa es ascender en la jerarquía, lo que lleva a más y más lenguajes y bibliotecas abstractas.

Frerich Raabe
fuente
1

"Si los programadores más viejos ven innovaciones como estas como un regalo del cielo o una capa adicional para abstraer, ¿y por qué podrían pensar eso?"

He estado programando desde que estaba en la escuela secundaria, alrededor de 34 años, comenzando con Basic y Z80 Assembler, pasando a C, varios lenguajes 4GL, Scheme, SQL y ahora varios lenguajes web. El alcance, la escala y la profundidad de los problemas abordados por la profesión experimentaron un período inflacionario durante ese tiempo, particularmente en la década de 1990. Las construcciones como bibliotecas, marcos y servicios del sistema operativo son todos artilugios destinados a abordar la complejidad que acompaña al espacio expandido de problemas. No son un regalo del cielo ni una carga en sí mismos, solo una exploración continua de un vasto espacio de soluciones.

Pero, en mi humilde opinión, la "innovación" se entiende mejor en términos de formas novedosas, y no se confunde con el movimiento lateral: reintroducir formas que ya hemos visto introducidas. De alguna manera, la fecundidad de un ecosistema sufre cuando las formas primitivas no se componen, cuando fijan decisiones tomadas al principio de la evolución, o no pueden reprocesar sus propios detritos. Algunas, si no la mayoría, de las construcciones en las que nos centramos no priorizan el sustento de valor a largo plazo como una preocupación. Eso ha comenzado a cambiar: enfoques como la Orientación del servicio y el Diseño impulsado por el dominio, por no mencionar el hipertexto y los modelos basados ​​en gráficos, por ejemplo, están alterando el panorama. Como cualquier ecosistema, eventualmente las formas dominantes darán paso a nuevas formas; estamos mejor atendidos al permitir la diversidad,

"¿Y los programadores más jóvenes se benefician de más aprendizaje de programación de bajo nivel ANTES de explorar los reinos de las bibliotecas expansivas? Si es así, ¿por qué?"

Yo diría que la mayoría del lenguaje humano se basa en metáforas olvidadas hace mucho tiempo, por lo que si bien apoyaría el aprendizaje de programación de bajo nivel desde un punto de vista de alfabetización científica / numérica, es más importante que busquemos primitivas que respalden la escala y el alcance de Los problemas que estamos abordando de una manera que podemos ignorar con seguridad el nivel más bajo de detalle. Un marco no es primitivo, ni un sistema operativo o una biblioteca; son bastante pobres para hacer el tipo de abstracción que realmente necesitamos. El progreso real llevará a las personas que (a) saben lo que sucedió antes y (b) pueden pensar de una manera lo suficientemente novedosa como para encontrar algo lo suficientemente diferente como para explorar un espacio de solución que no haya sido explorado antes o que haya sido explorado y olvidado.

OTOH, incluso si su objetivo es trabajar como técnico / nivel mecánico, algún nivel de exposición de programación de bajo nivel seguirá siendo útil para desarrollar sus habilidades de resolución de problemas.

jerseyboy
fuente
1

Mi primer programa (cuando era un adolescente de 15 años) fue en 1974 en PL / 1 en tarjetas perforadas para un mainframe IBM 370/168. Mi padre trabajaba en IBM y tuve la suerte de poder ir al centro de datos los domingos.

En ese momento, un programa de varios miles de declaraciones (es decir, tarjetas perforadas) era un gran programa (y también pesado, ya que muchos miles de tarjetas perforadas pesaban muchos kilogramos). Las interfaces visuales no existían (un programa típico leído desde su "entrada estándar" utilizando un comando de tarjeta perforada que comienza con //GO.SYSIN DD *IIRC, pero no dominaba JCL ). Los algoritmos eran importantes, y IIRC la biblioteca estándar era bastante pequeña para el estándar actual.

Hoy, los programas de varios miles de líneas generalmente se consideran pequeños. Por ejemplo, el compilador GCC tiene más de diez millones de líneas de código fuente, y nadie las comprende completamente.

Creo que la programación de hoy es bastante diferente de la década de 1970, porque necesita utilizar muchos más recursos (en particular, bibliotecas y marcos de software existentes). Sin embargo, supongo que las personas que desarrollan software de centro de datos (por ejemplo, motores de búsqueda en Google) o algún software integrado se preocupan tanto por los algoritmos y la eficiencia como el programador promedio de la década de 1970.

Sigo pensando que comprender la programación de bajo nivel es importante incluso hoy (incluso si la mayoría de los programadores no se codifican a sí mismos como algoritmos básicos de contenedor como árboles balanceados, arreglos ordenados con acceso dicotómico, etc.) porque entender la imagen completa sigue siendo importante.

Una diferencia importante entre la década de 1970 y hoy es la relación de costo entre los esfuerzos (humanos) del desarrollador y la potencia de la computadora.

Basile Starynkevitch
fuente