In che modo un aumento della complessità dei sistemi ha interessato le generazioni successive di programmatori?


127

Come "nuovo" programmatore (ho scritto per la prima volta una riga di codice nel 2009), ho notato che è relativamente facile creare un programma che presenta elementi abbastanza complessi oggi con cose come .NET framework, ad esempio. La creazione di un'interfaccia visiva o l'ordinamento di un elenco può essere eseguito con pochissimi comandi ora.

Quando stavo imparando a programmare, stavo anche imparando la teoria dell'informatica in parallelo. Cose come algoritmi di ordinamento, principi su come l'hardware funziona insieme, algebra booleana e macchine a stati finiti. Ma ho notato che se avessi mai voluto provare alcuni principi basilari che avevo imparato in teoria, era sempre molto più difficile iniziare perché tanta tecnologia è oscurata da cose come librerie, framework e sistema operativo.

40/50 anni fa era richiesto un programma efficiente in termini di memoria perché non c'era memoria sufficiente ed era costoso, quindi la maggior parte dei programmatori prestava molta attenzione ai tipi di dati e al modo in cui le istruzioni sarebbero state gestite dal processore. Al giorno d'oggi, alcuni potrebbero sostenere che a causa della maggiore potenza di elaborazione e della memoria disponibile, tali preoccupazioni non sono una priorità.

La mia domanda è se i programmatori più anziani vedono innovazioni come queste come una manna dal cielo o un livello aggiuntivo attraverso cui astrarre, e perché potrebbero pensarlo? E i programmatori più giovani traggono maggiori benefici dall'apprendimento della programmazione di basso livello PRIMA di esplorare i regni delle librerie espansive? Se è così allora perché?


24
L'articolo di Joel Spolsky del 2002 è rilevante: joelonsoftware.com/articles/LeakyAbstractions.html Come frase / formulata, tuttavia, questa domanda potrebbe finire per essere considerata principalmente basata sull'opinione pubblica.
BrianH,

Mi lamento della mancanza di opzioni più semplici per esplorare tecniche di programmazione molto basilari.
GrandmasterB,

1
Questo è rilevante. Una specie di. (Voglio dire, spero che l'immagine sia uno scherzo, ma con un po 'di quello che succede a StackOverflow ...)
Izkata

1
Ha i suoi pro e contro. Apre il mondo della programmazione a molti nuovi programmatori, che non hanno bisogno di competenze così elevate per avere successo - contrariamente a quanto alcune persone potrebbero dire, è una buona cosa. E stiamo ancora scrivendo programmi efficienti, che non sono mai cambiati - è solo che gli obiettivi sono cambiati. Salvare un byte in un anno in data non è più una buona cosa: di solito è improbabile che la differenza di memoria faccia la differenza, e usando ad es. due byte è più flessibile e a prova di futuro. Anche il costo dei programmatori rispetto al costo di SW e HW è un fattore significativo. La richiesta di nuovi software è enorme. I programmatori sono pochi.
Luaan,

1
La cronologia di 40/50 anni è errata. La programmazione efficiente in termini di memoria era ancora di fondamentale importanza in Windows a 16 bit (meno di 20 anni fa) e (purtroppo) nella maggior parte dei sistemi embedded / robotici di oggi.
david.pfx,

Risposte:


174

semplicemente non è necessario a causa della maggiore quantità di potenza di elaborazione e memoria disponibile.

Avere memoria economica, enormi dischi e processori veloci non è l'unica cosa che ha liberato le persone dalla necessità di ossessionarsi su ogni byte e ciclo. I compilatori ora sono molto, molto meglio degli umani nel produrre codice altamente ottimizzato quando è importante.

Inoltre, non dimentichiamo per cosa stiamo effettivamente cercando di ottimizzare, che è il valore prodotto per un dato costo. I programmatori sono molto più costosi delle macchine. Qualunque cosa facciamo per far sì che i programmatori producano programmi funzionanti, corretti, robusti, completi di funzionalità, più veloci ed economici, portano alla creazione di più valore nel mondo.

La mia domanda è: come si sentono le persone riguardo a questo "nascondersi" di elementi di livello inferiore. I programmatori più anziani lo vedono come una manna dal cielo o un livello superfluo da superare?

È assolutamente necessario svolgere qualsiasi lavoro. Scrivo analizzatori di codice per vivere; se dovessi preoccuparmi dell'allocazione dei registri o della programmazione del processore o di uno di quei milioni di altri dettagli, non passerei il mio tempo a correggere bug, a rivedere i rapporti sulle prestazioni, ad aggiungere funzionalità e così via.

Tutta la programmazione riguarda l'astrazione del livello sottostante per creare un livello più prezioso sopra di esso. Se fai un "diagramma a strati" che mostra tutti i sottosistemi e come sono costruiti l'uno sull'altro, scoprirai che ci sono letteralmente dozzine di livelli tra l'hardware e l'esperienza dell'utente. Penso che nel diagramma a torta del livello di Windows ci siano qualcosa come 60 livelli di sottosistemi necessari tra l'hardware grezzo e la capacità di eseguire "ciao mondo" in C #.

Pensi che i programmatori più giovani trarrebbero vantaggio dall'apprendimento di una programmazione di basso livello PRIMA di esplorare i regni delle librerie espansive?

Metti l'accento su PRIMA, quindi devo rispondere negativamente alla tua domanda. Sto aiutando un amico di 12 anni a imparare a programmare in questo momento e faresti meglio a credere che li sto avviando in Processing.js e non nell'assemblatore x86. Se inizi un giovane programmatore in qualcosa del genere Processing.js, scriveranno i loro giochi sparatutto tra circa otto ore. Se li avvii nell'assemblatore, moltiplicheranno tre numeri insieme in circa otto ore. Quale pensi sia più probabile che coinvolga l'interesse di un giovane programmatore?

Ora, se la domanda è "i programmatori che comprendono il livello n della torta traggono vantaggio dalla comprensione del livello n - 1?" la risposta è sì, ma è indipendente dall'età o dall'esperienza; è sempre possibile migliorare la programmazione di livello superiore comprendendo meglio le astrazioni sottostanti.


12
+1 citazione divertente: Dunbars Number è un buon esempio (ce ne sono altri) di quozienti di capacità cognitiva studiati che possono essere visti in molte persone, dimostrando che abbiamo uno spazio mentale fisso. Astrarre più cose in singolarizzazioni generalizzate è l'unico modo in cui possiamo aumentare in modo coeso il numero di cose nel nostro spazio mentale, ed è quello che la programmazione di livello superiore cerca di trarre vantaggio.
Jimmy Hoffa,

18
@Euforico: la tua domanda ha senso ma dove ti fermi? Supponiamo che io dica "bene, invece di imparare Processing.js impariamo a scrivere videogiochi in C ++ usando DirectX". Ok bene. Ora, cosa ti impedisce di dire "non creerà problemi se vogliono fare qualcosa di meno astratto?" e quindi forse vogliamo iniziare con come scrivere un driver della scheda grafica. Ma poi fai di nuovo la domanda e, prima di conoscerla, stiamo inserendo il codice macchina in un Altair con interruttori a levetta. Devi scegliere un livello di astrazione da qualche parte !
Eric Lippert,

35
@Euforico: faresti lo stesso argomento, per esempio, con la contabilità? Non abbiamo bisogno di più persone in grado di tenere i libri semplici per una nuova piccola impresa; abbiamo bisogno di GRANDI commercialisti di livello mondiale. Se i corsi introduttivi di contabilità sono così difficili da spaventare le persone che aspirano semplicemente ad essere contabili produttivi e operai, BUONO. Non abbiamo bisogno di quelle persone nel settore contabile! E i pianisti? Se le lezioni introduttive di piano spaventano le persone che non saranno GRANDI pianisti, va bene; vogliamo solo grandi pianisti al mondo. C'è qualcosa che non va in questo argomento?
Eric Lippert,

25
@Euforico: la risposta breve è BUONI CIELI SÌ abbiamo bisogno di programmatori più decenti! Abbiamo bisogno di più programmatori ad ogni livello di abilità ed esperienza. Il mondo gira su software . Più persone hanno una comprensione di come far funzionare il loro mondo, meglio è.
Eric Lippert,

6
@Euforico (e altri) - stiamo quasi colpendo il limite per quanto riguarda la costruttività dei commenti. Unisciti a noi nella chat di ingegneria del software se desideri continuare questa conversazione.

50

Ho avuto idee su questo argomento e le ho messe in un libro 20 anni fa . È fuori stampa da molto tempo, ma puoi ancora ottenere copie usate su Amazon .

Una semplice risposta alla tua domanda è vecchia quanto Aristotele: la natura detesta il vuoto . Per quanto le macchine siano diventate sempre più veloci, il software è diventato sempre più lento.

Per essere più costruttivo, quello che ho proposto era che la teoria dell'informazione, e la sua diretta rilevanza per il software, facessero parte dell'educazione informatica. Viene insegnato solo ora, se non del tutto, in modo molto tangenziale.

Ad esempio, il comportamento big-O degli algoritmi può essere compreso in modo molto ordinato e intuitivo se si considera un programma come un canale informativo di tipo Shannon, con simboli di input, simboli di output, rumore, ridondanza e larghezza di banda.

D'altra parte, la produttività di un programmatore può essere compresa in termini simili usando la teoria dell'informazione di Kolmogorov. L'input è una struttura concettuale simbolica nella tua testa e l'output è il testo del programma che esce attraverso la punta delle dita. Il processo di programmazione è il canale tra i due. Quando il rumore entra nel processo, crea programmi incoerenti (bug). Se il testo del programma di output ha una ridondanza sufficiente, può consentire la cattura e la correzione dei bug (rilevamento e correzione degli errori). Tuttavia, se è troppo ridondante, è troppo grande e le sue stesse dimensioni, combinate con il tasso di errore, causano l'introduzione di bug. Come risultato di questo ragionamento, ho passato buona parte del libro a mostrare come trattare la programmazione come un processo di progettazione del linguaggio, con l'obiettivo di poter definire le lingue specifiche del dominio appropriate per un'esigenza. Prestiamo un servizio labiale a linguaggi specifici del dominio nell'educazione CS ma, ancora una volta, è tangenziale.

Costruire lingue è facile. Ogni volta che definisci una funzione, una classe o una variabile, aggiungi il vocabolario alla lingua con cui hai iniziato, creando una nuova lingua con cui lavorare. Ciò che non è generalmente apprezzato è che l'obiettivo dovrebbe essere quello di rendere il nuovo linguaggio più vicino alla struttura concettuale del problema. Se questo è fatto, allora ha l'effetto di accorciare il codice e renderlo meno errori, semplicemente perché, idealmente, v'è una mappatura 1-1 tra i concetti e il codice. Se la mappatura è 1-1, potresti commettere un errore e codificare un concetto in modo errato come concetto diverso, ma il programma non si arresterà mai in modo anomalo, che è ciò che accade quando non codifica alcun requisito coerente .

Non stiamo ottenendo questo. Nonostante tutti i nostri audaci discorsi sulla progettazione di sistemi software, il rapporto tra codice e requisiti sta diventando sempre più grande.

È vero, abbiamo librerie molto utili. Tuttavia, penso che dovremmo essere molto avveduti sull'astrazione. Non dovremmo supporre che se B si basa su A e questo è positivo, se C si basa su B è ancora meglio. Lo chiamo fenomeno "principessa e il pisello". L'accumulo di strati sopra qualcosa di fastidioso non lo risolve necessariamente.

Per terminare un lungo post, ho sviluppato uno stile di programmazione (che a volte mi mette nei guai) dove

  • L'invenzione non è una brutta cosa. È una buona cosa, come lo è in altri rami dell'ingegneria. Sicuramente potrebbe creare una curva di apprendimento per gli altri, ma se il risultato complessivo è una migliore produttività, vale la pena.
  • Codice minimalista in stile Haiku. Ciò vale soprattutto per la progettazione della struttura dei dati. Nella mia esperienza, il problema più grande nel software in questi giorni è la struttura dei dati gonfia.

9
Sembra molto ciò che Chuck Moore (inventore di Forth ) ha sempre sostenuto. Ad esempio, da Comments on Forth di Chuck Moore , "Non credo sia intrinseco nella natura del software che debba essere grande, ingombrante, pieno di bug. È nella natura della nostra società ... C'è così tanto motivazione economica per produrre questo ... bloatware, che in un certo senso mi sento irresponsabile quando mi alzo e dico che l'imperatore non ha vestiti ".
Peter Mortensen,

3
@PeterMortensen: concordato. È solo C'è una parola per questo - complesso Cassandra .
Mike Dunlavey,

2
Mentre scrivere artefatti di codice per "estendere" le lingue non è un'impresa difficile, creare una buona API che rispecchi in modo accurato e intuitivo il dominio problematico lo è.
Robert Harvey,

3
@MikeDunlavey: BTW: Sei anche il ragazzo "no-profiler" (questo è inteso in modo positivo). Alcuni mesi fa, ho usato di nuovo la tua tecnica nel mondo reale per ridurre rapidamente il tempo di caricamento di un file di documento da 25 secondi a 1 secondo (un tempo di caricamento che l'utente sperimenta direttamente). Sono state necessarie alcune iterazioni e 10-20 campioni in tutte le iterazioni erano più che sufficienti. I problemi di prestazione erano ovviamente in luoghi inaspettati.
Peter Mortensen,

2
@Izkata e Peter: Sì, sono così strano. FWIW, ho realizzato un paio di video (estremamente amatoriali), nella speranza di renderlo più facile da capire. Pausa casuale. Esecuzione differenziale. Saluti.
Mike Dunlavey,

35

L'astrazione di alto livello è essenziale per raggiungere progressi in corso nell'informatica.

Perché? Perché gli umani possono avere solo tanta conoscenza nelle loro teste in un dato momento. I moderni sistemi su larga scala sono possibili solo oggi perché è possibile sfruttare tali astrazioni. Senza queste astrazioni, i sistemi software crollerebbero semplicemente sotto il loro stesso peso.

Ogni volta che scrivi un metodo, stai creando un'astrazione. Stai creando un po 'di funzionalità nascosta dietro una chiamata di metodo. Perché le scrivi? Perché puoi testare il metodo, dimostrare che funziona e quindi invocare quella funzionalità ogni volta che vuoi semplicemente chiamando il metodo, e non devi più pensare al codice che è all'interno di quel metodo.

All'inizio dell'informatica, abbiamo usato il linguaggio macchina. Abbiamo scritto programmi in metallo nudo molto piccoli con una profonda conoscenza dell'hardware per cui li abbiamo scritti. È stato un processo scrupoloso. Non c'erano debugger; il tuo programma di solito ha funzionato o si è bloccato. Non c'era GUI; tutto era da riga di comando o processo batch. Il codice che hai scritto funzionerebbe solo su quella particolare macchina; non funzionerebbe su una macchina con un processore o sistema operativo diverso.

Quindi abbiamo scritto linguaggi di alto livello per sottrarre tutti quei dettagli. Abbiamo creato macchine virtuali in modo che i nostri programmi possano essere trasferiti su altre macchine. Abbiamo creato la garbage collection in modo che i programmatori non debbano essere così diligenti nella gestione della memoria, il che ha eliminato un'intera classe di bug difficili. Abbiamo aggiunto limiti di controllo alle nostre lingue in modo che gli hacker non possano sfruttarli con sovraccarichi del buffer. Abbiamo inventato la programmazione funzionale in modo che potessimo ragionare sui nostri programmi in modo diverso e l'abbiamo riscoperta di recente per sfruttare al meglio la concorrenza.

Tutta questa astrazione ti isola dall'hardware? Certo che lo fa. Vivere in una casa invece di piantare una tenda ti isola dalla natura? Assolutamente. Ma tutti sanno perché vivono in una casa anziché in una tenda, e costruire una casa è un gioco con la palla completamente diverso rispetto al lancio di una tenda.

Tuttavia, puoi ancora montare una tenda quando è necessario farlo, e nella programmazione, puoi (se sei così incline) scendere ancora a un livello più vicino all'hardware per ottenere prestazioni o benefici di memoria che potresti non altrimenti raggiungere nella tua lingua di alto livello.


Puoi astrarre troppo? "Supera l'impianto idraulico", direbbe Scotty ? Certo che puoi. Scrivere buone API è difficile. Scrivere buone API che incorporano in modo corretto e completo il dominio problematico, in modo intuitivo e rilevabile, è ancora più difficile. Accumulare nuovi livelli di software non è sempre la soluzione migliore. I modelli di progettazione del software hanno, in una certa misura, peggiorato questa situazione, perché gli sviluppatori inesperti a volte li raggiungono quando uno strumento più nitido e snello è più appropriato.


1
+1, anche se penso che tu abbia la storia della programmazione funzionale all'indietro (il calcolo lambda precede i computer elettronici e molti linguaggi funzionali precedono la programmazione concorrente).
amon,

1
Ho aggiunto un piccolo chiarimento.
Robert Harvey,

2
"All'inizio dell'informatica, abbiamo usato il linguaggio macchina. Abbiamo scritto programmi molto piccoli e bare metal con una profonda conoscenza dell'hardware per cui li stiamo scrivendo." Alcuni di noi nella programmazione integrata lo fanno ancora occasionalmente, su 8 ma microcontrollori che hanno meno di 1 KB di memoria del programma, 64 byte di RAM e costano circa un quarto. Nessun compilatore C lì. (Ma di solito lavoro con microcontrollori a 32 bit con in genere 1/2 MB di spazio sul programma.)
tcrosley,

9

Un allenamento davvero buono coinvolge entrambi gli estremi, nonché un ponte tra.

Sul lato di basso livello: come un computer esegue il codice da zero *, inclusa la conoscenza del linguaggio assembly e cosa sta facendo un compilatore.

Sul lato di alto livello: concetti generali, ad es. Utilizzo di array associativi, chiusure, ecc. Senza dover perdere tempo a preoccuparsi di come funziona sotto il cofano.

IMHO tutti dovrebbero avere esperienza con entrambi, compresi i loro svantaggi, e avere un'idea di come passare da concetti di basso livello a concetti di alto livello. Ti piacciono le matrici associative? Bene, ora prova a usarli su un processore integrato da 50 cent con 1kB di RAM. Come scrivere codice veloce usando C? Bene, ora hai tre settimane per scrivere un'app Web; puoi passare il tempo a occuparti delle strutture dati e della gestione della memoria usando C, oppure puoi dedicare il tuo tempo all'apprendimento di un nuovo framework Web e quindi implementare l'app Web in pochi giorni.

Per quanto riguarda l'aspetto della complessità: penso che sia troppo facile oggigiorno realizzare sistemi complessi senza una chiara comprensione dei costi per farlo . Di conseguenza, come società, abbiamo accumulato un'enorme quantità di debito tecnico che ci morde di tanto in tanto. È come i terremoti (solo il costo della vita vicino a una faglia geologica, giusto?), Solo gradualmente sta peggiorando. E non so cosa fare al riguardo. Idealmente, impareremmo e miglioreremmo nella gestione della complessità, ma non credo che ciò accadrà. Una formazione ingegneristica responsabile deve includere molte più discussioni sulle conseguenze della complessità di quante la maggior parte delle nostre università stia attualmente offrendo.


* e, comunque, dov'è il "terreno" nel modo in cui un computer esegue il codice? È linguaggio di assemblaggio? O l'architettura del computer? O logica digitale? O transistor? O fisica del dispositivo?


7

Ritengo che la programmazione di alto livello abbia molti vantaggi ed è una parte essenziale di un linguaggio di programmazione. Uno dei motivi per cui Java ha avuto successo è che ha una libreria completa. Ottieni di più con meno codice: basta chiamare una funzione predefinita.

Ora possiamo distinguere gli utenti del linguaggio di programmazione dagli autori del linguaggio di programmazione (autori del compilatore). Lasciamo le ottimizzazioni agli autori di compilatori. Ci concentriamo maggiormente su manutenibilità, riutilizzo, ecc


7

L'aumento della complessità dei sistemi è implacabile, opprimente e infine paralizzante. Per me come programmatore di vecchia generazione, è anche amaramente deludente.

Sto programmando da oltre 40 anni, avendo scritto codice in 50-100 lingue o dialetti diversi, e sono diventato esperto in 5-10. Il motivo per cui posso rivendicare così tanti è che per lo più sono solo la stessa lingua, con modifiche. Le modifiche aggiungono complessità, rendendo ogni lingua un po 'diversa.

Ho implementato gli stessi algoritmi innumerevoli volte: raccolte, conversioni, ordinamento e ricerca, codifica / decodifica, formato / analisi, buffer e stringhe, aritmetica, memoria, I / O. Ogni nuova implementazione aggiunge complessità, perché ognuna è leggermente diversa.

Mi chiedo la magia esercitata dai trapezisti volanti dei framework web e delle app mobili, come possano produrre qualcosa di così bello in così poco tempo. Poi mi rendo conto di quanto non sanno, di quanto dovranno imparare su dati o comunicazioni o test o thread o qualsiasi altra cosa prima che ciò che fanno diventi utile.

Ho imparato il mio mestiere nell'era delle lingue di quarta generazione, dove credevamo sinceramente che avremmo prodotto una serie di linguaggi di livello superiore e superiore per acquisire progressivamente sempre più parti ripetitive del software di scrittura. Come è andata a finire esattamente?

Microsoft e IBM hanno abbandonato l'idea tornando a C per la scrittura di app per Windows e OS / 2, mentre dBase / Foxpro e persino Delphi hanno languito. Quindi il web lo ha fatto di nuovo con il suo trio finale di lingue assembly: HTML, CSS e JavaScript / DOM. È stato tutto in discesa da lì. Sempre più lingue e più librerie e più framework e più complessità.

Sappiamo che dovremmo farlo diversamente. Sappiamo di CoffeeScript e Dart, di Less e Sass, di template per evitare di dover scrivere HTML. Lo sappiamo e lo facciamo comunque. Abbiamo i nostri quadri, pieni di astrazioni che perdono, e vediamo quali meraviglie possono essere fatte da quei pochi eletti che imparano gli arcani incantesimi, ma noi e i nostri programmi siamo intrappolati dalle decisioni prese in passato. È troppo complicato cambiare o ricominciare.

Il risultato è che le cose che dovrebbero essere facili non sono facili e le cose che dovrebbero essere possibili sono quasi impossibili, a causa della complessità. Posso stimare il costo di apportare modifiche per implementare una nuova funzionalità in una base di codice consolidata ed essere fiducioso che avrò ragione. Posso stimare, ma non posso giustificarlo o spiegarlo. È troppo complicato

In risposta alla tua ultima domanda, consiglierei vivamente ai programmatori più giovani di iniziare il più in alto possibile sulla torta a strati e tuffarsi solo agli strati inferiori quando la necessità e il desiderio forniscono l'impulso. La mia preferenza è per le lingue senza loop, ramificazione scarsa o nulla e stato esplicito. Mi vengono in mente Lisp e Haskell. In pratica finisco sempre con C # / Java, Ruby, Javascript, Python e SQL perché è lì che si trovano le comunità.

Parole finali: la complessità è l'ultimo nemico! Batti questo e la vita diventa semplice.


I miei 30 + anni di programmazione mi hanno insegnato ad usare la lingua di livello più alto disponibile che farà ciò che deve essere fatto e consentirà comunque l'uso di lingue di livello inferiore quando richiesto. L'ambiente più semplice per questo è lo scripting della shell che può invocare moduli scritti in qualsiasi lingua. La parte difficile è spezzare la mentalità dominante secondo cui tutte le funzionalità di un progetto devono essere implementate nella stessa lingua.
DocSalvager

@dicsalvage: sono d'accordo e la mia grande delusione è la mancanza di livelli sempre più alti. Ciò che Awk potrebbe fare in 10 righe negli anni '80 ora prende 15 righe in Ruby o Python, ma cerco qualcosa per farlo in 3. E gli ambienti bloccati sui telefoni significano che la stessa cosa ne prende 50 in Java o nell'Obiettivo C. No script di shell lì!
david.pfx,

Google "bash per Android" mostra un sacco di gente che lavora sui porti. Esistono anche versioni di Python come Kivy
DocSalvager,

@DocSalvage: prima o poi l'ambiente telefonico entrerà a far parte della civiltà (come la conosciamo). La mia lamentela è il tempo impiegato per fare più e più volte le cose che sembrano essere finite. Continuiamo a dover tornare a gettare fondamenta, murature, drenaggi e baracche quando voglio costruire grattacieli.
david.pfx,

4

La mia domanda è: come si sentono le persone riguardo a questo "nascondersi" di elementi di livello inferiore. I programmatori più anziani lo vedono come una manna dal cielo o un livello superfluo da superare?

Nemmeno davvero.

La stratificazione è necessaria perché senza di essa, si raggiunge un punto in cui il sistema diventa spaghetti non mantenibili. È anche uno dei principi della riusabilità: se lo sviluppatore di una biblioteca ha fatto un buon lavoro, le persone che lo usano non dovrebbero preoccuparsi dei dettagli dell'implementazione. La quantità di codice fisso che usiamo nei nostri sistemi è cresciuta di ordini di mangime rispetto a quando ho scritto il mio primo programma 35 anni fa. Questa crescita significa che siamo in grado di fare cose più potenti col passare del tempo. Questo è buono.

Il posto in cui è stato un problema per me è interamente culturale. La mia metà pragmatica capisce che non è più possibile avvolgere la mia mente su ogni minimo dettaglio ed essere in grado di finire le cose che voglio fare. (Invecchiare non aiuta, neanche.) La mia cantankerous metà della barba grigia ha avuto difficoltà a lasciar andare molti anni per avere una comprensione così fine di tutto ciò su cui ho lavorato.

Pensi che i programmatori più giovani trarrebbero vantaggio dall'apprendimento di una programmazione di basso livello PRIMA di esplorare i regni delle librerie espansive?

Come è stato sottolineato in altre risposte, è necessario trovare un equilibrio tra l'attrazione e il mantenimento dell'attenzione dei neofiti e la loro educazione ideale dal basso verso l'alto. Se non riesci a fare il primo, il secondo non può succedere.

Vedo cose nel nostro settore che sono parallele al resto della società. In passato quasi tutti coltivavano il proprio cibo e passavano molto tempo a farlo. Da allora, abbiamo creato specialisti chiamati agricoltori che svolgono quel lavoro, liberando gli altri per fare altre cose che contribuiscono alla società. Compro il mio cibo in un negozio di alimentari e non sarei assolutamente in grado di produrlo per conto mio se dovessi. Abbiamo una cosa simile, anche se su una scala temporale molto più compressa. I programmatori si stanno specializzando in alcuni set di livelli e non in altri. Il tipo medio che scrive GUI potrebbe sapere che esiste qualcosa come lo spazio di scambio, ma probabilmente non sa o si preoccupa molto di come lo gestisce il sistema operativo.

Il risultato di tutto ciò è che non si tratta più solo di sviluppo. La specializzazione continua implica che gli sviluppatori dovranno continuare a migliorare le proprie capacità di comunicazione e integrazione.


3

Come per tutto, un po 'ti fa bene, ma fa troppo male. Il problema è che troppi sistemi non sanno quando fermarsi - solo un'altra astrazione, per aiutarti a programmare più velocemente ... ma poi finisci per scrivere codice nel mondo reale dove le cose non sono mai così semplici come vuoi, e tu trascorri più tempo a lavorare sui bordi di quanto avresti speso con un'astrazione meno caratteristica.

È abilmente descritto qui

o qui - "con una singola riga di codice potresti aggiungere 500 utenti al dominio" ...

Le tue astrazioni cercano di nasconderti la complessità, ma in realtà tutto ciò che fanno è nascondere quella complessità. La complessità è ancora lì, è solo che hai molto meno controllo su di essa - ed è per questo che finisci con questo tipo di situazione.


2

I programmatori più giovani traggono maggiore beneficio dall'apprendimento della programmazione di basso livello PRIMA di esplorare i regni delle librerie espansive? Se è così allora perché?

Io non la penso così. Ci sono ancora molte situazioni in cui è utile essere consapevoli dei bassi livelli di "livello sottostante", ad es

  • Quando si esegue il debug di un problema sul livello n, spesso può essere spiegato considerando ciò che accade sul livello n-1(ovvero il livello sottostante). Immagino che il livello 0 sarebbe "transistor" ma se vuoi spiegare un problema con i transistor probabilmente parleresti di fisica (es. Calore), quindi forse la fisica è davvero a livello 0.

  • Quando si ottimizza il codice, (purtroppo) a volte aiuta a ridurre il livello di astrazione, ovvero implementare un algoritmo in termini di un livello di livello inferiore. Tuttavia, i compilatori sono diventati davvero bravi a farlo per te se in realtà vedono tutto il codice coinvolto. Questo motivo è diventato più popolare di recente con il boom dei dispositivi mobili e embedded, che tendono ad avere processori più deboli e in cui le "prestazioni per Watt" sono molto più rilevanti rispetto ai sistemi desktop.

In generale, tuttavia, è diventato molto più facile fare in modo che i computer facciano cose (anche se in modi leggermente inefficienti), il che significa che ci sono molti più programmatori di quanti ce ne fossero prima. Questo a sua volta ha reso il fattore "umano" molto più importante: la risposta di Robert Harvey ha già menzionato che "gli umani possono contenere così tanta conoscenza nella loro testa in un dato momento", e penso che sia un aspetto molto rilevante al giorno d'oggi.

Una delle principali motivazioni nella progettazione del linguaggio di programmazione e della biblioteca (cioè API) è quella di rendere le cose più facili per il cervello umano. Fino ad oggi, tutto viene ancora compilato in codice macchina. Tuttavia, questo non è solo soggetto a errori, ma è anche notoriamente difficile da capire. Quindi è molto desiderabile

  • Chiedi al computer di aiutarti a trovare errori logici nei programmi che scrivi. Cose come i sistemi di tipo statico o gli analizzatori di codice sorgente (ho sentito che Eric Lippert lavora su uno abbastanza popolare in questi giorni) ci aiutano.

  • Avere un linguaggio che può essere elaborato in modo efficiente da un compilatore e che comunica l' intento del programmatore ad altri programmatori per facilitare il lavoro sul programma. Come assurdo estremo, immagina di poter scrivere programmi in inglese semplice. Compagni di programmazione potrebbero avere un momento più semplice per immaginare cosa stia succedendo, ma la descrizione sarebbe molto difficile da compilare in istruttori di macchine, ed è notoriamente ambigua. Quindi hai bisogno di un linguaggio che un compilatore possa comprendere ma che sia anche comprensibile.

Dato che molti compilatori (la maggior parte?) Sono ancora molto generici, presentano un set di istruzioni molto generico. Non ci sono istruzioni "Disegna un pulsante" o "Riproduci questo film". Quindi, spostarsi verso il basso nella gerarchia dell'astrazione ti fa finire con programmi che sono molto difficili da comprendere e mantenere (anche se banali da compilare). L'unica alternativa è quella di spostare in su nella gerarchia, portando a sempre più linguaggi astratti e biblioteche.



1

"se i programmatori più anziani vedono innovazioni come queste come una manna dal cielo o un livello aggiuntivo attraverso cui astrarre, e perché potrebbero pensarlo?"

Sto programmando da quando ero al liceo, circa 34 anni, a partire da Basic e Z80 Assembler, passando a C, vari linguaggi 4GL, Scheme, SQL e ora vari linguaggi Web. La portata, la portata e la profondità dei problemi affrontati dalla professione hanno subito un periodo inflazionistico in quel periodo, in particolare negli anni '90. Costrutti come librerie, framework e servizi del sistema operativo sono tutti strumenti pensati per affrontare la complessità che si accompagna allo spazio espanso dei problemi. Non sono una manna dal cielo né un peso in sé e per sé - solo una continua esplorazione di un vasto spazio di soluzione.

Ma, IMHO, "innovazione" è meglio compresa in termini di nuove forme e non confusa con il movimento laterale: reintrodurre forme che abbiamo già visto introdotte. In un certo senso, la fecondità di un ecosistema soffre quando le forme primitive non si compongono, quando fissano le decisioni prese nelle prime fasi dell'evoluzione o non possono rielaborare i loro detriti. Alcuni, se non la maggior parte, dei costrutti su cui rimaniamo concentrati non danno priorità al sostentamento a lungo termine del valore come una preoccupazione. Ciò ha iniziato a cambiare: approcci come Service Orientation e Domain Driven Design, per non parlare dei modelli ipertestuali e basati su grafici, ad esempio stanno modificando il panorama. Come ogni ecosistema, alla fine le forme dominanti lasceranno il posto a nuove forme; siamo meglio serviti consentendo la diversità,

"E i programmatori più giovani traggono maggiori benefici dall'apprendimento della programmazione di basso livello PRIMA di esplorare i regni delle librerie espansive? Se sì, allora perché?"

Direi che la maggior parte del linguaggio umano si basa su metafore dimenticate da tempo, quindi mentre sostengo l'apprendimento della programmazione di basso livello dal punto di vista dell'alfabetizzazione scientifica / numerica, è più importante cercare primitive che supportino la portata e la portata di i problemi che stiamo affrontando in modo da poter tranquillamente ignorare il livello inferiore di dettaglio. Un framework non è un primitivo, né è un sistema operativo o una libreria - sono abbastanza poveri nel fare il tipo di astrazione di cui abbiamo veramente bisogno. I progressi reali porteranno le persone che (a) sanno cosa è successo prima e (b) possono pensare in un modo abbastanza nuovo da trovare qualcosa di abbastanza diverso da esplorare uno spazio di soluzione che non è stato esplorato prima o che è stato esplorato e dimenticato.

OTOH, anche se il tuo obiettivo è quello di lavorare come tecnico / livello meccanico, un certo livello di esposizione di programmazione di basso livello sarà ancora utile per sviluppare le tue capacità di problem solving.


1

Il mio primo programma (come un adolescente di 15 anni) fu nel 1974 in PL / 1 su schede perforate per un mainframe IBM 370/168. Mio padre lavorava in IBM e ho avuto la fortuna di poter andare al datacenter la domenica.

A quel tempo, un programma di diverse migliaia di dichiarazioni (cioè carte lanciate) era un programma grande (e anche pesante, poiché molte migliaia di carte perforate pesavano molti chilogrammi). Non esistevano interfacce visive (un programma tipico letto dal suo "input standard" usando un comando di scheda perforata che inizia con //GO.SYSIN DD *IIRC, ma non ho padroneggiato JCL ). Gli algoritmi erano importanti e la libreria standard IIRC era piuttosto piccola per gli standard odierni.

Oggi, i programmi di diverse migliaia di righe sono generalmente considerati piccoli. Ad esempio, il compilatore GCC ha più di dieci milioni di righe di codice sorgente e nessuno le sta comprendendo appieno.

La mia sensazione è che la programmazione oggi sia abbastanza diversa dagli anni '70, perché è necessario utilizzare molte più risorse (in particolare librerie e framework software esistenti). Tuttavia, immagino che le persone che sviluppano software per data center (ad esempio i motori di ricerca di Google) o alcuni software embedded si preoccupino tanto degli algoritmi e dell'efficienza rispetto al programmatore medio degli anni '70.

Penso ancora che comprendere la programmazione a basso livello sia importante anche oggi (anche se la maggior parte dei programmatori non si codificherà algoritmi container di base come alberi bilanciati, array ordinati dicotomicamente accessibili, ecc ...) perché comprendere l'intero quadro è ancora importante.

Una grande differenza tra gli anni '70 e oggi è il rapporto tra costo tra gli sforzi (umani) dello sviluppatore e la potenza del computer.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.