Reflection



  • Shade Of Mine schrieb:

    FachmannFürReflection schrieb:

    Dann zitier doch mal die Definition von Reflection die dem entspricht was du sagst.

    Genau das ist der Punkt.
    Ich will Reflection nicht genau definieren. Genausowenig wie man OOP genau definieren kann. Es ist eine Idee, ein Konzept. Man versucht neue Auspraegungen davon zu finden, neue Ideen einzubauen aber man sollte nicht versuchen es sinnlos zu beschneiden.

    Die Idee hinter Reflection ist, dass das ein Programm Informationen aus (und nicht nur einfach über) die Programmstruktur holt und die Programmstruktur ändern kann.

    Die Information über einen Methodennamen wird nicht aus einem String geholt, dem der Programmierer irgendwie einen Wert zugewiesen hat sondern stammt direkt aus der Programmstruktur. Wie das gemacht wird ist völlig egal. Wenn dein Programm auf einem System läuft, dass den Aufbau aller Klassen in einer Datenbank hält, dann kannst du im Programm das System nach der Information fragen und es wird dir den Namen aus der Datenbank geben. Das wichtige ist einfach nur, dass der Name nicht vom Programmierer irgendwo als Programmdaten hinterlegt wird, sondern direkt aus der Programmstruktur ist.

    Beim ändern der Programmstruktur ist es ähnlich. In ABAP ist z.B. Reflection teilweise in die Syntax eingebaut und da sieht man sehr gut was die Idee hinter dem Ändern der Programmstruktur ist. Du kannst einem Element einer Struktur z.B. direkt einen Wert zuweisen oder per Reflection.
    Ich weiß die Syntax nicht mehr genau, aber ungefähr so war es.
    direkt

    struct-element = 'abc'.
    

    Reflection

    struct-(elementNameAlsString) = 'abc'.
    

    Wenn du jetzt in einer Schleife den Wert von elementNameAlsString änderst, dann ändert sich immer die Programmstruktur an der Stelle "struct-(elementNameAlsString) = 'abc'.". Ob da intern jetzt immer neu kompiliert oder nur die Adresse des Elements irgendwo gesetzt wird, weiß ich nicht. Es geht einfach um die Idee das hier zumindest theoretisch die Programmstruktur verändert wird und nicht, dass ein Programmierer eine einfache Adresszuweisung in sein Programm schreibt.



  • FachmannFürReflection schrieb:

    Die Information über einen Methodennamen wird nicht aus einem String geholt, dem der Programmierer irgendwie einen Wert zugewiesen hat sondern stammt direkt aus der Programmstruktur.

    In Java wird zB der String beim kompilieren in eine Liste geschrieben. Genauso wie bei den meisten C++ Reflection Libraries. Die Frage ist woher der String kommt - er wird meistens automatisch ermittelt (ist aber automatisch hier zwingend erforderlich?) zB anhand eines precompilers oder anhand von c++ makros oder aehnlichem.

    Wenn dein Programm auf einem System läuft, dass den Aufbau aller Klassen in einer Datenbank hält, dann kannst du im Programm das System nach der Information fragen und es wird dir den Namen aus der Datenbank geben. Das wichtige ist einfach nur, dass der Name nicht vom Programmierer irgendwo als Programmdaten hinterlegt wird, sondern direkt aus der Programmstruktur ist.

    Also muss es automatisch gemacht werden? dh, wenn ich haendisch eine java Datei in eine class Datei kompiliere (ich kann mich ja mit einer Referenz mal ein paar Wochen hinsetzen und das abtippen) dann ist es keine Reflection mehr?

    Ob da intern jetzt immer neu kompiliert oder nur die Adresse des Elements irgendwo gesetzt wird, weiß ich nicht. Es geht einfach um die Idee das hier zumindest theoretisch die Programmstruktur verändert wird und nicht, dass ein Programmierer eine einfache Adresszuweisung in sein Programm schreibt.

    Und was willst du damit aussagen? Java ohne Instrumentation API kann sowas nicht. Bietet jetzt Java erst seit es die Instrumentation API gibt Reflection?



  • Gregor schrieb:

    Ich sehe bei Reflection eigentlich nur die Analyse.

    nach --> http://www.petendi.de/seminare/reflection/parts/reflection_petendi_hausarbeit.pdf
    wird das, was du meinst Introspection genannt. zu reflection gehört mindestens das reflektive (wenn weder name noch typ zur compilezeit bekannt sind) verändern von variablen, umbiegen von funktionen etc. zur vollständigen reflection auch noch die möglichkeit zum ändern der programmstruktur selbst. jedenfalls ist für die letzten beiden ein 'lebendes' objekt nötig. parallel zum programm gespeicherte zusatzinformationen reichen nicht aus.
    🙂



  • Shade Of Mine schrieb:

    FachmannFürReflection schrieb:

    Die Information über einen Methodennamen wird nicht aus einem String geholt, dem der Programmierer irgendwie einen Wert zugewiesen hat sondern stammt direkt aus der Programmstruktur.

    In Java wird zB der String beim kompilieren in eine Liste geschrieben. Genauso wie bei den meisten C++ Reflection Libraries. Die Frage ist woher der String kommt - er wird meistens automatisch ermittelt (ist aber automatisch hier zwingend erforderlich?) zB anhand eines precompilers oder anhand von c++ makros oder aehnlichem.

    Wenn dein Programm auf einem System läuft, dass den Aufbau aller Klassen in einer Datenbank hält, dann kannst du im Programm das System nach der Information fragen und es wird dir den Namen aus der Datenbank geben. Das wichtige ist einfach nur, dass der Name nicht vom Programmierer irgendwo als Programmdaten hinterlegt wird, sondern direkt aus der Programmstruktur ist.

    Also muss es automatisch gemacht werden? dh, wenn ich haendisch eine java Datei in eine class Datei kompiliere (ich kann mich ja mit einer Referenz mal ein paar Wochen hinsetzen und das abtippen) dann ist es keine Reflection mehr?

    Es geht nicht um automatisch vs. manuell sondern um Programmdaten vs. Programmstruktur. Das was an einem Programm Daten sind bleiben Daten, egal in welchem Format du sie eingibst. Du schaust immer nur technische Unterschiede nicht auf logische.

    Ob da intern jetzt immer neu kompiliert oder nur die Adresse des Elements irgendwo gesetzt wird, weiß ich nicht. Es geht einfach um die Idee das hier zumindest theoretisch die Programmstruktur verändert wird und nicht, dass ein Programmierer eine einfache Adresszuweisung in sein Programm schreibt.

    Und was willst du damit aussagen? Java ohne Instrumentation API kann sowas nicht. Bietet jetzt Java erst seit es die Instrumentation API gibt Reflection?

    Keine Ahnung was Java vor und nach Instrumentation API konnte, ich hab mich noch nie so genau mit den Reflectionmöglichkeiten von Java beschäftigt. Vielleicht konnte Java vorher wirklich nicht alles was zu Reflection gehört. Es ist nicht immer das drin was auf der Packung steht. 😉



  • FachmannFürReflection schrieb:

    Es geht nicht um automatisch vs. manuell sondern um Programmdaten vs. Programmstruktur. Das was an einem Programm Daten sind bleiben Daten, egal in welchem Format du sie eingibst. Du schaust immer nur technische Unterschiede nicht auf logische.

    So einfach kann man das aber insofern nicht trennen, da ja die Programm Daten aufschluss ueber die Struktur geben koennen. In Java hast du das class Objekt dass die Strukturinformation besitzt. Wenn ich nun das class Objekt haendisch mit diesen Daten Fuelle sind es exakt die selben Daten ueber die Struktur des Programmes, nur eben haendisch eingetragen und nicht automatisch.

    Ist es dann Reflection?

    In C++ muss ich ja auch zB eine Header Datei schreiben die die Definition der Schnittstelle beinhaelt, obwohl die reine Implementierung ja reichen wuerde um an die Schnittstelle zu gelangen.

    Selbe Situation hier. Warum ist es so wichtig woher die Metainformationen kommen?



  • Shade Of Mine schrieb:

    In C++ muss ich ja auch zB eine Header Datei schreiben die die Definition der Schnittstelle beinhaelt, obwohl die reine Implementierung ja reichen wuerde um an die Schnittstelle zu gelangen.

    Selbe Situation hier. Warum ist es so wichtig woher die Metainformationen kommen?

    Wenn Du das zu einem Sprachenvergleich machst, dann ist doch die Frage: "Unterstützt die Sprache Reflection?". Und wenn man alles von Hand machen muss, dann unterstützt C++ Reflection genauso wie ein Assembler OOP unterstützt. Klar, Du kannst auch immer argumentieren, dass die JVM ja in C++ geschrieben ist, also kann man mit C++ alles machen, was man mit Java auch machen kann. Aber es ist viel viel umständlicher.



  • Gregor schrieb:

    ...also kann man mit C++ alles machen, was man mit Java auch machen kann. Aber es ist viel viel umständlicher.

    man kann auch wichtige details weglassen und sagen, es wäre das selbe. 😉



  • Gregor schrieb:

    Wenn Du das zu einem Sprachenvergleich machst, dann ist doch die Frage: "Unterstützt die Sprache Reflection?". Und wenn man alles von Hand machen muss, dann unterstützt C++ Reflection genauso wie ein Assembler OOP unterstützt. Klar, Du kannst auch immer argumentieren, dass die JVM ja in C++ geschrieben ist, also kann man mit C++ alles machen, was man mit Java auch machen kann. Aber es ist viel viel umständlicher.

    Man muss aber nicht alles haendisch machen - die Frage ist: wieviel automatisierungen sind notwendig. Wo genau ist die Grenze ab der es nicht genug Automatisierungen sind?

    C++ Reflection Libraries verlangen ja nicht dass man selber alles haarklein macht - wozu wuerde ich dann die Library brauchen?

    Die essentielle Frage ist also: wieviel Automatisierungen sind notwendig damit Reflection Reflection ist?

    Dass Reflection in C++ nicht so komfortabel ist wie in Java ist klar. Aber Reflection in Java ist dafuer auch nicht so komfortabel wie in Java Script. Und Design by Contract ist in Eiffel wesentlich Komfortabler als in Java Script...

    Wie komfortabel muss ein Konzept denn verwendbar sein damit es zaehlt? Checked Exceptions in Java sind zB recht unkomfortabel (zwar by Design, aber sie sind es) sind es deshalb keine Exceptions?



  • Shade Of Mine schrieb:

    Die essentielle Frage ist also: wieviel Automatisierungen sind notwendig damit Reflection Reflection ist?

    gar keine. ein programm, das in maschinencode geschrieben wurde (auf einer von neumann archtiketur --> gemeinsamer speicher für code und daten), ist ohne weiteres reflektiv, weil es sich selbst sehen und verändern kann. ganz ohne irgendwelche tricks.
    🙂



  • fricky schrieb:

    Shade Of Mine schrieb:

    Die essentielle Frage ist also: wieviel Automatisierungen sind notwendig damit Reflection Reflection ist?

    gar keine. ein programm, das in maschinencode geschrieben wurde (auf einer von neumann archtiketur --> gemeinsamer speicher für code und daten), ist ohne weiteres reflektiv, weil es sich selbst sehen und verändern kann. ganz ohne irgendwelche tricks.
    🙂

    Na sehr schön, dass Ihr das jetzt geklärt habt.

    Ich habe nur wenige Ausschnitte des Threads hier gelesen und sicherlich ist das in meinen Antworten auch klar geworden... Aber ich wollte nochmal zur ursprünglichen Frage des Threaderstellers zurückkommen.

    Die Frage war, wofür man Reflection benötigt. Und soweit ich die Beiträge überflogen habe, war die Antwort darauf: "Damit kannst Du ganz tolle Plugin-Architekturen realisieren!".

    Das ist zwar ein schönes Beispiel, aber ich möchte noch ein anderes nennen und danach noch ein Beispiel bringen, wie weit man Reflection treiben kann. Da ich mich am ehesten noch mit Java auskenne (auch wenn ich seit Monaten keine Zeile Javacode mehr geschrieben habe und momentan eher Code für Python, POVRay und Gnuplot produziere), kommen meine Beispiel natürlich auch aus dem Java-Bereich.

    Fangen wir mit dem weiteren Anwendungsbeispiel an:

    Ich wage mal die Behauptung, dass die Reflection-API, genau wie andere APIs in Java, wie zum Beispiel die Instrumentation-API oder die Compiler-API, ganz explizit auch die Bedürfnisse einer Zielgruppe befriedigen, zu denen die wenigsten Programmierer gehören. Und zwar die Entwickler von Entwicklungswerkzeugen. Wenn Du Dir moderne Java-IDEs anschaust, dann sind in den ganz zentralen Komponenten, wie zum Beispiel dem Editor, viele Dinge mit Hilfe von Reflection realisiert. Oder wenn Du Dir einen Profiler anschaust, dann schleust der mittels Instrumentation-API Code zum Zeitmessen in Deinen Code ein. In diesem Fall nutzt der 08/15-Entwickler diese Sprachfeatures zwar nicht direkt, aber er profitiert enorm davon, dass diese Features vorhanden sind. Die Entwicklungswerkzeuge im Java-Umfeld sind sehr mächtig und das liegt unter anderem daran, dass Java APIs zur Reflection und so weiter besitzt.

    Ok. Jetzt zu dem, was man alles mit Reflection machen kann bzw. wie starke Auswirkungen Reflection auf den eigenen Code haben kann. Dazu möchte ich ein Beispiel bringen, das aus meinem eigenen experimentellen Code entstanden ist. Ich fange mal ganz am Anfang an...

    Ich hatte vor langer Zeit mal angefangen, ein Programm ("Jimp") zu schreiben. Jimp sollte mir zum Testen von verschiedenen Algorithmen aus der Bildverarbeitung dienen. Ich wollte einen Algorithmus schreiben, seine Parameter bequem über eine GUI setzen können und ihn durch das Programm dann auf einen Datensatz loslassen können. Also im Prinzip etwas völlig simples aus Sicht der Softwaretechnik. Ich wusste damals aber nicht, wie man ein Programm eigentlich am Besten aufbauen sollte (weiß ich heute immer noch nicht). Wenn man eine derartige Frage in einem Forum stellt kriegt man ja als Antwort eh nur "MVC!" oder "Patterns!". Jeder weiß, dass das nicht wirklich eine Antwort auf diese Frage ist, aber viel mehr steht in Büchern auch nicht drin. Ok, ich fing also an, mein Programm zu schreiben und habe mich auch an MVC gehalten. Ich habe meinen Algorithmus geschrieben, dann einen passenden Dialog, mit dem ich ihn ansteuern wollte und dann habe ich beides in einem "Controller" miteinander verknüpft, der dann praktisch auch den Programmfluss im Großen gesteuert hat. Das Problem war nur, dass es sich relativ bald herausgestellt hat, dass der Anteil von Algorithmen bzw. dem gesamten "Model" nur ungefähr ein Drittel des Codes war. Die anderen beiden Drittel gingen zu gleichen Teilen auf den Controller und die GUI. Das fand ich doof, weil GUI-Programmierung, genau wie die Programmierung des Controllers, unglaublich öde ist. Alles Routine, die keinerlei geistige Leistung verlangt hat und pure Fleißarbeit war: Nichts für mich (Für andere Arten von Programmen sind derartige Bereiche natürlich oft viel wichtiger und auch herausfordernder).

    Ok, zumindest wurde mir das nach dem zehnten implementierten Algorithmus zu viel und ich habe einen Schlussstrich gezogen. Eine Lösung musste her, bei der sehr viel weniger Controller- und GUI-Code entsteht. Am Besten eine Lösung, bei der diese Programmteile nicht mit der Menge der implementierten Funktionalität wachsen. Meine Überlegungen damals führten dann ziehmlich schnell dazu, dass ich erkannt hatte, dass mein Programm die GUI, sowie den Controller, für die wachsende Funktionalität aus sich selbst heraus generieren könnte. Alle Informationen, die ich dazu benötigte, waren mittels Reflection ermittelbar. Ok, wenn man generelle Regeln zur Generierung derartiger Dinge erfindet, wird man es schwer haben, irgendetwas individuelles für eine Funktionalität zu erzeugen oder besonders hübsche Dialoge zu machen, aber das interessierte mich auch nicht. Es ging ums Testen von Algorithmen.

    Ich fing dann an, ein Nachfolgeprojekt zu schreiben: "JaRaDaP". Und was ich mir vorgenommen hatte, mittels Reflection zu erreichen, ging auch. Es war recht bald möglich, Funktionalität in dem Programm grafisch zur Verfügung zu haben, zu der man nur einen Algorithmus geschrieben hatte. Funktionalität, die man an keiner Stelle statisch im Code oder in irgendeiner Zusatzdatei mit dem eigentlichen Programm verknüpft hatte. Das Programm hat zum Programmstart selbst herausgefunden, aus was es eigentlich besteht. Es hat selbst festgestellt, was es kann, welche Algorithmen miteinander verknüpft werden können, wie die GUI auszusehen hat usw.. Im Prinzip hätte man aus dem Programm etwas völlig anderes machen können, indem man einfach nur das Model ausgetauscht hätte. Im Gesamten war das Programm ja eigentlich nur ein Model mit einer Art konstantem Overhead in Form einer Art reflektivem Framework.

    So weit kann man es also mit Reflection auf jeden Fall treiben. Allerdings sind dann durch die neuen Möglichkeiten, die sich durch die Reflection ergeben haben, und durch neue APIs in der Java-Standardbibliothek (z.B. Compiler-API, Annotations) auch die Begehrlichkeiten gewachsen. Mit der Compiler-API kann man zum Beispiel ganz toll einige Schwachstellen von Java ausbügeln. Zum Beispiel Schwachstellen bezüglich der Generizität bei primitiven Datentypen. Man kann mit diesen Sachen jede Menge coole und tolle Dinge anstellen, aber...

    Ich bin heute der Meinung, dass ich alle diese Sprachfeatures in hohem Maße missbraucht habe. Kein Problem, denn ich hatte meine Programme eh zu jedem Zeitpunkt als Experiment angesehen. Aber: Eine sehr intensive Nutzung derartiger Sprachfeatures führt zu ganz schwer lesbarem Code. Code, der im Zusammenhang mit diesen Features entsteht ist prinzipiell sehr komplex (naja, vielleicht gibt es Leute, die damit besser umgehen können). Code, der in diesem Zusammenhang entsteht ist auf dynamische Situationen zur Laufzeit ausgelegt: Etwas, mit dem man gedanklich viel schwerer umgehen kann, als wenn man sein Programm in einem statischen Kontext sehen kann. Am Schluss hatte ich ja sogar zur Laufzeit Javacode mit meinem Programm generiert und anschließend kompiliert, den ich dann mittels Reflection untersucht habe!?!? 😕

    Naja, was ich sagen will ist zumindest folgendes: Man kann viele tolle und coole Dinge mittels Reflection anstellen, wenn man sich mal überlegt, für was man die Informationen, die man damit erhalten kann, alles verwenden könnte. Aber man sollte in Code, der eine bestimmte Funktionalität erfüllen soll, IMHO recht vorsichtig damit sein. Sonst ist man ganz schnell dabei, immer coolere Trickserein in seinen Code einzubauen und dabei das eigentliche Ziel aus den Augen zu verlieren. 🤡 😋



  • erdtfghj schrieb:

    Wo hat hier jemand behauptet, dass das was in Java geht die Definition für Reflection ist?

    Eigentlich behauptet das nur "Shade of mine". Ich behaupte diese Java-Definition entspricht praktisch der Vorstellung, die auch in C#, Ruby, Python, Smalltalk, Groovy, etc. etc. etc. von Reflection vorherrscht.
    Wenn jetzt die Herren Stroustrup, Sutter usw. über Reflection mitreden wollen, müssen sie die Definition zwangläufig solange verbiegen und verdrehen, bis auch in ihrer Lieblingsprache Platz defür ist.
    Wenn es hier jetzt verquere Begriffsvorstellung gibt, ist das also kein Java-Problen, sondern eher ein C++-Problem.
    Rein praktisch ist diese Definition dann aber genauso irrelevant wie die Verwendung von Reflection in C++-Programmen.

    @OP: Frag lieber in einem Java-, C#-, Ruby- oder Python-Forum (falls du hier überhaupt noch mitliest).



  • Gregor schrieb:

    Naja, was ich sagen will ist zumindest folgendes: Man kann viele tolle und coole Dinge mittels Reflection anstellen, wenn man sich mal überlegt, für was man die Informationen, die man damit erhalten kann, alles verwenden könnte. Aber man sollte in Code, der eine bestimmte Funktionalität erfüllen soll, IMHO recht vorsichtig damit sein. Sonst ist man ganz schnell dabei, immer coolere Trickserein in seinen Code einzubauen und dabei das eigentliche Ziel aus den Augen zu verlieren. 🤡 😋

    Da fällt mir auch eine nette Anekdote aus einem (kommerziellen) Softwareprojekt ein: In generiertem Code ist an vielen Stellen Code enthalten, der Methodden von EJBs via Reflection dynamisch aufruft. So weit , so gut, denn an dieser Stelle war das notwendig. Das ging aber so weiter, dass auch an Stellen, an denen Klassenname und Methodensignatur zur Entwicklungszeit bekannt waren, diese Methoden im generierten Code per Reflection aufgerufen wurden, es sah wohl gut aus 😡

    Und da sitzen 30 hochbezahlte Akademiker im Team und es fällt ausgerechnet einem Praktikaten auf 😃



  • Chewie83 schrieb:

    Und da sitzen 30 hochbezahlte Akademiker im Team und es fällt ausgerechnet einem Praktikaten auf 😃

    Nicht wirklich verwunderlich. Derjenige der sich in eine Struktur einarbeiten muss erkennt Schwächen derer immer etwas leichter.


Anmelden zum Antworten