5 Stimmen

Von der statischen Typisierung zur dynamischen Typisierung

Ich habe immer mit statisch typisierten Sprachen gearbeitet (C/C++, Java). Ich habe mit Clojure gespielt und es gefällt mir wirklich.

Eine Sache, über die ich mir Sorgen mache, ist: Sagen wir, ich habe ein Windows, das 3 Module als Argumente annimmt und im Laufe der Zeit ändern sich die Anforderungen und ich muss ein weiteres Modul an die Funktion übergeben. Ich ändere einfach die Funktion und der Compiler beschwert sich überall, wo ich sie verwendet habe. Aber in Clojure wird er sich nicht beschweren, bis die Funktion aufgerufen wird. Ich kann einfach eine Regex-Suche und -Ersetzung durchführen, aber es scheint, dass die Chance besteht, einen Aufruf zu verpassen, und es wird unbemerkt bleiben, bis die Funktion tatsächlich aufgerufen wird. Wie geht ihr mit diesem Problem um?

4 Stimmen

Wie geht ihr damit um? Meiner Erfahrung nach lautet die richtige Antwort: "Nicht sehr gut".

8voto

zgchurch Punkte 2302

Dies ist einer der Gründe, warum automatisierte Tests/testgetriebene Entwicklung in dynamisch typisierten Sprachen noch wichtiger sind. Ich habe Clojure nicht verwendet (ich verwende meist Ruby), daher kann ich leider kein spezielles Test-Framework empfehlen.

2 Stimmen

+1. Im Wesentlichen ist das statische Typsystem nur ein automatisch generierter Satz von Unit-Tests (wie einer meiner Freunde, die Dynamik-Evangelisten sind, gerne hervorhebt). Sie müssen diese von Hand in der dynamischen Sprache codieren, was Ihnen mehr Flexibilität, aber auch mehr Aufwand bringt. Es liegt an Ihnen und Ihrem speziellen Design zu entscheiden, ob dieser Kompromiss zugunsten einer dynamischen oder statischen Sprache ausfällt.

1 Stimmen

Sie verschweigen, dass der Umgang mit dem statischen Typensystem Aufwand erfordert. Die Frage ist, was ist größer?

2 Stimmen

@jshen: aber wie viel Aufwand? In einem gut statisch typisierte Sprache, können Sie so gut wie vergessen, dass sie statisch typisiert ist. Nur bei Schrott wie den Sprachen der C-Familie muss man den Compiler ständig an die Typen von allem erinnern.

3voto

Edan Maor Punkte 9446

Die erste Sache Ich möchte erwähnen, dass Bruce Eckel einen sehr interessanten Artikel geschrieben hat, der den Titel Starke Typisierung vs. starke Prüfung (der Link ist im Moment leider nicht verfügbar, aber ich hoffe, er ist bald wieder da).

Seine Idee ist, dass bei kompilierten Sprachen der Compiler lediglich als erster, automatischer Schritt der automatischen Prüfung fungiert. Wenn man zu einer dynamischen Sprache übergeht, verliert man diese erste Stufe des automatischen Testens. Aber in beiden Fällen ist diese erste, automatische Stufe nur ein Teil des Testens, und nicht einmal ein sehr wichtiger Teil.

Sein Punkt ist, dass, wenn Sie Programme richtig entwickeln, d.h. eine Form von Tests und Regressionstests durchführen, das Fehlen eines Compilers Sie nur dazu zwingen wird, einige weitere, eher grundlegende Tests hinzuzufügen, weshalb es kein großer Verlust ist.

Ich denke, die erste Antwort, die ich Ihnen geben würde, ist: Konzentrieren Sie sich auf Ihre Tests, was Sie ohnehin tun sollten, und solche Änderungen sollten Sie nicht allzu sehr beeinträchtigen.

Die zweite Sache Ich möchte erwähnen, dass viele dynamische Sprachen, die ich gesehen habe (z. B. Python), viel bessere Möglichkeiten haben, die Methoden/Klassen zu ändern, ohne den bestehenden Code zu zerstören.

Wenn Ihre Methode in Python beispielsweise früher zwei Parameter akzeptierte, jetzt aber einen dritten benötigt, können Sie immer einen Standardparameter hinzufügen, ohne den bestehenden Code zu verändern, den Sie jetzt aber verwenden können. Dies ist eine sehr einfache Technik, aber im Fall von Python (und ich nehme an, auch bei den meisten anderen dynamischen Sprachen) können diese Techniken viel interessanter werden; da sie dynamisch sind, können Sie die Implementierung von Funktionen für bestimmte Module ziemlich genau ändern, die Bedeutung von Variablen ändern, usw.

Ich würde vorschlagen, zu schauen, welche Techniken Clojure hat, die ähnliche Dinge ermöglichen, und zu entscheiden, ob sie in Ihrer Situation gelten.

2voto

tomjen Punkte 3685

Sie tun dasselbe, was Sie tun würden, wenn die Methode Teil einer öffentlichen Schnittstelle wäre, deren einziger Benutzer Sie nicht wären.

Sie fügen eine neue Methode mit dem zusätzlichen Modul hinzu und ändern die alte Methode so, dass sie die neue Methode mit einem geeigneten Standardwert aufruft.

Oh, und wenn Ihr Programm so groß ist, stellen Sie sicher, dass Sie gute Tests haben (test-is sollte es einfacher machen als Java)

1voto

ndp Punkte 20756

Die Testabdeckung ist definitiv wichtig. Aber eine dynamisch typisierte Sprache erlaubt es Ihnen, auf eine andere Weise zu arbeiten. In einer stark typisierten Sprache (wie Java) muss eine Änderung an der Schnittstelle alle Aufrufer ändern. In Ruby könnten Sie das tun, werden es aber wahrscheinlich nicht tun. Stattdessen werden Sie die Methode auf eine von mehreren Arten flexibel machen. Nämlich:

  • gibt es in Ruby (im Gegensatz zu Java) nur sehr wenige Methoden, die bis zu drei Parameter benötigen. Da man keine stark typisierte Schnittstelle wie in Java hat, kann man das Problem in kleinere Teile und Schritte zerlegen. Es ist viel üblicher, Methoden zu schreiben, die nur einen Parameter benötigen, und dann zu refaktorisieren, wenn es komplexer wird.
  • ist es möglich - und üblich -, das alte Verhalten beizubehalten und gleichzeitig weitere Argumente hinzuzufügen. Wenn Sie beispielsweise ein drittes Argument zu einer Methode mit zwei Argumenten hinzufügen müssen, setzen Sie dessen Standardwert, um das alte Verhalten beizubehalten (und Ihnen eine Umstrukturierung zu ersparen). Wenn Sie mit Javascript-Bibliotheken wie jQuery vertraut sind, machen sie sich dies überall mit "optionalen" Argumenten zunutze.
  • Ähnlich wie bei optionalen Argumenten können Methoden eine flexible Parameterliste annehmen. Mit einer soliden Testabdeckung können Sie ganz einfach ein neues Verhalten zu einer bestehenden Methode hinzufügen und sicher sein, dass Sie den bestehenden Code nicht beschädigt haben. In Rails können Methoden wie "render" eine breite Palette von Optionen annehmen.

1voto

Jim Downing Punkte 1471

Sie sind nicht völlig ohne Compiler-Unterstützung in Clojure. In dem konkreten Beispiel, das Sie anführen, hat sich die Arität der Funktion geändert, was beim Kompilieren des Clojure-Codes erkannt werden würde. Ich mache immer noch den Übergang von der starken zur dynamischen Typisierung und finde das beruhigend!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X