Wie ist statisches Tippen in größeren Projekten wirklich hilfreich?

9

Beim Kuriosieren auf der Hauptseite einer Website einer Skript-Programmiersprache bin ich auf folgende Passage gestoßen:

Wenn ein System zu groß wird, um im Kopf zu bleiben, können Sie statische Typen hinzufügen.

Dies erinnerte mich daran, dass in vielen Religionskriegen zwischen statischen, kompilierten Sprachen (wie Java) und dynamischen, interpretierten Sprachen (hauptsächlich Python, weil es häufiger verwendet wird, aber es ist ein "Problem", das von den meisten Skriptsprachen geteilt wird) eine der Beschwerden von statisch ist Fans typisierter Sprachen gegenüber dynamisch getippten Sprachen sind, dass sie sich nicht gut für größere Projekte skalieren lassen, weil "eines Tages Sie den Rückgabetyp einer Funktion vergessen und nachschlagen müssen, während bei statisch typisierten Sprachen alles vorhanden ist wird ausdrücklich deklariert ".

Ich habe solche Aussagen nie verstanden. Um ehrlich zu sein, selbst wenn Sie den Rückgabetyp einer Funktion deklarieren, können und werden Sie ihn vergessen, nachdem Sie viele Codezeilen geschrieben haben, und Sie müssen immer noch zu der Zeile zurückkehren, in der sie mit der Suchfunktion von deklariert wurde Ihr Texteditor, um es zu überprüfen.

Wenn Funktionen mit deklariert werden type funcname()..., ohne zu wissen, dass typeSie über jede Zeile suchen müssen, in der die Funktion aufgerufen wird, weil Sie nur wissen funcname, während Sie in Python und dergleichen nur suchen def funcnameoder function funcnamewas nur einmal vorkommt die Erklärung.

Darüber hinaus ist es bei REPLs trivial, eine Funktion auf ihren Rückgabetyp mit verschiedenen Eingaben zu testen, während Sie bei statisch typisierten Sprachen einige Codezeilen hinzufügen und alles neu kompilieren müssen, um den deklarierten Typ zu kennen.

Wie ist die statische Typisierung in größeren Projekten wirklich hilfreich, außer um den Rückgabetyp einer Funktion zu kennen, die eindeutig keine Stärke statisch typisierter Sprachen ist?

user6245072
quelle
2
Wenn Sie die Antworten auf die andere Frage lesen, werden Sie wahrscheinlich die Antworten erhalten, die Sie für diese Frage benötigen. Sie fragen im Grunde das Gleiche aus verschiedenen Perspektiven :)
Sara
1
Swift und Spielplätze sind eine REPL einer statisch typisierten Sprache.
daven11
2
Sprachen werden nicht kompiliert, Implementierungen sind. Die Möglichkeit, eine REPL für eine "kompilierte" Sprache zu schreiben, besteht darin, etwas zu schreiben, das die Sprache interpretieren oder zumindest Zeile für Zeile kompilieren und ausführen kann, wobei der erforderliche Status beibehalten wird. Außerdem wird Java 9 mit einer REPL ausgeliefert.
Sebastian Redl
2
@ user6245072: So erstellen Sie eine REPL für einen Interpreter: Lesen Sie den Code, senden Sie ihn an den Interpreter, drucken Sie das Ergebnis aus. So erstellen Sie eine REPL für einen Compiler: Lesen Sie den Code, senden Sie ihn an den Compiler, führen Sie den kompilierten Code aus und drucken Sie das Ergebnis aus. Einfach wie Torte. Genau das tun FSi (F♯ REPL), GHCi (GHC Haskells REPL), Scala REPL und Cling.
Jörg W Mittag

Antworten:

21

Darüber hinaus ist es bei REPLs trivial, eine Funktion auf ihren Rückgabetyp mit verschiedenen Eingaben zu testen

Es ist nicht trivial. Es ist nicht trivial überhaupt . Es ist nur trivial, dies für triviale Funktionen zu tun.

Sie können beispielsweise trivial eine Funktion definieren, bei der der Rückgabetyp vollständig vom Eingabetyp abhängt.

getAnswer(v) {
 return v.answer
}

In diesem Fall getAnswernicht wirklich hat einen einzigen Rückgabetyp. Es gibt keinen Test, den Sie jemals schreiben können, der dies mit einer Beispieleingabe aufruft, um den Rückgabetyp zu ermitteln. Es wird immer vom tatsächlichen Argument abhängen. Zur Laufzeit.

Und dies schließt nicht einmal Funktionen ein, die z. B. Datenbanksuchen durchführen. Oder machen Sie Dinge basierend auf Benutzereingaben. Oder suchen Sie nach globalen Variablen, die natürlich vom dynamischen Typ sind. Oder ändern Sie den Rückgabetyp in zufälligen Fällen. Ganz zu schweigen von der Notwendigkeit, jede einzelne Funktion jedes Mal manuell zu testen.

getAnswer(x, y) {
   if (x + y.answer == 13)
       return 1;
   return "1";
}

Grundsätzlich ist es mathematisch unmöglich, den Rückgabetyp der Funktion im allgemeinen Fall zu beweisen (Halting Problem). Die einzige Möglichkeit, den Rückgabetyp zu garantieren, besteht darin, die Eingabe so einzuschränken, dass die Beantwortung dieser Frage nicht in den Bereich des Halteproblems fällt, indem Programme, die nicht nachweisbar sind, nicht zugelassen werden. Dies ist die Aufgabe der statischen Typisierung.

Da Funktionen mit dem Typ funcname () ... deklariert sind, müssen Sie ohne Kenntnis des Typs jede Zeile durchsuchen, in der die Funktion aufgerufen wird, da Sie nur den Funktionsnamen kennen, während Sie in Python und dergleichen nur cd Suche nach def funcname oder function funcname, was bei der Deklaration nur einmal vorkommt.

Statisch typisierte Sprachen haben Dinge, die "Werkzeuge" genannt werden. Dies sind Programme, die Ihnen helfen, Dinge mit Ihrem Quellcode zu tun. In diesem Fall würde ich dank Resharper einfach mit der rechten Maustaste klicken und zur Definition gehen. Oder verwenden Sie die Tastenkombination. Oder fahren Sie einfach mit der Maus darüber und es wird mir sagen, um welche Typen es sich handelt. Es ist mir nicht im geringsten wichtig, Dateien zu greifen. Ein Texteditor allein ist ein erbärmliches Werkzeug zum Bearbeiten des Programmquellcodes.

Aus dem Speicher def funcnamewürde in Python nicht ausreichen, da die Funktion beliebig neu zugewiesen werden könnte. Oder könnte in mehreren Modulen wiederholt deklariert werden. Oder im Unterricht. Etc.

und Sie müssen immer noch zu der Zeile zurückkehren, in der es deklariert wurde, indem Sie die Suchfunktion Ihres Texteditors verwenden, um dies zu überprüfen.

Das Durchsuchen von Dateien nach dem Funktionsnamen ist eine schreckliche primitive Operation, die niemals erforderlich sein sollte. Dies stellt einen grundlegenden Fehler Ihrer Umgebung und Ihrer Werkzeuge dar. Die Tatsache, dass Sie sogar in Betracht ziehen würden, eine Textsuche in Python zu benötigen, ist ein massiver Punkt gegen Python.

DeadMG
quelle
2
Um fair zu sein, diese "Werkzeuge" wurden in dynamischen Sprachen erfunden, und dynamische Sprachen hatten sie lange vor statischen Sprachen. Gehe zu Definition, Code-Vervollständigung, automatisiertem Refactoring usw. gab es in grafischen Lisp- und Smalltalk-IDEs, bevor statische Sprachen überhaupt Grafiken oder IDEs hatten, geschweige denn grafische IDEs.
Jörg W Mittag
Wenn Sie den Rückgabetyp von Funktionen kennen, wissen Sie nicht immer, welche Funktionen dies tun . Anstatt Typen zu schreiben, könnten Sie Doc-Tests mit Beispielwerten geschrieben haben. Vergleichen Sie zum Beispiel (Wörter 'einige Wörter oue') => ['einige', 'Wörter', 'oeu'] mit (Wörtern Zeichenfolge) -> [Zeichenfolge], (zip {abc} [1..3]) => [(a, 1), (b, 2), (c, 3)] mit seinem Typ.
aoeu256
18

Denken Sie an ein Projekt mit vielen Programmierern, das sich im Laufe der Jahre geändert hat. Sie müssen dies beibehalten. Es gibt eine Funktion

getAnswer(v) {
 return v.answer
}

Was um alles in der Welt macht es? Was ist v? Woher kommt das Element answer?

getAnswer(v : AnswerBot) {
  return v.answer
}

Jetzt haben wir noch ein paar Infos -; es braucht eine Art von AnswerBot.

Wenn wir zu einer klassenbasierten Sprache gehen, können wir sagen

class AnswerBot {
  var answer : String
  func getAnswer() -> String {
    return answer
  }
}

Jetzt können wir eine Variable vom Typ haben AnswerBotund die Methode aufrufen, getAnswerund jeder weiß, was sie tut. Alle Änderungen werden vom Compiler abgefangen, bevor Laufzeitprüfungen durchgeführt werden. Es gibt viele andere Beispiele, aber vielleicht kommt Ihnen das auf die Idee?

daven11
quelle
1
Sieht schon klarer aus - es sei denn, Sie weisen darauf hin, dass eine solche Funktion keinen Grund hat zu existieren, aber das ist natürlich nur ein Beispiel.
user6245072
Das ist das Problem, wenn Sie mehrere Programmierer in einem großen Projekt haben, solche Funktionen existieren (und schlimmer noch), es sind Albträume. Berücksichtigen Sie auch, dass sich Funktionen in dynamischen Sprachen im globalen Namespace befinden, sodass Sie im Laufe der Zeit einige getAnswer-Funktionen haben können - und beide funktionieren und sie sind beide unterschiedlich, da sie zu unterschiedlichen Zeiten geladen werden.
Daven11
1
Ich denke, es ist ein Missverständnis der funktionalen Programmierung, das das verursacht. Was meinen Sie jedoch damit, dass sie sich im globalen Namespace befinden?
user6245072
3
"Funktionen in dynamischen Sprachen sind standardmäßig im globalen Namespace enthalten" Dies ist ein sprachspezifisches Detail und keine Einschränkung, die durch dynamische Typisierung verursacht wird.
Sara
2
@ daven11 "Ich denke hier an Javascript", aber andere dynamische Sprachen haben tatsächliche Namespaces / Module / Pakete und können Sie bei Neudefinitionen warnen. Möglicherweise verallgemeinern Sie etwas.
Coredump
10

Sie scheinen einige Missverständnisse über die Arbeit mit großen statischen Projekten zu haben, die Ihr Urteilsvermögen trüben könnten. Hier sind einige Hinweise:

Selbst wenn Sie den Rückgabetyp einer Funktion deklarieren, können und werden Sie ihn vergessen, nachdem Sie viele Codezeilen geschrieben haben, und Sie müssen immer noch zu der Zeile zurückkehren, in der er mit der Suchfunktion Ihres Texteditors deklariert wurde prüfen Sie.

Die meisten Leute, die mit statisch typisierten Sprachen arbeiten, verwenden entweder eine IDE für die Sprache oder einen intelligenten Editor (wie vim oder emacs), der in sprachspezifische Tools integriert ist. In diesen Tools gibt es normalerweise eine schnelle Möglichkeit, den Typ einer Funktion zu finden. Bei Eclipse in einem Java-Projekt gibt es beispielsweise zwei Möglichkeiten, den Typ einer Methode zu ermitteln:

  • Wenn ich eine Methode für ein anderes Objekt als 'this' verwenden möchte, gebe ich eine Referenz und einen Punkt (z. B. someVariable.) ein, und Eclipse sucht nach dem Typ von someVariableund stellt eine Dropdown-Liste aller in diesem Typ definierten Methoden bereit. Während ich in der Liste nach unten scrolle, werden Typ und Dokumentation der einzelnen Elemente angezeigt, während sie ausgewählt sind. Beachten Sie, dass dies mit einer dynamischen Sprache sehr schwierig zu erreichen ist, da es für den Editor schwierig (oder in einigen Fällen unmöglich) someVariableist, den Typ zu bestimmen , sodass er nicht einfach die richtige Liste erstellen kann. Wenn ich eine Methode für verwenden möchte, thiskann ich einfach Strg + Leertaste drücken, um dieselbe Liste zu erhalten (obwohl dies in diesem Fall für dynamische Sprachen nicht so schwer zu erreichen ist).
  • Wenn ich bereits einen Verweis auf eine bestimmte Methode habe, kann ich den Mauszeiger darüber bewegen und der Typ und die Dokumentation für die Methode werden in einem Tooltip angezeigt.

Wie Sie sehen können, ist dies etwas besser als das typische Tool, das für dynamische Sprachen verfügbar ist (nicht, dass dies in dynamischen Sprachen unmöglich ist, da einige über eine ziemlich gute IDE-Funktionalität verfügen - Smalltalk fällt mir ein -, aber es ist schwieriger für eine dynamische Sprache und daher weniger wahrscheinlich verfügbar).

Da Funktionen mit dem Typ funcname () ... deklariert sind, müssen Sie ohne Kenntnis des Typs jede Zeile durchsuchen, in der die Funktion aufgerufen wird, da Sie nur den Funktionsnamen kennen, während Sie in Python und dergleichen nur cd Suche nach def funcname oder function funcname, was bei der Deklaration nur einmal vorkommt.

Statische Sprachwerkzeuge bieten normalerweise semantische Suchfunktionen, dh sie können die Definition und Verweise auf bestimmte Symbole genau finden, ohne dass eine Textsuche durchgeführt werden muss. Wenn ich beispielsweise Eclipse für ein Java-Projekt verwende, kann ich ein Symbol im Texteditor markieren und mit der rechten Maustaste darauf klicken und entweder "Zur Definition gehen" oder "Referenzen suchen" auswählen, um eine dieser Operationen auszuführen. Sie müssen nicht nach dem Text einer Funktionsdefinition suchen, da Ihr Editor bereits genau weiß, wo er sich befindet.

Das Umgekehrte ist jedoch, dass die Suche nach einer Methodendefinition per Text in einem großen dynamischen Projekt nicht so gut funktioniert, wie Sie vorschlagen, da es in einem solchen Projekt leicht mehrere Methoden mit demselben Namen geben kann und Sie wahrscheinlich keine haben leicht verfügbare Tools, um zu unterscheiden, welches von ihnen Sie aufrufen (da solche Tools bestenfalls schwer zu schreiben oder im allgemeinen Fall unmöglich sind), müssen Sie dies also von Hand tun.

Darüber hinaus ist es bei REPLs trivial, eine Funktion auf ihren Rückgabetyp mit verschiedenen Eingaben zu testen

Es ist nicht unmöglich, eine REPL für eine statisch typisierte Sprache zu haben. Haskell ist das Beispiel, das mir in den Sinn kommt, aber es gibt auch REPLs für andere statisch typisierte Sprachen. Der Punkt ist jedoch, dass Sie keinen Code ausführen müssen, um den Rückgabetyp einer Funktion in einer statischen Sprache zu finden - er kann durch Prüfung ermittelt werden, ohne dass etwas ausgeführt werden muss.

Bei statisch typisierten Sprachen müssten Sie einige Codezeilen hinzufügen und alles neu kompilieren, um den deklarierten Typ zu kennen.

Selbst wenn Sie dies tun müssten, müssten Sie wahrscheinlich nicht alles neu kompilieren . Die meisten modernen statischen Sprachen verfügen über inkrementelle Compiler, die nur den kleinen Teil Ihres Codes kompilieren, der sich geändert hat, sodass Sie bei Tippfehlern fast sofort eine Rückmeldung für Typfehler erhalten. Eclipse / Java beispielsweise hebt Tippfehler hervor, während Sie sie noch eingeben .

Jules
quelle
4
You seem to have a few misconceptions about working with large static projects that may be clouding your judgement.Nun, ich bin erst 14 Jahre alt und programmiere nur ab weniger als einem Jahr auf Android, also ist es möglich, denke ich.
user6245072
1
Selbst ohne IDE gibt Ihnen jeder Java-Compiler eine Liste aller Zeilen, die diese Methode verwendet haben, wenn Sie eine Methode aus einer Klasse in Java entfernen und es Dinge gibt, die von dieser Methode abhängen. In Python schlägt dies fehl, wenn der ausführende Code die fehlende Methode aufruft. Ich benutze sowohl Java als auch Python regelmäßig und ich liebe Python dafür, wie schnell Sie Dinge zum Laufen bringen können und welche coolen Dinge Sie tun können, die Java nicht unterstützt, aber die Realität ist, dass ich Probleme in Python-Programmen habe, die einfach nicht passieren (gerade) Java. Insbesondere das Refactoring ist in Python viel schwieriger.
JimmyJames
6
  1. Weil statische Prüfer für statisch typisierte Sprachen einfacher sind.
    • Zumindest ohne dynamische Sprachfunktionen gibt es zur Laufzeit keine ungelösten Funktionen, wenn es kompiliert wird. Dies ist in ADA-Projekten und C auf Mikrocontrollern üblich. (Mikrocontroller-Programme werden manchmal groß ... wie Hunderte von Klocs groß.)
  2. Statische Kompilierungsreferenzprüfungen sind eine Teilmenge von Funktionsinvarianten, die in einer statischen Sprache auch zur Kompilierungszeit überprüft werden können.
  3. Statische Sprachen haben normalerweise mehr referenzielle Transparenz. Das Ergebnis ist, dass ein neuer Entwickler in eine einzelne Datei eintauchen und einige der Vorgänge verstehen und einen Fehler beheben oder eine kleine Funktion hinzufügen kann, ohne all die seltsamen Dinge in der Codebasis kennen zu müssen.

Vergleichen Sie beispielsweise mit Javascript, Ruby oder Smalltalk, wo Entwickler zur Laufzeit die Kernsprachenfunktionen neu definieren. Dies erschwert das Verständnis des großen Projekts.

Größere Projekte haben nicht nur mehr Leute, sie haben auch mehr Zeit. Genug Zeit für alle, um zu vergessen oder weiterzumachen.

Anekdotischerweise hat ein Bekannter von mir eine sichere "Job For Life" -Programmierung in Lisp. Niemand außer dem Team kann die Codebasis verstehen.

Tim Williscroft
quelle
Anecdotally, an acquaintance of mine has a secure "Job For Life" programming in Lisp. Nobody except the team can understand the code-base.ist es wirklich so schlimm Hilft ihnen die hinzugefügte Personalisierung nicht, produktiver zu sein?
user6245072
@ user6245072 Es mag ein Vorteil für die Leute sein, die derzeit dort arbeiten, aber es macht die Rekrutierung neuer Leute schwieriger. Es braucht mehr Zeit, um jemanden zu finden, der bereits eine Nicht-Mainstream-Sprache kennt, oder um ihm eine beizubringen, die er noch nicht kennt. Dies kann es für das Projekt schwieriger machen, zu skalieren, wenn es erfolgreich ist, oder sich von Schwankungen zu erholen - Menschen ziehen weg, werden in andere Positionen befördert ... Nach einer Weile kann es auch für die Spezialisten selbst ein Nachteil sein - Wenn Sie erst seit etwa einem Jahrzehnt eine Nischensprache geschrieben haben, kann es schwierig sein, zu etwas Neuem überzugehen.
Hulk
Können Sie nicht einfach einen Tracer verwenden, um Unit-Tests aus dem laufenden Lisp-Programm zu erstellen? Wie in Python können Sie einen Dekorator (Adverb) namens print_args erstellen, der eine Funktion übernimmt und eine geänderte Funktion zurückgibt, die ihr Argument ausgibt. Sie können es dann in sys.modules auf das gesamte Programm anwenden. Eine einfachere Möglichkeit ist jedoch die Verwendung von sys.set_trace.
aoeu256
@ aoeu256 Ich bin nicht mit den Funktionen der Lisp-Laufzeitumgebung vertraut. Sie verwendeten jedoch häufig Makros, sodass kein normaler Lisp-Programmierer den Code lesen konnte. Es ist wahrscheinlich, dass der Versuch, "einfache" Dinge zur Laufzeit zu tun, nicht funktionieren kann, da die Makros alles an Lisp ändern.
Tim Williscroft
@ TimWilliscroft Sie können warten, bis alle Makros erweitert sind, bevor Sie solche Dinge tun. Emacs verfügt über viele Tastenkombinationen, mit denen Sie Makros (und möglicherweise Inline-Funktionen) inline erweitern können.
aoeu256
4

Ich habe solche Aussagen nie verstanden. Um ehrlich zu sein, selbst wenn Sie den Rückgabetyp einer Funktion deklarieren, können und werden Sie ihn vergessen, nachdem Sie viele Codezeilen geschrieben haben, und Sie müssen immer noch zu der Zeile zurückkehren, in der sie mit der Suchfunktion von deklariert wurde Ihr Texteditor, um es zu überprüfen.

Es geht nicht darum, dass Sie den Rückgabetyp vergessen - das wird immer passieren. Es geht darum, dass das Tool Sie darüber informieren kann, dass Sie den Rückgabetyp vergessen haben.

Da Funktionen mit Typ deklariert sind funcname()..., müssen Sie ohne Kenntnis des Typs jede Zeile durchsuchen, in der die Funktion aufgerufen wird, da Sie nur wissen funcname, während Sie in Python und dergleichen nur suchen können def funcnameoder function funcnamewas nur einmal vorkommt bei der Erklärung.

Dies ist eine Frage der Syntax, die völlig unabhängig von der statischen Typisierung ist.

Die Syntax der C-Familie ist in der Tat unfreundlich, wenn Sie eine Deklaration nachschlagen möchten, ohne über spezielle Tools zu verfügen. Andere Sprachen haben dieses Problem nicht. Siehe Rusts Deklarationssyntax:

fn funcname(a: i32) -> i32

Darüber hinaus ist es bei REPLs trivial, eine Funktion auf ihren Rückgabetyp mit verschiedenen Eingaben zu testen, während Sie bei statisch typisierten Sprachen einige Codezeilen hinzufügen und alles neu kompilieren müssen, um den deklarierten Typ zu kennen.

Jede Sprache kann interpretiert werden und jede Sprache kann eine REPL haben.


Wie ist statische Typisierung in größeren Projekten wirklich hilfreich, außer den Rückgabetyp einer Funktion zu kennen, die eindeutig keine Stärke statisch typisierter Sprachen ist?

Ich werde abstrakt antworten.

Ein Programm besteht aus verschiedenen Operationen, und diese Operationen sind aufgrund einiger Annahmen, die der Entwickler trifft, so angeordnet, wie sie sind.

Einige Annahmen sind implizit und andere explizit. Einige Annahmen betreffen eine Operation in ihrer Nähe, andere eine Operation außerhalb von ihnen. Eine Annahme ist leichter zu identifizieren, wenn sie explizit und so nah wie möglich an den Stellen ausgedrückt wird, an denen ihr Wahrheitswert wichtig ist.

Ein Fehler ist die Manifestation einer Annahme, die im Programm vorhanden ist, aber in einigen Fällen nicht gilt. Um einen Fehler aufzuspüren, müssen wir die falsche Annahme identifizieren. Um den Fehler zu beseitigen, müssen wir entweder diese Annahme aus dem Programm entfernen oder etwas ändern, damit die Annahme tatsächlich gilt.

Ich möchte Annahmen in zwei Arten einteilen.

Die erste Art sind die Annahmen, die abhängig von den Eingaben des Programms gelten können oder nicht. Um eine fehlerhafte Annahme dieser Art zu identifizieren, müssen wir im Raum aller möglichen Eingaben des Programms suchen. Mit fundierten Vermutungen und rationalem Denken können wir das Problem eingrenzen und auf viel kleinerem Raum suchen. Da ein Programm jedoch nur ein wenig wächst, wächst sein anfänglicher Eingaberaum mit einer enormen Geschwindigkeit - bis zu dem Punkt, an dem es für alle praktischen Zwecke als unendlich betrachtet werden kann.

Die zweite Art sind die Annahmen, die definitiv für alle Eingaben gelten oder definitiv für alle Eingaben falsch sind. Wenn wir eine solche Annahme als falsch identifizieren, müssen wir nicht einmal das Programm ausführen oder Eingaben testen. Wenn wir eine solche Annahme als richtig identifizieren, müssen wir uns um einen Verdächtigen weniger kümmern, wenn wir einen Fehler (einen beliebigen Fehler) aufspüren . Es ist daher sinnvoll, möglichst viele Annahmen zu dieser Art zu haben.

Um eine Annahme in die zweite Kategorie einzuteilen (immer wahr oder immer falsch, unabhängig von Eingaben), benötigen wir eine Mindestmenge an Informationen, um an dem Ort verfügbar zu sein, an dem die Annahme getroffen wird. Im gesamten Quellcode eines Programms werden Informationen ziemlich schnell veraltet (zum Beispiel führen viele Compiler keine Interprocedural-Analyse durch, was jeden Aufruf zu einer harten Grenze für die meisten Informationen macht). Wir brauchen eine Möglichkeit, die erforderlichen Informationen aktuell zu halten (gültig und in der Nähe).

Eine Möglichkeit besteht darin, die Quelle dieser Informationen so nah wie möglich an dem Ort zu haben, an dem sie konsumiert werden sollen. Dies kann jedoch für die meisten Anwendungsfälle unpraktisch sein. Eine andere Möglichkeit besteht darin, die Informationen häufig zu wiederholen und ihre Relevanz im gesamten Quellcode zu erneuern.

Wie Sie bereits erraten können, sind statische Typen genau das - Beacons mit Typinformationen, die über den Quellcode verteilt sind. Diese Informationen können verwendet werden, um die meisten Annahmen über die Typkorrektheit in die zweite Kategorie aufzunehmen, was bedeutet, dass fast jede Operation in Bezug auf die Typkompatibilität als immer korrekt oder immer falsch klassifiziert werden kann.

Wenn unsere Typen falsch sind, spart uns die Analyse Zeit, indem wir den Fehler eher früh als spät auf uns aufmerksam machen. Wenn unsere Typen korrekt sind, spart uns die Analyse Zeit, indem sichergestellt wird, dass wir bei Auftreten eines Fehlers Tippfehler sofort ausschließen können.

Theodoros Chatzigiannakis
quelle
3

Sie erinnern sich an das alte Sprichwort "Müll rein, Müll raus". Nun, das ist es, was statische Eingabe verhindert. Es ist kein universelles Allheilmittel, aber die Strenge darüber, welche Art von Daten eine Routine akzeptiert und zurückgibt, bedeutet, dass Sie die Gewissheit haben, dass Sie richtig damit arbeiten.

Eine getAnswer-Routine, die eine Ganzzahl zurückgibt, ist daher nicht hilfreich, wenn Sie versuchen, sie in einem stringbasierten Aufruf zu verwenden. Die statische Eingabe sagt Ihnen bereits, dass Sie aufpassen müssen, dass Sie wahrscheinlich einen Fehler machen. (und sicher, Sie können es dann überschreiben, aber Sie müssen genau wissen, was Sie tun, und es im Code mithilfe einer Besetzung angeben. Im Allgemeinen möchten Sie dies jedoch nicht tun - Hacking in a runder Stift in ein quadratisches Loch funktioniert am Ende nie gut)

Jetzt können Sie mit komplexen Typen noch weiter gehen, indem Sie eine Klasse mit Erzfunktionalität erstellen, diese weitergeben und plötzlich viel mehr Struktur in Ihrem Programm erhalten. Strukturierte Programme sind viel einfacher zu verwalten und zu warten.

gbjbaanb
quelle
Sie müssen keine statische Typinferenz (pylint) durchführen, sondern können eine dynamische Typinferenz durchführen chrislaffra.blogspot.com/2016/12/…, die auch vom JIT-Compiler von PyPy durchgeführt wird. Es gibt auch eine andere Version der dynamischen Typinferenz, bei der ein Computer zufällig Scheinobjekte in die Argumente einfügt und erkennt, was einen Fehler verursacht. Das Problem des Anhaltens spielt in 99% der Fälle keine Rolle. Wenn Sie sich zu viel Zeit nehmen, stoppen Sie einfach den Algorithmus (so behandelt Python die unendliche Rekursion, es kann ein Rekursionslimit festgelegt werden).
aoeu256