
Als mein Freund und ich im schulpflichtigen Alter waren und Softwareentwickler werden wollten, träumten wir davon, gemeinsam ein paar coole Sachen zu entwerfen - wie ein Spiel oder eine äußerst nützliche App.
Ich habe mich entschieden, C ++ und C # zu lernen, er hat sich für JavaScript entschieden. Wir beendeten die Schule, absolvierten unsere Universitäten, dienten in der Armee und begannen unsere Arbeit. Wir hatten eine ziemlich arbeitsreiche Zeit in der industriellen Softwareentwicklung mit vielen verschiedenen Jobs und Positionen, und nachdem sich alles auf uns ausgewirkt hatte, erinnerten wir uns daran, wo alles begonnen hatte.
Nachdem wir uns endlich als reife Entwickler zusammengetan hatten, beschlossen wir, an unserem eigenen Projekt zu arbeiten - einem 2D-Videospiel. Da die Domain meines Freundes Front-End war und ich ein Full-Stack-Entwickler war, war unsere unmittelbare Wahl der Entwicklungsplattform ein Internetbrowser. Da ich es nur gewohnt war, beim Entwerfen des Frontends mit TypeScript zu arbeiten, dachten wir, ok, kein Problem, schließlich ist TS nur JavaScript im Maßstab. Lassen Sie es uns verwenden und die Dinge werden reibungslos verlaufen. Wenn ich nur wüsste, wie falsch ich war! Als wir anfingen, das Projekt zu diskutieren, stießen wir auf eine große Kluft von Missverständnissen zwischen uns.
Hier war meine Vision des Spiels. Ich dachte, ok, wir haben solche Typen wie Spiel, Werkzeug, Gegenstand, Karte, Ort. Ich habe ein grundlegendes Verständnis dafür, wie sie zusammenarbeiten, also beschreibe ich sie, kompiliere das Projekt - und es funktioniert. Immerhin hat der Compiler meinen Code überprüft und ich habe es richtig gemacht. Als nächstes beginne ich mit dem Schreiben von Code, der diese Typen verwendet. Sie machen mein Leben viel einfacher. Meine IDE gibt mir Tooltips und prüft auf Fehler. Wenn ein Projekt kompiliert werden kann, funktioniert es wahrscheinlich. Ich habe einige Anstrengungen zur Typbeschreibung unternommen und es wurden Ergebnisse erzielt. Das ist mein Ansatz auf den Punkt gebracht.
Mein Freund hatte die gegenteilige Idee - sofort mit dem Schreiben von Code zu beginnen, ohne sich Zeit zu nehmen, um die Typen zu beschreiben. Er war nicht bereit, das Problem als eine Familie von Typen zu definieren. Er war nicht daran interessiert, es als Grundlage zu verwenden, da er das Problem nicht als eine Reihe von Klassen, Typen, Aufzeichnungen jeglicher Art ansah. Ich fand es unvorstellbar. Wir hatten beide einen Punkt, es ist nur so, dass sich unsere Punkte gegenseitig ausschlossen.
Im Ernst, wir unterhielten uns stundenlang, aber jeder sagte sein eigenes Ding, als würden wir verschiedene Sprachen sprechen. Wohlgemerkt, ich konnte es nicht dafür verantwortlich machen, dass wir auf unsere alte Art feststeckten. Noch vor einem Jahr bin ich schmerzlos von der Welt der objektorientierten Programmierung in die Welt der funktionalen Programmierung und zurück gewandert. Außerdem habe ich eine ganze Weile damit verbracht, JS zu lernen, und er - eine Reihe statisch typisierter Sprachen zu lernen.
Für jeden Entwickler definiert die Technologie, die er für seinen ersten richtigen Job verwendet hat, sie jedoch oft insofern, als zwei erfahrenen Erwachsenen einfach die Geduld fehlt, einander zuzuhören. In diesen Jahren des Software-Engineerings waren unsere Visionen so unterschiedlich gestaltet, dass unsere Ansätze zur Problemlösung einfach nicht gut zusammen passten.
Am Ende haben wir die Idee, als Team zu arbeiten, aufgegeben. Ihre erste Antwort könnte sein, dass das Problem in unserer Persönlichkeit lag. Sie haben vielleicht Recht, aber ich habe auch gesehen, dass dies anderen in der Branche passiert ist.
Der grundlegende, unvereinbare Unterschied zwischen statischer und dynamischer Typisierung
Mein Code bietet die Lösung für das Problem, wie man damit arbeitet, während der Code erfahrener Befürworter der dynamischen Typisierung das Problem löst, wie es funktioniert. Beide Denkweisen sind legitim und werden von vorhandenen Toolsets unterstützt, aber nur eine kann zu jedem Zeitpunkt die höchste Priorität haben.
Die statische Typisierung eignet sich für Großprojekte, an denen Hunderte von Entwicklern arbeiten, die jahrelang daran arbeiten, während die dynamische Typisierung für kleinere Teams und Projekte geeignet ist, für die häufig nur Schreibcode erforderlich ist. Durch dynamisches Tippen können Sie zu Beginn der Entwicklung Zeit und Mühe sparen, während Sie durch statisches Tippen am Ende der Entwicklung einen Schub erhalten.
Die Idee, Typen an die erste Stelle zu setzen, hat mein Denken als Entwickler ernsthaft beeinflusst. Nachdem ich mich zu Beginn meiner Karriere für C # entschieden habe, habe ich die statische Eingabe in meine Denkweise fest programmiert und zahle jetzt den Preis für diese Inflexibilität. Sobald ich eine Aufgabe sehe, versuche ich, mir ihre Lösung als eine Reihe von Typen und Regeln ihrer Beziehung vorzustellen. Wenn ich ein Modul entwickle, besteht mein erster Schritt darin, die Typen zu definieren, die es betreibt und für die Interaktion mit seiner Umgebung verwendet. Ich erinnere mich nur nicht, wie ich vorher Probleme gelöst habe.
Beim gesamten Programmierenlernen in Java geht es darum, das Entwerfen und Verwenden von Typen zu lernen. .NET CLR - die C # -Runtime - basiert auf Typen und für Typen. Die statische Typisierung steht im Mittelpunkt des objektorientierten Programmierparadigmas (Hallo, JS-Klassen, ich habe beschlossen, Ihnen eine Pause zu gönnen). Die kanonischen Implementierungen der meisten OOP-Muster sind mit dem Schlüsselwort Interface gesättigt, was in einer dynamisch typisierten Sprache überhaupt keinen Sinn ergibt.
Die Entwurfsmuster selbst sind sprachübergreifende Konzepte, aber kann mir jemand sagen, warum um alles in der Welt ich das Zustandsmuster in einer dynamisch typisierten Sprache benötigen würde? Was ist mit Builder? Diese Muster haben nichts mit Entwicklung zu tun, sie handeln hauptsächlich von Typen. Typen und OOP sind eng miteinander verbunden.
Sie können Ihre Geschäftslogik nicht auf Typen aufbauen und wissen dennoch nichts über sie, wenn Sie mit dem Schreiben von Code beginnen. Aus diesem Grund haben wir Front-End-Entwickler, die ihren Code mit einer unglaublichen Anzahl von Komponententests ausstatten, die die Codebasis speziell auf Typfehler überprüfen.
Wir alle wissen, dass Schutz basierend auf Codeabdeckung eine Illusion ist. Tests werden manuell geschrieben und sind per Definition weniger zuverlässig als das in der Sprache verfügbare integrierte System zur Typüberprüfung.
Das bedeutet nicht, dass dynamisch getippte Sprachen keinen Sinn ergeben (obwohl ich gestehe, dass ich glaube, dass dies nicht der Fall ist). Dies bedeutet, dass Sie bei der Verwendung von OOP als dominierendem Paradigma zurücktreten müssen. All diese Einheit von Daten und datengesteuerten Operationen ist für Stipendiaten mit statischer Typisierung.
Die Entwickler, denen ich begegnet bin, glauben nicht, dass statische Typisierung die Art der Codierung in irgendeiner Weise beeinflusst. Sie schreiben ihren Code einfach so, als ob sie eine dynamische Sprache verwenden würden, nur fügen sie eine Typprüfung hinzu. Ich glaube, das ist von Natur aus falsch. Besonders deutlich wird dies beim modernen Frontend.
Ich weiß, ich weiß, es gibt ein Tabu, Front-End-Entwickler zu kritisieren. Mein Freund und ich haben einmal einen KI-Bot zusammengestellt, der Twitter-Nutzer trollte, und wir haben Brendan Eich dazu gebracht, sich darauf einzulassen. Im Ernst, der JavaScript-Ersteller hatte ein Hin und Her mit unserem neuronalen Netzwerk in Kommentaren.
Aus irgendeinem Grund sind diese Jungs einfach nicht bereit, in einer Welt zu leben, in der ihre Vision spürbare Mängel aufweist. Deshalb kritisiere ich nur diejenigen von ihnen, die mein definitiv typisiertes Projekt manipulieren, um es auf ihre entspannte Art und Weise zu überarbeiten.
Wir würden weiter in unseren winzigen Welten wohnen, aber TypeScript brachte uns zusammen
Nehmen Sie zum Beispiel: Aufgrund der Typbeschränkungen kann mein Code nicht falsch verwendet werden. Wenn ich an einem Projekt arbeite, verlasse ich mich auch darauf, dass andere Typen verwenden. Dann funktioniert mein Code genauso wie geplant. Daher gehe ich nicht auf alle Fälle ein, in denen dieser Code falsch verwendet werden kann (weil die Eingabe dies unmöglich macht). Aber dann tritt ein JS-Entwickler meinem Projekt bei, nimmt meinen Typ, schließt ihn in Any ein und verwendet ihn falsch, was zu schwer zu replizierenden Fehlern führt.
JavaScript-Entwickler sind zuversichtlich, dass TypeScript das gleiche alte JS ist, jedoch mit der Option, statische Typprüfungen hinzuzufügen, falls sie diese benötigen. Das ist falsch TypeScript ist hundertmal leistungsfähiger, interessiert sich jedoch nur für einen Bruchteil seines Potenzials.
Ihr Killerargument ist, dass TypeScript nur eine Obermenge von JS ist. In der Praxis kann man die Tatsache nicht ignorieren, dass TypeScript eine unabhängige Sprache ist, selbst wenn man ein verdammter König des Frontends ist. Weil es einen anderen Ansatz erfordert - den der statischen, nicht der dynamischen Überprüfung.
Der Hauptvorteil der statischen Typisierung besteht darin, dass Sie Garantien erhalten. Wenn Sie es in einem Modul verwenden und es nicht in einem anderen Modul verwenden, verschwenden Sie nur Ihre Zeit und Energie damit, diese Typen zu beschreiben und zu entwerfen, ohne irgendwelche Garantien zu erhalten.
Viele denken, dass TypeScript ein Kompromiss zwischen Typsystemen zwischen JS und Java ist. Nun, es ist kein Kompromiss, es hat ein eigenes spezielles Typsystem.
Am schlimmsten ist jedoch, dass heute jede zweite Front-End-Position Kenntnisse in TypeScript erfordert. Dies spornt JS-Entwickler an, einen Blick auf die Funktionen von TypeScript zu werfen und sofort Code darin zu schreiben, was zu einer Zunahme schädlicher Praktiken führt. Situationen treten auf, wenn sie nicht wirklich eine statische Typprüfung benötigen, diese aber ihnen auferlegt wurde, sodass sie damit herumspielen. Wir müssen endlich anerkennen, dass Ansätze zur Programmierung mit statischer und dynamischer Typisierung in Konflikt miteinander stehen und nicht verwechselt werden können.
Ich sehe JavaScript als ein großartiges Werkzeug zum Schreiben von Quick-Hack-Code, der Lösungen bietet, ohne unnötige Abstraktionen auszuarbeiten. Das empörendste Beispiel hier ist das Muster der Eisfabrik. Sie können Ihre Instanzen damit füttern, und sie werden zur Unveränderlichkeit zur Laufzeit verpackt. Wenn ich mein Objekt durch eine solche Factory verarbeite, gibt es sein Äquivalent zurück. Wenn ich jedoch versuche, eine seiner Eigenschaften zu ändern, wird eine Ausnahme ausgelöst. WAT?!?
Das Muster entstand, weil Front-End-Entwickler irgendwo von cooler Unveränderlichkeit hörten, und sie beschlossen, diese Scheiße in ihre Sprache zu ziehen, die sie wie ein Loch im Kopf braucht. In TypeScript kann ich eine ähnliche Factory entwerfen, jedoch mit einer Einschränkung der Kompilierungszeit für Mutationen und ohne Ausnahmen.
Andererseits brauche ich das kaum, weil es die reine funktionale Programmierung gibt. Nehmen wir zum Beispiel F #, Haskell, OCaml, Clojure, ReasonML - sie haben ein sofort einsatzbereites Verbot der Veränderlichkeit. Aber irgendetwas sagt mir, dass ein Front-End-Entwickler, wenn er eine funktionale Sprache in die Hände bekommt, bereit ist, sie zu aktualisieren, um ihr Verhalten dem von JavaScript zu ähneln.
Das liegt daran, dass die Wahl Ihrer Schreibreligion eine Einbahnstraße ist. All-in-Between-Lösungen bieten nur eine Illusion von Kompromissen. Sie verlassen sich entweder auf Typen oder nicht. Ich weiß nicht, ob mein Leben anders wäre, wenn ich parallel C # und JavaScript gelernt hätte. Heute identifiziere ich mich so hoffnungslos mit meiner Denkweise, dass ich keine Vorteile des dynamischen Tippens sehe (und sie nicht sehen möchte). Sie existieren nur außerhalb meines Sichtbereichs, also kann ich nur meine Augen vor ihnen schließen, so wie ich es mit allen Phänomenen tue, die ich in dieser Welt ertragen muss. Ich weiß, dass ich im Unrecht bin, aber ich muss hier und jetzt arbeiten, und ich habe nicht das Budget, um weiter auf dem Zaun zu sitzen.
Ich möchte also nicht nach Kompromissen suchen, sondern es klarstellen. Wenn Sie gerade erst Ihre ersten Entwicklungsschritte machen, beginnen Sie mit der statischen Eingabe!