Wie vermeide ich typische "dynamische Sprachfehler"?


42

Ich habe kürzlich ein paar Stunden in JavaScript investiert, weil ich von der massiven Nutzerbasis profitieren wollte. Dabei ist mir ein Muster aufgefallen, das die meisten Menschen dynamischen Sprachen zuschreiben. Sie bekommen Dinge sehr schnell zum Laufen, aber sobald Ihr Code eine bestimmte Größe erreicht, verschwenden Sie viel Zeit mit Typ-, Rechtschreib- und Refactoring-Fehlern im Allgemeinen. Fehler, die mir ein Compiler normalerweise ersparen würde. Und ich muss nicht nach Fehlern in der Logik suchen, wenn ich gerade in einem anderen Modul einen Tippfehler gemacht habe.

Angesichts der unglaublichen Folge von JavaScript und anderen dynamisch typisierten Sprachen bin ich zu der Annahme gelangt, dass mit meinem Ansatz etwas nicht in Ordnung ist. Oder ist das nur der Preis, den Sie zahlen müssen?

Um es kurz zu machen:

  • Wie nähern Sie sich einem JavaScript-Projekt (oder einer anderen dynamischen Sprache) mit ~ 2000 LOC?
  • Gibt es Tools, die verhindern, dass ich diese Fehler mache? Ich habe versucht, durch Facebook und JSHint fließen, die etwas helfen, aber keine Tippfehler fangen.

2
Obwohl es Möglichkeiten gibt, die Kosten zu senken, gibt es auch Kosten .
Dcastro

29
Ich würde versuchen, Ihr Programm in einer statisch typisierten Sprache zu schreiben, die sich mit Javascript kompilieren lässt, wie Typescript, Scala.js oder Elm.
Dcastro

6
Testen, Testen, weitere Tests und Abdeckungsberichte.
njzk2

7
~ 2000 LOC ist ein kleines Projekt. Es sollte leicht in das passen, was eine dynamische Sprache leicht und gut kann. Wenn Sie mit solchen Größenprojekten zu kämpfen haben, haben Sie ein grundlegenderes Problem mit Ihren Programmierkenntnissen als alles, was speziell für dynamische Sprachen relevant ist.
Jack Aidley

5
@ JackAidley nicht einverstanden. OP wird verwendet, um sich auf allgemeine Probleme zu konzentrieren und nicht darauf, ob ein Bezeichner richtig geschrieben ist. Das ist Programmierkunst. Die korrekte Rechtschreibung kann durch einen Mittelschreiber und / oder eine Werkzeugunterstützung sichergestellt werden.
Mucaho

Antworten:


37

Insbesondere in Bezug auf JavaScript könnten Sie stattdessen TypeScript verwenden. Es bietet einige der Dinge, auf die Sie sich beziehen. Zitieren der Website:

Mithilfe von Typen können JavaScript-Entwickler hochproduktive Entwicklungstools und -verfahren wie statische Überprüfung und Code-Refactoring beim Entwickeln von JavaScript-Anwendungen verwenden.

Und es ist nur eine Obermenge von JS, was bedeutet, dass ein Teil Ihres vorhandenen Codes mit TS problemlos funktioniert:

TypeScript basiert auf der gleichen Syntax und Semantik, die Millionen von JavaScript-Entwicklern heute kennen. Verwenden Sie vorhandenen JavaScript-Code, integrieren Sie gängige JavaScript-Bibliotheken und rufen Sie TypeScript-Code in JavaScript auf.


11
... und TypeScript ist im Wesentlichen Ecmascript 6.
Robert Harvey

11
Äh, das Zitat tut weh. Es zeigt nur, dass Microsoft seit jeher ein Unternehmen mit statischen Sprachen ist, das dynamische Sprachen einfach nicht versteht. "Typen ermöglichen ... Code Refactoring"? "Ja wirklich?" Stellt die PR-Abteilung von Microsoft fest, dass das Code-Refactoring als eine Praxis in Smalltalk (einer dynamischen Sprache) erfunden wurde und bereits zuvor in Forth (einer typenlosen Sprache) existierte? Dass das erste automatisierte Refactoring-Tool Teil einer Smalltalk-IDE war, bevor statische Sprachen überhaupt über IDEs verfügten? Haben moderne Smalltalk-IDEs Refactoring-Tools, die mindestens so leistungsfähig sind wie Java, C # und C ++? Komm schon.
Jörg W Mittag

5
TypeScript ist eine großartige Sprache für sich. Warum müssen Sie versuchen, sie mit solchem ​​Unsinn zu pushen?
Jörg W Mittag

29
@ Jörg Ich weiß nicht genug über Smalltalk, aber jede einzelne IDE für JavaScript oder Python, die ich gesehen habe, ist meilenweit dahinter, was eine gute IDE für Java oder C # kann. Außerdem gibt es einige Dinge, die in einer dynamischen Sprache schlicht unmöglich zu tun sind (einige der beliebtesten Refactorings): Angenommen, Sie haben eine öffentliche Funktion foo(x) { return x.bar;}oder so etwas. Da es keine Typinformationen gibt und die Funktion öffentlich ist (daher können Sie nicht alle Anrufer kennen), können Sie nicht herausfinden, ob die Leiste in baz umbenannt werden soll, wenn Sie eine Klasse umbenennen.
Voo

10
Diese Antwort besagt, dass die Lösung für "dynamische Sprachfehler" darin besteht, überhaupt keine dynamische Sprache zu verwenden.
bgusach

19

Es gibt einige Ansätze, die helfen können:

Unit-Test

Schreiben Sie nach Möglichkeit Komponententests. Sich nur auf manuelle Tests oder das Auffinden von Fehlern in der Natur zu verlassen, ist ein Glücksfall.

Verwenden Sie Frameworks

Verwenden Sie nach Möglichkeit etablierte Frameworks, anstatt Ihre eigenen zu erstellen und die Einführung von Fehlern zu riskieren.

Bevorzugen Sie CSS / Hochsprachen

Wo Sie Funktionalität an CSS oder eine andere Hochsprache abgeben können, in der Sie schreiben.

Refactor

Refactor zur Reduzierung der Codemenge. Weniger Code = weniger Orte, an denen etwas schief gehen kann.

Wiederverwendung

Bestehenden Code weiterverwenden, wo Sie können. Auch wenn der Code nicht exakt übereinstimmt, kann es besser sein, ihn zu kopieren, einzufügen und zu ändern, als ihn neu zu schreiben.

IDEs

Moderne IDEs unterstützen in der Regel mindestens etwas Javascript. Einige Texteditoren sind auch Javascript-fähig.


5
Ihr Rat gilt zwar grundsätzlich für jede Programmiersprache und zielt hauptsächlich darauf ab, logische Fehler zu beheben, anstatt solche, die sich aus dynamischen Sprachen ergeben.
Edmz

1
"Ihr Rat gilt grundsätzlich für jede Programmiersprache" . Sehr richtig - ähnlich wie beim Gang durch Hobbyprojekte bis hin zu Full-Fat-Enterprise-Lösungen, für die eine zunehmende Anzahl von Einschränkungen erforderlich ist - je mehr Javascript geschrieben wird, desto mehr Disziplin ist erforderlich, wenn die Räder nicht funktionieren schnell abziehen. Eric Lippert beschreibt das sehr gut.
Robbie Dee

4
"Bevorzugen Sie CSS / Hochsprachen" - Ich verstehe nicht wirklich, was dieses Bit in Bezug auf JavaScript bedeutet: Wollen Sie Elemente (wie z. B. Animationen?) In Stylesheets anstatt in JS-Code verschieben? In welcher Beziehung steht CSS zu Hochsprachen?
anotherdave

@anotherdave Vieles, was früher als Domäne von Javascript galt, kann jetzt in CSS3 erreicht werden. Einige Funktionen könnten möglicherweise auch in eine höhere Sprache verschoben werden, die strengeren Kontrollen unterliegt.
Robbie Dee

4
@anotherdave Vieles, was die Leute mit JavaScript versuchen, ist irrelevant und unangemessen. Bibliotheken, die Standard-Sprachtools bereitstellen, Frameworks, die Standard-HTML-Elemente mit wenig mehr enthalten, Code, der grundlegende Funktionen wie Anker, MVC-Emulation, Stile, DOM-Neuimplementierung, AJAX-Abstraktion, Rendern trivialer Objekte (Neuimplementierung von SVG) und Polyfilling-Funktionen, die dies nicht tun, repliziert Nutzen für den Benutzer ... Sie sollten die Menge an JS, die Sie schreiben, minimieren. Wenn Sie es ohne JS tun können, tun Sie es ohne JS.
bjb568

2

Ein noch nicht erwähntes Tool ist die einfache, dateilokale oder projektweite Textsuche .

Es klingt einfach, aber wenn Sie einige reguläre Ausdrücke einfügen, können Sie grundlegende bis erweiterte Filterungen durchführen, z. B. nach Wörtern in der Dokumentation oder im Quellcode suchen.

Es war ein effektives Tool für mich (neben statischen Analysatoren) und angesichts Ihrer Projektgröße von 2k LOC, die meiner Meinung nach nicht besonders groß ist, sollte es hoffentlich Wunder wirken.


2
grepgeht ein langer Weg. Wenn Sie nicht zu seltsame dynamische Dinge tun, macht es den Trick. Es fühlt sich jedoch sehr manuell an, wenn Sie an IDEs für statisch typisierte Sprachen gewöhnt sind.
bgusach

1

Derzeit überarbeite ich mehrere tausend Codezeilen in einem großen AngularJS-Projekt. Eine der größten Schwierigkeiten ist es, den genauen Vertrag einer bestimmten Funktion herauszufinden. Manchmal habe ich die API-Dokumentation gelesen, weil Elemente der API-Rohantwort Variablen zugewiesen wurden, die 6 Codeebenen durchliefen, bevor sie geändert und durch 6 weitere Codeebenen zurückgegeben wurden.

Mein erster Rat ist, nach Vertrag zu entwerfen . Nehmen Sie bestimmte Eingaben vor, erzeugen Sie bestimmte Ausgaben, vermeiden Sie Nebenwirkungen und dokumentieren Sie diese Erwartungen mit TypeScript oder mindestens JSDoc.

Mein zweiter Rat ist, so viele Prüfungen wie möglich durchzuführen. Wir folgen dem AirBnB-Standard und verwenden eslint für unsere gesamte Codebasis. Commit Hooks stellen sicher, dass wir uns immer an den Standard halten. Wir haben natürlich eine Reihe von Einheits- und Abnahmetests, und alle Festschreibungen müssen von einem Kollegen überprüft werden.

Der Wechsel von einem Texteditor (Sublime Text) zu einer geeigneten IDE (WebStorm) erleichterte die Arbeit mit Code im Allgemeinen erheblich. WebStorm verwendet JSDoc, um Hinweise zu den erwarteten Parametertypen zu geben und einen Fehler auszulösen, wenn Sie den falschen Typ angeben oder den Rückgabewert falsch verwenden.

In JavaScript können neue Funktionen wie Symbole und Getter / Setter dazu beitragen, ein bestimmtes Qualitätsniveau durch das Hinzufügen von Zusicherungen zur Variablenzuweisung durchzusetzen (z. B. stellen Sie sicher, dass die Ganzzahl innerhalb des Bereichs liegt oder dass das Datenobjekt bestimmte Attribute aufweist).

Leider glaube ich nicht, dass es eine echte Lösung gibt, um dynamische Sprachfehler zu vermeiden, sondern nur eine Reihe von Maßnahmen, mit deren Hilfe die Häufigkeit verringert werden kann.


0

Meine Antwort auf die Frage "Wie nähern Sie sich einem JavaScript-Projekt (oder einer anderen dynamischen Sprache) mit ~ 2000 LOC?"

Ich entwickle PDF-Formularanwendungen. Ich nähere mich meinem JavaScript-Softwareentwicklungsprojekt (unabhängig von der Größe des Quellcodes) mit Petris Netzelementen und Anmerkungen. Die Methode ist nicht an eine bestimmte Programmiersprachentechnologie gebunden. Somit kann es für andere „Programmiersprachen“ verwendet werden.

Ich erstelle ein Diagramm der Anwendungslogik. Um das Diagramm übersichtlich zu halten, füge ich die meisten meiner Anmerkungen einem Formular hinzu, das ich mit dem Diagramm verwende. Die Einträge im Formular enthalten Verweise auf Eigenschaften oder Funktionen. Dann schreibe ich den Quellcode basierend auf den Informationen im Diagramm und den Einträgen im Formular aus. Die Methode ist systematisch, da jeder geschriebene Quellcode direkt aus dem Diagramm und den Einträgen im Formular abgebildet wird. Der Quellcode kann einfach überprüft werden, da ich beim Schreiben des Codes auch die Namens- und Codierungskonventionen befolge.

Ich habe zum Beispiel eine Konvention gewählt, nach der alle Funktionen Prototypen sind. Wenn die Leistung zum Problem wird, kann sie durch Deklarieren der Funktionen im Konstruktor verbessert werden. Für einige Eigenschaften verwende ich Arrays. Auch hier kann die Leistung durch direkte Verweise verbessert werden, wenn sie zu einem Problem wird.

Ich benutze auch eval. Dies kann die Größe des Quellcodes erheblich reduzieren. Aufgrund von Leistungsproblemen verwende ich eval am Anfang oder am Anfang der Initialisierung meiner Anwendung. Ich verwende es nie in der „Laufzeitlogik“ - dies ist eine andere Kodierungskonvention, der ich folge.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.