Gibt es einen Zusammenhang zwischen dem Umfang des Projekts und der Strenge der Sprache?

72

Als ich einem Kollegen den Unterschied zwischen der Strenge von Sprachen und Paradigmen erklärte, stellte ich fest, dass:

  • Tolerante Sprachen wie dynamische und interpretierte Sprachen werden am besten für Prototypen und kleine Projekte oder mittelgroße Webanwendungen verwendet. Bei der Auswahl eleganter dynamischer Sprachen wie Python oder JavaScript mit Node.js ergeben sich folgende Vorteile:

    1. Schnelle Entwicklung,

    2. Reduzierter Kesselschildcode,

    3. Die Fähigkeit, junge, kreative Programmierer anzuziehen, die aus Unternehmenssprachen   wie Java fliehen .

  • Statisch typisierte / kompilierte Sprachen eignen sich am besten für Anwendungen, die eine höhere Genauigkeit erfordern, z. B. geschäftskritische Apps oder Apps für mittlere bis große Apps.

    1. Bekannte Paradigmen und Muster, die sich über Jahrzehnte entwickelt haben,

    2. Einfache statische Überprüfung

    3. Fähigkeit, viele professionelle Entwickler mit jahrzehntelanger Erfahrung zu finden.

  • Strenge Sprachen wie Haskell, Ada oder Techniken wie Codeverträge in C # sind besser für Systeme, die Sicherheit gegenüber Flexibilität bevorzugen (auch wenn Haskell extrem flexibel sein kann), wie lebenswichtige Systeme und Systeme, die voraussichtlich extrem stabil sind. Die Vorteile sind:

    1. Möglichkeit, zur Kompilierungszeit so viele Bugs wie möglich zu finden,

    2. Einfache statische Überprüfung

    3. Einfache formale Beweise.

Wenn ich mir jedoch die Sprachen und Technologien anschaue, die von großen Unternehmen für Großprojekte verwendet werden, scheint meine Behauptung falsch zu sein . Beispielsweise wird Python erfolgreich für große Systeme wie YouTube oder andere Google-Anwendungen verwendet, die ein hohes Maß an Strenge erfordern.

Gibt es immer noch einen Zusammenhang zwischen dem Umfang des Projekts und der Strenge der Sprache / des Paradigmas, das verwendet werden sollte?

Gibt es einen dritten Faktor, den ich vergessen habe zu berücksichtigen?

Wo irre ich mich

Arseni Mourzenko
quelle
12
Strenge Typprüfung und statische Typprüfung sind nicht dasselbe. Python ist dynamisch typisiert, aber strenger als C. Der Vorteil der statischen Typprüfung liegt nicht in der Strenge an sich, sondern darin, dass die Typen zur Erstellungszeit und nicht zur Laufzeit geprüft werden. Ich habe mich in meiner Karriere wegen des impliziten Castings mit vielen C / C ++ - Problemen befasst.
Gort the Robot
5
Über den Lebenszyklus lässt sich wahrscheinlich etwas sagen: Software, die in Ihrer ersten Kategorie beginnt, kann sich in die anderen weiterentwickeln und die Sprache mit sich ziehen.
Mat
11
Das einzig Elegante an Javascript ist, dass es in den meisten Browsern ausgeführt wird.
JeffO
1
@StevenBurnap: Was den Unterschied zwischen statisch und streng betrifft, kann ich mir nicht mehr einigen. Java ist ein weiterer Punkt im Spektrum, der statisch und zu streng ist. Entwickler beschimpfen häufig die statische Typisierung mit Java als Beispiel, aber ein Großteil dieser Kritik sollte eigentlich an Javas übermäßig strengen Compiler gerichtet werden , nicht an die statische Typisierung im Allgemeinen. Schauen Sie sich Scala auf derselben JVM an, die statisch geschrieben ist, aber aufgrund der fantastischen Typ-Inferenz-Fähigkeiten des Compilers viel weniger ausführlichen Code enthält.
Cornel Masson
2
"Python wird erfolgreich für große Systeme eingesetzt" - was ist hier die Definition von "Erfolg"? Dass es meistens läuft und ein Ergebnis bringt? Ist der erforderliche Test- und Personalaufwand enthalten? Was ist mit Wartbarkeit?
Den

Antworten:

39

Eine interessante Fallstudie zum Thema Skalierung von Projekten, die dynamische und interpretierte Sprache verwenden, finden Sie in Beginning Scala von David Pollak.

Ich suchte nach einer Möglichkeit, den Code in meinem Gehirn einfacher und direkter auszudrücken. Ich habe Ruby und Rails gefunden. Ich fühlte mich befreit. Mit Ruby konnte ich Konzepte in weitaus weniger Codezeilen ausdrücken. Rails war viel einfacher zu verwenden als Spring MVC, Hibernate und die anderen „optimierten“ Java-Webframeworks. Mit Ruby und Rails konnte ich in kürzerer Zeit viel mehr ausdrücken, was in meinem Kopf war. Es war ähnlich wie die Befreiung, die ich empfand, als ich von C ++ nach Java wechselte ...

Als meine Ruby- und Rails-Projekte über einige tausend Codezeilen hinauswuchsen und ich Teammitglieder zu meinen Projekten hinzufügte , wurden die Herausforderungen dynamischer Sprachen offensichtlich.

Wir haben mehr als die Hälfte unserer Programmierzeit für das Schreiben von Tests aufgewendet, und ein Großteil der Produktivitätssteigerungen ging beim Schreiben von Tests verloren . Die meisten Tests wären in Java unnötig gewesen, da die meisten darauf abzielten, sicherzustellen, dass wir die Aufrufer aktualisiert haben, als wir den Code überarbeitet haben, indem wir die Methodennamen oder die Parameteranzahl geändert haben. Außerdem stellte ich fest, dass es bei der Arbeit in Teams, in denen zwei bis vier Teammitglieder sich in Gedanken versammelten, in Ruby gut lief, aber als wir versuchten, neue Mitglieder in das Team zu holen, war es schwierig , die mentalen Verbindungen auf neue Teammitglieder zu übertragen .

Ich habe mich auf die Suche nach einer neuen Sprache und Entwicklungsumgebung gemacht. Ich suchte nach einer Sprache, die so aussagekräftig war wie Ruby, aber so sicher und leistungsstark wie Java ...

Wie Sie sehen, waren die größten Herausforderungen bei der Projektskalierung für den Autor die Testentwicklung und der Wissenstransfer.

Insbesondere geht der Autor ausführlicher auf die Unterschiede beim Schreiben von Tests zwischen dynamisch und statisch getippten Sprachen in Kapitel 7 ein.

Why the Lucky Stiff ... stellt einige von Rubys Metaprogrammkonzepten in Dwemthys Array vor, in denen ein Kaninchen gegen eine Reihe von Kreaturen kämpft. N8han14 hat das Beispiel für die Arbeit in Scala aktualisiert ...

Im Vergleich zum Ruby-Code waren die Bibliotheksteile des Scala-Codes komplexer. Wir mussten viel arbeiten, um sicherzustellen, dass unsere Typen korrekt waren. Wir mussten die Eigenschaften von Creature in den Klassen DupMonster und CreatureCons manuell umschreiben. Das ist mehr Arbeit als method_missing. Wir mussten auch eine Menge Arbeit leisten, um die Unveränderlichkeit unserer Kreaturen und Waffen zu unterstützen.

Andererseits war das Ergebnis viel leistungsfähiger als die Ruby-Version. Wenn wir Tests für unseren Ruby-Code schreiben müssten, um zu testen, was der Scala-Compiler uns zugesichert hat, bräuchten wir viel mehr Codezeilen. Zum Beispiel können wir sicher sein, dass unser Kaninchen keine Axt führen kann. Um diese Gewissheit in Ruby zu erhalten, müssten wir einen Test schreiben, der sicherstellt, dass das Aufrufen |^eines Rabbits fehlschlägt. Unsere Scala-Version stellt sicher, dass nur die für eine bestimmte Kreatur definierten Waffen von dieser Kreatur verwendet werden können, was in Ruby eine Menge Reflexion zur Laufzeit erfordern würde ...


Das Lesen oben kann den Eindruck erwecken, dass das Schreiben von Tests mit zunehmender Größe der Projekte möglicherweise unhandlich wird. Diese Argumentation wäre falsch, wie Beispiele für erfolgreiche sehr große Projekte belegen, die in dieser Frage erwähnt wurden ("Python wird erfolgreich für ... YouTube verwendet").

Die Skalierung der Projekte ist nicht ganz einfach. Sehr große, langlebige Projekte können sich unterschiedliche Testentwicklungsprozesse "leisten", mit Test-Suiten in Produktionsqualität, professionellen Test-Entwicklerteams und anderem Schwergewicht.

Youtube-Testsuiten oder das Java-Kompatibilitätskit führen ein anderes Leben als Tests in einem kleinen Tutorial-Projekt wie Dwemthy's Array .

Mücke
quelle
24

Ihre Behauptung ist nicht falsch. Sie müssen nur etwas tiefer graben.

Einfach gesagt, verwenden große Systeme mehrere Sprachen, nicht nur eine Sprache. Es kann Teile geben, die mit "strengen" Sprachen erstellt wurden, und es kann Teile geben, die mit dynamischen Sprachen erstellt wurden.

In Bezug auf Ihr Google- und YouTube-Beispiel habe ich gehört, dass sie Python hauptsächlich als "Klebstoff" zwischen verschiedenen Systemen verwenden. Nur Google weiß, woraus diese Systeme bestehen, aber ich wette, dass viele der kritischen Systeme von Google unter Verwendung strenger und "korporativer" Sprachen wie C ++ oder Java oder etwas, das sie selbst erstellt haben, wie Go, erstellt wurden.

Es ist nicht so, dass Sie keine toleranten Sprachen für große Systeme verwenden können. Viele Leute sagen, Facebook benutze PHP, aber sie vergessen zu erwähnen, dass Facebook extrem strenge Programmierrichtlinien erstellen musste, um es in dieser Größenordnung effizient zu nutzen.

Ja, für Großprojekte ist ein gewisses Maß an Strenge erforderlich. Dies kann entweder aus der Strenge der Sprache oder des Frameworks oder aus Programmierrichtlinien und Code-Konventionen herrühren. Sie können nicht nur ein paar Hochschulabsolventen schnappen, ihnen Python / Ruby / JavaScript geben und von ihnen erwarten, dass sie Software schreiben, die sich über Millionen von Benutzern erstreckt.

Euphorisch
quelle
"Man kann nicht nur ein paar Hochschulabsolventen" ... "schnappen und von ihnen erwarten, dass sie Software schreiben, die sich über Millionen von Benutzern erstreckt." hätte wohl gereicht.
Farbstoffe
Erwähnenswert ist hier, dass wie bei Google und Python die Verwendung von PHP bei Facebook größtenteils nur als Klebstoff dient ... Meines Wissens nach wird PHP für die meisten Funktionen meist nur als relativ einfacher Client auf einem komplexeren Serversystem verwendet, das normalerweise implementiert wird in einer traditionelleren "schwergewichtigen" Sprache wie Java, C ++, Haskell, OCaML usw.
Jules
"Nur Google weiß, womit diese Systeme gebaut sind" .. Ich habe sogar einige Zweifel daran :) Nach meiner Erfahrung kann keine einzelne Entität (Person oder auf andere Weise) alle Teile eines sehr großen Systems auflisten. In vielen Fällen ist in den Schüsseln eines Servers ein längst vergessenes Stück Perl-, Fortran- oder KSH-Skript verborgen, das 'Magic' ausführt.
Mattnz
3

Es gibt zwei Arten von Fehlern, auf die geprüft werden muss: Typfehler (Verketten einer Ganzzahl + Liste von Gleitkommazahlen) und Geschäftslogikfehler (Überweisen von Geld auf ein Bankkonto, Überprüfen, ob das Quellkonto über Geld verfügt).

Der "dynamische" Teil einer dynamischen Programmiersprache ist genau der Ort, an dem die Typprüfung stattfindet. In einer "dynamisch typisierten" Programmiersprache wird die Typprüfung während der Ausführung jeder Anweisung durchgeführt, während in einer "statisch typisierten Sprache" die Typprüfung zur Kompilierungszeit durchgeführt wird. Und Sie können einen Interpreter für eine statische Programmiersprache schreiben (wie es emscriptem tut), und Sie können auch einen statischen Compiler für eine dynamische Programmiersprache schreiben (wie es gcc-python oder shed-skin tut).

In einer dynamischen Programmiersprache wie Python und Javascript müssen Sie Komponententests nicht nur für die Geschäftslogik des Programms schreiben, sondern auch prüfen, ob Ihr Programm keine Syntax- oder Typfehler enthält. Wenn Sie beispielsweise einer Float-Liste "+" eine Ganzzahl hinzufügen (was nicht sinnvoll ist und einen Fehler ausgibt), wird der Fehler in einer dynamischen Sprache zur Laufzeit ausgelöst, während Sie versuchen, die Anweisung auszuführen. In einer statischen Programmiersprache wie C ++, Haskell und Java wird diese Art von Typfehler vom Compiler abgefangen.

Eine kleine Codebasis in einer dynamisch überprüften Programmiersprache ist einfacher, nach Typfehlern zu suchen, da der Quellcode leichter zu 100% abgedeckt wird . Das war's, Sie führen den Code einige Male mit unterschiedlichen Werten von Hand aus und sind fertig. Eine 100% ige Abdeckung des Quellcodes gibt Ihnen einen guten Hinweis darauf, dass Ihr Programm möglicherweise keine Tippfehler enthält .

Mit einer großen Codebasis in einer dynamisch überprüften Programmiersprache ist es schwieriger, jede Anweisung mit jeder möglichen Typkombination zu testen, insbesondere wenn Sie nachlässig sind und eine Funktion schreiben, die abhängig von ihren Argumenten möglicherweise einen String, eine Liste oder ein benutzerdefiniertes Objekt zurückgibt.

In einer statisch überprüften Programmiersprache erkennt der Compiler die meisten Typfehler beim Kompilieren. Ich sage die meisten, weil ein Fehler bei der Division durch Null oder ein Fehler bei einem Array außerhalb der Grenzen auch Typfehler sind.

Meist geht es bei der eigentlichen Diskussion nicht um Programmiersprachen, sondern um die Menschen, die diese Sprachen verwenden. Dies ist der Fall, weil die Assemblersprache beispielsweise genauso leistungsfähig ist wie jede andere Programmiersprache, wir jedoch Code in JavaScript schreiben. Warum? Weil wir Menschen sind. Erstens machen wir alle Fehler und es ist einfacher und weniger fehleranfällig, ein spezielles Tool für eine bestimmte Aufgabe zu verwenden. Zweitens gibt es eine Ressourcenbeschränkung. Wir haben nur eine begrenzte Zeit, und es würde ewig dauern, bis Webseiten für die Montage fertiggestellt sind.

vz0
quelle
3

Meine Erfahrung mit großen Systemen ist, dass sie nicht nach der Wahl der Sprache stehen oder fallen, sondern nach Design- / Architektur- oder Testaspekten . Ich hätte lieber ein talentiertes Python-Team für mein großes Unternehmensprojekt als ein mittelmäßiges Java-Team.

Allerdings muss jede Sprache, mit der Sie deutlich weniger Code schreiben können, einen Blick wert sein (z. B. Python vs Java). Vielleicht liegt die Zukunft in cleveren, statisch typisierten Sprachen mit fortgeschrittener Typinferenz (z. B. in der Scala-Form). Oder Hybrid wie C # versucht es mit seinem dynamicQualifier ...?

Und vergessen wir nicht den "anderen" Vorteil der statischen Typisierung: die ordnungsgemäße IDE-Code-Vervollständigung / Intellisense, die meiner Ansicht nach ein wesentliches Merkmal ist und nicht gut zu haben ist.

Cornel Masson
quelle
1
"Code-Vervollständigung / Intellisense" - automatisiertes Refactoring ist ebenfalls sehr wichtig.
Den
@Den Auf jeden Fall. Könnte es sein, dass dynamische Sprachen Ihnen helfen, erste Versionen sehr schnell zu schreiben (einfacher, weniger Code zu schreiben), sich aber später festsetzen, da es immer schwieriger wird, die Auswirkungen von Änderungen oder Refactorings zu beurteilen (ohne automatisierte Refactoringtools)?
Cornel Masson
0

Eine weitere Überlegung ist, wer hinter dem Schreiben von Großanträgen steht. Ich habe an vielen Orten gearbeitet, die Ruby oder Python für einige große Projekte im Enterprise-Stil verwenden möchten, aber von IT-Managern und Unternehmenssicherheitsteams aufgrund der Open-Source-Natur der Projekte konsequent "abgeschossen" werden.

Mir wurde gesagt: "Wir können Ruby on Rails nicht verwenden, weil es Open Source ist und jemand dort Hacks einsetzen könnte, die kritische oder geschützte Informationen stehlen." Es tut mir leid, aber wenn jemand diese Einstellung zu Open Source == böse hat, ist es fast unmöglich, dies zu ändern. Diese Denkweise ist eine korporative Krankheit.

C # und Java sind vertrauenswürdige Sprachen mit vertrauenswürdigen Plattformen. Ruby und Python sind keine vertrauenswürdigen Sprachen.

Jarrett Meyer
quelle
2
Ich bin mit der letzten Zeile nicht einverstanden. Java befindet sich an einem der niedrigsten Vertrauenspunkte aller Zeiten. C # wird von der gesamten Open-Source-Community mit Bedacht betrachtet. Ruby gilt als solide, aber langsam (auch wenn es nicht mehr ist) und Python ist das vertrauenswürdige Arbeitspferde-Glamourkind der gesamten Branche (maschinelles Lernen und Datenwissenschaft, wer?).
CodeBeard
1
Dynamische Sprachen sind sicherheitsschädlich, aber "Open Source" ist kein guter Grund. Vielleicht meinten sie "es ist einfach, einen Teil des Codes von einem ganz anderen Teil des Codes aus zu beeinflussen". Siehe programmers.stackexchange.com/questions/206558/…
Euphoric
1
Beachten Sie, dass "offene Quellen" in der Tat einer der Aspekte bei der Wahl einer Sprache ist. Das ist zum Beispiel einer von drei Gründen, die Jeff Atwood genannt hat, um zu erklären, warum Discourse Ruby verwendet.
Arseni Mourzenko
C # ist jetzt komplett Open-Source, wird aber immer noch von professionellen Entwicklern kuratiert, geplant und entwickelt, was ich denke, sehr schön ist. Hoffen wir, dass "Python 3 vs 2" hier nicht vorkommt.
Den
Bugs und Sicherheitslücken werden von Programmierern und nicht von Sprachen eingeführt, und ich habe eine Reihe von Sicherheitsverbesserungen für Open Source-Projekte vorgenommen. Wie vielen abgeschlossenen Projekten habe ich geholfen ??? Null!
Reactgular