Was sind die Vor- und Nachteile einer bestimmten Programmiersprache? Ist X eine gute Sprache für meine Aufgabe? Wenn Sie die „beste Programmiersprache“ googeln, erhalten Sie eine Standardliste mit „Python, Java, JavaScript, C #, C ++, PHP“ und einer vagen Liste mit Vor- und Nachteilen. Wenn ich solche Artikel sehe, erschrecke ich – ihre Autoren müssen geradezu faul, unerfahren und ohne Vorstellungskraft gewesen sein. Lassen Sie uns tief eintauchen und herausfinden, was wirklich scheiße ist – und was nicht.
In diesem Artikel werde ich versuchen, einen objektiven und hoffentlich unvoreingenommenen Überblick über beliebte (und nicht so beliebte) moderne Programmiersprachen zu geben, die vom schlechtesten zum besten bewertet werden.
Denken Sie daran, es gibt keine perfekte Programmiersprache. Einige eignen sich am besten für die Back-End- / API-Entwicklung, andere eignen sich hervorragend für die Systemprogrammierung.
Ich werde zwei der häufigsten Sprachfamilien der Welt behandeln: Sprachen, die von C abstammen , und Sprachen, die von ML abstammen .
Programmiersprachen sind nur Werkzeuge in der Toolbox eines Entwicklers. Es ist wichtig, das richtige Werkzeug für den Job auszuwählen. Ich hoffe sehr, dass dieser Leitfaden Ihnen bei der Auswahl der für Ihre Aufgabe am besten geeigneten Programmiersprache hilft. Wenn Sie die richtige Wahl treffen, sparen Sie möglicherweise Monate (oder sogar Jahre) Entwicklungsaufwand.
Welche Sprachmerkmale sind wirklich wichtig?
Die meisten ähnlichen Artikel stützen ihre Vergleiche auf Faktoren wie Popularität und Verdienstmöglichkeiten . Popularität ist selten eine gute Maßnahme, insbesondere in der Welt der Software (obwohl eine große Community und ein großes Ökosystem helfen). Stattdessen werde ich die Stärken und Schwächen einer bestimmten Sprache berücksichtigen .
Ich verwende ein Daumen hoch-👍 (dh +1), ein Daumen-runter em oder ein OK em (weder gut noch schlecht) Emojis, um die Punktzahl eines bestimmten Sprachmerkmals zu kennzeichnen.
Wie werden wir nun messen? Mit anderen Worten, was ist wirklich wichtig, außer der Popularität der Sprache?
Geben Sie System ein
Viele Menschen schwören auf Typsysteme. Deshalb haben Sprachen wie TypeScript in den letzten Jahren an Popularität gewonnen. Ich stimme eher zu, dass Typsysteme eine große Anzahl von Fehlern in Programmen beseitigen und das Refactoring erleichtern. Ein Typsystem ist jedoch nur ein Teil der Geschichte.
Wenn eine Sprache ein Typsystem hat, ist es auch sehr nützlich, eine Typinferenz zu haben . Die besten Typsysteme können auf die meisten Typen schließen, ohne Funktionssignaturen explizit zu kommentieren. Leider bieten die meisten Programmiersprachen nur eine rudimentäre Typinferenz.
Es ist auch schön, wenn ein Typsystem algebraische Datentypen unterstützt (dazu später mehr).
Die leistungsstärksten Typsysteme unterstützen höherwertige Typen, die eine Abstraktionsebene über den Generika darstellen, und ermöglichen es uns, auf einer noch höheren Abstraktionsebene zu programmieren.
Wir müssen auch bedenken, dass Menschen dazu neigen, Typensystemen zu viel Bedeutung beizumessen. Es gibt Dinge, die weitaus wichtiger sind als statisches Tippen, und das Vorhandensein oder Fehlen eines Typsystems sollte nicht der einzige Faktor bei der Auswahl einer Sprache sein.
Lernaufwand
Wir haben vielleicht die perfekte Programmiersprache, aber was nützt es, wenn das Einbinden neuer Entwickler Monate oder sogar Jahre dauern kann (Vorabinvestition)? Auf der anderen Seite des Spektrums brauchen einige Programmierparadigmen Jahre, um gut zu werden.
Eine gute Sprache sollte für Anfänger zugänglich sein und es sollte nicht Jahre dauern, sie zu beherrschen.

Nullen
Ich nenne es meinen Milliardenfehler. Es war die Erfindung der Nullreferenz im Jahr 1965. Zu dieser Zeit entwarf ich das erste umfassende Typsystem für Referenzen in einer objektorientierten Sprache. Mein Ziel war es sicherzustellen, dass jede Verwendung von Referenzen absolut sicher ist, wobei die Überprüfung automatisch vom Compiler durchgeführt wird. Aber ich konnte der Versuchung nicht widerstehen, eine Nullreferenz einzugeben, einfach weil es so einfach zu implementieren war. Dies hat zu unzähligen Fehlern, Schwachstellen und Systemabstürzen geführt, die in den letzten vierzig Jahren wahrscheinlich eine Milliarde Dollar an Schmerzen und Schäden verursacht haben.
– Tony Hoare, der Erfinder von Null References
Warum sind Nullreferenzen schlecht? Nullreferenzen brechen Typsysteme. Wenn null der Standardwert ist, können wir uns nicht mehr darauf verlassen, dass der Compiler die Gültigkeit des Codes überprüft. Jeder nullbare Wert ist eine Bombe, die darauf wartet, explodiert zu werden. Was ist, wenn wir versuchen, den Wert zu verwenden, von dem wir nicht dachten, dass er null ist, der aber tatsächlich null ist? Wir bekommen eine Laufzeitausnahme.
Wir müssen uns auf manuelle Laufzeitprüfungen verlassen , um sicherzustellen, dass der Wert, mit dem wir uns befassen, nicht null ist. Selbst in einer statisch typisierten Sprache nehmen Nullreferenzen viele Vorteile eines Typsystems weg.
Solche Laufzeitprüfungen (manchmal auch als Null-Guards bezeichnet) sind in der Realität Problemumgehungen für schlechtes Sprachdesign. Sie verunreinigen unseren Code mit Boilerplate. Und das Schlimmste ist, dass es keine Garantie gibt, dass wir nicht vergessen, nach Null zu suchen.
In einer guten Sprache sollte das Fehlen oder Vorhandensein eines Werts beim Kompilieren typgeprüft werden.
Sprachen, die andere Mechanismen zum Arbeiten mit fehlenden Daten fördern, werden höher eingestuft.
Fehlerbehandlung
Das Abfangen von Ausnahmen ist ein schlechter Weg, um mit Fehlern umzugehen. Das Auslösen von Ausnahmen ist in Ordnung, jedoch nur in Ausnahmefällen , wenn das Programm keine Wiederherstellung durchführen kann und abstürzen muss. Ausnahmen brechen genau wie Nullen das Typsystem.
Wenn Ausnahmen als primäre Methode zur Fehlerbehandlung verwendet werden, ist es unmöglich zu wissen, ob eine Funktion einen erwarteten Wert zurückgibt oder in die Luft sprengt. Funktionen, die Ausnahmen auslösen, können ebenfalls nicht erstellt werden.
Offensichtlich ist es nicht in Ordnung, dass eine gesamte Anwendung abstürzt, nur weil wir einige Daten nicht abrufen konnten. Dies geschieht jedoch öfter, als wir zugeben möchten.
Eine Möglichkeit besteht darin, manuell nach ausgelösten Ausnahmen zu suchen. Dieser Ansatz ist jedoch fragil (wir vergessen möglicherweise, nach einer Ausnahme zu suchen) und fügt viel Rauschen hinzu:
Heutzutage gibt es viel bessere Mechanismen zur Fehlerbehandlung. Mögliche Fehler sollten beim Kompilieren typgeprüft werden. Sprachen, die standardmäßig keine Ausnahmen verwenden, werden höher eingestuft.
Parallelität
Wir haben das Ende von Moores Gesetz erreicht: Prozessoren werden nicht schneller, Punkt. Wir leben im Zeitalter der Multi-Core-CPUs. Jede moderne Anwendung muss mehrere Kerne nutzen.
Leider wurden die meisten der heute verwendeten Programmiersprachen im Zeitalter des Single-Core-Computing entwickelt und verfügen einfach nicht über die Funktionen, um effektiv auf mehreren Kernen ausgeführt zu werden.
Bibliotheken, die bei der Parallelität helfen, sind ein nachträglicher Gedanke. Sie fügen einfach Band-Aids zu Sprachen hinzu, die ursprünglich nicht für die Parallelität ausgelegt waren. Dies zählt nicht wirklich als gute Entwicklererfahrung. In einer modernen Sprache muss die Unterstützung für Parallelität integriert sein (denken Sie an Go / Erlang / Elixir).