Sviluppare conoscenze di programmazione approfondite


136

Occasionalmente vedo domande su casi limite e altre stranezze su Stack Overflow a cui è facile rispondere da artisti del calibro di Jon Skeet ed Eric Lippert, dimostrando una profonda conoscenza della lingua e delle sue molte complessità, come questa:

Potresti pensare che per usare un foreachciclo, la collezione su cui stai iterando debba implementare IEnumerableo IEnumerable<T>. Ma a quanto pare, questo non è in realtà un requisito. Ciò che è richiesto è che il tipo di raccolta deve avere un metodo pubblico chiamato GetEnumeratore che deve restituire un tipo con un getter di proprietà pubblica chiamato Currente un metodo pubblico MoveNextche restituisce a bool. Se il compilatore può determinare che tutti questi requisiti sono soddisfatti, il codice viene generato per utilizzare tali metodi. Solo se tali requisiti non sono soddisfatti verifichiamo se l'oggetto implementa IEnumerableo IEnumerable<T>.

È roba interessante da sapere. Posso capire perché Eric lo sappia; fa parte del team del compilatore, quindi deve saperlo. Ma che dire di quelli che dimostrano una conoscenza così profonda che non sono addetti ai lavori?

In che modo i semplici mortali (che non fanno parte del team di compilatori C #) scoprono cose come questa?

In particolare, ci sono metodi che queste persone usano per sradicare sistematicamente tali conoscenze, esplorarle e interiorizzarle (renderle proprie)?


10
Penso che questo sia in particolare dove brilla il software open source. È bello poter entrare nel framework / sistema / librerie fino in fondo. Una volta, quando lavoravo con Qt, avevo una migliore comprensione degli interni del framework rispetto a quando lavoravo con WinForms.
Vitor Py,

2
Quando avresti bisogno di conoscere questo esempio specifico, oltre a non sembrare stupido di fronte a una folla speciale? Lo hanno reso a prova di idiota. Oltre a ciò, la serie C #, Java, C ++, ecc. Potrebbe contenere alcune cose interessanti. Anche il blog di Eric Lippert è una buona fonte. In generale, spesso non sappiamo cosa non sappiamo, quindi come si suol dire "vivi per 100 anni, impara per 100 anni e muori scemo".
Giobbe

26
Ne vale la pena? Sono bilingue e sto cercando di imparare alcune altre lingue parlate. Ho seguito alcune lezioni di matematica, ma non abbastanza. Vorrei imparare a giocare a tennis a metà decenza e imparare a nuotare usando il colpo di farfalla. Vorrei viaggiare di più. Voglio imparare un po 'di Clojure. Quello che non voglio è essere esperto in una lingua, avere un dottorato in matematica, trascorrere 30 ore settimanali in un pool come Michael Phelps, ecc. Le conoscenze di Lippert e Skeet sono dovute al fatto che mettono molto sforzo in una (o poche) cose mentre perdendo altre esperienze. Forse cambi lavoro?
Giobbe

10
"Posso capire perché Eric lo sappia; fa parte del team di compilatori, quindi deve saperlo." - è probabile che lo sappia perché lo ha pensato in primo luogo . Dubito che abbia dovuto "scoprire" che funziona così :)
Alex ten Brink,

10
@Alex: In realtà ho lavorato solo su C # da quando abbiamo iniziato a costruire l'implementazione di C # 3. La specifica "foreach" è stata scritta più di sei anni prima. Ogni giorno scopro ancora pazze cose storiche sulla lingua. Ad esempio, ho imparato oggi che per i delegati, ((A + B) + C) - (A + C) = A + B + C, ma ((A + B) + C) - (B + C) = A Strano!
Eric Lippert,

Risposte:


167

Prima di tutto, grazie per le belle parole.

Se vuoi conoscere a fondo C #, è senza dubbio un vantaggio avere le specifiche del linguaggio, dieci anni di note di progettazione, il codice sorgente, il database dei bug e Anders, Mads, Scott e Peter in fondo al corridoio. Sono sicuramente fortunato, non c'è dubbio.

Tuttavia, anche senza quei vantaggi, è ancora possibile ottenere una profonda conoscenza della materia.

Quando ho iniziato a lavorare a Microsoft, stavo lavorando all'interprete JScript fornito con Internet Explorer 3. All'epoca il mio manager mi aveva detto qualcosa che era tra i migliori consigli che avessi mai ricevuto. Ha detto che voleva che diventassi l'esperto riconosciuto di Microsoft sulla sintassi e la semantica del linguaggio JScript e che avrei dovuto farlo cercando domande su quegli aspetti di JScript e rispondendo a loro. In particolare rispondendo alle domande a cui non sapevo le risposte, perché quelle sono quelle da cui imparerei.

Ovviamente StackOverflow e altri forum di domande e risposte pubbliche sono come bere da una manichetta antincendio per quel genere di cose. Allora, ho letto religiosamente comp.lang.javascript e i nostri forum interni "JS User" di Microsoft e ho seguito il consiglio del mio manager: quando ho visto una domanda sulla semantica del linguaggio a cui non conoscevo la risposta, l'ho fatta i miei affari per scoprirlo.

Se vuoi fare una "immersione profonda" come quella, devi scegliere con cura. Ad oggi ignoro notevolmente il funzionamento del modello a oggetti del browser. Da quando mi sono concentrato sul diventare l'esperto di linguaggio C # negli ultimi anni, sono notevolmente ignaro di come funzionano le varie classi nelle librerie delle classi di base. Sono fortunato per il fatto di avere un lavoro che premia specifiche conoscenze profonde; se il tuo lavoro o i tuoi talenti sono più in linea con l'essere un generalista, andare in profondità potrebbe non funzionare per te.

Anche scrivere un blog è estremamente utile; imponendomi di spiegare argomenti complessi ad altre persone, sono costretto a confrontarmi continuamente con la mia inadeguata comprensione di vari argomenti.


14
Non trascinare questo fuori tema, ma dopo aver letto questa risposta sono curioso di sapere perché non hai posto domande qui o su Stack Overflow. I tuoi colleghi, blog, ecc. Sono sufficienti per te a questo punto? Ci sono risorse migliori di SO che dovremmo conoscere?
Matteo Leggi l'

6
Forse hai frainteso quello che sta dicendo. Contro-intuitivamente, non stava facendo domande per imparare le cose, stava rispondendo a domande.
jhocking

65

Essendo stato dalla parte del "guru" della conversazione una o due volte, posso dirti che molte volte ciò che percepisci come "conoscenza profonda" di un linguaggio o sistema di programmazione è spesso il risultato del "guru" di recente in lotta per un mese per risolvere esattamente lo stesso problema. Ciò è particolarmente vero in un forum in cui le persone possono scegliere a quali domande rispondere. Anche artisti del calibro di Jon Skeet e Eric Lippert hanno dovuto imparare il mondo del ciao a un certo punto. Raccolgono le loro conoscenze un concetto alla volta, come chiunque altro.


1
Un ottimo punto. Quando intraprendo lunghi periodi di ricerca trovo spesso che trovo domande alle quali ora posso rispondere a causa di cose che ho imparato all'inizio della giornata.
Matteo Leggi l'

47

Parafrasando Yogi Bhajan:

"Se vuoi imparare qualcosa, leggi su di esso; se vuoi capire qualcosa, scrivi su di esso; se vuoi padroneggiare qualcosa, programmalo ."

La programmazione è come l'ultima sfida dell'insegnamento. Insegnare al computer a fare qualcosa richiede che tu conosca davvero bene le tue cose - o imparerai a dominarle.

Ad esempio, se vuoi imparare la fisica, scrivi un motore fisico. Se vuoi imparare gli scacchi, programma una partita a scacchi. Se vuoi imparare una conoscenza approfondita di C #, scrivi un compilatore C # (o qualche altro strumento).


2
La programmazione è anche un modesto tentativo di scrivere (per essere letto dalle persone, ovviamente) in un modo molto inequivocabile.
vpit3833,

4
Quella citazione suonò molto in profondità fino a quando non ho letto l'esempio degli scacchi. Sfortunatamente, programmare un'intelligenza artificiale per gli scacchi non ti renderà un giocatore di scacchi migliore (è fondamentalmente una ricerca in un albero Min-Max). Ancora +1
bughi,

1
@bughi Forse puoi padroneggiare le regole: D
Julio Rodrigues,

@bughi, "programmalo" è un termine molto ampio non sempre correlato alla scrittura del codice !! Pensa un po 'fuori dagli schemi.
Nitesh Verma,

25

Per quanto ne so, i modi per imparare questo sono:

  • Leggi a riguardo da qualcuno come Eric Lippert
  • Sperimenta e risolvi i problemi in prima persona.

Il secondo modo potrebbe richiedere molto più tempo ma probabilmente porterà a una comprensione più profonda (ma non sempre).


17
O entrambi. [15 caratteri]
Michael K,

23

Direi di fare quanto segue:

Dopo aver appreso una pila di lingue relativamente utile (quelle necessarie per un vero lavoro) al livello in cui puoi svolgere le attività più comuni, smetti di imparare più lingue fino a quando non ne avrai studiato almeno uno in profondità. Parte del problema nel nostro settore in questo momento, secondo me, è che le persone imparano solo il primo 5-10% della lingua prima di passare ad un'altra lingua. Una volta che hai la possibilità di svolgere le attività più comuni in un lavoro, quindi inizia a esaminare una cosa in profondità. (Puoi tornare ad acquisire ampiezza dopo aver acquisito una certa profondità, quindi andare avanti e indietro tra i due.)

Volontariato per i compiti più complessi e difficili, quelli che ti fanno andare in profondità per risolvere i problemi. Se non ci sono persone in cui lavori, cerca attività open source da svolgere o inizia a lavorare su un progetto personale che ti farà andare in profondità. Se il tuo lavoro non ha problemi interessanti, considera di cercare un lavoro più stimolante.

Leggi i libri avanzati su una lingua (ad esempio per SQl Server ciò includerebbe la lettura dell'ottimizzazione delle prestazioni e degli interni del database) invece del tipo di libri X in 30 giorni.

Leggi le domande interessanti qui e in altri luoghi in cui vengono poste e prova a risolverne alcune tu stesso. Se vuoi imparare, prova a risolverne alcuni senza prima leggere le altre risposte. Anche se alla domanda è già stata data una risposta, imparerai di più se trovi tu stesso la risposta. Potresti persino trovare una risposta migliore di quella della domanda.

Poni alcune delle domande più difficili. Valuta le risposte che ti vengono date, non solo usarle. Assicurati di capire perché la risposta dovrebbe funzionare o meno. Usa quelle risposte come punto di partenza per la ricerca.

Trova alcuni buoni blog tecnici di esperti noti nel settore e leggili.

Smetti di buttare via le tue conoscenze dopo aver finito. Impara a conservare. La maggior parte degli esperti non deve cercare la sintassi comune. Non devono reinventare la ruota ogni volta che affrontano un problema perché ricordano come hanno affrontato un problema simile in precedenza. Possono collegare i punti e vedere come il problema X che hanno fatto due anni fa sia simile al problema Y che hanno in questo momento (mi stupisce di come poche persone sembrano in grado di stabilire connessioni del genere). Di conseguenza, hanno più tempo a disposizione per dedicarsi alla ricerca di argomenti più interessanti.


Una bella risposta Ma mi chiedo, come posso migliorare nel mantenere la conoscenza e nel collegare i punti?

Ti suggerisco di prendere nota di tutto ciò che impari. Ho iniziato a farlo nel mio Evernote e, nel giro di pochi anni, ho scoperto di poter vivere con i miei appunti. Lentamente, sono anche arrivato al punto in cui i miei appunti possono essere trasformati in presentazioni, che sono pronto a presentare in un momento.
Shivasubramanian A

9

Puoi iniziare studiando a fondo le specifiche linguistiche di quelle che cerchi di essere un esperto. Per esempio:


3
Buona risposta - ad esempio, la sezione 15.8.4 della specifica C # collegata copre l'implementazione foreache illustra il comportamento descritto nel post di blog citato da Eric Lippert. Se qualcuno dovesse mai ritrovarsi a pensare a qualcosa del tipo "Mi chiedo come funziona davvero foreach .." questo sarebbe un buon posto per iniziare a cercare.
Carson63000,

6

Ottieni Reflector o qualsiasi altro decompilatore (dal momento che sta pagando ora) e inizia ad aprire alcune delle librerie .NET più utilizzate per imparare come funzionano gli interni. In combinazione con un libro come CLR via C # diventerai abbastanza profondo (più in profondità di quanto la maggior parte di noi andrà a svolgere il proprio lavoro normale).


5
In realtà l'ho fatto con le BitConverterclassi e ho scoperto la IsLittleEndianbandiera specifica del sistema.
Robert Harvey,

LOL. +1 per isLittleEndian
Rudy

4

Ho sviluppato quel tipo di conoscenza in C ++ comp.lang.c++.moderatedrestando in contatto per un paio d'anni, anche se a quel punto non stavo davvero lavorando così duramente per codificarlo. Tuttavia, non sono sicuro di quanto possa essere il guru.

Penso che ci siano due tipi di conoscenza che si possono acquisire su un linguaggio di programmazione:

  1. Conoscere curiosità sulla lingua e sapere come evitare le insidie.
  2. Saper risolvere i problemi in modo efficace.

Il numero 2 può essere raggiunto solo programmando nella lingua e guardando il codice di altre persone, ma il numero 1 può essere raggiunto prendendo molto tempo per leggere la lingua sui suoi forum di discussione, vedendo che tipo di domande le persone fanno e quali le risposte sono. StackOverflow è un buon posto anche per quello.


4

Conoscenza profonda e competenza di programmazione significa sentirsi a proprio agio a tutti i livelli di astrazione. ie

  • librerie e API
  • semantica linguistica
  • ottimizzazioni del compilatore
  • interni del compilatore e generazione del codice
  • runtime e comportamento del garbage collector
  • problemi relativi all'architettura e alle istruzioni

Tutto ciò che ho visto negli ultimi 15 anni ha dimostrato che solo se riesci davvero a entrare nel compilatore e nel runtime hai la possibilità di diventare profondamente competente. Potrebbe essere necessario forzare te stesso a fare il passo e iniziare a ragionare (e costruire) il software al livello successivo di astrazione più in basso nello stack , ma è l'unico modo per fare esperienza.

Tutto ciò che abbiamo è il linguaggio per l'astrazione. Devi capire come sono progettati e costruiti i linguaggi di programmazione per sapere veramente cosa sta facendo la macchina.


3

Leggi il manuale fine Questa non è una conoscenza particolarmente approfondita. È pubblicato nella sezione 8.6.4 delle specifiche del linguaggio C # . Dovresti prendere l'abitudine di scremare almeno le specifiche per le lingue che usi, così come scremare la documentazione per tutte le librerie integrate.

Comunque, questa non è la mia idea di profonda conoscenza; è solo un dettaglio di implementazione poco interessante. Potrebbe essere più interessante se il designer spiegasse perché è stato fatto in questo modo più dinamico, invece di verificare semplicemente che l'oggetto implementa Iterable.


1
Non penso che esista "scremare" le specifiche del linguaggio C #.
Robert Harvey,

@RobertHarvey: puoi sfogliare la maggior parte del linguaggio formale che copre cose che già conosci, come la precedenza degli operatori e la sintassi delle dichiarazioni, e concentrarti su dettagli inaspettati ma utili, come il comportamento esatto dei costruttori di foreach C # o Java enum.
Kevin Cline,

È possibile acquistare una versione annotata dello standard. Ora è un po 'datato ma i commenti sono ancora molto interessanti per le parti del linguaggio che sono coperte.
Jørgen Fogh,
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.