it-swarm.dev

Lohnt sich die statische Eingabe für Sie?

Ich begann mit dem Codieren in Python hauptsächlich dort, wo es keine Typensicherheit gibt, und wechselte dann zu C # und Java wo es gibt. Ich stellte fest, dass ich ein bisschen arbeiten konnte schneller und mit weniger Kopfschmerzen in Python, aber andererseits sind meine C # - und Java - Apps viel komplexer, daher habe ich nie Python a wahrer Stresstest, nehme ich an.

Die Java und C # -Lager lassen es so klingen, als würden die meisten Leute ohne die vorhandene Typensicherheit links und rechts auf alle möglichen schrecklichen Fehler stoßen, und es wäre mehr Ärger als es wert wäre.

Dies ist kein Sprachvergleich. Behandeln Sie daher keine Probleme wie kompiliert oder interpretiert. Lohnt sich die Typensicherheit für die Geschwindigkeit der Entwicklung und die Flexibilität? WARUM?

an die Leute, die ein Beispiel für die Meinung wollten, dass dynamisches Tippen schneller ist:

"Verwenden Sie während der Entwicklung eine dynamisch typisierte Sprache. Sie erhalten schnelleres Feedback, schnellere Bearbeitungszeit und schnellere Entwicklungsgeschwindigkeit." - http://blog.jayway.com/2010/04/14/static-typing-is-the-root-of-all-evil/

110

Es ist eine Art Mythos, dass sich Programmierer nicht um Typen in dynamisch typisierten Sprachen kümmern müssen.

In dynamisch getippten Sprachen:

  • Sie müssen immer noch wissen, ob Sie mit einem Array, einer Ganzzahl, einer Zeichenfolge, einer Hash-Tabelle, einer Funktionsreferenz, einem Wörterbuch, einem Objekt oder was auch immer arbeiten.

  • Wenn es sich um ein Objekt handelt, müssen Sie wissen, zu welcher Klasse es gehört.

  • Das Zuweisen eines dieser Typen zu einer Variablen oder einem Funktionsparameter, von dem erwartet wird, dass es sich um einen anderen Typ handelt, ist fast immer ein Fehler.

  • Auf einer niedrigeren Ebene müssen Dinge wie die Anzahl der Bits oder häufig vorzeichenlose oder vorzeichenlose häufig berücksichtigt werden, wenn Sie beispielsweise ein TCP -Paket) füllen.

  • Sie können auf Probleme stoßen, bei denen Sie eine Null erhalten, bei der Sie wirklich eine leere Zeichenfolge wollten. Mit anderen Worten, Sie debuggen immer noch Fehler, die nicht übereinstimmen. Der einzige wirkliche Unterschied ist, dass der Compiler die Fehler nicht abfängt.

  • Ich würde argumentieren, dass Sie sparen nicht einmal viel Eingabe -, weil Sie dazu neigen, in Kommentaren zu dokumentieren, welchen Typ Ihre Funktionsparameter haben, anstatt ihn in Ihrem Code zu dokumentieren. Aus diesem Grund sind Kommentarblöcke im Sauerstoff-Stil in der Praxis in dynamisch typisiertem Code viel beliebter, wo sie in statisch typisierten Sprachen meist nur für Bibliotheken angezeigt werden.

Das heißt nicht, dass sich das Programmieren in dynamisch typisierten Sprachen nicht angenehmer anfühlt , weil der Compiler nicht immer auf Ihrem Rücken liegt und erfahrene Programmierer dies nicht tun. Es ist in der Regel schwierig, die Art von Fehlern zu finden und zu korrigieren, die bei der statischen Typisierung ohnehin auftreten würden. Dies ist jedoch ein völlig anderes Problem als eine angebliche Steigerung der Effizienz oder eine Verringerung der Fehlerrate, für die die dynamische Typisierung selbst bei statischer Typisierung bestenfalls geeignet ist.

164
Karl Bielefeldt

Wenn die Typen stärker werden, können sie Ihnen mehr helfen - if Sie verwenden sie richtig, anstatt sie zu bekämpfen. Entwerfen Sie Ihre Typen so, dass sie Ihren Problembereich widerspiegeln, und Logikfehler führen eher zu Fehlanpassungen beim Typ zur Kompilierung als zu Laufzeitabstürzen oder Unsinnsergebnissen.

124
geekosaur

Haftungsausschluss: Ich bin ein Typ-Liebhaber;)

Ihre Frage ist schwer zu beantworten: Was sind das Kompromisse?

Ich nehme ein extremes Beispiel: Haskell , es ist statisch typisiert. Vielleicht eine der am stärksten typisierten Sprachen, die es tatsächlich gibt.

Haskell unterstützt jedoch Generic Programming in dem Sinne, dass Sie Methoden schreiben, die mit jedem Typ funktionieren, der einem bestimmten Konzept (oder einer bestimmten Schnittstelle) entspricht.

Darüber hinaus verwendet Haskell Type Inference, Damit Sie den Typ Ihrer Variablen nie deklarieren müssen. Sie werden während der Kompilierung statisch berechnet, ähnlich wie ein Python Interpreter würde sie beim Ausführen des Programms berechnen.

Ich habe festgestellt, dass die meisten Leute, die sich mit statischer Typisierung beschäftigen, sich tatsächlich über etwas anderes beschwert haben (Ausführlichkeit, Schmerzen beim Wechseln eines Typs zugunsten eines anderen), aber Haskell weist keines dieser Probleme auf, während er statisch getippt wird ...


Beispiel der Kürze:

-- type
factorial :: Integer -> Integer

-- using recursion
factorial 0 = 1
factorial n = n * factorial (n - 1)

Abgesehen von der eingebauten Unterstützung ist es schwierig, kürzer zu werden.

Beispiel für generische Programmierung:

> reverse "hell­o" -- Strings are list of Char in Haskell
=> "olleh"
> reverse [1, 2, 3, 4, 5]
=> [5,4,3,2,1]

Beispiel für Typinferenz:

> :t rever­se "hell­o"
:: [Char]

was einfach berechnet werden kann:

  • "hello" ist eine Liste von Char (ausgedrückt als [Char])
  • reverse angewendet auf einen Typ [A] gibt einen Typ zurück [A]

Probieren Sie es aus in Ihrem Browser

78
Matthieu M.

Ich mag sowohl statisch als auch dynamisch typisierte Sprachen. Die zwei größten Vorteile der Typensicherheit sind für mich:

1) Oft kann man aus der Typensignatur ziemlich genau ableiten, was eine Funktion tut (dies gilt insbesondere für funktionale Sprachen wie Haskell).

2) Wenn Sie einen signifikanten Refactor durchführen, teilt Ihnen der Compiler automatisch alles mit, was Sie tun müssen, damit alles funktioniert. Wenn ich etwas in C++ umgestalte, besteht meine Prozedur oft einfach darin, a) den einen Teil zu ändern, von dem ich weiß, dass ich ihn ändern möchte, und dann b) jeden Kompilierungsfehler zu beheben.

37
dfan

Persönlich finde ich, dass Typensicherheit mir hilft, mich in meinem aktuellen Job schneller zu entwickeln. Der Compiler führt einen Großteil der Überprüfung der Integrität für mich durch, fast während ich tippe, sodass ich mich mehr auf die Geschäftslogik konzentrieren kann, die ich implementiere.

Fazit für mich ist, dass ich zwar etwas an Flexibilität verliere, aber etwas Zeit gewinne, die sonst für das Aufspüren von Typproblemen aufgewendet würde.

29
Michael K

Es gibt viele starke Meinungen rund um die Debatte, aber offensichtlich ist dies keine Ansichtssache, sondern eine Frage von Fakten. Also wir sollten uns empirische Forschung ansehen. Und die Beweise dafür sind klar:

Ja , statische Typisierung ist die Kompromisse wert - und zwar nicht nur ein bisschen, sondern tatsächlich im Wesentlichen. Tatsächlich zeigen solide Beweise, dass statische Typisierung die Anzahl der Fehler im Code um mindestens 15% reduzieren kann (und dies ist eine niedrige Schätzung, die tatsächliche Prozentsatz ist mit ziemlicher Sicherheit größer). Das ist eine schockierend hohe Zahl: Ich denke, selbst die meisten Befürworter der statischen Typisierung hätten nicht gedacht, dass dies einen so drastischen Unterschied macht.

Bedenken Sie Folgendes: Wenn Ihnen jemand gesagt hat, dass es eine einfache Möglichkeit gibt, die Fehler in Ihrem Projekt über Nacht um 15% zu reduzieren, sollte dies ein Kinderspiel sein.1  Es ist fast die sprichwörtliche Silberkugel.

Die Beweise werden in der Arbeit Tippen oder nicht tippen: Quantifizierung nachweisbarer Fehler in JavaScript von Zheng Gao, Christian Bird und Earl T. Barr präsentiert. Ich ermutige alle, es zu lesen. Es ist ein gut geschriebenes Papier, das beispielhafte Forschung präsentiert.

Es ist schwer zusammenzufassen, wie streng die Autoren ihre Analyse durchgeführt haben, aber hier ist eine (sehr grobe) Übersicht:

TypeScript und Flow sind zwei auf JavaScript basierende Programmiersprachen, die, obwohl sie ansonsten kompatibel bleiben, Typhinweise und statische Typprüfungen hinzufügen. Dies ermöglicht es, vorhandenen Code nach Typen zu erweitern und ihn dann zu überprüfen.

Die Forscher sammelten Open Source-Projekte, die in JavaScript von GitHub geschrieben wurden, untersuchten gelöste Fehlerberichte und versuchten, jeden der gemeldeten Fehler auf einen Code zu reduzieren, der von der statischen Typprüfung von TypeScript oder Flow abgefangen wurde. Dies ermöglichte es ihnen, eine Untergrenze des Prozentsatzes der Fehler zu schätzen, die durch statische Typisierung behoben werden konnten.

Die Forscher haben strenge Vorkehrungen getroffen, um sicherzustellen, dass bei ihrer Analyse ein nicht typbezogener Fehler nicht als typbezogen betrachtet wird.2

Im Vergleich zu früheren Studien weist diese neue Studie besondere Stärken auf:

  • Es gibt einen direkten Vergleich der statischen vs dynamischen Typisierung mit wenigen (wenn überhaupt) Störfaktoren, da der einzige Unterschied zwischen JavaScript und TypeScript/Flow der ist Tippen.
  • Sie führen die Replikation über mehrere Dimensionen hinweg durch, indem sie sowohl TypeScript als auch Flow (d. H. Systeme unterschiedlichen Typs) überprüfen und verschiedene Personen die (manuelle) Typanmerkung reproduzieren lassen, um die Fehler zu beheben. Und sie führen dies über eine große Anzahl von Codebasen aus verschiedenen Projekten aus.
  • Das Papier misst die direkten Auswirkungen der statischen Typisierung auf behebbare Fehler (und nicht auf eine vage Qualität).
  • Die Autoren definieren ein strenges Modell dafür, was und wie im Voraus gemessen werden soll. Darüber hinaus ist ihre Beschreibung unglaublich klar und erleichtert die Analyse auf Fehler (es ist immer gut, wenn sich ein Forschungsbericht Angriffen öffnet: Wenn keine Angriffe es schaffen, ihre Argumente einzudämmen, wird es noch stärker).3
  • Sie führen eine ordnungsgemäße Leistungsanalyse durch, damit ihre Stichprobengröße ausreicht und ihre anschließende statistische Analyse luftdicht ist.
  • Sie sind zu konservativ, um verwirrende Erklärungen auszuschließen, und messen nur einen einzigen beweglichen Teil. Darüber hinaus beschränken sie ihre Analyse auf Fehler, die durch das Einschließen von Typen sofort behoben werden können, und schließen alles aus, was möglicherweise ein erweitertes Refactoring erfordert, um die Eingabe zu ermöglichen. In Wirklichkeit ist der Effekt also plausibel viel größer, aber sicherlich nicht kleiner als das, was sie berichtet haben.
  • Und schließlich finden sie keinen leichten Effekt, sondern einen erstaunlichen Unterschied. Trotz ihres übermäßig konservativen Verfahrens stellen sie selbst am unteren Ende des 95% -Konfidenzintervalls fest, dass mindestens 10% der Fehler mit minimalen zusätzlichen Typprüfungen einfach verschwinden würden.

Sofern es keinen grundlegenden Fehler in dem Papier gibt, den noch niemand entdeckt hat, zeigt das Papier schlüssig einen großen Vorteil der statischen Typisierung, fast kostenlos.4


Historisch gesehen hat die Forschung zu Typisierungsdisziplinen in der Programmierung einen schwierigen Anfang gehabt, da die Beweise nicht Lange Zeit überhaupt klar waren. Der Grund dafür ist, dass systematische Experimente zur Untersuchung des Effekts der statischen vs dynamischen Typisierung nicht einfach sind: Ein systematisches Experiment muss den von uns untersuchten Effekt isolieren. Und leider können wir die Wirkung der Schreibdisziplin nicht isolieren, da sie an die Programmiersprachen gebunden ist.

Es gab tatsächlich waren Programmiersprachen, die sowohl statische als auch dynamische Eingabe in verschiedenen Dialekten ermöglichten (zB VB mit Option StrictOn oder Off oder statisch typisiertes LISP). Diese waren jedoch für einen direkten Vergleich nicht gut geeignet, vor allem, weil es keine ausreichend großen Codebasen gab, die einen direkten Vergleich ermöglichen. Bestenfalls konnten wir sie vergleichen „Laboreinstellungen“, bei denen Testpersonen eine Aufgabe in der statisch oder dynamisch typisierten Variante der Sprache zufällig lösen.

Leider modellieren diese künstlichen Programmieraufgaben die reale Nutzung nicht gut. Insbesondere sind viele von ihnen klein und lösen ein genau definiertes Problem, das auf einer halben Textseite zusammengefasst werden kann.

Glücklicherweise ist dies in der Vergangenheit der Fall, da TypeScript, Flow und JavaScript bis auf die statische Typisierung tatsächlich dieselben Sprachen sind und es einen umfangreichen realen Datensatz mit Code und Fehlern gibt, aus dem Beispiele erstellt werden können.


1 Inspiriert von einem Zitat aus dem Originalpapier.

2 Ich bin damit nicht ganz zufrieden: Eine der Hauptstärken statisch typisierter Sprachen besteht darin, dass angeblich typunabhängige Probleme auf eine Weise formuliert werden können, die statisch typgeprüft werden kann. Dies wandelt viele logische Fehler in Typfehler um, was drastisch die Rate der Fehler erhöht, die durch statische Typisierung abgefangen werden können. Tatsächlich klassifiziert das Papier grob typunabhängige Fehler, und ich behaupte, dass ein großer Prozentsatz davon tatsächlich durch statische Typisierung abgefangen werden könnte.

3 Ich lade jeden ein, insbesondere Befürworter der dynamischen Typisierung, zu versuchen, nicht adressierte Fehler in der Analyse zu finden. Ich glaube nicht, dass es viele gibt (wenn überhaupt), und ich bin zuversichtlich, dass kein potenzieller Fehler das Ergebnis wesentlich verändern würde.

4 Ich vermute, dass die tatsächlichen Kosten für die statische Eingabe in realen Großprojekten nicht vorhanden sind, da sie dann zu einem natürlichen Bestandteil der Architektur werden und möglicherweise sogar vereinfachen Planung. Das Beheben von Fehlern vom statischen Typ nimmt Zeit in Anspruch, ist jedoch viel weniger als später entdeckte Fehler. Dies wurde ausführlich empirisch untersucht und ist seit Jahrzehnten bekannt (siehe z. B. Code Complete).

14
Konrad Rudolph

Lohnt sich die Typensicherheit für die Geschwindigkeit der Entwicklung und Flexibilität?

Das hängt also wirklich davon ab, was Sie tun. Wenn Sie beispielsweise die Backup-Systeme für Flugzeuge programmieren, ist die Typensicherheit wahrscheinlich der richtige Weg.

Dynamische Sprache vs. statische Sprachprogrammierung sind wirklich zwei verschiedene Tiere. Beide erfordern einen grundlegend unterschiedlichen Ansatz. Sie können meistens eine Annäherungsmethode zwischen statisch und dynamisch portieren, aber Sie werden die Vorteile der anderen verlieren.

Es ist wirklich eine Denkweise. Ist einer besser als der andere? Das hängt wirklich davon ab, wer du bist und wie du denkst. Die meisten Leute, mit denen ich zusammenarbeite, würden niemals eine dynamische Sprache berühren, wenn sie nicht müssten, weil sie der Meinung sind, dass es zu viel Raum für Fehler gibt. Sind sie falsch, das zu denken? Nein, natürlich nicht, aber es bedeutet, dass sie erkannt haben, dass ihr Ansatz, ihren Codierungsstil anzuwenden, in einer dynamischen Umgebung nicht funktioniert. Andere Leute, mit denen ich zu Benutzergruppen gehe, sind genau das Gegenteil. Sie finden statisches Tippen zu umständlich, weil es ihren Ansatz zur Lösung bestimmter Arten von Problemen einschränkt.

Ich kann ehrlich sagen, ich springe viel zwischen JavaScript und C #. Das Wissen und Arbeiten in beiden Sprachen beeinflusst den anderen in gewissem Maße, aber in Wahrheit sieht der Code, den ich in beiden Sprachen schreibe, völlig anders aus. Sie erfordern einen anderen Ansatz, weil sie sich grundlegend unterscheiden. Was ich gefunden habe, ist, dass wenn Sie denken: "Mann, das ist so viel schwieriger, dies in X-Sprache zu tun", Ihr Ansatz wahrscheinlich ein wenig falsch ist. Hier ist ein Beispiel, die Leute sprechen über die "pythonische" Art, Dinge zu tun. Was es bedeutet, ist, dass es eine Möglichkeit gibt, wie die Sprache Python) ein Problem einfacher macht. Eine andere Vorgehensweise ist im Allgemeinen schwieriger und umständlicher. Sie müssen über den Buckel des Wissens hinwegkommen Wie funktioniert eine Sprache, damit sie wirklich für Sie funktioniert? Genau das Gleiche gilt für dynamische und statische Sprachen.

12
kemiller2002

Kürzlich wurde eine ähnliche Frage gestellt: Dynamische oder statisch typisierte Sprachen für Websites

Um den Kern meiner Antwort noch einmal zu wiederholen:

Wenn Systeme größer werden, gewährleisten statisch typisierte Sprachen Robustheit auf Komponentenebene und damit Flexibilität auf Systemebene.

Ja, Java ist streng getippt und ja, Java ist zum Kotzen (keine Beleidigung. Es ist schrecklich. Tolle Plattform und Ökosystem, aber eine der schlechtesten Sprachen aller Zeiten (tatsächlich verwendet)).
Aber daraus zu schließen, dass striktes Tippen scheiße ist, ist nur ein Trugschluss. Es ist, als würde man auf PHP zeigen und auf dynamisches Tippen schließen (wieder keine Beleidigung. Es verbessert sich langsam, das gebe ich dir).

Persönlich mache ich den größten Teil meiner Entwicklung in haXe , das ein statisches Typsystem hat. Es ist nicht nur wesentlich ausdrucksvoller als das von Java und erfordert aufgrund der Typinferenz viel weniger Aufwand, sondern ist auch optional. Sollte es Ihnen jemals in die Quere kommen, umgehen Sie es einfach.

Typensicherheit ist eine Funktion (dies ist etwas, was viele angeblich hochrangige Sprachen nicht richtig machen) , um Ihnen zu helfen Vermeiden Sie es, sich in den Fuß zu schießen .
Und über jede erfolgreiche dynamisch getippte Sprache wäre es einfach besser, wenn Sie die Option hätten, Ihren Codetyp nach Belieben überprüfen zu lassen.
Zum Beispiel hat es mir sicherlich Spaß gemacht, Ruby zu experimentieren, aber das lag hauptsächlich daran, dass Ruby vollständig objektorientiert ist, was völlig orthogonal zum Vorhandensein eines Systems vom Typ der Kompilierungszeit ist.

Ich denke, die Behauptung, dass statische Typsysteme aufdringlich sind, beruht lediglich auf mangelnder Kenntnis guter statischer Typsysteme. Es gibt eine Reihe von Sprachen, die es richtig machen, haXe ist eine davon und wohl nicht einmal die beste in dieser Hinsicht.

Beispiel haXe Code:

class Car {
    public function new();
    public function wroom() trace('wroooooooom!')
}
class Duck {
    public function new();
    public function quack(at) trace('quackquack, ' + at + '!')
}

function letQuack(o) o.quack();
letQuack(new Car());
letQuack(new Duck());

Dies führt zu einem Fehler bei der Kompilierung:

Car should be { quack : Void -> Unknown<0> }
Car has no field quack
For function argument 'o'
Duck should be { quack : Void -> Unknown<0> }
Invalid type for field quack :
to : String -> Void should be Void -> Unknown<0>
For function argument 'o'

Man kann nicht wirklich behaupten, dass ich mich sehr um die Typensicherheit bemühen musste.

Noch idiotischer ist es zu sagen, dass Sie keine Typensicherheit benötigen, weil Sie Tests haben. Das Schreiben von Tests ist langweilig und wiederholt sich. Und ich möchte wirklich keinen Test schreiben, nur um herauszufinden, dass eine Instanz von Car nicht quaken wird und eine Ente jemanden zum Quaken braucht.

Am Ende des Tages werden Sie feststellen, dass die Sicherheit, unabhängig davon, wie viel Overhead-Sicherheit Sie gekostet hat, letztendlich amortisiert wird (sogar in Java - obwohl dies möglicherweise nicht so bald der Fall ist).

7
back2dos

Es hängt davon ab, ob.

Menschliche Versagensmodi sind oft statistisch. Eine starke Typprüfung verringert die Wahrscheinlichkeit einiger bestimmter Arten menschlicher Fehler (die fehlerhaften Code verursachen). Aber nur weil du scheitern kannst, heißt das nicht immer, dass du es wirst (Murphy nicht widerstehen).

Ob diese Reduzierung der potenziellen Ausfallwahrscheinlichkeiten die Kosten wert ist, hängt davon ab.

Wenn Sie Code für ein Kernkraftwerk oder ein ATC-System schreiben, kann jede Reduzierung des menschlichen Versagensmodus extrem wichtig sein. Wenn Sie Rapid Prototyping für eine Website-Idee durchführen, die keine Spezifikation hat und nahezu keine Fehlerfolgen hat, kann die Reduzierung der Fehlermodi oder -wahrscheinlichkeiten Sie möglicherweise etwas kaufen oder nicht, kostet Sie jedoch möglicherweise Entwicklungszeit (mehr Tastenanschläge usw.). und in Gehirnzellen, die durch das Auswendiglernen der aktuell benötigten Typen abgelenkt werden.

5
hotpaw2

Aus irgendeinem Grund mache ich nicht mehr so ​​oft Fehler in Bezug auf den Typ eines Objekts. In Sprachen wie C # mache ich eher Fehler im Zusammenhang mit Laufzeitumwandlungen als einen vom Compiler erkennbaren Typ-Sicherheitsfehler, der, wie ich zugebe, normalerweise durch die gelegentliche Notwendigkeit verursacht wird, die Statik eines statischen zu umgehen getippte Sprache. Wenn ich Ruby schreibe, deutet der Code ziemlich stark auf den Typ eines Objekts und die Verfügbarkeit von a hin REPL bedeutet, dass ich bereits experimentell überprüft habe, ob die gewünschten Methoden/Attribute vorhanden sind, oder Ich werde einen Komponententest durchführen lassen, der im Grunde das Gleiche tut, daher stoße ich in Ruby auch selten auf Sicherheitsprobleme.

Das heißt aber nicht, dass statisch typisierte Systeme nicht besser sein können als sie.

In statisch typisierten Sprachen spielt auch der Typ System eine große Rolle. Wenn Sie beispielsweise die Monade Some in funktionalen Sprachen (Typ <Some>: = yes x | no) verwenden, erhalten Sie Überprüfungen zur Kompilierungszeit, die die gefürchtete NullReferenceException, die in den meisten Typsystemen häufig vorkommt, im Wesentlichen verhindern. Wenn Mustervergleichscode ausgeführt wird, werden Fehler bei der Kompilierung angezeigt, die darauf hinweisen, dass Sie die Nullbedingung nicht behandelt haben (wenn Sie diesen Mechanismus zum Deklarieren des Typs verwenden). Sie reduzieren ähnliche Fehlertypen auch, wenn Sie beispielsweise den Pipeline-Operator |> in F # verwenden.

In der Hindley-Milner-Tradition der statischen Typisierung können Sie Dinge erstellen, die Ihnen weit mehr als die Garantie geben, dass ein Typ behauptet, die Schnittstelle X zu unterstützen, und sobald Sie diese Dinge haben, würde ich sagen, dass das statisch typisierte System viel wird wertvoller.

Wenn dies keine Option ist, können Design By Contract-Erweiterungen für C # weitere Mechanismen hinzufügen, die den Wert des statischen Typsystems erhöhen. Sie erfordern jedoch immer noch mehr Disziplin als einige dieser Funktionsparadigmen.

5
JasonTrue

Typen sind Einschränkungen für Schnittstellen, daher sind sie eine Teilmenge dessen, was Sie möglicherweise mit Komponententests testen möchten, und daher sind viele Kompromisse ähnlich:

  • Statische Typen geben früheres Feedback darüber, ob der Code die Anforderungen erfüllt, die vom Typensystem ausgedrückt werden können, als Gegenleistung für die Verzögerung des Feedbacks beim Erstellen von Funktionen mit minimaler Funktionsfähigkeit (wie Kundenfeedback oder Tests auf höherer Ebene).
  • Das Wissen, dass der Code bestimmte Anforderungen erfüllt, kann das Refactoring und Debuggen vereinfachen, erhöht aber auch den Aufwand für das Ändern von Schnittstellen und Anforderungen.
  • Insbesondere wenn eine statisch typisierte Sprache keinen Zwang hat, bietet sie zusätzliche Sicherheit gegen die Verwendung von Code für Daten, die Fehler verursachen würden (wodurch die Notwendigkeit von Bedingungen und Zusicherungen verringert wird). Bei übermäßig restriktiven Einschränkungen muss der Benutzer jedoch mehr Code schreiben, um seine Daten in eine Sprache zu massieren akzeptable Form (wie explizites Typgießen).
  • Explizite Typanmerkungen können das Verständnis beim Lesen von Code verbessern oder Code mit redundanten oder unnötigen Informationen überladen.
  • Je nach Implementierung kann dies die Knappheit beeinträchtigen. Dies hängt beispielsweise davon ab, ob Typanmerkungen erforderlich sind oder abgeleitet werden, wie gut das Typsystem generische Typen/Schnittstellen ausdrücken kann, von der Syntax und davon, ob Sie auf Einschränkungen testen möchten, die vom Typsystem ausgedrückt werden können (z Der gleiche Test ist als Sprachmerkmal wahrscheinlich knapper als als Komponententest, aber Sie haben möglicherweise nicht beabsichtigt, ihn zu testen.
  • Darüber hinaus (jedoch ohne Bezug zu TDD) können statische Typen die Optimierung der Kompilierungszeit unterstützen, auf Kosten der Überprüfung dieser Typen (und der Zeit, um sie zu überprüfen und die Optimierungen durchzuführen). Eine bessere Optimierung kann durchgeführt werden, wenn die Daten auf Typen beschränkt sind diese Karte gut auf Hardware. Dies erleichtert die Entwicklung von Code mit Leistungsanforderungen, kann jedoch Probleme für Code verursachen, der diesen Einschränkungen nicht gut entspricht (gemäß Punkt 3).

Zusammenfassend würde ich argumentieren, dass dynamische Sprachen für das Prototyping besonders nützlich sind. Wenn Sie jedoch sicher sein müssen, dass Ihr Code korrekt ist, sollten Sie ein starkes Typsystem bevorzugen.

4
T.R.

Ja auf jeden Fall. Wenn Sie sowohl stark typisierte Sprachen als auch Python (Python ist stark typisiert) verwenden, werden Sie feststellen, dass der meiste gut geschriebene Code in dynamischen Sprachen ohnehin den gleichen Konventionen folgt wie stark typisierter Code. Dynamische Typisierung ist sehr nützlich für die Serialisierung und Deserialisierung, aber für die meisten anderen Dinge trägt sie nicht wirklich zum Vorteil bei. Und wenn der größte Teil Ihres Codes nicht mit der Serialisierung zusammenhängt, warum sollten Sie dann die kostenlose Fehlerprüfung nicht mehr durchführen?

3
Mason Wheeler

Morgan, ich habe eine interessante Idee für Sie: statische + dynamische Eingabe. Sie haben Python, C # und Java erwähnt. Wussten Sie, dass es einige ziemlich gute Ports von Python für .NET und Java) gibt? In beiden Fällen können Sie mit den Ports die Bibliotheken dieser Plattformen verwenden und/oder mit vorhandenem Code zusammenarbeiten. Dies gibt Ihnen mehrere Möglichkeiten:

  1. Bewahren Sie Legacy-Code in einer statischen, unflexiblen Sprache auf. Verwenden Sie Python für neue Inhalte).
  2. Verwenden Sie Python, um neue Inhalte auf ausgereiften Plattformen zu prototypisieren. Codieren Sie die Komponenten, die Sie behalten möchten, in der ausgereifteren Sprache neu.
  3. Verwenden Sie die dynamische Sprache für Teile, die Sie häufig ändern.
  4. Verwenden Sie möglicherweise die dynamische Sprache, um mit Ideen wie dem Ändern von laufendem Code zu spielen.
  5. Führen Sie alles in der dynamischen Sprache aus, mit Ausnahme der kritischen Teile, in denen Sie die stark typisierte Sprache verwenden.

Ich habe diese Ansätze bereits Ende der 90er Jahre verwendet, um den Schmerz der Entwicklung in C/C++ zu umgehen. Ich brauchte die nativen Bibliotheken und manchmal Leistung. Ich wollte jedoch die bessere Syntax, Flexibilität, Sicherheit usw. Der Trick bestand also darin, sie sorgfältig zu kombinieren, um die richtigen Kompromisse zu erzielen. In der Praxis war es oft besser, als die gesamte Sprache und den alten Code für eine andere Sprache/Plattform herauszugeben.

(Hinweis: Eine Antwort hat es bereits gesagt, aber ich möchte auch noch einmal betonen, dass dynamische Typisierung! = Keine/schwache Typisierung. Viele dynamische Typsysteme verwenden eine starke Typisierung im Inneren. Die Art und Weise, wie ich über eine Typendynamik nachdenke, ist die folgende Ein Variablentyp wird zur Laufzeit festgelegt, benötigt keine Typanmerkung und/oder kann sich zur Laufzeit ändern.

3
Nick P

Es wurden viele sehr komplizierte Systeme in LISP geschrieben, und ich habe keinen Lisper darüber klagen hören, dass er statische Typisierung wünschte. Als ich damit gearbeitet habe, erinnere ich mich an keine Probleme, die mich stark verlangsamt haben, die ein statisches Typsystem (und Sie können Typen statisch in Common LISP angeben) gefangen hätte.

Darüber hinaus scheinen statisch typisierte Mainstream-Sprachen nicht gut geeignet zu sein, um Fehler zu erkennen. Beim Entwerfen eines Layouts ist es wichtig, dass eine bestimmte Zahl ein vertikales Maß auf der Seite ist und nicht, ob es sich um int, unsigned, float oder double handelt. Der Compiler hingegen kennzeichnet häufig Typkonvertierungen, die er als unsicher erachtet, und lässt mich gerne eine vertikale Messung und die Anzahl der Zeichen in einer Zeichenfolge hinzufügen. Diese Schwäche des statischen Typensystems war die ursprüngliche Idee hinter Simonyis ungarischer Notation, bevor es in hässliche Nutzlosigkeit verwandelt wurde.

3
David Thornley

Ich sehe, dass diese Frage häufig auftaucht, und ich denke, dass Ihre Softwarequalität (und das Fehlen von Fehlern) mehr mit Ihrem Entwicklungsprozess, der Architektur Ihres Systems und dem Engagement von Ihnen und Ihren Kollegen für die Codequalität zu tun hat.

Mein letzter Job war hauptsächlich python Entwicklung. Ich habe für ein großes internationales Webhosting-Unternehmen gearbeitet und wir hatten Entwicklerteams in den USA, Kanada und Südkorea. Benutzerdefiniert python Web-Framework für die Front-End-Kunden-App, mit dem die Benutzer ihre Domain-Namen und Webhosting-Konten verwalten konnten. Backend: all python auch. Python Web Service, um mit einzelnen Servern zu sprechen, um beispielsweise eine neue Webhosting-Site bereitzustellen, ein neues Blog zu erstellen, DNS-Einträge in unserem Namensdienstsystem zu erstellen usw. usw. In meinem aktuellen Job sind Client-Apps alles in Java, unserem Hauptprodukt ist eine Mischung aus Java und Flash. Custom Java Web Framework für unsere älteren Apps, Wicket für unsere neueren internen Tools.

Nachdem ich in beiden gearbeitet habe, muss ich sagen, dass mich diese Frage jedes Mal nervt, wenn ich sie sehe. Wenn Sie eine dynamisch typisierte Sprache verwenden und Ihren Code tatsächlich testen, ist alles in Ordnung. Wenn das System gut ausgelegt ist und Sie den Standards folgen, wird es Ihnen gut gehen. Es gab nie viele Fehler, die auftraten, weil kein Compiler die Typen überprüfte. Die meisten Fehler waren logische Fehler, genau wie mein Java Job heute.

2
LGriffel

Lohnt sich die Sicherheit von Typen für die Geschwindigkeit der Entwicklung und die Flexibilität? WARUM?

Statische Typisierung ist ein Netto Anstieg in der Geschwindigkeit und Flexibilität der Entwicklung während des gesamten Lebenszyklus der Software. Es reduziert den Gesamtaufwand und die Unannehmlichkeiten, verschiebt jedoch einen Großteil des Aufwands und der Unannehmlichkeiten nach vorne, wo es auffälliger ist. Die Eintrittsbarriere für Arbeitscode ist höher, aber sobald Sie diese Barriere überwunden haben (indem Sie die Typprüfung erfüllt haben), erfordert das Erweitern und Verwalten dieses Codes viel weniger Arbeit.

Es wird immer einige Kopfschmerzen in der Softwareentwicklung geben, weil:

  • Die inhärente Komplexität dessen, was Sie erreichen möchten

  • Die inhärente Fehlbarkeit des Menschen, insbesondere wenn man bedenkt, dass wir mehr Fehler machen, wenn wir versuchen, etwas Komplexeres zu tun

Früher oder später müssen Sie sich etwas Zeit nehmen, um diese Herausforderungen anzugehen. Daran führt kein Weg vorbei. Statische Typisierung adressiert diese Herausforderungen einfach eher früher als später. Früher ist besser als später, denn je später Sie einen Fehler entdecken (keine Frage von wenn, sondern wann), desto mehr kostet es, diesen Fehler zu korrigieren.

Die Korrektur eines von einer Typprüfung gemeldeten Fehlers kostet viel weniger als das Debuggen einer zur Laufzeit ausgelösten typbezogenen Ausnahme. Wenn Sie die Typprüfung auf die Laufzeit verschieben, wird das Problem nur unter den Teppich gekehrt.

2
Jordan

Sie werden keine wirklich objektive Antwort darauf erhalten, aber meiner Erfahrung nach ist die Typensicherheit von unschätzbarem Wert bis Sie beherrschen TDD. Sobald Sie eine starke Abdeckung durch Unit-Tests haben, bei der die Tests vor dem Code geschrieben wurden, wird die Compiler-Überprüfung zu einem Problem und beginnt Ihnen tatsächlich im Weg zu stehen.

2
pdr

JA.

Ich habe in PHP - Anwendungen gearbeitet, in denen Typen nicht so "stark" sind wie in Java oder C #. Normalerweise habe ich "Typen simulieren" beendet, weil in um schlechte automatische Konvertierungen oder die Validierung von Daten zu vermeiden.

Dynamische Typensprachen sind gut für O.S. Skripte und schnelle kleine Apps, keine komplexen Apps.

Zusammenfassung: Wenn ich für eine komplexe Geschäftsanwendung zwischen einer Programmiersprache "Schwacher Typ" oder "Dynamischer Typ" oder einer Programmiersprache "Starker Typ" wählen muss, wähle ich die Option "Stark" Geben Sie "Programmiersprache " ein.

0
umlcat

Ich denke, es lohnt sich, einen Schritt zurückzutreten und zu überlegen, wann dynamisches Tippen Probleme verursacht.

Ein Fall ist, wenn ein Code-Zweig überhaupt nicht getestet wird, aber offen gesagt, Code, der niemals getestet wird, wahrscheinlich fehlerhaft ist, unabhängig davon, ob dynamische Typisierung verwendet wird oder nicht.

Ein weiteres subtileres Problem ist jedoch die unvollständige Substituierbarkeit.

Wenn ein Typ nur völlig falsch ist, wird ein bestimmter Codepfad wahrscheinlich nicht schnell erkannt, es sei denn, er wird nie verwendet.

Wenn andererseits ein Typ ein unvollständiger Ersatz ist, funktioniert der Code möglicherweise meistens, bricht jedoch auf subtile Weise, die erst viel später erkannt werden.

Zwei der häufigsten Programmiertypen sind Zahlen und Zeichenfolgen. In vielen dynamischen Sprachen sind sie ein unvollkommener Ersatz für einander. In Javascript oder PHP, wenn Sie eine Zahl angeben, bei der eine Zeichenfolge erwartet wird, oder umgekehrt, läuft Ihr Programm ohne Fehler aus, kann sich aber auf subtile Weise schlecht verhalten.

Python hat dieses spezielle Problem vermieden. Zahlen und Zeichenfolgen ersetzen sich in keiner Weise, und der Versuch, eines dort zu verwenden, wo das andere erwartet wird, führt normalerweise zu einem schnellen Ausfall.

Das Problem der unvollständigen Susbstituierbarkeit wurde jedoch nicht vollständig vermieden. Verschiedene Arten von Zahlen können unvollkommene Substitute für einander sein, ebenso wie verschiedene Arten von Sequenzen.


Was ich hier bekomme, ist, dass ich nicht denke, dass es möglich ist, die Vorteile und Kosten der statischen und dynamischen Typisierung generisch zu vergleichen, da ich denke, dass sowohl die Vorteile als auch die Kosten von der besonderen Variation der statischen oder dynamischen Typisierung einer Sprache abhängen Verwendet.

0
Peter Green

Dies ist nur meine eigene Meinung, aber nein, ich denke nicht, dass sich die Typensicherheit lohnt. Nicht einmal für eine Sekunde.

Ich bin schon lange Entwickler. Beginnen Sie mit c ++, c # und wechseln Sie dann zu Javascript (Frontend und Backend über node.js). Seit ich mich in Javascript entwickelt habe, ist meine Produktivität in die Höhe geschossen, bis ich mich mit typbasierten Sprachen tatsächlich verschlimmert habe. Ich bin auch gegen das Kompilieren, ich möchte, dass jetzt alles zur Laufzeit läuft. In interpretierten Sprachen habe ich wirklich meine Liebe zum Programmieren gefunden.

Was die Typen betrifft, sehe ich einfach keine Vorteile. Ich sehe Typen jetzt genauso wie Speicherverwaltung. Völlig unnötig. Die Sprachen von morgen sollten den Entwickler vollständig davor schützen, etwas über Typen zu wissen. Der Computer sollte Typen verstehen und den Entwickler davon abhalten.

Hier ist ein Beispiel. Ich habe nur Swift (Apples neue Sprache)) verwendet, in der Hoffnung, dass es vor einem Tag tatsächlich seinem Namen gerecht wird, und habe versucht, Folgendes zu tun: var n = 1/2 hat nicht funktioniert wie, was hier los ist. und dann wurde mir leider klar, dass ich var n: Float = 1/2 machen musste. Dies erinnerte mich daran, wie sehr ich Typsysteme hasse und wie unnötig sie sind.

Ich würde sogar noch eine Meile weiter gehen, um zu sagen, dass ich nicht einmal benutzerdefinierte Typen (wie Klassen) möchte. Ich will überhaupt keine Typen. Alles was ich will ist var und Objekte. Wo jedes Objekt als beliebiges Objekt verwendet werden kann. Und Objekte sind dynamisch und verändern sich ständig. Wo es zu einem Laufzeitproblem wird, was funktioniert und was nicht.

Entwickler lieben es zu sagen, dass lose getippte Sprachen für große Projekte nicht gut sind. Aber ich würde sagen, es ist das Gegenteil. Stark typisierte Sprachen sind für große Projekte schrecklich. Und wenn Sie sagen, dass Javascript für große Projekte nicht funktioniert, fragen Sie Uber, ein Unternehmen mit mehr als 40 Milliarden Mitarbeitern, das sein gesamtes Backend auf node.js/javascript oder Facebook ausführt, das mit PHP gestartet wurde.

In Bezug auf statisch typisierte Sprachen ist es für die heutigen schnellen Iterationen nicht gut. Hier ist ein einfaches Beispiel: Sie haben 10 Entwickler, die an einem .net-Projekt mit einem kontinuierlichen Integrationsserver arbeiten, ein Entwickler gibt einen Fehler ein und der gesamte Build ist fehlerhaft, obwohl die 10 Entwickler an verschiedenen Dingen arbeiten, die jetzt alle gestoppt sind und warten für den beleidigenden Entwickler, um seinen Fehler zu korrigieren. Sprechen Sie über effizient, oder? Typsystem/statische Sprachen sind auf diese Weise voneinander abhängig und machen Ihren Code voneinander abhängig. Skriptdateien sind jedoch niemals voneinander abhängig. Wenn bei einem der Skripte ein Problem auftritt, wird die Produktion nicht gestoppt. Alle Probleme, die angezeigt werden, bleiben der Laufzeit überlassen. Und die Laufzeit hört nie auf. Es bricht nie. Es kann zu falschen Ausgaben führen, aber es stoppt nicht nur den gesamten Prozess wie bei Typsystemen.

0
user19718