Vorrei aggiungere una risposta a questa domanda dato che ultimamente ho attraversato un po 'di buono, cattivo ma soprattutto brutto Java e ho un nuovo carico enorme di generalizzazioni eccessive grossolane su sviluppatori Java e Java rispetto a JS e Gli sviluppatori di JS che potrebbero effettivamente basarsi su qualcosa che ricorda vagamente la verità utile.
Ci sono IDE ma può essere utile capire perché non ce ne sono stati molti
Ho provato Webstorm ora che mi trovo attratto dallo sviluppo di Node e non è poi così male che l'ho effettivamente comprato, ma tendo ad aprire i file js in Scite più spesso di WS. Il motivo è che puoi fare molto di più con molto meno in JS ma anche perché il lavoro dell'interfaccia utente fornisce un feedback immediato, gli strumenti di sviluppo del browser (Chrome e Firebug in particolare) sono in realtà piuttosto eccellenti e (tenendo conto dei contesti non browser ) rieseguire il codice modificato è semplice e veloce senza un passo di compilazione.
Un'altra cosa di cui sono abbastanza convinto è che gli IDE fondamentalmente creano la propria domanda abilitando il codice sciatto che non si può davvero permettere in JavaScript. Vuoi imparare come gestiamo JS? Potrebbe essere utile iniziare cercando di scrivere qualcosa di non banale in Java senza un IDE e prestare molta attenzione alle cose che devi iniziare a fare e pensare per poter effettivamente mantenere / modificare quel codice senza un IDE in movimento inoltrare. IMO, quelle stesse cose sono ancora fondamentali per la scrittura di codice gestibile sia che tu abbia un IDE o meno. Se dovessi scrivere un curriculum di programmazione di 4 anni, non ti lascerei toccare un IDE per i primi due anni, nell'interesse di non stravolgere strumenti e dipendenze.
Struttura
Gli sviluppatori esperti di JS che si occupano di applicazioni complesse possono e strutturare il loro codice. In effetti è una cosa su cui tendiamo a essere migliori con una storia antica in cui mancavano gli IDE per leggere il codice per noi, ma anche perché i linguaggi fortemente espressivi possono esprimere in modo potente potenze di codice di disastro completamente non mantenibili molto rapidamente se non si codifica pensieroso.
In realtà ho avuto una curva di apprendimento piuttosto ripida nel comprendere la nostra base di codice Java di recente fino a quando ho finalmente capito che nessuno di questi era OOP corretto. Le classi non erano altro che fasci di metodi vagamente correlati che alterano i dati disponibili a livello globale in giro in bean o DTO o getter / setter statici. È sostanzialmente la stessa vecchia bestia che OOP avrebbe dovuto sostituire. Quindi ho praticamente smesso di cercare e pensare al codice. Ho appena appreso i tasti di scelta rapida e tracciato i pasticci e tutto è andato molto più agevolmente. Quindi, se non hai già l'abitudine, pensa molto di più a OOD.
Un'app JS ben strutturata ai massimi livelli tenderà a consistere di funzioni complesse (ad esempio jQuery) e oggetti che interagiscono tra loro. Direi che il segno di un'app ben strutturata e facilmente gestibile in qualsiasi lingua è che è perfettamente leggibile se la stai guardando con un IDE o Notepad ++. È uno dei motivi principali per cui sono estremamente critico nei confronti dell'iniezione di dipendenza e del TDD test-first portato all'estremo.
E infine, lascia andare le lezioni. Scopri l'eredità prototipale. In realtà è abbastanza elegante facile da implementare quando in realtà hai bisogno dell'eredità. Trovo che gli approcci di composizione tendano a funzionare molto meglio in JS, tuttavia, e personalmente inizio a ammalarmi e ho terrori notturni EXTJS ogni volta che vedo più di uno o due livelli di eredità in qualsiasi lingua.
Principi fondamentali in primo luogo
Sto parlando delle cose fondamentali da cui dovrebbero derivare tutte le altre buone pratiche: DRY, YAGNI, il principio del minimo stupore, la netta separazione dei domini problematici, la scrittura su un'interfaccia e la scrittura di codice leggibile umano sono il mio nucleo personale. Qualunque cosa un po 'più complessa che sostenga l'abbandono di tali pratiche dovrebbe essere considerata un aiuto Kool in qualsiasi lingua, ma soprattutto una lingua come JavaScript in cui è estremamente facile lasciare un'eredità di codice molto confuso per il prossimo. L'accoppiamento allentato, ad esempio, è una grande cosa fino a quando non lo spingi così lontano da non riuscire nemmeno a capire dove sta avvenendo l'interazione tra gli oggetti.
Non temere la digitazione dinamica
Non ci sono molti tipi principali in JavaScript. Per la maggior parte, le regole di casting dinamico sono pratiche e dirette, ma vale la pena apprenderle in modo da poter imparare meglio a gestire il flusso di dati senza cast inutili e routine di validazione inutili. Fidati di me. I tipi rigorosi sono ottimi per le prestazioni e individuano i problemi durante la compilazione, ma non ti proteggono da nulla.
Impara la schifezza di JS Funzioni e chiusure
Le funzioni di prima classe di JS sono probabilmente il motivo principale per cui JS ha vinto il premio "Solo la lingua che vale la pena toccare il Web lato client con il premio". E sì, in realtà c'era competizione. Sono anche una caratteristica centrale di JS. Costruiamo oggetti con loro. Tutto è mirato alle funzioni. E hanno funzioni utili. Possiamo esaminare i parametri tramite la parola chiave argomenti. Possiamo collegarli e licenziarli temporaneamente nel contesto di essere metodi di altri oggetti. E rendono gli approcci guidati dagli eventi a cose oscenamente facili da implementare. In breve, hanno reso JS un'assoluta bestia nel ridurre la complessità e nell'adattare le diverse implementazioni di JS stesso (ma principalmente l'API DOM) direttamente alla fonte.
Rivalutare i modelli / le pratiche prima di adottare
Le funzioni di prima classe e i tipi dinamici rendono molti dei modelli di progettazione più complessi completamente inutili e ingombranti in JS. Alcuni dei modelli più semplici, tuttavia, sono incredibilmente utili e facili da implementare data la natura altamente flessibile di JS. Gli adattatori e i decoratori sono particolarmente utili e ho trovato i singoli utili per le complesse fabbriche di widget UI che fungono anche da gestori di eventi per gli elementi dell'interfaccia utente che costruiscono.
Segui l'esempio della lingua e fai di più con meno
Credo che uno dei principali honchos di Java renda l'argomento da qualche parte che la verbosità è in realtà una caratteristica positiva che rende il codice più facile da capire per tutte le parti. Fesserie. Se ciò fosse vero, il legalese sarebbe più facile da leggere. Solo lo scrittore può rendere ciò che hanno scritto più facile da capire e puoi farlo solo mettendoti nei panni dell'altro ragazzo di tanto in tanto. Abbraccia quindi queste due regole. 1. Sii il più diretto e chiaro possibile. 2. Arriva già a quel dannato punto. La vittoria è che il codice pulito e conciso rende gli ordini di grandezza più facili da capire e mantenere rispetto a qualcosa in cui devi attraversare venticinque livelli per passare dal grilletto all'azione desiderata reale. La maggior parte dei modelli che sostengono quel genere di cose in linguaggi più rigorosi sono in realtà soluzioni alternative per limitazioni che JavaScript non ha.
Tutto è malleabile e va bene
JS è probabilmente uno dei linguaggi meno protezionistici di uso popolare. Abbraccialo. Funziona bene Ad esempio, puoi scrivere oggetti con varchi "privati" persistenti inaccessibili semplicemente dichiarando var regolari in una funzione di costruzione e lo faccio spesso. Ma non è per proteggere il mio codice o gli utenti "da se stessi" (potrebbero comunque sostituirlo con la propria versione durante il runtime). Ma piuttosto è un segnale dell'intenzione perché il presupposto è che l'altro ragazzo è abbastanza competente da non voler manipolare alcuna dipendenza e vedrà che non sei destinato a raggiungerlo direttamente forse per una buona ragione.
Non ci sono limiti di dimensione, solo domini problematici
Il problema più grande che ho con tutte le basi di codice Java che ho visto è una sovrabbondanza di file di classe. Prima di tutto SOLID è solo una reiterazione confusa di ciò che dovresti già sapere su OOP. Una classe dovrebbe gestire una serie specifica di problemi correlati. Nessun problema con un metodo. Questo è solo prendere il vecchio codice C concatenato di funzioni-spaghetti solo con l'aggiunta di tutta la sintassi della classe inutile per l'avvio. Non ci sono limiti di dimensioni o metodi. Se ha senso aggiungere qualcosa a una funzione o classe o costruttore già lunga, ha senso. Prendi jQuery. È un intero set di strumenti della lunghezza di una libreria in un'unica funzione e non c'è nulla di sbagliato in questo. Se abbiamo ancora bisogno di jQuery dipende da un ragionevole dibattito, ma in termini di design,
Se Java è tutto ciò che sai, cavalca in qualcosa con una sintassi non basata su C.
Quando ho iniziato a fare scherzi con Python perché mi piaceva quello che stavo ascoltando su Django, ho imparato a iniziare a separare la sintassi dal design del linguaggio. Di conseguenza, è diventato più facile capire Java e C come una somma delle loro parti di progettazione del linguaggio piuttosto che una somma di cose che fanno diversamente con la stessa sintassi. Un piacevole effetto collaterale è che più capisci le altre lingue in termini di design, meglio capirai i punti di forza / debolezza di quello che conosci meglio attraverso il contrasto.
Conclusione
Ora, considerando tutto ciò, lascia che colpisca tutti i tuoi punti problematici:
- Nessun modo immediato per trovare il punto di ingresso di una funzione (diverso da una ricerca in testo semplice, che può quindi portare a una successiva ricerca di metodi più in alto nella gerarchia di chiamate, dopo due o tre dei quali hai dimenticato da dove hai iniziato)
Chrome e Firebug hanno effettivamente il tracciamento delle chiamate. Ma vedi anche i miei punti sulla struttura e sul mantenere le cose concise e dirette. Più puoi pensare alla tua app come costrutti ben incapsulati più grandi che interagiscono tra loro, più è facile capire di chi è la colpa quando le cose vanno male. Direi che questo vale anche per Java. Abbiamo costruttori di funzioni di classe che sono perfettamente utili per le preoccupazioni tradizionali di OOP.
function ObjectConstructor(){
//No need for an init method.
//Just pass in params and do stuff inside for instantiation behavior
var privateAndPersistent = true;
//I like to take advantage of function hoisting for a nice concise interface listing
this.publicAndPointlessEncapsulationMurderingGetterSetter
= publicAndPointlessEncapsulationMurderingGetterSetter;
//Seriously though Java/C# folks, stop with the pointless getter/setters already
function publicAndPointlessEncapsulationMurderingGetterSetter(arg){
if(arg === undefined){
return privateAndPersistent;
}
privateAndPersistent = arg;
}
}
ObjectConstructor.staticLikeNonInstanceProperty = true;
var instance = new ObjectConstructor();//Convention is to capitalize constructors
Nel mio codice, non uso quasi mai i letterali degli oggetti {}
come componenti strutturali dell'app poiché non possono avere var interni (privati) e preferiscono invece riservarli per l'uso come strutture di dati. Ciò aiuta a stabilire un'aspettativa che mantiene la chiarezza delle intenzioni. (se vedi i ricci, sono i dati, non un componente dell'architettura dell'app).
- I parametri vengono passati alle funzioni, senza alcun modo di sapere quali proprietà e funzioni sono disponibili su quel parametro (tranne che eseguire effettivamente il programma, navigare fino al punto in cui viene chiamata la funzione e usare console.logs per generare tutte le proprietà a disposizione)
Ancora una volta, vedi i moderni strumenti del browser. Ma anche, perché è un tale peccato eseguire nuovamente il programma? Ricaricare è qualcosa che un web dev lato client colpisce in genere ogni pochi minuti perché non ti costa assolutamente nulla per farlo. Anche in questo caso, un altro punto con cui può essere utile la struttura dell'app ma è uno svantaggio di JS che devi eseguire la tua convalida quando far rispettare i contratti è fondamentale (qualcosa che faccio solo agli endpoint esposti ad altre cose che la mia base di codice non fa controllo). IMO, il compromesso vale i vantaggi.
- L'uso comune di funzioni anonime come callback, che spesso porta a uno spaghetto di percorsi di codice confusi, che non è possibile navigare rapidamente.
Sì, è negativo per qualsiasi cosa non banale. Non farlo. Dai un nome alle tue funzioni per bambini. È anche più facile rintracciare le cose. È possibile definire, valutare (richiesto per assegnare) e assegnare una semplice funzione banale in linea con:
doSomethingWithCallback( (function callBack(){}) );
Ora Chrome avrà un nome per te quando segui le chiamate. Per funzioni non banali lo definirei al di fuori della chiamata. Si noti inoltre che le funzioni anonime assegnate a una variabile sono ancora anonime.
- E sicuramente, JSLint rileva alcuni errori prima del runtime, ma anche questo non è utile come avere linee ondulate rosse sotto il tuo codice direttamente nel browser.
Non tocco mai le cose. Crockford ha dato alcune cose positive alla comunità, ma JSLint supera le preferenze stilistiche e suggerisce che alcuni elementi di JavaScript sono parti cattive senza una ragione particolarmente buona, IMO. Ignora definitivamente quella cosa su regEx e le classi di negazione seguite da * o +. I caratteri jolly si comportano in modo più scadente e puoi facilmente limitare la ripetizione con {}. Inoltre, ignora tutto ciò che dice sui costruttori di funzioni. Puoi avvolgerli facilmente in una funzione di fabbrica se la nuova parola chiave ti dà fastidio. CSSLint (non quello di Crockford) è ancora peggio sul fronte dei cattivi consigli. Prendi sempre le persone che fanno molti discorsi con un granello di sale. A volte giuro che stanno solo cercando di stabilire autorità o generare nuovo materiale.
E di nuovo, devi disimparare ciò che hai imparato con questa preoccupazione di runtime che hai. (è comune che ho visto con molti sviluppatori Java / C #) Se vedere gli errori in fase di esecuzione ti disturba ancora 2 anni dopo, voglio che ti sieda e lo spam venga ricaricato in un browser fino a quando non affonda. non è una divisione tempo di compilazione / runtime (benché comunque non visibile - JS viene eseguito su un JIT ora). Scoprire i bug in fase di esecuzione non è solo corretto, ma è estremamente vantaggioso ricaricare lo spam in modo così economico e facile e scoprire i bug in ogni punto di arresto.
E fai crackin su quegli strumenti di sviluppo di Chrome. Sono integrati direttamente nel webkit. Fare clic con il tasto destro in Chrome. Ispeziona elemento. Esplora le schede. Un sacco di potenza di debug lì con la possibilità di alterare il codice nella console durante il runtime essendo una delle opzioni più potenti ma meno ovvie. Ottimo anche per i test.
In una nota correlata, gli errori sono i tuoi amici. Non scrivere mai una dichiarazione di cattura vuota. In JS non nascondiamo o seppelliamo errori (o almeno non dovremmo tossire YUI / tosse ). Ci occupiamo di loro. Qualcosa di meno provocherà dolore di debug. E se scrivi un'istruzione catch per nascondere potenziali errori nella produzione, registra almeno in silenzio l'errore e documenta come accedere al registro.