Come evitare i tipici "errori linguistici dinamici"?


42

Di recente ho inserito un paio d'ore in JavaScript perché volevo beneficiare dell'enorme base di utenti. In questo modo ho notato uno schema che la maggior parte delle persone attribuisce a linguaggi dinamici. Fai in modo che le cose funzionino molto rapidamente, ma una volta che il tuo codice raggiunge una certa dimensione, perdi molto tempo con errori di tipo, ortografia e refactoring in generale. Errori di cui un compilatore mi risparmierebbe normalmente. E non farmi cercare errori nella logica quando ho appena fatto errori di battitura in un altro modulo.

Considerando l'incredibile seguito di JavaScript e altri linguaggi tipizzati dinamicamente, sono portato a credere che ci sia qualcosa di sbagliato nel mio approccio. O è solo il prezzo che devi pagare?

Per dirla in modo più conciso:

  • Come approcci un progetto JavaScript (o qualsiasi altro linguaggio dinamico per quella materia) con ~ 2000 LOC?
  • Ci sono strumenti per impedirmi di fare quegli errori? Ho provato a fluire da Facebook e JSHint che aiutano un po ', ma non catturano errori di battitura.

2
Anche se ci sono modi per mitigare i costi, ci sono costi .
dcastro,

29
Proverei a scrivere il tuo programma in un linguaggio tipicamente statico che si compila in javascript, come Typescript, Scala.js o Elm.
dcastro,

6
test, test, ulteriori test e rapporti di copertura.
njzk2,

7
~ 2000 LOC è un piccolo progetto. Dovrebbe adattarsi facilmente a ciò che un linguaggio dinamico fa facilmente e bene. Se stai lottando con quel tipo di progetto di dimensioni, hai un problema più fondamentale con le tue capacità di programmazione rispetto a qualsiasi cosa che sia rilevante per i linguaggi dinamici.
Jack Aidley,

5
@JackAidley non è d'accordo. L'OP viene utilizzato per concentrarsi su problemi di alto livello e non sull'ortografia corretta di un identificatore. Questa è abilità di programmazione. Garantire l'ortografia corretta può essere eseguita da un selezionatore medio e / o dal supporto dello strumento.
mucaho,

Risposte:


37

Specificamente parlando di JavaScript, è possibile utilizzare TypeScript invece. Offre alcune delle cose a cui ti riferisci. Citando il sito Web:

I tipi consentono agli sviluppatori JavaScript di utilizzare strumenti e pratiche di sviluppo altamente produttivi come il controllo statico e il refactoring del codice durante lo sviluppo di applicazioni JavaScript.

Ed è solo un superset di JS, il che significa che parte del codice esistente funzionerà bene con TS:

TypeScript parte dalla stessa sintassi e semantica che milioni di sviluppatori JavaScript conoscono oggi. Utilizza il codice JavaScript esistente, incorpora le librerie JavaScript più diffuse e chiama il codice TypeScript da JavaScript.


11
... e TypeScript è essenzialmente Ecmascript 6.
Robert Harvey,

11
Quella citazione fa male. Mostra solo che Microsoft è sempre stata un'azienda di linguaggi statici che semplicemente non capisce i linguaggi dinamici. "I tipi abilitano ... refactoring del codice"? Veramente? Il dipartimento PR di Microsoft si rende conto che il refactoring del codice come pratica è stato inventato in Smalltalk (un linguaggio dinamico) ed esisteva anche prima in Forth (un linguaggio non tipizzato)? Che il primissimo strumento di refactoring automatizzato faceva parte di un IDE Smalltalk, prima ancora che i linguaggi statici avessero IDE? Che gli IDE Smalltalk moderni abbiano strumenti di refactoring almeno altrettanto potenti se non più di Java, C # e C ++? Andiamo, forza.
Jörg W Mittag,

5
TypeScript è un grande linguaggio a sé stante, perché devi provare a spingerlo con tale assurdità?
Jörg W Mittag,

29
@ Jörg Non so abbastanza di Smalltalk, ma ogni singolo IDE per JavaScript o Python che ho visto è miglia dietro a ciò che un buon IDE per Java o C # può fare. Inoltre ci sono alcune cose che sono semplicemente impossibili da fare in un linguaggio dinamico (alcuni dei refactoring più popolari in realtà): supponiamo che tu abbia una funzione pubblica foo(x) { return x.bar;}o qualcosa del genere. Dal momento che non ci sono informazioni sul tipo e la funzione è pubblica (quindi non puoi conoscere tutti i chiamanti), è impossibile per te capire se la barra dovrebbe essere rinominata in baz se rinomini una classe.
Voo,

10
Questa risposta afferma che la soluzione agli "errori linguistici dinamici" non è affatto usare un linguaggio dinamico.
bgusach,

19

Ci sono alcuni approcci che possono aiutare:

Test unitari

Scrivi test unitari ove possibile. Affidarsi esclusivamente a test manuali o trovare bug in natura è incostante.

Usa i framework

Invece di creare il tuo e rischiare l'introduzione di bug, usa i framework stabiliti dove possibile.

Preferisci le lingue CSS / di alto livello

Dove puoi cedere le funzionalità ai CSS o in qualsiasi linguaggio di alto livello in cui stai scrivendo.

Refactor

Rifattore per ridurre la quantità di codice. Meno codice = meno luoghi in cui le cose vanno male.

riutilizzo

Riutilizzare il codice esistente dove è possibile. Anche se il codice non è una corrispondenza esatta, può essere meglio copiare, incollare e modificare piuttosto che scrivere qualcosa di nuovo.

IDE

Gli IDE moderni in genere hanno almeno un supporto Javascript. Alcuni editor di testo sono anche JavaScript.


5
Sebbene sia vero, i tuoi consigli si applicano sostanzialmente a tutti i linguaggi di programmazione e mirano principalmente a correggere errori logici piuttosto che quelli derivanti da linguaggi dinamici.
Edmz,

1
"il tuo consiglio si applica sostanzialmente a tutti i linguaggi di programmazione" . Molto vero - in un modo simile a passare dagli ingranaggi da progetti di hobby a soluzioni aziendali piene di grassi, che richiede una quantità crescente di restrizioni, allo stesso modo - più Javascript è scritto, più disciplina ha bisogno se le ruote non vanno a staccarsi rapidamente. Eric Lippert lo descrive molto bene.
Robbie Dee,

4
"Preferisci CSS / linguaggi di alto livello" - Non capisco davvero cosa significhi questo bit in relazione a JavaScript: stai dicendo di spostare elementi (come l'animazione, forse?) In fogli di stile piuttosto che in codice JS? In che modo i CSS si collegano a linguaggi di alto livello?
AnotherDave

@anotherdave In CSS3 è ora possibile ottenere molto di quello che un tempo era il dominio di Javascript. Alcune funzionalità potrebbero anche essere spostate in un linguaggio di livello superiore che sarebbe soggetto a controlli più rigorosi.
Robbie Dee,

4
@anotherdave Gran parte di ciò che le persone cercano di fare con JavaScript è estraneo e inappropriato. Librerie che forniscono strumenti linguistici standard, framework che forniscono elementi HTML standard con poco altro, codice che replica funzionalità di base come ancore, emulazione MVC, styling, reimplementazione DOM, astrazione AJAX, rendering di oggetti banali (reimplementazione di SVG), funzionalità di polifilling avvantaggia l'utente ... Dovresti ridurre al minimo la quantità di JS che scrivi. Se riesci a farlo senza JS, fallo senza JS.
bjb568,

2

Uno strumento che non è stato ancora menzionato è la ricerca di testo semplice, a livello di file o di progetto .

Sembra semplice, ma quando si includono alcune espressioni regolari è possibile eseguire un filtro di base o avanzato, ad esempio cercare parole che si trovano nella documentazione o nel codice sorgente.

È stato uno strumento efficace per me (oltre agli analizzatori statici) e, date le dimensioni del tuo progetto di 2k LOC, che secondo me non è particolarmente grande, si spera che faccia miracoli.


2
grepfa molta strada. A meno che tu non faccia cose troppo strane e dinamiche, fa il trucco. Tuttavia, sembra molto manuale se sei abituato agli IDE per linguaggi tipizzati statici.
bgusach,

1

Attualmente sto refactoring diverse migliaia di righe di codice su un grande progetto AngularJS. Una delle maggiori seccature è capire il contratto esatto di una determinata funzione. A volte finivo per leggere la documentazione dell'API perché elementi della risposta API non elaborata venivano assegnati a variabili che attraversavano 6 livelli di codice prima di essere modificati e restituiti tramite altri 6 livelli di codice.

Il mio primo consiglio è di progettare per contratto . Prendi input specifici, produce output specifici, evita gli effetti collaterali e documenta queste aspettative usando TypeScript o almeno JSDoc.

Il mio secondo consiglio è quello di attuare il maggior numero possibile di controlli. Seguiamo lo standard AirBnB e utilizziamo eslint su tutta la nostra base di codice. I hook di commit verificano che seguiamo sempre lo standard. Naturalmente disponiamo di una batteria di test unitari e di collaudo e tutti i commit devono essere esaminati da un peer.

Il passaggio da un editor di testo (Sublime Text) a un IDE corretto (WebStorm) ha anche reso molto più semplice lavorare con il codice in generale. WebStorm utilizzerà JSDoc per fornire suggerimenti sui tipi di parametri previsti e generare errori se si fornisce il tipo errato o si utilizza un valore di ritorno in modo errato.

In JavaScript, nuove funzionalità come simboli e getter / setter possono aiutare a far rispettare un certo livello di qualità aggiungendo asserzioni all'assegnazione variabile (ad es. Assicurarsi che l'intero sia compreso nell'intervallo o che l'oggetto dati abbia determinati attributi).

Sfortunatamente, non penso che ci sia una vera soluzione per prevenire errori linguistici dinamici, solo una serie di misure che possono aiutare a ridurne la frequenza.


0

La mia risposta alla domanda "Come affrontate un progetto JavaScript (o qualsiasi altro linguaggio dinamico per quella materia) con ~ 2000 LOC?"

Sviluppo applicazioni per moduli PDF. Mi avvicino al mio progetto di sviluppo software JavaScript (indipendentemente dalle dimensioni del codice sorgente) utilizzando gli elementi e le annotazioni netti di Petri. Il metodo non è legato a nessuna particolare tecnologia del linguaggio di programmazione. Pertanto può essere utilizzato per altri "linguaggi di programmazione".

Creo un diagramma della logica dell'applicazione. Per mantenere il diagramma ordinato, aggiungo la maggior parte delle mie annotazioni a un modulo che utilizzo con il diagramma. Le voci nel modulo includono riferimenti a proprietà o funzioni. Quindi scrivo il codice sorgente in base alle informazioni nel diagramma e alle voci nel modulo. Il metodo è sistematico perché ogni codice sorgente scritto viene mappato direttamente dal diagramma e dalle voci nel modulo. Il codice sorgente può essere facilmente controllato perché seguo anche le convenzioni di denominazione e codifica quando scrivo il codice.

Ad esempio, ho scelto una convenzione secondo cui tutte le funzioni sono prototipi. Se le prestazioni diventano un problema, è possibile migliorarle dichiarando le funzioni nel costruttore. Per alcune proprietà utilizzo array. Ancora una volta se le prestazioni diventano un problema, possono essere migliorate utilizzando riferimenti diretti.

Uso anche eval. Ciò può ridurre notevolmente le dimensioni del codice sorgente. A causa di problemi di prestazioni, utilizzo eval all'inizio o all'inizializzazione della mia applicazione; Non lo uso mai nella "logica di runtime": questa è un'altra convenzione di codifica che seguo.

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.