Ich habe oft die Behauptung gehört, dass dynamisch getippte Sprachen produktiver sind als statisch getippte Sprachen. Was sind die Gründe für diesen Anspruch? Arbeiten Sie nicht einfach mit modernen Konzepten wie Konvention statt Konfiguration, der Verwendung von funktionaler Programmierung, fortschrittlichen Programmiermodellen und der Verwendung konsistenter Abstraktionen? Zugegeben, es gibt weniger Unordnung, da die (beispielsweise in Java) häufig redundanten Typdeklarationen nicht benötigt werden. Sie können jedoch auch die meisten Typdeklarationen in statisch typisierten Sprachen, die Typinferenz verwenden, weglassen, ohne die anderen Vorteile der statischen Typisierung zu verlieren. Und all dies ist auch für moderne statisch typisierte Sprachen wie Scala verfügbar.
Also: Was kann man für die Produktivität mit dynamischer Eingabe sagen, was wirklich ein Vorteil des Typmodells selbst ist?
Klarstellung: Ich interessiere mich mehr für große / mittlere Projekte als für schnelle Hacks. :-)
quelle
Antworten:
Ich denke eigentlich, dass es ein ziemlich enger Anruf ist. Sowohl die dynamische als auch die statische Eingabe haben ihre Vorteile.
Gründe für eine produktivere dynamische Eingabe:
Gründe für eine produktivere statische Typisierung:
Im Durchschnitt bin ich (nach vielen Jahren Erfahrung auf beiden Seiten des Zauns) zu dem Schluss gekommen, dass dynamisches Tippen kurzfristig produktiver sein kann, aber letztendlich schwierig zu warten ist, wenn Sie nicht über sehr gute Testsuiten und Testdisziplinen verfügen.
Auf der anderen Seite bevorzuge ich statisch typisierte Ansätze insgesamt, weil ich denke, dass die Vorteile der Korrektheit und der Toolunterstützung langfristig zu einer besseren Produktivität führen.
quelle
Mit dynamischen Sprachen können Sie beschissenen Code schneller schreiben als mit einer getippten Sprache.
Sobald Sie schnell einen riesigen Stapel dynamischer Elemente erstellt haben, können Sie problemlos zu einem anderen Projekt wechseln, ohne sich um die langfristige Wartung kümmern zu müssen.
Das ist Produktivitätsgewinn :)
Ich mache Witze, aber nachdem ich in ein Projekt mit "dynamischer Sprache" involviert war, hatte ich Angst vor der Menge unnötiger Tests, Dokumentationen und Konventionen, mit denen Sie sich auseinandersetzen müssen, wenn Sie ein funktionierendes Produkt wünschen.
Und mit der Freude an vielen Laufzeitfehlern, die beim Kompilieren hätten auftreten können.
Oh, ich habe auch vergessen, mich über all die Hacks und Voodoos zu lustig zu machen, mit denen Sie Meta-Programmierung in Ihren Code einführen können!
Der Produktivitätsgewinn könnte also ein Mythos für ein mittelgroßes / großes Projekt während seiner gesamten Lebensdauer sein.
quelle
Auch für dieses Problem gibt es eine theoretische Sichtweise: Ein statisches Typensystem ist im Wesentlichen ein spezialisierter Theorembeweiser, der das Programm nur dann akzeptiert, wenn es die Typkorrektheit beweisen kann. Alle statischen Typsysteme lehnen einige gültige Programme ab, da kein entscheidbares statisches Typsystem leistungsfähig genug ist, um alle möglichen typkorrekten Programme zu beweisen.
Man könnte argumentieren, dass diese Programme, die nicht durch einen statischen Typechecker nachweisbar sind, Hacks und / oder einen schlechten Stil darstellen, aber wenn Sie bereits ein gültiges Programm haben und der Typechecker es nicht akzeptiert, beeinträchtigt dies Ihre Produktivität auf kurze Sicht.
Einige Fälle, in denen Sie möglicherweise bemerken, dass die Typprüfung im Weg steht, sind generische Container und Co- / Contravarianz in Argumenten und Rückgabetypen.
quelle
Ein Vorteil, den ich bei den meisten dynamischen Sprachen festgestellt habe, ist, dass sie das Schreiben von generischem Code erleichtern. Es ist viel einfacher, auf einer höheren Abstraktionsebene zu schreiben, wenn Sie nicht mit dem Typensystem kämpfen müssen, um dies zu tun.
Sie müssen nicht so viel darüber nachdenken - das Schreiben von Code, der mit einem Objekt in Java etwas nicht Triviales bewirkt, ist schwierig und erfordert wahrscheinlich eine Reflexion, die im Grunde genommen dynamisch getippt wird. Mit so etwas wie JavaScript ist es selbstverständlich, eine Funktion zu schreiben, die für alle Objekte etwas Interessantes bewirkt. Ein perfektes Beispiel wäre eine Funktion, die ich kürzlich geschrieben habe und die ein Objekt nimmt und alle Methoden durch Methoden ersetzt, die dasselbe tun, aber auch ein Ereignis auslösen. Ich habe keine Ahnung, wie ich so etwas in Java angehen soll. Ich bin mir jedoch nicht sicher, wie viel davon auf die Typsysteme zurückzuführen ist und wie viel auf andere Sprachunterschiede.
Ich habe jedoch vor kurzem begonnen, Haskell zu verwenden. Mit Haskell kann ich abstrakten, generischen Code so einfach schreiben wie jede dynamisch getippte Sprache, die ich verwendet habe. Mein obiges Java / JavaScript-Beispiel macht in Haskell keinen Sinn, da es keine Objekte, Methoden, Ereignisse oder sogar viel Mutation enthält, aber andere Arten von generischem Code sind wirklich einfach zu schreiben.
Tatsächlich kann Haskell einen generischen Code schreiben, den dynamisch getippte Sprachen nicht können. Ein perfektes Beispiel ist die
read
Funktion, die im Grunde das Gegenteil von isttoString
. Sie können einenInt
oder einenDouble
oder einen beliebigen Typ abrufen (sofern er zu einer bestimmten Typklasse gehört). Sie können sogar polymorphe haben Konstanten , somaxBound
kann das Maximum seinInt
,Double
,Char
... etc., Die alle je nachdem , welche Art es angenommen hat , sein.Meine Theorie ist nun, dass der Produktivitätsgewinn durch die Verwendung einer dynamischen Sprache immer im Vergleich zu Sprachen wie Java mit weniger fähigen, ausführlicheren und weniger flexiblen Typsystemen ist.
Jedoch hat selbst das Typensystem von Haskell einige lästige Probleme, die Sie in einer dynamisch getippten Sprache nicht hätten. Das größte Problem, über das ich mich geärgert habe, ist der Umgang mit Zahlen. Sie müssen beispielsweise mit dem Typensystem herumspielen, um
length
(von einer Liste) als Double zu verwenden, was Sie ohne ein Typensystem problemlos hätten. Eine andere ärgerliche Sache, die ich getroffen habe, ist die Arbeit mitWord8
(einem nicht signierten Int-Typ) und Funktionen, die es erwartenInt
.Das Fehlen eines Typensystems erleichtert es letztendlich, allgemeinen Code zu schreiben, ohne zu viel darüber nachzudenken, und vermeidet außerdem lästige Fallstricke von Typensystemen. Sie müssen das Typensystem nie in einer dynamischen Sprache bekämpfen, können sich aber auch nicht darauf verlassen.
quelle
Int
Rückgabe durch eine Liste trivial. Beispiel:,1.0 + fromIntegral (length myList)
dh nur verwendenfromIntegral
.F: Ich habe oft die Behauptung gehört, dass dynamisch getippte Sprachen produktiver sind als statisch getippte Sprachen. Was sind die Gründe für diesen Anspruch? "
Das hat historische Gründe. In den letzten Jahrzehnten waren dynamische Sprachen unbestreitbar weitaus produktiver als statische Sprachen (wenn auch deutlich langsamer). Perl ist deutlich produktiver als C, wenn Sie beide kennen und die jeweilige Aufgabe dies zulässt. Im Laufe der Zeit haben sich die Sprachen jedoch stark voneinander geliehen, und neuere Sprachen verringern die Kluft (sowohl in Bezug auf Produktivität als auch in Bezug auf Leistung).
Hier sind einige Punkte zu beachten:
Müllabfuhr : Müllabfuhr ist ein enormer Produktivitätsschub. Ich glaube, Java war die erste statische Standardsprache mit GC. Davor bedeutete statisch im Wesentlichen manuelle Speicherverwaltung. (Hinweis: Hier und im Folgenden werde ich nur die Hauptsprachen betrachten. Es gibt viele experimentelle und Nischensprachen, die Gegenbeispiele zu jedem Punkt liefern, den ich mache.)
Speichersicherheit : Dies ist eine Produktivitätsverbesserung, bei der Sie sich keine Sorgen machen müssen, wenn Sie sich in den Fuß schießen. Vor "verwalteten" statischen Sprachen wie Java bedeutete statisch normalerweise direkten Speicherzugriff. Das Debuggen ist auch ein Teil der Produktivität, und ein unsicherer Speicherzugriff kann zu wirklich undurchsichtigen Fehlern führen.
Umständliche Systeme. Vor der Einführung parametrisierter Typen (wie Vorlagen oder Generika) in statischen Sprachen waren die Einschränkungen der Systeme für statische Typen häufig eine Belastung. In Java mussten Sie beispielsweise jedes Mal, wenn Sie einen Artikel aus einer Sammlung auswählten, explizit einen Downcast ausführen. Sie haben also den syntaktischen Aufwand einer Besetzung und keine Typensicherheit. Angesichts der Tatsache, wie allgegenwärtig Sammlungen in der Programmierung sind, war dies ein großer Nachteil.
Das Deklarieren des Typs von allem ist eine Menge redundanter Typisierung, aber mit moderner Typisierung kann dies erheblich reduziert werden.
Große Standardbibliothek. Python wurde wegen der großen Standardbibliothek berühmt als "inklusive Batterien" beworben. Dies ist im Vergleich zu C, die eine sehr minimalistische Standardbibliothek haben. Aber mit Plattformen wie Java und .net wird eine riesige Standardbibliothek zum Standard, und neuere Sprachen wie Scala und F # erben dies "kostenlos".
Erstklassige Datenstrukturen. Dynamische Sprachen wie Perl und Python verfügen über erstklassige Datenstrukturen wie Listen und Maps mit praktischen syntaktischen Verknüpfungen für allgemeine Operationen. Im Vergleich dazu verfügt C über keine integrierten Sammlungen mit Ausnahme von Arrays mit fester Größe.
Closures und Lambda-Syntax - dynamische Sprachen hatten dies normalerweise von Anfang an, aber statische Sprachen haben dies übernommen, zuletzt Java.
REPL die Fähigkeit , schnell Schnipsel Code zu testen , ist interaktiv ein großer Segen. Obwohl IDE-Tools, wie das "unmittelbare" Fenster in Visual Studio, statische Sprachen in gewissem Maße emulieren können.
Erweitertes Tooling - Zusätzlich zu den oben genannten Punkten, in denen statische Sprachen dem Komfort dynamischer Sprachen immer näher kommen, nutzen moderne Editoren die statische Analyse so, dass dynamische Sprachen nur schwer miteinander übereinstimmen können. Zum Beispiel können Redakteure sichere automatische Refactorings bereitstellen, was in einer dynamischen Sprache streng genommen unmöglich ist.
Fazit: Historisch gesehen stimmte das, aber heute ist die Antwort weniger eindeutig.
F: Also, was kann man für die Produktivität beim dynamischen Tippen sagen, was wirklich ein Vorteil des Typmodells selbst ist?
Es ist etwas schwierig, das dynamische Typisierungsmodell von dynamischen Sprachen zu trennen, aber als Beispiel hat C # im Laufe der Zeit mehr und dynamischere Funktionen übernommen, obwohl es als Kern eine statische Sprache ist. Dies ist ein echter Beweis für den Nutzen des dynamischen Typmodells. Beispiele:
Reflexion Reflexion ist im Grunde eine dynamische Schreibfunktion. Sie überprüfen die Objekttypen zur Laufzeit nach der Kompilierungszeit. Als es eingeführt wurde, war es ein bisschen verpönt, aber in C # wird die Verwendung von Reflektion immer allgegenwärtiger, zum Beispiel verwendet ASP.Net MVC stark Reflektion.
Attribute Attribute sind ein Beispiel für die dynamische Typisierung. Sie können einer Klasse zur Kompilierungszeit beliebige Attribute hinzufügen und dann zur Laufzeit (durch Reflektion) inspizieren und darauf basierende Objekte bearbeiten. So etwas wie MEP ist im Grunde ein Erweiterungsframework, das auf einem dynamischen Typmodell basiert.
Linq to SQL, EF mv. Die verschiedenen Linq-Transformer prüfen Abfragen als Laufzeitobjekte und generieren SQL-Code im laufenden Betrieb. Es wird nicht dynamischer als das Untersuchen von Code zur Laufzeit. CodeDom ist die andere Seite der Medaille, auf der Code zur Laufzeit generiert werden kann
Roslyn Roslyn implementiert im Grunde genommen das
eval
, was einst als bestimmendes Merkmal einer wirklich dynamischen Sprache galt.Dynamisch Der
dynamic
-Typ ist die explizit dynamischste Funktion in C # und wird verwendet, um die Interaktion mit externen Objekten und Sprachen einfacher und produktiver zu gestalten. Es wird jedoch auch in Asp.net MVC verwendet.Der Nutzen aller oben genannten Merkmale zeigt, dass das dynamische Modell selbst in einer statischen Sprache mit parametrisierten Typen, strukturellen Typen und Typinferenz deutliche Vorteile hat .
quelle
Alle modernen Sprachfunktionen sind so umfangreich, dass statische und dynamische Eingaben allein nicht viel Gewicht haben.
Die Regel lautet: Je besser Ihre Sprachfunktionen sind, desto kürzer ist Ihr Code. Das ist ganz einfach. Java zeigt, wie sehr statische Eingaben schief gehen können, was den Gegnern viel zu bieten hat. Schlecht gestaltete Sprachfunktionen sind in der Regel mit Kosten verbunden, und die statische Eingabe in Java ist erstens eine obligatorische Funktion (andernfalls würden die meisten Benutzer sie wahrscheinlich nicht einmal verwenden) und zweitens wird sie schlecht ausgeführt.
Dies ist der Grund, warum im Vergleich die meisten dynamischen Sprachen glänzen, obwohl ich behaupten würde, dass PHP Ihr Leben in der Gesamtsumme (zumindest bis vor kurzem) nicht wirklich verbessert, weil es viele andere Macken gibt, die nichts mit Typsystemen zu tun haben.
Auf der anderen Seite gibt es viele Sprachen mit expressiven Schriftsystemen, die sich nicht in die Quere kommen und die nicht einmal obligatorisch sind. Einige von ihnen erlauben sogar das Einbetten von untypisiertem Code, wann immer Sie dem Typsystem entkommen müssen.
Persönlich benutze ich haXe, eine Sprache mit Typinferenz, sowohl nominaler als auch struktureller Subtypisierung, optionalem untypisiertem Code, erstklassigen Funktionstypen, algebraischen Datentypen und (nicht ganz ausgereiften, aber äußerst leistungsfähigen) lexikalischen Makros, wobei die arkane Syntax vermieden wird. Nachdem ich haXe nun seit ungefähr 3 Jahren benutze, bin ich zu einem einfachen Schluss gekommen:
Das Programmieren wird viel einfacher, wenn Ihre Sprache Sie nicht an religiöse Entscheidungen über Paradigmen bindet, sondern nur versucht, ein gutes Werkzeug zu sein. Es gibt eine Reihe von statischen und dynamischen Sprachen und gemischten Sprachen, die das schaffen. Einige von ihnen sind leicht zu erlernen und am schwersten zu meistern.
Ihre Stärke ergibt sich aus der Art und Weise, in der ihre einzelnen Merkmale so zusammengesetzt werden können, dass auf einfache Weise einfache Lösungen für komplexe Probleme erstellt werden können. Dies schließt eine gewisse Orthogonalität aus, die nur durch ein ausgewogenes Verhältnis von Einbeziehung oder Auslassung aller bisher untersuchten Sprachmerkmale erreicht werden kann. Wenn Sie versuchen würden, Ruby mit statischer Typisierung zu versehen, würden Sie es lähmen. Wenn Sie versuchen würden, es Haskell zu entziehen, würden Sie es lähmen. Im Gegensatz dazu: Wenn Sie es von C wegnehmen würden, würden die Leute es kaum bemerken, und wenn Sie es von Java wegnehmen würden, könnten einige es Ihnen danken.
Aus meiner persönlichen Erfahrung kann ich Ihnen Folgendes sagen: Ich mag Ruby. Es hat meinen Horizont erweitert und die Art, wie ich Systeme entwerfe. IMHO sollte es verwendet werden, um Menschen die Programmierung in erster Linie zu lehren. Es ist unauffällig, kraftvoll, prägnant und macht Spaß. Ich verstehe, warum jemand, der aus einer orthodoxen Sprache kommt, es genießen wird.
Auf lange Sicht ermöglicht es die statische Typisierung jedoch, die Arbeit auf den statischen Analysator zu verschieben, und bei einer Typinferenz ist dies im Grunde genommen kostenlos. Das Ergebnis ist Code, der einfacher zu warten ist und häufig schneller ausgeführt wird.
Aber auch hier kann statisches Tippen allein nichts bewirken. Es ist eine Frage der Kombination. Ich denke irgendwo zwischen F #, Scala, Nemerle, OCaml oder haXe kann man sein eigenes Optimum finden. Aber das hängt letztendlich von Ihnen ab, denn die Sprache sollte es Ihnen ermöglichen, Ihre Gedanken mühelos einzubetten, anstatt Sie zu zwingen, sie herumzubiegen. Und nichts bringt mehr Produktivitätsgewinn, als wenn Programmieren Spaß macht.
quelle
Persönlich ist der einzige Grund, warum dynamisches Tippen hilfreich ist, wenn Sie ein sehr langsamer Typist sind oder riesige Funktionen / Methoden / was auch immer erstellen, die schwer zu navigieren sind. Sie müssen sich auch mit dem gesamten Unit-Testing befassen. Dynamische Typen erfordern (es sei denn, Sie schreiben gerne gebrochenen Code) intensive Komponententests (um sicherzustellen, dass Ihre dynamischen Typen nicht unerwartet in die Luft jagen (dh die Variable ist meistens enttäuscht, manchmal jedoch versehentlich)). Statik wird sich viel mehr bemühen, dies zu verhindern (und ja, Sie können das Argument für strenge Komponententests vorbringen)
quelle
Ich denke, zuerst muss man "Produktivität" definieren. Was bedeutet und beinhaltet "Produktivität"?
Wenn Sie mit "produktiver" weniger Codezeilen schreiben, um dieselbe Funktion zu implementieren, dann sind dynamische Programmiersprachen "produktiver" als statische.
Berücksichtigt man jedoch auch die Zeit, die für das Debuggen und Beheben von Fehlern aufgewendet wird, sind Sprachen mit dynamischer Typisierung möglicherweise nicht so produktiv, da Sprachen mit dynamischer Typisierung dazu neigen, die Fehlerprüfung auf die Laufzeit zu verlagern, während Sprachen mit statischer Typisierung im Gegensatz dazu ausgeführt werden kann in der Kompilierungszeit einige Fehlerprüfungen durchführen. Es wird allgemein angenommen, dass die Behebung dieses Fehlers umso teurer ist, je später ein Fehler gefunden wird. Aus diesem Grund kann der Code für die dynamische Eingabe im Allgemeinen die gleiche oder sogar eine geringere Produktivität als der Code für die statische Eingabe aufweisen.
quelle
Der große Vorteil des dynamischen Tippens ist die Produktivität.
Python, Ruby usw. bieten neben der dynamischen Typisierung (Standardparameter, Wörterbücher usw.) noch viele weitere Produktivitätssteigerungen. Die kumulative Auswirkung auf die Programmiererproduktivität ist beeindruckend.
Die Nachteile in Bezug auf Geschwindigkeit (oder Mangel an!) Und Ressourcenverbrauch sind nicht so schlimm wie erwartet und werden in den meisten Fällen durch Entwicklungsgeschwindigkeit und Flexibilität mehr als ausgeglichen.
Zu diesem Thema gibt es eine (sehr alte!) Zeitung . Es ist eine der wenigen ordnungsgemäß durchgeführten Studien zur Produktivität von Programmierern, und viele der Schlussfolgerungen sind noch gültig.
Was wäre (wahrscheinlich) anders, wenn die Studie heute durchgeführt würde:
Die Botschaft ist also, dass dynamische Sprachen Ihre Produktivität steigern, es sei denn, die Leistung ist ein wirklich ernstes Problem.
quelle