Ab und zu gibt es eine Debatte über den Wert des typisierten JavaScript. "Schreiben Sie mehr Tests!" Einige Gegner riefen. "Ersetzen Sie Unit -Tests durch Typen!" andere riefen. Beide haben in gewisser Weise Recht und in anderen falsch. Der Raum von Twitter reicht nicht aus, um die Feinheiten widerzuspiegeln. In diesem Artikel können wir jedoch versuchen, ein vernünftiges Argument darüber auszuarbeiten, wie und wie die beiden koexistieren sollten.
Richtigkeit: Was wir wirklich wollen
Beginnen Sie am besten mit den Ergebnissen. Was wir von all diesen Meta-Engineering wirklich wollen, ist die Korrektheit . Ich beziehe mich nicht auf eine strenge theoretische Informatik -Definition, sondern eine allgemeinere Einhaltung des Programmverhaltens und deren Normen: In unserer Gedanken steckt eine Idee darüber, wie Programme funktionieren, und der Programmierungsprozess organisiert Bits und Bytes, was diese Idee Wirklichkeit werden lässt. Da wir nicht immer genau wissen, was wir wollen, und wir sicher sein möchten, dass unser Programm bei Änderungen nicht brechen, schreiben wir Typen und Tests über vorhandenen Originalcode, um die Dinge überhaupt zu ermöglichen.
Wenn wir also akzeptieren, dass Korrektheit das ist, was wir wollen, und diese Typen und Tests nur automatisierte Möglichkeiten sind, dies zu erreichen, ist es besser, ein intuitives Modell zu haben, um zu zeigen, wie Typen und Tests uns helfen, die Korrektheit zu erreichen und so zu verstehen, wo sie sich überschneiden und wo sie sich ergänzen.
Visualisierungsmodell der Programmkorrektheit
Wenn wir uns vorstellen, dass der gesamte unendliche Turing-Vervollständigungsraum aller Vorgänge, die ein Programm ausführen kann ( einschließlich Fehlern ), als riesige Grauzone durchführen kann, ist das, was das Programm ausführen soll, unsere Spezifikation eine sehr, sehr kleine Untergruppe dieses möglichen Raums (der grüne Rhombus in der folgenden Abbildung, übertrieben, um etwas anzuzeigen):
Unsere Aufgabe bei der Programmierung ist es, unsere Programme so weit wie möglich mit den Spezifikationen auszurichten (wir wissen natürlich, dass wir unvollkommen sind. Unsere Spezifikationen ändern sich ständig, z.
Beachten Sie erneut, dass für die Zwecke unserer Diskussion hier auch die Grenzen des Verfahrens sowohl geplante als auch ungeplante Fehler enthalten sind . Unsere Bedeutung der „Korrektheit“ umfasst geplante Fehler, aber keine ungeplanten Fehler.
Testen und Korrektheit
Wir schreiben Tests, um sicherzustellen, dass unser Programm unsere Erwartungen entspricht. Es gibt jedoch viele Optionen für das Testen:
Der ideale Test sind die orangefarbenen Punkte in der Abbildung - sie testen genau, ob unser Programm die Spezifikation überlappt. In dieser Visualisierung unterscheiden wir nicht wirklich zwischen Testtypen, aber Sie können sich Unit-Tests als sehr kleine Punkte vorstellen, und Integrations-/End-to-End-Tests sind die großen Punkte. In jedem Fall sind sie Punkte, da kein Test jeden Weg im Programm vollständig beschreiben kann. (Tatsächlich können Sie eine 100% ige Codeabdeckung haben, können aber immer noch nicht jeden Pfad testen, da es eine Kombinationsexplosion gibt!)
Der blaue Punkt im Bild ist ein schlechter Test. Natürlich wird getestet, ob unser Programm funktioniert, aber es ist es nicht wirklich an die zugrunde liegende Spezifikation (letztendlich wollen wir wirklich aus dem Programm). Dieser Test bricht, wenn wir das Programm so festlegen, dass sie enger mit der Spezifikation übereinstimmen, wodurch uns ein falsch positives Positiv ist.
Der lila Punkt ist ein wertvoller Test, da er getestet wird, wie wir glauben, dass das Programm funktionieren sollte, und Bereiche bestimmt, in denen das Programm derzeit nicht funktioniert. Die Führung von lila Tests und Fixierung der Programmimplementierung entsprechend wird auch als testgetriebene Entwicklung bezeichnet.
Der rote Test auf dem Bild ist ein seltener Test. Es ist kein normaler (orangefarbener) Test, der den "glücklichen Pfad" (einschließlich des falschen Zustands des Plans) testet, sondern ein Test, der den " unglücklichen Pfad" erwartet und bestätigt, fehlgeschlagen ist. Wenn dieser Test "bestehen", wo es "scheitern" sollte, ist es ein großes Frühwarnzeichen, dass etwas nicht stimmt - aber es ist im Grunde unmöglich, genügend Tests zu schreiben, um die enormen möglichen unglücklichen Wege zu decken, die außerhalb des grünlichen Bereichs existieren. Es ist selten zu finden, dass das Testen von Dingen, die nicht funktionieren sollten, wertvoll ist, damit sie es nicht tun. Aber wenn die Dinge schief gehen, kann es immer noch ein hilfreiches Frühwarnzeichen sein.
Typ und Korrektheit
Wenn der Test ein einzelner Punkt im Wahrscheinlichkeitsraum ist, an dem das Programm einen Vorgang ausführen kann, repräsentiert der Typ die Kategorie, die den gesamten Teil vom Gesamtwahrscheinlichkeitsraum unterteilt. Wir können sie als Rechtecke visualisieren:
Wir wählen ein Rechteck, um die Diamanten zu vergleichen, die das Programm darstellen, da kein Typensystem selbst Typen verwenden kann, um unser Programmverhalten vollständig zu beschreiben. (Um ein einfaches Beispiel zu geben, ist eine ID, die immer eine positive Ganzzahl sein sollte, ein numerischer Typ, aber numerische Typen akzeptieren auch Brüche und negative Zahlen. Abgesehen von der sehr einfachen Vereinigung numerischer Literale ist es unmöglich, numerische Typen auf einen bestimmten Bereich zu beschränken.)
Typen dienen als Einschränkung, wo das Programm ausgeführt wird, wenn Sie Ihren Code schreiben. Wenn unser Programm beginnt, die angegebene Grenze des Programmtyps zu überschreiten, lehnt unser Typ -Checker (z. B. TypeScript oder Flow) einfach ab, das Programm zusammenzustellen. Dies ist gut, weil es in einer dynamischen Sprache wie JavaScript einfach ein Crash -Programm erstellen kann, das sicherlich nicht das ist, was Sie erstellen möchten. Die einfachste Wertschöpfung ist die automatische Nullwert -Wertprüfung. Wenn FOO keine Methode namens Bar hat, ist es keine Funktionsausnahme, Foo.bar () zu rufen. Wenn FOO vollständig eingegeben ist, können Sie dieses Problem zum Zeitpunkt des Schreibens nach dem Typ Checker aufnehmen und auf die problematischen Codezeilen (und die dazugehörigen Vorteile von Autoperete) hinweisen. Dies ist etwas, das das Test einfach nicht kann.
Möglicherweise möchten wir strenge Typen für unsere Programme schreiben, als ob wir versuchen würden, so klein wie möglich zu schreiben, die unseren Spezifikationen immer noch entsprechen. Dies hat jedoch eine Lernkurve, da die Nutzung des Typsystems das Lernen von vollständig neuer Syntax und Operatoren sowie die Syntax der generischen Typlogik beinhaltet, die erforderlich ist, um den vollständigen dynamischen Bereich von JavaScript zu simulieren. Handbücher und Cheat -Blätter helfen dabei, die Lernkurve zu senken, und hier sind weitere Investitionen erforderlich.
Glücklicherweise muss uns diese Adoptions-/Lernkurve nicht aufhalten. Da die Typ -Überprüfung ein optionaler Prozess für den Fluss ist und die konfigurierbare Stringenz von TypeScript (die Möglichkeit, die fragliche Codezeile selektiv zu ignorieren), können wir aus dem Geltungsbereich der Type Sicherheit wählen. Wir können dies sogar modellieren:
Größere Rechtecke wie das große rote Rechteck im obigen Bild zeigen eine sehr lose Übernahme des Typsystems der Codebasis - zum Beispiel, die implizite und vollständig auf Typinferenz zulassen, um unser Programm einfach an die schlimmste Codierung zu beschränken.
Mittelgroße Stringenz (wie mittelgroße grüne Rechtecke) können auf mehr treue Typifizierung hinweisen, aber es gibt viele Schwachstellen, z. Selbst wenn solche leichten Schreibarbeiten durchgeführt werden, wird die mögliche Oberfläche effektiver Programme, die unseren Spezifikationen nicht übereinstimmen, stark reduziert.
Die maximale Strenge wie lila Rechtecke macht die Dinge so eng, dass es manchmal nicht verfassende Teile Ihres Programms findet (diese sind normalerweise ungeplante Fehler im Programmverhalten). Die Suche nach Fehlern in vorhandenen Programmen wie diesen ist ein sehr häufiger Fall in Teams, die eine normale JavaScript -Codebasis konvertieren. Wenn Sie jedoch die maximale Sicherheitsprüfungssicherheit von unserem Typ -Checker erhalten, können Sie generische Typen und spezielle Bediener für die Verfeinerung und Eingrenzung möglicher Typräume für jede Variable und Funktion erfordern.
Beachten Sie, dass wir keine Programme schreiben müssen, bevor wir Typen schreiben. Schließlich möchten wir nur, dass unsere Typen unsere Spezifikationen genau simulieren, damit wir zuerst unsere Typen schreiben und später die Implementierung füllen können. Theoretisch wäre dies typorientierte Entwicklung ; In der Praxis entwickeln sich nur wenige Menschen auf diese Weise, weil Typen mit unserem tatsächlichen Programmcode eindringen und miteinander verbunden sind.
Setzen Sie sie zusammen
Was wir letztendlich erstellen möchten, ist eine intuitive Visualisierung, die zeigt, wie sich die Typen und Tests gegenseitig ergänzen, um die Richtigkeit des Programms zu gewährleisten.
Unsere Tests behaupten, dass unser Programm speziell wie erwartet im ausgewählten kritischen Pfad durchgeführt wird (obwohl es, wie oben erwähnt, bestimmte andere Testvarianten gibt, die überwiegende Mehrheit der Tests tun dies). In den visuellen Sprachen, die wir entwickelt haben, "reparieren" sie die dunkelgrüne Rhombus des Programms auf die kanonisch hellgrüne Rhombus. Jede Bewegung des Programms wird diese Tests zerstören, die dazu führen, dass sie alarmiert werden. Es ist toll! Das Testen hat auch unbegrenzte Flexibilität und Konfigurierbarkeit für die am meisten angepassten Anwendungsfälle.
Unser Typ behauptet, dass unser Programm nicht außer Kontrolle geraten wird, indem er mögliche Fehlermodi über die von uns gezogenen Grenzen hinaus verbietet, in der Hoffnung, unsere Spezifikation so genau wie möglich zu umgeben. In unserer visuellen Sprache "enthalten" sie die mögliche Drift von Programmen, die von der Norm abweichen (weil wir immer Mängel haben und jeder Fehler, den wir machen, unseren Programmen zusätzliche Fehler verleiht). Typen sind auch stumpf, aber leistungsstarke Tools (aufgrund von Typ -Inferenz- und Editor -Tools), die von einer starken Community profitieren, die Typen bietet, die Sie nicht von Grund auf neu schreiben müssen.
Zusamenfassend:
- Das Testen ist am besten sicher, dass der glückliche Pfad funktioniert.
- Die Typen können am besten verhindern, dass unglückliche Wege vorhanden ist.
Verwenden Sie sie zusammen nach ihren Stärken für die besten Ergebnisse!
Wenn Sie mehr darüber erfahren möchten, wie sich Typen und Tests überschreiten, hat Gary Bernhardts große Rede über Grenzen und Kent C. Dodds 'Test Trophy einen signifikanten Einfluss auf mein Denken über diesen Beitrag.
Das obige ist der detaillierte Inhalt vonTypen oder Tests: Warum nicht beides?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

CSS Grid ist ein leistungsstarkes Tool zum Erstellen komplexer, reaktionsschneller Weblayouts. Es vereinfacht das Design, verbessert die Zugänglichkeit und bietet mehr Kontrolle als ältere Methoden.

In Artikel wird CSS Flexbox erörtert, eine Layoutmethode zur effizienten Ausrichtung und Verteilung des Raums in reaktionsschnellen Designs. Es erklärt die Verwendung von Flexbox, vergleicht es mit CSS -Gitter und Details Browser -Unterstützung.

In dem Artikel werden Techniken zum Erstellen von reaktionsschnellen Websites mithilfe von CSS erörtert, einschließlich Ansichtsfenster -Meta -Tags, flexiblen Gitter, Flüssigkeitsmedien, Medienabfragen und relativen Einheiten. Es deckt auch mit CSS -Raster und Flexbox zusammen und empfiehlt CSS -Framework

In dem Artikel wird die CSS-Box-Größeneigenschaft erörtert, in der die Berechnung der Elementabmessungen steuert. Es erklärt Werte wie Inhaltsbox, Border-Box und Padding-Box sowie deren Auswirkungen auf das Layout-Design und die Form von Formularausrichtung.

In Artikel wird das Erstellen von Animationen mithilfe von CSS, Schlüsseleigenschaften und Kombination mit JavaScript erläutert. Hauptproblem ist die Browserkompatibilität.

In Artikel werden CSS für 3D -Transformationen, wichtige Eigenschaften, Browserkompatibilität und Leistungsüberlegungen für Webprojekte erläutert. (Charakterzahl: 159)

In dem Artikel werden CSS -Gradienten (linear, radial, wiederholt) beschrieben, um die Website -Visuals, das Hinzufügen von Tiefe, Fokus und moderne Ästhetik zu verbessern.

In Artikel werden Pseudoelemente in CSS, deren Verwendung bei der Verbesserung des HTML-Stylings und der Unterschiede zu Pseudoklassen erläutert. Bietet praktische Beispiele.


Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

SecLists
SecLists ist der ultimative Begleiter für Sicherheitstester. Dabei handelt es sich um eine Sammlung verschiedener Arten von Listen, die häufig bei Sicherheitsbewertungen verwendet werden, an einem Ort. SecLists trägt dazu bei, Sicherheitstests effizienter und produktiver zu gestalten, indem es bequem alle Listen bereitstellt, die ein Sicherheitstester benötigen könnte. Zu den Listentypen gehören Benutzernamen, Passwörter, URLs, Fuzzing-Payloads, Muster für vertrauliche Daten, Web-Shells und mehr. Der Tester kann dieses Repository einfach auf einen neuen Testcomputer übertragen und hat dann Zugriff auf alle Arten von Listen, die er benötigt.

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Dreamweaver Mac
Visuelle Webentwicklungstools
