Vorschläge zur objektorientierten Programmierung

drfunfrock

Level-1
Beiträge
934
Reaktionspunkte
72
Zuviel Werbung?
-> Hier kostenlos registrieren
Die folgenden Vorschläge sind nicht als Ultima Ratio der Automatiserung gedacht, sondern nur als eine Art lautes Nachdenken. Vielleicht hat ja der ein oder andere Lust daran mitzubasteln. Ich weiss dass es grundlegende Bedenken gibt, aber ich pflege so lange nachzudenken, bis ich ich der Meinung bin auf dem Holzweg zu sein oder esist machbar.

Grundsätze:

1) Kein Objekt wird dynamisch erzeugt
2) Alle Methoden werden zur Compile-Time gelinkt
3) Access-Spezifier wie Public, Private usw. werden nicht benötigt
4) Der Programmierer muss wissen was er tut und nicht blind drauflos programmieren. Wer z.B. Vererbung einsetzt, muss sich über den Preis dafür im klaren sein. Eine Soft-SPS auf einem PC schafft, das evtl. spielend, was bei einer kleineren Hard-SPS zu riesen Zyklus-Zeiten führt. Eigentlich ist das selbstverständlich, kann ja nicht schaden es hier aufzunehemen.

Ich glaube das könnte mit einer Erweiterung zu ST machbar sein. Was würde man benötigen?

1) Methoden die Klassenorientiert sind wie
Code:
ergebnis := klasse.anzahl_klassenelemente() ;

2) Methoden die nur mit den Daten des Objektes arbeiten wie z.B.
Code:
ergebnis := station.station_besetzt();

3) Polymorphismus ist möglich, da alles statisch verlinkt wird. Damit sind Objekt-Methoden grundsätzlich virtuell.

4) Overloading ist möglich, weil alles statisch gelinkt wird.
5) Properties als Pseudo-Variable-Member sind recht nett zu haben, weil sie komplexe Zugriffe nach aussen hin etwas vereinfachen.

Nun schliesse ich hier vorläufig, um ein Beispiel auszuarbeiten...[/code]
 
drfunfrock schrieb:
Grundsätze:
1) Kein Objekt wird dynamisch erzeugt
Da müsste man auch erst eine dynamische Speicherverwaltung haben. Mit allen Risiken und Nebenwirkungen...
2) Alle Methoden werden zur Compile-Time gelinkt
Warum? Das Linken zur Laufzeit "späte Bindung" verlangt nur den Eintrag einer passenden Funktion in die Tabelle der Methoden ("VMT"). Im Gegensatz zu den meisten Systemen beherrschen fast alle SPS etwas ähnliches meisterhaft: Wenn ich nämlich einen Programmbaustein zur Laufzeit ersetze. Dazu ist eh schon eine Tabelle mit den Sprungzielen, indirekte CALLs/JMPs zum Aufruf und ein Mechanismus nötig, der bewirkt, daß die Tabelle erst verändert wird, wenn der Code geladen und der laufende Zyklus abgearbeitet ist.
Wenn man natürlich einen FB so ändert, daß die Aufruf-Schnittstelle inkompatibel wird, geht die SPS in Stop. Wer das verhindern will, muß eine Typ- und "Verträglichkeitsprüfung" zur Laufzeit einführen, siehe JAVA.
Wo liegt der Nutzen in JAVA? Hauptsächlich in der Programmentwicklung. Wenn ein fertiges Programm beim Anwender mit einer Fehlermeldung wie "incompatible calss cast exception" abstürzt nützt es dem Anwender auch nichts mehr, es sei denn er versteht, daß er bei der nächsten Sitzung vielleicht auf das Anklicken einer einzeln nachladbren Zusatzfunktion verzichten könnte.
Im Automatisierungsbereich könnten die Folgen katastrophal und die Fehlersituation schwer reproduzierbar sein.
Hier meine ich, es müsste einen zusätzlichen Testlauf geben, der jede an einer bestimmten Stelle wahlweise einsetzbare Klasse einmal "probelädt" und ihre Kompatibilität nachweist.
3) Access-Spezifier wie Public, Private usw. werden nicht benötigt
Die braucht man meiner Meinung nach unbedingt, um den OO-Grundsatz der "Kapselung" eines Objekts durchzusetzen. Natürlich kann man auf einen der beiden verzichten, indem alles default private ist.
4) Der Programmierer muss wissen was er tut und nicht blind drauflos programmieren.
Na sowieso...
Wer z.B. Vererbung einsetzt, muss sich über den Preis dafür im klaren sein. Eine Soft-SPS auf einem PC schafft, das evtl. spielend, was bei einer kleineren Hard-SPS zu riesen Zyklus-Zeiten führt. Eigentlich ist das selbstverständlich, kann ja nicht schaden es hier aufzunehemen.
(Einfach-)Vererbung benötigt nur eine Kopie der VMT der Elternklasse, in der die überschriebenen Methoden ersetzt werden. Bis hier kostet es nur minimale Performance, dadurch daß die indirekten Sprungziele gelesen werden müssen. Erst wenn man bei der Implementierung hier Speicherplatz sparen will, indem man keine komplette neue VMT anlegt, sondern mit Rückverweisen auf Methodentabellen der Elternklasse(n) fängt es, Zeit für die Suche zu kosten.

Ich glaube das könnte mit einer Erweiterung zu ST machbar sein. Was würde man benötigen?
Einer Klasse zugehörige Methoden und Daten kann man schon dadurch schaffen, daß der Compiler separate Namensräume benutzt.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Zottel schrieb:
drfunfrock schrieb:
Grundsätze:
1) Kein Objekt wird dynamisch erzeugt
Da müsste man auch erst eine dynamische Speicherverwaltung haben. Mit allen Risiken und Nebenwirkungen...
Deinen Beitrag verstehe ich an dieser Stelle nicht so recht.

Ansonsten finde ich deine Einwürfe gut und werde sie übernehmen. Das Konzept mit den Namensräumen macht in Perl und ich finde das nicht unbedingt schlecht. Allerdings zwingt es einem dort zu manchen seltsamen Dingen. Nein, ich denke, dass eine Syntax angelehnt an Object-Pascal besser wäre. Bitte verwechselt, das nicht mit einer Forderung nach gleicher Funktionalität.
 
drfunfrock schrieb:
Zottel schrieb:
drfunfrock schrieb:
Grundsätze:
1) Kein Objekt wird dynamisch erzeugt
Da müsste man auch erst eine dynamische Speicherverwaltung haben. Mit allen Risiken und Nebenwirkungen...
Deinen Beitrag verstehe ich an dieser Stelle nicht so recht.
Ein Objekt, daß zur Laufzeit erzeugt wird, muß Platz für seine Daten haben. Dazu muß ein Teil des Speichers bei der Entstehung des Objekts reserviert und bei seiner Entsorgung freigegeben werden.
Die offenkundigen Risiken bestehen darin, daß der Programmierer die Freigabe vergißt und der Speicher ausgeht.
Ein anderes ist die Zuweisung von Objekten mit dem überladenen = Operator. Wenn das Objekt seinerseits (Referenzen) auf Objekte enthält die nur ihm gehören, müssen solche Objekte dabei erstellt werden. Sollen Objekte von mehreren anderen referenziert werden, braucht es Zähler, die angeben, wann keine Referenz mehr existiert.
Die händische Verwaltung solcher Zähler birgt wieder Gefahren. Diese Dinge sind wenig wünschenswert insbesondere bei Automatisierungsaufgaben, weil die Programme monate- oder jahrelang ohne restart/reboot laufen sollten.
Manche Implementierung dynamischer Speicherverwaltung neigt auch dazu, den vorhandenen Speicher zu fragmentieren. Die Ausführung derselben Operationen wird dann immer langsamer.
Dies ist schlecht, wenn man eine garantierte obere Schranke der Reaktionszeit braucht.

JAVA löst das Problem der vergessenen Freigaben, indem ein Garbage-Collector regelmäßig nach Speicherbereichen sucht, die weder direkt noch indirekt referenziert werden und diese freigibt. Es entzieht sich meiner Kenntnis, ob man für die verwendeten Algorithmen obere Schranken der Laufzeit angeben kann (wahrscheinlich ja) und in welchem Verhältnis diese zu den mittleren Ausführungszeiten stehen.
Denn der Programmierer wird anhand der mittleren Ausführungszeiten subjektiv beurteilen, daß sein System noch "Luft" für weitere Aufgaben hat.
Hier wäre wieder ein automatisches Tool wünschenswert, daß ein garantierte worst-case-Laufzeit ermittelt. Keine Ahnung wie es das machen soll.
 
Zottel schrieb:
drfunfrock schrieb:
Zottel schrieb:
drfunfrock schrieb:
Grundsätze:
1) Kein Objekt wird dynamisch erzeugt
Da müsste man auch erst eine dynamische Speicherverwaltung haben. Mit allen Risiken und Nebenwirkungen...
Deinen Beitrag verstehe ich an dieser Stelle nicht so recht.
Ein Objekt, daß zur Laufzeit erzeugt wird, muß Platz für seine Daten haben. Dazu muß ein Teil des Speichers bei der Entstehung des Objekts reserviert und bei seiner Entsorgung freigegeben werden.
Ich denke es wird bei rein statischen Objekten nicht notwendig sein. In Funktionen können dann nur Referenzen auf Objekte benutzt werden. Und du hast recht, wenn du die Problematik einer dynamischen Spericherverwaltung ansprichst.

Nur diese habe ich quasi jetzt schon: Ich benutze für diverse Dinge FIFOs in Form eines Arrays und benutze reichlich Pseudopointer. Das kann denn in etwa so aussehen:

VAR
fifo : ARRAY[0..TOP] OF UINT;
first : UINT;
last : UINT;
END_VAR

Push in die FIFO:
first := (first + 1) MOD TOP;
fifo[first] := 2;

Pop aus der FIFO:
result := fifo[last];
last := (last + 1) MOD TOP;

Das ganze funktioniert, wenn man es vernünftig macht, nur bietet es keine Garantie. Und das ist der Punkt, wie weit geht man?

Ich habe eine SPS-Programmierumgebung, die nicht zwischen verschiedenen Enumerated-Values unterscheidet. So kommt es zu einem Konflikt, wenn ich beispielsweise OVERFLOW_ERROR in 2 verschiedenen Typen brauchen will, dann gibt es Fehler. Da braucht es wohl und eine strengere Typisierung und mehr Namensräume. Diesbzgl. hast du recht.

Ich will keine Kopie von Java. Es wäre einfach schön wenn man den SPS-Produzenten einfach Vorschläge zur Erweiterung machen könnte.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
drfunfrock schrieb:
[
Ich will keine Kopie von Java. Es wäre einfach schön wenn man den SPS-Produzenten einfach Vorschläge zur Erweiterung machen könnte.
Es war einer meiner wesentlichen Punkte in dem JAVA-als-Programmiersprache-Thread, das es genügen würde, einen Assembler für den Maschinencode der SPS(en) zu haben. Dann könnten Werkzeuge wie gcc Programmierung in C ermöglichen, gcj JAVA. Da die Werkzeuge open source sind, könntest du (mit Mühe) die unerwünschten features rausschmeissen oder (mit Mühe) einen Precompiler für eine deiner Lieblings(-Meta-)Problembeschreibung angepassten Beschreibungssprache erstellen.
So wäre man nicht von den SPS-Produzenten abhängig.

Wenn ich Zeit fände, könnte ich mal, als "proof of concept", gcc oder sdcc (small devices c compiler) "Assembler code", de facto AWL mit makros, für die S7 oder S5 produzieren lassen...
Für große C++ oder JAVA-Sachen wird der Speicher nicht reichen...
 
Zurück
Oben