Java in C++ programmieren - Programmier- und Designunterschiede



  • Ich dachte das ursprüngliche Konzept von C++ war, moderne Dinge wie OOP nach C zu bringen. Das C++ mehr als C mit Klassen ist, heißt nicht, dass C++ nicht OOP sein sollte.
    C++ ist doch eben Multiparadigmisch, sodass jeder so programmieren kann, wie er es als am sinnvollsten betrachtet und das ist für mich der Kerngedanke vom modernen C++ und nicht, dass auf einmal alles so aufgebaut ist wie die funktionalgenerische Standardbibliothek.

    Das man in C++ nicht so streng OOP programmiert wie in Java, ist klar, aber der funktionale Ansatz ist meines Erachtens veraltet und ein Schritt in die falsche Richtung(C++ funktional programmieren und C OOP scheint ja ein Trend zu sein).
    Ebenso ist die Templatemetaprogrammierung Schwachsinnig, solche Optimierung braucht kein Mensch, wenn dadurch das Programm derart unleserlich wird.
    Um auf deine Aussage zurückzukommen, effektiv ist anders.



  • !!! schrieb:

    der funktionale Ansatz ist meines Erachtens veraltet und ein Schritt in die falsche Richtung

    Setzen, 6.

    Aktuell ist die einzige Antwort die es auf die Multi-Core Problemstellung gibt: funktionales programmieren. Es gibt einfach keine andere vernünftige Antwort. OpenMP ist nett, aber wenn man sich Sachen wie Erlang ansieht oder moderne Konzepte wie plinq -> funktionale konzepte ueberall.

    Ebenso ist die Templatemetaprogrammierung Schwachsinnig, solche Optimierung braucht kein Mensch, wenn dadurch das Programm derart unleserlich wird.

    templatemetaprogrammierung != optimierung

    man _kann_ templatemetaprogrammierung zur laufzeitoptimierung verwenden, aber es ist nur ein einsatzgebiet von vielen...



  • Und um mehrere Kerne zu unterstützen, was zur Zeit sowieso nur wenige Anwendungen benötigen, soll man wie vor Urzeiten programmieren?
    Das ist doch schon wieder so eine Performanceoptimierung auf Kosten einer ordentlichen Software.
    Nur weil es in manchen Situationen notwendig ist, macht es das noch lange nicht modern oder erstrebenswert.



  • !!! schrieb:

    Und um mehrere Kerne zu unterstützen, was zur Zeit sowieso nur wenige Anwendungen benötigen, soll man wie vor Urzeiten programmieren?

    jetzt kommt das wirklich fiese: gerade für parallelisierung kann man mit templateprogrammierung das leben leichter machen, da sie viele automatische optimierung des compilers erst ermöglichen und händische leichter zugänglich machen. wenn es dich interessiert, schau dir mal die template-basierten lineare-algebra-libs an. die schaffen in c++, was sonst eigentlich nur in sprachen wie fortran mit der eingebauten vektorunterstützung, möglich ist. der code, den der "normale" anweder schreiben muss, ist nebenbei genauso wie sonst auch. das ist doch schicke an templates in c++...

    !!! schrieb:

    Das ist doch schon wieder so eine Performanceoptimierung auf Kosten einer ordentlichen Software.

    auch hier ein klassisches: nein. sie nutzen der software, da sie zum einen den wartungsaufwand verringern und zum anderem zur copilezeit vollständig ausgewertet werden. oder auch: ein template sagt dir viel früher, dass du auf dem falschen dampfer bist, als sein äquivalent in runtime-polymorphismus. (das ist nebenbei der grund, warum es seit java5 dort generics gibt...)



  • !!! schrieb:

    Und um mehrere Kerne zu unterstützen, was zur Zeit sowieso nur wenige Anwendungen benötigen, soll man wie vor Urzeiten programmieren?
    Das ist doch schon wieder so eine Performanceoptimierung auf Kosten einer ordentlichen Software.
    Nur weil es in manchen Situationen notwendig ist, macht es das noch lange nicht modern oder erstrebenswert.

    omg
    n/c



  • !!! schrieb:

    Und um mehrere Kerne zu unterstützen, was zur Zeit sowieso nur wenige Anwendungen benötigen, soll man wie vor Urzeiten programmieren?
    Das ist doch schon wieder so eine Performanceoptimierung auf Kosten einer ordentlichen Software.
    Nur weil es in manchen Situationen notwendig ist, macht es das noch lange nicht modern oder erstrebenswert.

    Struktiert != Funktional



  • Shade Of Mine schrieb:

    fricky schrieb:

    Shade Of Mine schrieb:

    die performance kosten waeren enorm.

    warum?
    🙂

    befass dich mal mit GCs. Was du willst ist ein Refcounting GC und die sind ewig veraltet. GC mit deterministic finalization ist einfach nicht schnell implementierbar. Aber der GC ist auch der komplett falsche Ansatzpunkt. Du willst für die meisten Resourcen keine deterministische finalization haben. Die meisten Resourcen sind in Pools wie sie der GC anbietet perfekt aufgehoben.

    Korrekt, die meisten Resourcen.

    Für die Resourcen für die man allerdings deterministische Finalisierung haben möchte (oder muss) ist das aber keine Lösung.

    Dummerweise färbt die Forderung "muss deterministisch finalisiert werden" ab: wenn eine Klasse X eine Klasse Y als Member oder Basisklasse verwendet, und Y deterministisch finalisiert werden muss, dann muss X das auch. Was dazu führt dass selbst die "wenigen" Resourcen die man deterministisch finalisieren möchte zu viel Aufwand führen.

    Aus dem Grund fände ich wichtig hier Support von der Sprache zu haben.

    Die fast schon "kanonische" Lösung in Java (und C# und ...) ist das Problem ab einem gewissen Punkt einfach zu ignorieren. Das kanns dann aber auch irgendwie nicht sein. Ich ärgere mich jedesmal wenn ich das dumme Visual Studio zu machen muss, nur weil irgendwo noch ein Handle auf irgendein Verzeichnis rumhängt, in dem ich vor Stunden mal drinnen ein Projekt offen hatte. Mit dem Effekt dass ich das Verzeichnis nicht löschen kann solange das Studio offen ist. Und solche Fehler sind nicht die Ausnahme, sondern eher die Regel.

    Aus dem Grund fände ich wichtig hier Support von der Sprache zu haben.
    (ja, ich weiss dass ich den Satz 1:1 so oben schon stehen habe)

    ----

    Es müsste doch irgendwie möglich sein beides unter einen Hut zu bringen, also billige & nicht deterministische Collection für die Klassen wo es OK ist, und teurere, dafür deterministische Finalisierung für Klassen wo es wichtig ist.

    Die Collection könnte ja unverändert bleiben, dass der rohe Speicher bis zur nächsten Collection stehen bleibt stört ja keinen. Zusätzlich müsste es aber einen Mechanismus geben, der bestimmte Klassen deterministisch finalisiert. Dabei sollte auch sichergestellt sein dass wirklich keine Referenzen auf die jeweiligen Objekte mehr existieren. Was gleich der nächste Punkt ist: die "übliche" Lösung über "Close" oder "Dispose" führt dazu dass man mit Zombie-Objekten rechnen muss. D.h. jede öffentliche Methode einer solchen Klasse muss checken ob die Instanz nicht vielleicht ein Zombie ist, und falls ja eine entsprechende Exception werfen (z.B. ObjectDisposedException). Spätestens wenn man 100 solche Checks irgendwo eingebaut hat hängt es einem zum Halse heraus.

    BTW: dass deterministische Finalisierung langsam ist ist klar, allerdings bremst es ja nur analog zur Anzahl der Objekte die deterministisch finalisiert werden müssen. Da diese üblicherweise sowieso recht teuer sind sollte das IMO kein Problem sein.

    uswusf.

    @Shade Of Mine:

    Funktionale Programmierung hat IMO ein ähnliches Problem: mutable State. Auf dem Papier sieht es nett aus ohne mutable State zu arbeiten, aber es geht nicht. Die Lösungen wie dieser nachträglich irgendwo dazugepfriemelt wird sind oft grausam. Was in Java "Close" ist ist in funktionalen Sprachen mutable State (IO oder was auch immer).
    Ich sollte allerdings dazusagen dass ich ganz sicher kein Experte bin was funktionale Programmierung angeht. Und ich lasse mich gerne eines besseren belehren, falles es doch halbwegs saubere Lösungen für das "mutable State" Problem geben sollte.



  • Shade Of Mine schrieb:

    Aktuell ist die einzige Antwort die es auf die Multi-Core Problemstellung gibt: funktionales programmieren. Es gibt einfach keine andere vernünftige Antwort.

    LOL, du kannst das sagen, weil du ja jede Lösung kennst, du hast ja auch jeden Sourcecode auf diesem Planeten gesehen, nur unseren anscheinend nicht... 🙄



  • hustbaer schrieb:

    BTW: dass deterministische Finalisierung langsam ist ist klar,

    Warum sollte sie langsam sein? Entweder man muß deterministisch Finalisieren oder man muß es nicht machen. Egal welche Programmierungsprache man verwendet, die Arbeit fällt hält in unterschiedlichen Programmkonstrukten an. In C++ ist über RAII gelöst in Java gibt es viele finally Blöcke abzuarbeiten. Es scheint mir, daß hier einige inkorrekt formulierte Programme zum Vergleich heranziehen, was ein unzuverlässiger Vergleich wäre.



  • is klar schrieb:

    Shade Of Mine schrieb:

    Aktuell ist die einzige Antwort die es auf die Multi-Core Problemstellung gibt: funktionales programmieren. Es gibt einfach keine andere vernünftige Antwort.

    LOL, du kannst das sagen, weil du ja jede Lösung kennst, du hast ja auch jeden Sourcecode auf diesem Planeten gesehen, nur unseren anscheinend nicht... 🙄

    das multicore problem haengt wie ein damokles schwert ueber der software entwicklung. apple hat zB fuer das neue mac os x einen feature freeze ausgerufen und ueberarbeiten jetzt die architektur fuer multi cores.

    es ist ein ziemliches problem im moment. die ghz zahlen bewegen sich nicht und die ersten consumer pcs haben 4 cores. mit nehalem werden 16 logische cores einzug in den consumer bereich erhalten.

    wie nuetzt man diese aus? jede software plattform entwickelt mit hochturen an loesungen. bis her kam nur funktionale programmierung als loesung daher. und das ist nicht zufrieden stellend. ms geht den weg der integration von funktionalen komponenten in .net -> parallel.for und plinq. bei java hat sich noch nichts ausgezeichnet, bis auf java.util.concurrent und futures sind schon nicht uninteressant, aber es fehlt etwas. was apple zeigen wird, wird man auch noch sehen.

    aber aktuell gibt es keine bessere antwort als funktionale programmierung. damit umgeht man eine menge der probleme. da man damit aber massig legacy code wegschmeissen muss, ist es keine tragbare loesung...



  • Shade Of Mine schrieb:

    aber aktuell gibt es keine bessere antwort als funktionale programmierung.

    Doch es gibt eine bessere Antwort darauf, ein besseres Prozessordesign. Intels x86 sind extrem schlecht auf Multithreadabarbeitung ausgelegt. IBM macht das mit den Power 6 MCM sehr viel besser. Natürlich bleibt hier das Problem der Nebenläufigkeit bestehen, aber je größer die Kommunikationsbandbreite ist desto weniger signifikant ist das Problem.



  • Es gibt ne Menge Anwendungen, die verteilen nicht nur auf die Cores eines PCs, sondern sogar noch auf mehrere PCs. Und das geht auch mit ganz normaler OOP, wenn man Aufgaben hat die man gut verteilen kann. Da braucht man kein parallel.for.



  • ~john schrieb:

    Shade Of Mine schrieb:

    aber aktuell gibt es keine bessere antwort als funktionale programmierung.

    Doch es gibt eine bessere Antwort darauf, ein besseres Prozessordesign. Intels x86 sind extrem schlecht auf Multithreadabarbeitung ausgelegt. IBM macht das mit den Power 6 MCM sehr viel besser. Natürlich bleibt hier das Problem der Nebenläufigkeit bestehen, aber je größer die Kommunikationsbandbreite ist desto weniger signifikant ist das Problem.

    Aber du wirst auf absehbare Zeit keinen nicht-x86er auf dem normalen PC-Markt durchsetzen können. Das ging schon häufiger grandios in die Hose. Abgesehen davon, hast du einen Link (oder eine eigene Erklärung), was da der wichtige Unterschied ist?

    is klar schrieb:

    Es gibt ne Menge Anwendungen, die verteilen nicht nur auf die Cores eines PCs, sondern sogar noch auf mehrere PCs. Und das geht auch mit ganz normaler OOP, wenn man Aufgaben hat die man gut verteilen kann. Da braucht man kein parallel.for.

    Sowas geht meines Erachtens wenn überhaupt nur mit einem Objektmodell, wie Objective C es benutzt halbwegs problemlos.

    Warum sträubst du dich so gegen funktionale Programmierung? Die ist wirklich unfassbar elegant (bis auf E/A-Operationen, wie hustbaer schon sagte) und die Programme sehr gut parallelisierbar (/ohne/ fehleranfälliges Zutun des Programmierers). Schau dir einfach mal Erlang an.



  • Ich hab mir Gestern mal nach Lesen dieses Threads Erlang angeschaut und anfangs dachte ich mir bei der Syntax schon ein wenig "WTF??", aber wenn man ein Schrittweises Tutorial durchgeht, dann erkennt man tatsächlich wie einfach die Syntax eigentlich ist.
    An das Programmiermodell muss man sich natürlich gewöhnen, aber wer schon einmal etwas in das funktionale Programmieren reingeschaut hat wird schnell zurecht kommen.

    Ich frage mich nur immer wieder ob solche Operationen wie die Länge einer Liste über abzählen und das Invertieren einer Liste wirklich effizient in solchen Sprachen sind.
    In meinen vertrauten Sprachen hat man für gewöhnlich doppelt verkettete Listen und ein Attribut das die Länge speichert.

    Dazu kommt, dass Erlang in einer VM läuft und ich nicht weiß wei ausgereift diese ist.



  • Ich glaub nicht daran, dass das Paradigma entscheidet ist. Der Vorteil in Erlangen ist das Synchronisationskonzept. C++ bietet nix, Java Monitore mit JCSP sorgar synchrone Messageverarbeitung. Erlangen hat asynchrone Messageverarbeitung.



  • Zeus schrieb:

    Ich glaub nicht daran, dass das Paradigma entscheidet ist. Der Vorteil in Erlangen ist das Synchronisationskonzept. C++ bietet nix, Java Monitore mit JCSP sorgar synchrone Messageverarbeitung. Erlangen hat asynchrone Messageverarbeitung.

    Der Unterschied ist, dass du in diesen Sprachen immer über globale Variablen/Objekte Daten austauschen kannst. Bei Erlang hast du gar nicht erst diese Möglichkeit, es gibt also keinen globalen State der irgendwie manipuliert werden kann.
    Somit gibt es einfach keine Möglichkeit auf verborgene Art und Weise auf andere Threads einfluss zu nehmen.

    Das ist schon eine ganze Menge, denn so lange man die Möglichkeit hat einen globalen State zu haben und zu manipulieren wird es auch gemacht, aus Bequemlichkeit, Gewohnheit, etc.

    Von daher hat die neue Sprache und das neue Paradigma (bezogen auf eine Umstellung) den Effekt, dass man quasi die alte Herangehensweise wegwerfen muss und gar nicht erst in die Falle tappt so zu programmieren wie man es bisher gewohnt war (siehe C+ statt C++).

    Gegen Lernresistenz ist natürlich kein Kraut gewachsen, so im Sinne von dem Spruch "You can program Fortran in any language".



  • Oder machen wir es einfacher:

    Es gibt keine bessere Antwort auf das Multicore Problem (und auch Power Prozessoren bringen hier keinen entscheidenden Vorteil gegenüber x86 da das Problem nicht der Prozessor sondern die Software ist - Power macht ein paar Sachen einfacher, aber das wirkliche Problem dass wir haben ist Shared State) als Shared State zu eliminieren. Oder einfacher ausgedrückt: pure funktionen.

    Nur sind pure funktionen in Sprachen wie C++ nicht wirklich integriert - man verwendet sie zwar aber es gibt das Konzept nicht. Funktionale Sprachen haben idR nur pure Funktionen und dann wenige Funktionen die auf shared state zugreifen.

    DAS ist der Vorteil.



  • Shade Of Mine schrieb:

    Oder machen wir es einfacher:

    Es gibt keine bessere Antwort auf das Multicore Problem (und auch Power Prozessoren bringen hier keinen entscheidenden Vorteil gegenüber x86 da das Problem nicht der Prozessor sondern die Software ist - Power macht ein paar Sachen einfacher, aber das wirkliche Problem dass wir haben ist Shared State) als Shared State zu eliminieren. Oder einfacher ausgedrückt: pure funktionen.

    Nur sind pure funktionen in Sprachen wie C++ nicht wirklich integriert - man verwendet sie zwar aber es gibt das Konzept nicht. Funktionale Sprachen haben idR nur pure Funktionen und dann wenige Funktionen die auf shared state zugreifen.

    DAS ist der Vorteil.

    Pah! Das geht in Java auch. Siehe Java Monitor



  • !!! schrieb:

    ...wie vor Urzeiten programmieren?...

    Kleiner Tipp: Nicht alles, was man auch früher schon gemacht hat, ist "veraltet" (im Sinne von "ist heutzutage unnötig/schlecht/falsch/...").

    Beispiel: Atmen

    Ansonsten hat es IMHO rüdiger gut auf den Punkt gebracht:

    rüdiger schrieb:

    ...Jede Programmiersprache bringt eigene Strategien, Ideen und Konzepte mit...

    Deswegen ist es ziemlich quatschig zu fragen, ob man mit Java besser C++ oder mit C++ besser Java programmieren kann. (lediglich Fortran ist dafür bekannt, dass man es in jeder Programmiersprache schreiben kann. 😉 )

    Z.B.: Ich würde als Trend (aus meiner Erfahrung heraus) sagen, dass

    • C++ eher compilezeitverliebt ist, wo Javaisten stärker auf die Laufzeit vertrauen,
    • C++ eher min- und Java eher maximalistisch beim Thema "Standardfunktionsumfang" ist ("Nur, was wirklich jeder braucht" <-> "Alles, was irgendjemand brauchen könnte")
    • ...

    Das hat nichts mit "gut"/"schlecht" zu tun, sondern sind einfach unterschiedliche Philosophien, denen man sich tunlichst unterwerfen sollte.
    Wer krampfhaft versucht, in Java soviel RAII einzusetzen wie in C++ oder Reflection in C++ wie in Java, der bricht sich übelst und in 99% unnötig die Finger.
    ... und kommt am Ende (für niemanden überraschend) zu dem Schluss, die jeweils andere PG-Sprache sei total unbrauchbar und werde nur von Idioten benutzt.

    Gruß,

    Simon2.



  • fricky schrieb:

    Pah! Das geht in Java auch. Siehe Java Monitor

    Bemüh dich beim trollen wenigstens...

    Ich habe nie gesagt dass funktionale Sprachen das beste sind was es gibt. Aber ich habe das Gefühl dass sobald neue Informationen kommen viele Leute einfach automatisch abblocken.

    Natürlich können Java Montors verwendet werden um das Problem des shared state zu umgehen, aber wie funktionen die denn? Das weisst du natürlich nicht, oder? Du kannst nicht pro Funktion einen eigenen Monitor bauen.

    Monitors sind auf Thread ebene recht nett, aber sind sie es auch auf function ebene? In funktionalen Sprachen kann ich zB ohne probleme folgendes automatisch parallelisieren:
    let f = add(x, 7) * foo()

    oder viel lustiger:
    let f = fib(100)
    ich kann DAS parallelisieren. (wobei fibonacci zahlen jetzt n doofes beispiel sind, aber man kann rekursion einfach parallelisieren ohne irgendwelche probleme und zwar AUTOMATISCH).

    Das ganze geht in Java nicht. Denn Monitors, was sind sie denn genau: nichts anderes als automatisch synchronisierte Blöcke. Und das ist schonmal das essentielle Problem: synchronisation.

    Man will aber nicht synchronisieren. denn das bedeutet dass man wieder engstellen hat. indem man aber keinen shared state hat, hat man _keine_ synchronisierung notwendig.

    das ganze läuft dann soweit, dass man nur sehr sehr sehr wenige shared resources hat auf die man uU sogar block-free zugreifen kann...


Anmelden zum Antworten