"Moderne" Programmiersprachen


#1

Ich lese in letzter Zeit immer häufiger über andere „moderne“ Programmiersprachen wie Kotlin, Scala, Rust oder aber Go. Nun verstehe ich den Hype um diese Sprache nicht ganz und auch die Argumentation nicht.

Ich programmiere seit nun etwa 15 Jahren, seit einiger Zeit beruflich mit JavaEE bin äußerst zufrieden. Moderne Ansätze sind ja möglichst wenig zu tippen, was ich jedoch nicht nachvollziehen kann. Java hat so gute Tools, das meiste davon tippe ich gar nicht, sondern die Idee. Und dennoch kann ich oder wer anders den Code lesen und sieht genau was da eigentlich passiert. Oder Ruby: geschweifte Klammern sind so kompliziert, also schreiben wir halt “end”. Das ist doch Unsinn…

Und noch besser wird es wenn es um das Typing geht. Dynamische Typisierung ist ja offenbar deutlich besser. Warum eigentlich? Damit ich später dann prüfen kann ob die Typen stimmen um Laufzeitprobleme zu verhindern? Gutes Beispiel ist hier JavaScript, wo man einfach mal Funktionen aufrufen kann mit weniger Argumenten als vorhanden. Naja und wenn man es in der Funktion aufruft, dann knallt es halt, eventuell…

Soo… Okay, das wäre soweit mein Frust. :slight_smile:


Frust-Thread
#2

Jain. Weniger Tippen ist eher ein “Abfallprodukt” anderer Techniken, und um die geht es eigentlich. Pattern-Matching ist intuitiver als das Visitor Pattern, interne Iteration weniger fehleranfällig als Schleifen u.s.w.

Ich stimme zu, dass das Tippen mit modernen Werkzeugen nicht das Problem ist. Was aber damit trotzdem noch nicht gelöst ist, ist das Lesen der Bleiwüsten aus Settern, Gettern u.s.w. Und Code wird eben viel häufiger gelesen als geschrieben. Sicher gibt es auch da teilweise schon Tools (Code Folding u.s.w.), aber letztendlich stellt sich dann die Frage: Warum brauchen wir erst Tools, die eine Latte Text erzeugen, nur damit dann andere diese Latte vor dem Nutzer wieder verstecken? Wäre da nicht weniger schreiben müssen die bessere Lösung?

Ist es nicht, wer behauptet das? Scala und Kotlin (und Haskell und andere) zeigen, dass statisch getypte Sprachen genau so kurz und lesbar wie dynamische sein können. Ein statisches Typsystem ist ein mächtiges Werkzeug, wenn es Leitplanke und nicht ein Klotz am Bein ist. Das Typsystem von Scala bietet ganz neue Möglichkeiten auszudrücken, welche Eigenschaften Code haben soll, und erschlägt damit ganze Klassen von möglichen Fehlern (so wie Java Generics einst Cast-Fehler stark reduziert haben).


#3

Wenn sowieso getter und setter benötigt werden und nicht anderes machen als return value und this.value = value kann man sich diese auch einfach sparen. Diese explizit zu haben zeigt ja an, dass man sich bewusst Gedanken darüber gemacht hat.

Wobei ich speziell in diesem Fall sage, dass eine Lösung wie sie Ruby beispielsweise bietet ganz nett finde:

class Foo
  attr_accessor :bar, :baz
end

Ich habe mich in letzter Zeit mit verschiedenen Sprachen auseinandergesetzt um zu schauen, welche ich eventuell lernen möchte. Bin dann irgendwann bei Kotlin hängengeblieben, da es mit seiner guten Java-Kompatibilität sogar für meine Arbeit nutzbar wäre. In diesem Zusammenhang bin ich auf verschiedene Artikel und Diskussionen im Netz gestoßen, wo die Autoren immer wieder sagen, dass variable Typsystem ja so toll sei, weil man sonst so viele Zeichen tippen muss.
Wobei ich persönlich ein private CatFold fold; attraktiver finde als ein def fold bei dem ich ohne Kommentar rein gar nichts über das Objekt erfahre.
Letztlich führte es bisher einige Male in die Situation, dass ich zur Laufzeit andere Typen in den Variablen hatte, als ich dachte. Daher versuche ich wenn ich Groovy schreibe (brauche es zurzeit) möglichst immer die Typen anzugeben, was neben den defs in wenig deplaziert aussieht.


#4

Hab’ das mal abgetrennt, da es ja eine allgemeinere Diskussion zu werden scheint. Vermutlich mische ich mich später auch nochmal ein - eine Gelegenheit zum Rant über JavaScript und Lobeshymnen über Java kann ich mir nicht entgehen lassen :smiley:


#5

Was ist den an den Argumentationen nicht zu verstehen?

Bei Java brauchte man eine Sprache für die Plattformübergreifende VM.

Bei Go hat man auf die VM verzichten wollen und wollte an der stelle
ein einzelnes Binary
Garbage Collection in der Runtime
Schnelle Compilezeiten
eine Sprache die Ähnlichkeiten zu C hat
Concurrency eingebaut hat
vom Sprachumfang her so gering wie möglich ausfällt.
Das ist eigentlich ganz gut gelungen.

Bei Rust wollte man noch zusätzlich auf einen Garbage Collector verzichten ohne aber die Probleme die C/C++ in Puncto Sicherheit mit sich bringen einzugehen. Also hat man eine Sprache designt die die ganzen Probleme grundsätzlich ausräumt. Zur Compilezeit versteht sich. Stichwort Borrow Checker.

Der Erfolg von Kotlin liegt in vielen kleinen Punkten, die vieles besser machen. Features von Java 8 sind damit auf mit Android Java 6 beschränkten Geräten verfügbar. Das null Handling ist in die Sprache eingebaut, was dieses wesentlich vereinfacht. Kompatibilität zu Java. Die Möglichkeit kompakte DSLs zu erzeugen

html {
  head {
    title(“Example”)
  }
  body {
    ul {
      li { +“Item 1” }
      li { +“Item 2” }
    }
  }
}

Das ist Kotlin code, der ein HTML-Template obsolet macht. Das gleiche lässt sich auch auf JavaFX anwenden um FXML zu ersetzen (TornadoFX) und auch die Layout-XML Dateien in Android bekommt man mit Anko in einer schönen DSL formuliert. Mit Java Sicher auch möglich, aber schlichtweg nicht in dieser Eleganz.

Jede dieser Sprachen hat irgendwo eine Herkunft und auch eine Zielgruppe deren Probleme es zu lösen gilt.

Zum Thema dynamic typing hat Rich Hickey ein paar interessante Einsichten (ab Minute 37)

Ein statisches Typsystem beschreibt ein Model der Welt. Aber in der Regel schafft es dieses Model nicht alles soweit abzudecken, was nützlich, sinnvoll, hilfreich ist. Daher kann es ein Ansatz sein, auf die Einschränkungen die ein statisches Typsystem mit sich bringt zu verzichten. OO kommt mit Microservice, DDD und Bounding Context daher und versucht die Domäne so klein wie Möglich zu gestalten um dort alles abzudecken, bekommt dann aber eine Kleinteiligkeit die andere Probleme mit sich bringt. Wäre JavaScript statisch, dann müsste auch HTML, der Kontext in dem das JavaScript steht, statisch sein.
Wo zieht man die Grenze? Ist Java noch statisch wenn man Casts hat oder Datenstrukturen hat die Object erlauben?


#6

Moin ionut!

Hohe Typsicherheit, statisch typisiert, (sehr) streng typisiert… (grundlagen Programmiersprachen)

Frage: Wie würdest du eine Tabelle mit Spalten unterschiedlichen Typs (String, int und bspw float, String) beschreiben? Da bietet sich Object an, toString habn alle gemeinsam, und zum Sortieren nach einer Spalte kann der actual Typ ggf zur Laufzeit festgestellt werden. :slight_smile:

Dass der Dreischritt auf Zweischritt “verkleinert” wird, übersetzen, interpretieren u ausführen, zu/nach/auf nur: übersetzen u ausführen, dabei aber das GC-Management “mitübersetzt” werden muss, ist sicherlich auch ein Vorteil, den ich bislang nicht kannte.

Schönen Sonntag! :wink:


#7

Ich habe mittlerweile einige Jahre in meinen Job investiert. Lange fand ich Java (über 10 Jahre) als vollkommen ausreichend. Dann habe ich einmal einen Umweg über C# gemacht und war von Properties einfach so begeistert und kann bis heute nicht verstehen, warum dies in Java nicht umgesetzt wird.

Jetzt habe ich mich mit Kotlin beschäftigt und bin hin und weg. Funktioniert auf der VM. Ist voll mit Java einsetzbar (sprich alle Frameworks laufen). Lässt sich neuerdings auch nativ kompilieren und jetzt läuft es sogar schon im Frontend (z.B. über Webpack mit React.js). Von der Syntax her ist es einfach ein riesiger Sprung.


#8

Das empfand ich anfangs auch so, jedoch finde ich speziell die Konstruktoren in der Sprache absolut schlecht. Hier kann man es mal so machen wie man es kennt, oder aber man gibt die Attribute einer Klasse nur im Konstruktor an. Das erinnert mich stark an Ruby: du kannst es auf dem Weg X, oder aber Weg Y, oder aber Weg Z, oder aber noch viel besserer auf dem Weg J oder wenn du wirklich gut bist auf dem Weg H lösen, wobei man nicht vergessen sollte dass es noch einen Weg K gibt, das Problem zu lösen.
Aber natürlich, Kotlins großer Vorteil ist die Kompatibilität zu Java, aber sind Kotlins Features nun so toll oder neu, dass man unbedingt eine andere Sprache nutzen muss?

Ganz einfach: Java ist soweit eine Sprache die sehr gut ist und sich sehr gut entwickelt. Sicher, nicht so schnell wie Framework X, Y aus JavaScript, jedoch schnell genug, dass sogar einige Firmen es adaptieren können. Und sicher ist in Java nicht alles gut und es gibt eine Menge zu kritisieren, jedoch ist es deutlich stabiler als die meisten anderen Sprachen da draußen und es gibt viel mehr Ressourcen als für die meisten anderen.

Go hat nette Features, lässt aber essentielle Teile, die zumindest zurzeit in moderner Programmierung genutzt werden außen vor. Das halte ich für unsinnig. Vielleicht fehlt mir auch die Vorstellungskraft dafür ein Programm mit einem gewissen Umfang vernünftig ohne OOP strukturieren zu können.
Rust finde ich schon eher interessant, wobei mir auch hier der Anwendungsfall fehlt. Verschiedene Altsysteme an denen ich zurzeit arbeite sind entweder in C oder C++ geschrieben. Diese werden nun nicht einfach weggeworfen sondern mit neuen C+±Standards weiterentwickelt.


#9

Naja, man kann ja in beiden Richtungen gutes und schlechtes sehen, oder?

Die “neuen” Sprachen die momentan durchs Dorf getrieben werden haben meiner Meinung durchaus ihre Berechtigung (als ob mich da jemand nach fragen würde :smiley: ). Viele von ihnen versuchen das Problem zu lösen, dass Java, C# und Konsorten sehr Syntax-heavy sind. Es gibt viel Boilerplate Code, viele Wiederholungen, den selben Code den man immer wieder tippt (if(v != null && v.attr != null)). Mein Problem mit den meisten Ansätzen ist, dass man zwar weniger Code schreiben, sich aber mehr Syntax merken muss (hust Scala *hust). Ich habe oft das Gefühl, dass gerade viele dieser neuen Sprachen diesem Ziel viel unterordnen, oft auch mit Breaking Changes. Ein Kollege von mir entwickelt mit Swift, so viele Breaking Changes wie jedes Major Release da hat würdest du kaum jemandem verkauft bekommen.

Auf der anderen Seite gibt es Sprachen, die so konservativ weiterentwickelt werden, dass sich gefühlt kaum etwas tut, vielleicht auch weil sie sehr gut anpassbar sind. Ein Beispiel hierfür ist Clojure (oder generell viele Lisp Dialekte). Immer wieder wird die Community ein wenig unruhig, weil sie den Eindruck hat es tut sich kaum etwas. Diese Woche kam Version 1.9 heraus, und das Changelog zeigt ganz gut, dass an der Sprache an sich kaum etwas geändert sondern nur leicht optimiert wurde (https://clojure.org/community/devchangelog). Eine der größten Änderungen die eingeplant war ist Spec, welches den Entwicklern umfangreiche Validierungen auf Datenstrukturen erlaubt. Und sogar Spec wurde im April aus dem Core entfernt und wird nun als Bibliothek geführt - weil es möglich ist, und die Sprache keine neuen Syntaxkonstrukte benötigt um erweitert zu werden, Lisp hat unheimlich wenig Syntax.

Java steckt jetzt irgendwo zwischen diesen beiden Extremen. Es muss die Kompatibilität in die Vergangenheit halten, um die Enterprise Anwender nicht zu verprellen. Gleichzeitig werden neue Konstrukte eingeführt, um den Entwicklern die Arbeit leichter zu machen, und z.B. funktionale Features in die Sprache einzubinden. Das bekommt Java erstaunlich gut hin, ohne andauernd neue Syntax einzuführen, auf der anderen Seite wird Java deshalb diese “neuen” Features nie so bequem und elegant umsetzen können wie andere Sprachen. Und gerade diese vergleichen natürlich viele.

Ich persönlich fühle mich auch eher zum konservativen Ansatz hingezogen und entwickle privat auch viel in Clojure. Ich mag die Idee, dass das Handwerkszeug gleich bleibt und ich nicht bei jedem Release neue Syntax lernen muss, trotzdem aber moderne Features in der Sprache benutzen kann. Mir ist an Code auch eher wichtig, dass er ausdrucksstark ist, nicht, dass ich zwei Minuten weniger brauche ihn zu schreiben oder nur die Hälfte der LoC brauche. Trotzdem schaue ich mir natürlich auch die neuen Sachen in Java an, mit denen ich beruflich momentan fast gar nichts zu tun habe. Im letzten Monat habe ich ein Spielprojekt aufgesetzt und mich mal intensiv mit den neuen Konstrukten (seit Java 8 hust) beschäftigt, und das geht gut und flott von der Hand, das gefällt mir. Als nächstes ist Kotlin dran, aber eher weil ich das Gefühl habe, dass man es in den nächsten Jahren können muss, nicht unbedingt weil ich die Sprache sexy finde.


#10

In erster Linie hat Google Go für Google entwickelt. Welchen Umfang die Programme bei Google haben, kann ich dir nicht sagen, aber einen gewissen Umfang werden sie schon erreichen. Go hat structs, methods, interfaces, Composition, aber keine Vererbung.

Unter Programmierern gibt es welche, denen fehlt ohne Vererbung was. Dann gibt es einige die Übertreiben es damit, was dazu führt das andere sagen, dann lass den Quatsch am besten komplett weg. Viele Java Programme könnte man auch hervorragend ohne jegliche Klassenvererbung (Object mal ausgenommen, weil Sprachbestandteil) schreiben. Und sie wären sogar einfacher/besser.

Die Frage ist wie lange eines dieser Altsysteme gebraucht hat, bis es “abgehangen” genug war, das alle Fehler mal aufgetaucht sind um dann behoben werden zu können. Wenn das Programm soweit funktioniert und die Weiterentwicklung überschaubar ist, dann verlangt doch niemand das ganze wegzuwerfen.
Aber wenn die Resourcen da sind für Rust, die Anforderungen für ein Binary ohne GC gesetzt sind, das Altsystem dauernd zicken macht, weil die Programmierer mit dem Memorymanagement nicht zurande kommen, Concurrency und Security eine wesentliche Rolle spielen, dann sollte man genauer auf Rust schauen. Das wäre dann aus meiner Sicht heraus der Anwendungsfall. Bei C und C++ ist es schon aberwitzig, was einem da um die Ohren fliegen kann.
https://www.openssl.org/news/vulnerabilities.html und mal STRG+F “buffer”


#11

Das allein wäre ja auch ein absolut käsiges Kriterium. Außerhalb des Java-Kosmos gab es quasi schon immer Sprachen die es einem, innerhalb ihrer jeweiligen Domäne, ermöglichten mit vergleichsweise wenig Aufwand ein angestrebtes Ziel zu erreichen. Das Ziel möglichst wenig zu tippen erreicht man i.d.R. am ehesten mit einer der Aufgabe angepassten Sprache (Haskell, Matlab, Occam, Prolog, Assembler etc. pp.). In Perl beispielsweise kann man bei einem Funktionsaufruf nicht nur die Argumente weglassen, man kann in der Funktion auch darauf verzichten die Eingabewerte oder den Returnwert zu definieren (und man kann in Perl auch sehr vielen anderen recht praktischen Mist machen, der einem Programmierer zwar Tipparbeit erspart, der einem Leser des Programms jedoch viel Kopfzerbrechen bereitet…). Besonders “hypewürdig” finde ich ein solches Verhalten allerdings nicht.

Unter’m Strich darf man imho auch heute noch die altbekannte Quintessenz anbringen: Die Wahl der Sprache hängt von der Aufgabenstellung ab. Punkt.
Lobeshymnen auf irgendwelche konkreten Sprachderivate basieren vermutlich auf irgendwelchen ungenannten Prämissen.

Kurzum: Völlig unabhängig von irgendwelchen Hypes sollte man nach wie vor selber seinen Grips bemühem um zu entscheiden welche Sprache man für eine gegebene Aufgabenstellung wählt. Das macht einfach am meisten Sinn*.

* damit erzähle ich wahrscheinlich niemandem hier etwas Neues; ich wollte es aber dennoch mal in Erinnerung rufen. :slight_smile: