Java...



  • ich bin auch in den eher theoretischen bereichen der informatik wie mustererkennung oder algorithmische geometrie zuhause, würde aber dennoch nicht die mir aus der praxis unbekannten dinge als "same old story" abstempeln...



  • dto-depp schrieb:

    würde aber dennoch nicht die mir aus der praxis unbekannten dinge als "same old story" abstempeln...

    Ich habe keine Erfahrung bzgl. deines konkreten Beispiels. Aber ich kenne Designpatterns und Architekturmuster. Auch wenn ich keine Erfahrung mit Sessionmanagment habe, so habe ich dennoch Software mit mehreren Schichten geschrieben. Es haut mich aber nicht aus dem Hocker, wenn da von Multi-Tier- Multi-Layer- Multi- ... gesprochen wird. Haben andere und frueher auch schon so gemacht ... so what's the point?



  • Moment, es geht doch gerade um die Frage, wie man die Vorteile, die man bei Java durch DI hat, in C++ reproduzieren würde, oder? Die Vorteile erscheinen gerade einfache und flexible Integration von Abhängigkeiten, für die man keinen extra Code schreiben muss. Das scheint ja die Übersichtlichkeit innerhalb der Klasse zu erhöhen. Lebenszeitverwaltung könnte ein Vorteil sein, aber das kann man vermutlich günstiger mit einem shared_ptr oder so in C++ abdecken.

    Hm... wobei: wo genau ist denn der Vorteil, wenn man alles in den Header via Annotation schreibt statt einfach ein Attribut zu haben und das dann über Setter/ctor zu übergeben? Man spart sich etwas Schreibarbeit, okay. Aber ist das viel?

    Was wären weitere Vorteile?



  • Vorteile, die man bei Java durch DI hat

    Das ist sehr subjektiv. Man kann auch jede Schicht/Teilsystem als Service implementieren und Nachrichten samt Kontext hin- und herschicken. Dann gibt es nur Abhaengigkeiten zu den einzelnen Messagequeues, die dem Konstruktor der Schicht/Teilsystem/Modul als Parameter uebergeben werden. Im Extremfall gibt es nur eine Messagequeue fuer alle Teilsysteme. Nun, hier injiziere ich die Abhaengigkeit zur Messagequeue. Warum? Na weil sie von mehreren Teilsystemen benutzt wird, sollte sie keinem einzelnen Teilsystem zugeordnet werden. D.h. es ist ein Ding fuer sich. Das klingt vernuenftigt. Und Menschen waren lange vor dem Begriff DI schon vernueftig.

    Wenn man im Inet nach DI sucht: http://stackoverflow.com/questions/130794/what-is-dependency-injection

    "Dependency Injection" is a 25-dollar term for a 5-cent concept. [...] Dependency injection means giving an object its instance variables. [...].

    Suuuper. Um deine Frage neu zu formulieren: Was ist der Vorteil, dem Konstruktor Parameter/Objekte mitzugeben?



  • Daher versuche ich es ja zu objektifizieren, indem ich nach Vorteilen von Java-DI frage. Ich selbst nutze Java nicht, kann mir aber vorstellen, dass es Projekte, wie das obige Beispiel mit den Schichten, gibt, in denen das hilfreich ist.



  • knivil schrieb:

    Suuuper. Um deine Frage neu zu formulieren: Was ist der Vorteil, dem Konstruktor Parameter/Objekte mitzugeben?

    1. Muss man sie mit einem DI-Container nicht selbst angeben, und kann in einer Konfiguration (die in einer Datei oder im Code etc. steht) die Abhängigkeiten austauschen.
    2. Die Gleichen Vorteile die man beispielsweise mit dem Strategiemuster auch hat: Man kann leicht das Verhalten ändern.

    Das wesentliche Ziel ist aber die Abhängigkeiten in Schnittstellen herauszulösen. Sei es nun zur besseren Wartbarkeit, sei es nun weil z.B. Lizenzabhängig ein unterschiedlicher Funktionsumfang freigeschaltet werden soll, sei es um eine Komponente unabhängig für sich zu testen, sei es um diesen Mechanismus auch für ein Pluginsystem zu verwenden (z.B. wenn ein Konstruktor eine Collection von allen Registrierten Elementen einer bestimmten Art übergeben bekommt)...

    Grundsätzlich müssen es aber nicht zwangsläufig Konstruktorparameter sein (es gibt noch mehr Möglichkeiten).



  • Kellerautomat schrieb:

    allweare schrieb:

    In Java die Fibonaccizahlen ausgeben, sollte mit 10 Zeilen leicht gehen. In C++ brauchen erfahrene Programmierer schon mal 40 oder mehr Zeilen ➡ http://www.c-plusplus.net/forum/311250

    https://ideone.com/fdaWg7

    Du bis halt noch kein erfahrener C++ Programmierer.



  • Nun, die Frage war leicht ironisch gestellt. Wenn ich Objekte als Parameter habe und Objekte Daten+Verhalten sind, dann kann ich Verhalten nicht nur durch Werte parametrisieren sondern auch durch Verhalten anderer Objekte.



  • Kellerautomat schrieb:

    allweare schrieb:

    In Java die Fibonaccizahlen ausgeben, sollte mit 10 Zeilen leicht gehen. In C++ brauchen erfahrene Programmierer schon mal 40 oder mehr Zeilen ➡ http://www.c-plusplus.net/forum/311250

    https://ideone.com/fdaWg7

    Es geht kürzer:

    std::vector<int> v(30, 1); //na gut, unnötig, aber was solls
    
        std::adjacent_difference(v.begin(), v.end() - 1, v.begin() + 1, std::plus<int>());
    
        std::copy( v.begin(), v.end(), std::ostream_iterator<int>(std::cout, ", ") );
    


  • allweare schrieb:

    Kellerautomat schrieb:

    allweare schrieb:

    In Java die Fibonaccizahlen ausgeben, sollte mit 10 Zeilen leicht gehen. In C++ brauchen erfahrene Programmierer schon mal 40 oder mehr Zeilen ➡ http://www.c-plusplus.net/forum/311250

    https://ideone.com/fdaWg7

    Du bis halt noch kein erfahrener C++ Programmierer.

    Die Lösung von Werner Salomon ist auch ein wenig Overkill.



  • Sone schrieb:

    Es geht kürzer:

    std::vector<int> v(30, 1); //na gut, unnötig, aber was solls
    std::adjacent_difference(v.begin(), v.end() - 1, v.begin() + 1, std::plus<int>());
    std::copy( v.begin(), v.end(), std::ostream_iterator<int>(std::cout, ", ") );
    

    Geht das auch ohne dieses unnötige ", " am Schluss?



  • Sone schrieb:

    Kellerautomat schrieb:

    allweare schrieb:

    In Java die Fibonaccizahlen ausgeben, sollte mit 10 Zeilen leicht gehen. In C++ brauchen erfahrene Programmierer schon mal 40 oder mehr Zeilen ➡ http://www.c-plusplus.net/forum/311250

    https://ideone.com/fdaWg7

    Es geht kürzer:

    std::vector<int> v(30, 1); //na gut, unnötig, aber was solls
    
        std::adjacent_difference(v.begin(), v.end() - 1, v.begin() + 1, std::plus<int>());
    
        std::copy( v.begin(), v.end(), std::ostream_iterator<int>(std::cout, ", ") );
    

    Höh? Deine Lösung ist deutlich länger.

    Edit: Okay, den Kommentar entfernt. Immer noch länger.



  • Aber, Ethon, doch nicht nach Zeichen, nach signifikanten Zeilen! (Nach Zeichen wäre natürlich was anderes)



  • Anzahl Zeilen, Ok:

    #include <algorithm>
    #include <iostream>
    #include <vector>
    int main(){std::vector<int> v(30);v[0] = 1;std::adjacent_difference(v.begin(), v.end() - 1, v.begin() + 1, [](int a, int b) {return a + b;});for(int i : v)std::cout << i << ", ";}
    

    Winner! :p



  • std::adjacent_difference ist in <numeric> und nicht in <algorithm> definiert.



  • tntnet schrieb:

    Java Programme können 4 mal kürzer sein als C++. Manchmal ist es so, manchmal anders herum. Und was für eine sinnfreie Aussage.

    Die Frage ist durchaus interessant, da sie einen Einblick in die Abstraktionsmöglichkeiten unterschiedlicher Programmiersprachen gewährt. Mit der "alle haben Recht"-Einstellung kommen wir hier leider nicht weiter.

    tntnet schrieb:

    Wenn Programme schneller laufen, weniger Speicher verbrauchen, gut wartbar sind oder skalierbar. Das sind Vorteile. Aber wie kurz oder lang der Code ist, ist kein Qualitätskriterium. Das kann ein Hinweis sein. Längerer Code kann schlechter wartbar sein.

    Natürlich ist die Länge des Codes ein Qualitätskriterium. Und natürlich muss man dabei Codes vergleichen, die im Bezug auf andere Kriterien einigermassen äquivalent sind -- wie sonst auch immer.

    Wenn du die gleiche Funktionalität mit weniger Code erreichen kannst, ohne dabei Vorteile wie Wartbarkeit oder Performance einzubüssen, dann ist der kürzere Code besser. Alleine schon, weil man ihn schneller schreiben und lesen kann, wodurch wiederum weniger Fehler entstehen. Als Konsequenz benötigen Entwicklung und Wartung weniger Zeit.



  • Michael E. schrieb:

    std::adjacent_difference ist in <numeric> und nicht in <algorithm> definiert.

    Kompiliert aber.



  • In Java ist OOP das zentrale Paradigma, wodurch gewisse Ansätze eher umständlich zu lösen sind. Generell sieht man in Java viel öfter tiefere Vererbungshierarchien als in C++ (z.B. wenn man Collections und STL vergleicht). Beispielsweise werden Callbacks in Java über implementierte Interfaces realisiert, wodurch mehrere Klassen definiert werden müssen. C++ erlaubt hier mit std::function , std::bind() und Lambda-Ausdrücken viel kompakteren Code, der keineswegs schlechter verständlich ist. Allerdings wird immer wieder erkannt, dass Features fehlen, und entsprechend nachgerüstet. Java soll in Version 8 auch Lambda-Ausdrücke bekommen.

    Andererseits ist in Java schon vieles vorgefertigt. Gerade wenns um weiterführende Zeichenkettenverarbeitung geht, sucht man in der C++-Standardbibliothek vergebens und muss auf Bibliotheken wie Boost zurückgreifen, oder selbstgestrickte Lösungen verwenden. Zum Beispiel hat die std::string -Klasse wahnsinnig viele Memberfunktionen, aber sehr viele wichtige Fälle sind doch nicht abgedeckt. Globale Funktionen helfen oft auch nur begrenzt weiter. Für weiterführende Funktionalität wie GUI trifft das umso mehr zu -- mit den richtigen Bibliotheken zur Hand kann man in C++ aber schnell viel erreichen, sofern man genügend Sprachkenntnisse hat. Was leider bei sehr vielen C++-Programmierern ein ernstes Problem ist, wodurch diese mit Java schneller ans Ziel kämen.

    Die STL-Algorithmen in C++ sind nicht immer ideal. Gerade wenn man etwas Spezielleres braucht, muss man oft komplizierte Lambda-Ausdrücke zusammenbauen. Das hat zur Folge, dass einfache Schleifen oder Range-Based-For gleich viel Code wie die STL-Lösung benötigen, aber besser zu verstehen sind. Gerade Stream-Iteratoren sind recht unelegant in der Anwendung. Iteratoren im Allgemeinen führen zu teilweise kompliziertem Code, alleine schon weil man ständig begin-end-Paare übergeben muss. Hier ist mit Ranges enorm viel Verbesserungspotential vorhanden.

    Nathan schrieb:

    Kompiliert aber.

    Und? Wie dein Compiler die Header handhabt, ist irrelevant -- die automatische Inkludierung ist nicht vom Standard garantiert.



  • Den Teil des Codes habe ich von den Vorpostern übernommen, gebe keine Garantie und so.



  • volkard schrieb:

    dto-depp schrieb:

    @volkard: Was spricht gegen Dependency Injection (das meintest du doch mit DI?)?

    Brauchbare Sprachen brauchen sowas nicht.

    +1 👍


Anmelden zum Antworten