Die Hierarchie ist das große Manko der objektorientierten
Programmierung.
Die "Eltern" haben Zugriff auf ihre "Kinder", die "Kinder" aber nicht
auf ihre "Eltern" oder ihre "Familie".
Mit einer subjektorientierten Programmierung, in der das möglich wäre,
wären viele Aufgaben leichter zu lösen. So geht das leider nur über den
Umweg des globalen Scopes.
Jobst Q. schrieb:> Die Hierarchie ist das große Manko der objektorientierten> Programmierung.>> Die "Eltern" haben Zugriff auf ihre "Kinder", die "Kinder" aber nicht> auf ihre "Eltern" oder ihre "Familie".> Mit einer subjektorientierten Programmierung, in der das möglich wäre,> wären viele Aufgaben leichter zu lösen. So geht das leider nur über den> Umweg des globalen Scopes.
Was hat ein "Scope" mit OOP zu tun? Scopes gibt es auch in C.
Jobst Q. schrieb:> Die Hierarchie ist das große Manko der objektorientierten> Programmierung.
Das ist aber gar kein OOP, es gibt hier gar keine Klassen-Objekte außer
std::cout ... Da Funktionen aber sowieso nicht so lang werden sollten,
dass so etwas relevant wird, ist das auch nicht so schlimm - es sei
denn, es wird etwas Fieses mit Makros gemacht, was sich aber in C++
bestimmt anders lösen lässt...
mh schrieb:> Was hat ein "Scope" mit OOP zu tun? Scopes gibt es auch in C.Niklas G. schrieb:> Das ist aber gar kein OOP, es gibt hier gar keine Klassen-Objekte außer> std::cout
Entschuldigt, dass ich schon ein bischen weiter gedacht habe.
Jobst Q. schrieb:> Entschuldigt, dass ich schon ein bischen weiter gedacht habe.
Wenn man über X redet, sagst du dass Y schlecht ist? Außerdem:
Jobst Q. schrieb:> Die "Eltern" haben Zugriff auf ihre "Kinder", die "Kinder" aber nicht> auf ihre "Eltern" oder ihre "Familie".
Wie haben die Eltern denn Zugriff auf die Kinder? Über
Pointer/Referenzen. Den Kindern kann man genauso Zeiger auf die Eltern
übergeben, wobei das im Sinne der Kapselung/Wiederverwendbarkeit nicht
unbedingt eine gute Idee ist. OOP hat bestimmte Probleme, aber das
gehört nicht dazu.
Jobst Q. schrieb:> Niklas G. schrieb:>> Das ist aber gar kein OOP, es gibt hier gar keine Klassen-Objekte außer>> std::cout>> Entschuldigt, dass ich schon ein bischen weiter gedacht habe.
Hast Du nicht. Du hast prozedurale Denke auf etwas angewendet, das mit
OOP nicht einmal am Rande zu tun hat.
Dirk B. schrieb:> Du kannst vor der Definition von a (3) eine Referenz auf a (2)> definieren.
Stimmt, man könnte es irgendwie zwischen sichern. Aber eine von der
Sprache bereitgestellte Möglichkeit wäre vermutlich sicherer und
effizienter... vorausgesetzt man findet einen Use-Case. ;-)
Dennis S. schrieb:> Dirk B. schrieb:>> Du kannst vor der Definition von a (3) eine Referenz auf a (2)>> definieren.>> Stimmt, man könnte es irgendwie zwischen sichern. Aber eine von der> Sprache bereitgestellte Möglichkeit wäre vermutlich sicherer und> effizienter... vorausgesetzt man findet einen Use-Case. ;-)
Ganz ehrlich: Du verlangst von der Sprache Mechanismen,
um schlecht strukturierten Code umzusetzen. Wenn ich in
einem Teil des Codes Zugriff auf die "Umgebung" benötige,
dann stimmen die Abhängigkeiten nicht.
merciless
Dennis S. schrieb:> Stimmt, man könnte es irgendwie zwischen sichern. Aber eine von der> Sprache bereitgestellte Möglichkeit wäre vermutlich sicherer und> effizienter... vorausgesetzt man findet einen Use-Case. ;-)Dennis S. schrieb:> Dirk B. schrieb:>> Du kannst vor der Definition von a (3) eine Referenz auf a (2)>> definieren.>> Stimmt, man könnte es irgendwie zwischen sichern. Aber eine von der> Sprache bereitgestellte Möglichkeit wäre vermutlich sicherer und> effizienter... vorausgesetzt man findet einen Use-Case. ;-)
Und dann wird irgendwann ein weiterer scope eingefügt und man hat nen
bug. Also müsste man scopes einen Namen geben können. Aber wenn man dem
scope einen Namen geben muss, könnte mach auch einfach eine Referenz
anlegen, die im richtigen Scope sichtbar ist. Oder man benennt einfach
eine der Variablen um. Letzteres ist vermutlich der "richtige" Weg, auch
wenn man nur Zugriff auf eine von beiden Variablen braucht (ich habe
immer -Wshadow aktiviert).
Wenn du allen a einen eigenen Namen gibst, kannst du ganz normal darauf
zugreifen. Was du gemacht hast nennt sich Variable shadowing und sollte
unbedingt vermieden werden. Der Compiler warnt dich sicher sogar davor.
Karl Käfer schrieb:> Jobst Q. schrieb:>> Niklas G. schrieb:>>> Das ist aber gar kein OOP, es gibt hier gar keine Klassen-Objekte außer>>> std::cout>>>> Entschuldigt, dass ich schon ein bischen weiter gedacht habe.>> Hast Du nicht. Du hast prozedurale Denke auf etwas angewendet, das mit> OOP nicht einmal am Rande zu tun hat.
Natürlich hat OOP etwas mit Scopes zu tun, nämlich über das Prinzip der
Kapselung. Ich übe keine Kritik an der OOP aus prozeduraler Sicht, im
Gegenteil, sie geht mir nicht weit genug.
Was ich mir wünsche, wäre eine Sprache, die subjektorientierte
Programmierung unterstützt. Darunter verstehe ich eine
nichthierarchische Programmierung, in der untergeordnete Objekte nicht
nur Befehlsempfänger sind, sondern im Sinne einer Teamarbeit mitdenken.
Als Beispiel mal eine Pumpstation mit 8 Pumpen, von denen je nach
Anforderungen 1-3 laufen. Wenn nun eine der laufenden Pumpen ausfällt,
muss eine andere dafür einspringen. Ohne Zugriff der Pumpenobjekte auf
gemeinsame Daten der Pumpstation ist das eine recht komplizierte
Angelegenheit. Die Station muss den Zustand aller Pumpen abfragen, sich
dann für eine neue entscheiden und dieser in Zukunft die Befehle
erteilen.
Mit Zugriff von unten nach oben lässt sich das viel einfacher mit ein
paar Zeilen mehr im Pumpencode lösen. Da hat dann zB die Station eine
Variable NummerHauptpumpe. Die wird von den einzelnen Pumpen gelesen und
wenn sie identisch mit der eigenen Nummer ist, wird die Boolvariable
AnforderungHauptpumpe ausgeführt.
Ist diese Pumpe nun gestört,setzt sie die NummerHauptpumpe auf Null, um
damit zu sagen "Ich kann nicht mehr". Liest nun eine andere Pumpe, die
bereit ist, aber noch keine Aufgabe hat, diese Null, schreibt sie ihre
eigene Nummer in die Variable und übernimmt damit die Aufgabe.
Je nach Anforderungen ist es etwas komplizierter, aber auf jeden Fall
werden viele Zeilen Stationscode durch wenige Zeilen Pumpencode ersetzt,
das macht es kürzer,übersichtlicher und effizienter.
Das Prinzip hat sich bei mir in der SPS-Programmierung vielfach bewährt.
Aber da ein solcher Zugriff von unten nach oben nicht unterstützt wird,
geht es nur über globale Variablen, wodurch es dem Prinzip Kapselung
widerspricht. Gäbe es einen solchen Scope für Teamvariablen, bliebe die
Kapselung der Station erhalten.
Niklas G. schrieb:> Wie haben die Eltern denn Zugriff auf die Kinder? Über> Pointer/Referenzen. Den Kindern kann man genauso Zeiger auf die Eltern> übergeben, wobei das im Sinne der Kapselung/Wiederverwendbarkeit nicht> unbedingt eine gute Idee ist. OOP hat bestimmte Probleme, aber das> gehört nicht dazu.
Ich halte es für eine gute Idee, siehe oben.
>Das Prinzip hat sich bei mir in der SPS-Programmierung vielfach bewährt.
Dann wende dein Prinzip mal auf ein Softwareprojekt an mit
Durchschnittsumfang d.h. mehrere Mannjahre(dauergewartet), 500k-1.5Mio
Zeilen Code, 5-10 Personen Team - dann wirst du sehen wie schlecht das
funktioniert - noch dazu muss ich dir leider sagen das ein SPS-Projekt
nicht wirklich den tiefen/strukturellen Umfang von "normaler" Software
erreicht weil man dort einfach viel weniger Einflüssen unterliegt
(geplant, damit das System noch handelbar bleibt) - womit ich nicht
sagen will das SPS-Projekte einfach sind
gute Konzepte skalieren (beschleunigte/fehlerfreiere Entwicklung) mit
dem Umfang und der Menge an Personen
Jobst Q. schrieb:> Das Prinzip hat sich bei mir in der SPS-Programmierung vielfach bewährt.
Ja, es klingt nach SPS-Denke, wo alles irgendwie gleichzeitig läuft und
es mehr um Datenflüsse geht. Das ist das Pipes-and-Processors-Modell; es
hat andere Ziele als OOP und ist z.B. nicht so gut auf komplexe und
wiederverwendbare Datenstrukturen & sequentielle Algorithmen anwendbar.
Jobst Q. schrieb:> Ohne Zugriff der Pumpenobjekte auf> gemeinsame Daten der Pumpstation ist das eine recht komplizierte> Angelegenheit.
Einen solchen Zugriff kann man sich natürlich bauen:
}elseif(true/* hier einfügen: Habe ich nichts zu tun? */){
28
if(m_station.m_haupt==nullptr){
29
m_station.m_haupt=this;
30
}
31
}
32
}
So sollte man das aber nicht machen. Die Pumpe hat hier Zugriff auf die
Interna der Station, funktioniert nicht ohne diese, kann nicht isoliert
wieder verwendet werden. Man kann nicht später eine andere Art von
Station einsetzen. Ein besserer Ansatz wäre:
if(braucheNeueHauptpumpe/* hier einfügen: Bin ich bereit? */){
5
returntrue;// Signalisiere dass ich Hauptpumpe werden kann
6
}
7
if(istHauptpumpe){
8
// Mache was wichtiges
9
10
returntrue;// Bleibe Hauptpumpe
11
}
12
returnfalse;// Werde nicht Hauptpumpe
13
}
14
};
15
16
classStation{
17
public:
18
Station():m_haupt(nullptr){}
19
voidrun(){
20
for(auto&p:m_pumpen){
21
if(p.run(m_haupt==&p,m_haupt==nullptr)){
22
m_haupt=&p;
23
}
24
}
25
}
26
private:
27
Pumpem_pumpen[8],*m_haupt;
28
};
Der Pumpe greift nicht mehr auf die Station zu. Der Pumpe wird über ein
klares Interface signalisiert, ob sie Hauptpumpe ist ("istHauptpumpe"),
eine neue Hauptpumpe gebraucht wird ("braucheNeueHauptpumpe"), und sie
gibt per Rückgabewert an ob sie neue Hauptpumpe werden möchte.
Die Interna der Station sind jetzt wirklich intern (private), sie werden
nur von einer einzigen Stelle aus verwendet (Station::run), man kann die
Pumpen problemlos in eine andere Station packen (vielleicht eine mit
mehreren Hauptpumpen). Man braucht keine Forward Declarations mehr - ein
gutes Zeichen :) Der Code ist sogar tatsächlich kürzer.
Das kann man natürlich immer noch verbessern, z.B. mit dem Factory
Pattern.
Jobst Q. schrieb:> Gäbe es einen solchen Scope für Teamvariablen, bliebe die> Kapselung der Station erhalten.
Auch solche Variablen (im 1. Beispiel: Station::m_haupt) würden von
mehreren Stellen aus verwendet. Es wäre schwierig, diese abzuändern,
weil alles mögliche davon abhängt. Besser ist es, solche Zustände zu
kapseln (hier: Station) und über ein sauberes Interface von außen darauf
zuzugreifen (hier: Parameter & Rückgabewerte von Pumpe::run).
Wenn du mehr Nebenläufigkeit ins Spiel bringen möchtest, schaue dir mal
das Aktor-Modell an.
Dennis S. schrieb:> Dirk K. schrieb:>> Du verlangst von der Sprache Mechanismen,>> um schlecht strukturierten Code umzusetzen.>> Ganz und gar nicht.
Oh doch. Und ganz nebenbei ist es auch noch
schlechter Stil, den selben Namen für Variablen
in verschachtelten Scopes zu verwenden.
merciless
>Als Beispiel mal eine Pumpstation mit 8 Pumpen, von denen je nach>Anforderungen 1-3 laufen. Wenn nun eine der laufenden Pumpen ausfällt,>muss eine andere dafür einspringen. Ohne Zugriff der Pumpenobjekte auf>gemeinsame Daten der Pumpstation ist das eine recht komplizierte>Angelegenheit. Die Station muss den Zustand aller Pumpen abfragen, sich>dann für eine neue entscheiden und dieser in Zukunft die Befehle>erteilen.
das ist entweder ein zu simples Beispiel oder mir ist unklar was daran
so kompiliziert sein soll
1
classPumpe(akaPumpenkontroller)
2
//das findet der Pumpenkontroller der Pumpe selbständig raus - eine Art "Sensor"
3
voidIchBinBeschaedigt();//z.B. Callback oder Singal Interface, mit Queue oder direkt
Es ist in jedem Fall sinnfrei die Pumpe in jeglicher Form an der
Wechsel-Entscheidung zu beteiligen - außer das sie "IchBinBeschaedigt"
sendet und dann die Station die Entscheidung trifft
Es gibt absolut keinen Grund - nicht technisch und nicht vom
topologischen Aufbau her das eine Pumpe mehr Codezeilen hat als ihre
reine Ansteuerung - wenn man mehr als das macht hat man eben kein
Konzept oder denkt Code-Zeilen-sparen-an-sich ist das zu erreichende
Ziel
Es passiert auch gerne das man denkt das wäre der richtige Weg und
überlegt sich dann wie solch ein etwas sinnfreier Aufbau sogar noch
begünstig werden kann - und ab dem Zeitpunkt muss ich dann leider
~fehlende Erfahrung~ flüstern... :)
Was wäre wenn zusätzlich zu den Pumpenauswahl auch noch spezifische
Ventile geöffnet/geschlossen werden müssen (und manche Ventile auf 2
Pumpen gehen usw.), dann kommt man ganz schnell in die Situation das nur
die Station die Entscheidung treffen kann - noch weniger sinn das in die
Pumpe zu machen
Jobst Q. schrieb:> Das Prinzip hat sich bei mir in der SPS-Programmierung vielfach bewährt.
Ich befürchte Dein Prinzip verstößt gegen einige Regeln strukturierter
Softwareentwicklung und ist auch in der SPS-Welt bestimmt nicht gern
gesehen.
Ganz einfach weil es schlecht nachvollziehbar ist!
Nur als Anmerkung zu den schon genannten Punkte werfe ich mal den
Begriff "race-condition" in Verbindung mit Deinen globalen Variablen in
den Raum. Soll heißen: was, wenn mehrere Pumpen gleichzeitig die Null
als NummerHauptpumpe lesen? Wer oder was regelt hier den Zugriff?
Am Ende gibt es keine definierte Stelle, woher die Entscheidung zur
neuen Hauptpumpe kam, womit die Entscheidung schlicht nicht
nachvollziehbar oder gar zufällig ist.
Dirk K. schrieb:> Oh doch. Und ganz nebenbei ist es auch noch> schlechter Stil, den selben Namen für Variablen> in verschachtelten Scopes zu verwenden.>> merciless
Ähhm... neee, verlange ich kein Stück. Ich weiß ja noch nicht mal einen
Use-Case in dem man das gebrauchen könnte.
Dennis S. schrieb:> Dirk K. schrieb:>> Oh doch. Und ganz nebenbei ist es auch noch>> schlechter Stil, den selben Namen für Variablen>> in verschachtelten Scopes zu verwenden.>>>> merciless>> Ähhm... neee, verlange ich kein Stück. Ich weiß ja noch nicht mal einen> Use-Case in dem man das gebrauchen könnte.Dennis S. schrieb:> Aber eine von der> Sprache bereitgestellte Möglichkeit wäre vermutlich sicherer und> effizienter...
DA lese ich aber etwas anderes heraus:
"Wäre schön, wenn es da was geben würde,
das mir erlaubt, Käse zu codieren."
merciless
Dirk K. schrieb:> "Wäre schön, wenn es da was geben würde,> das mir erlaubt, Käse zu codieren."
Kannst du die Quelle zu dem Zitat angeben? Rein aus Interesse... genau
wie die Ursprungsfrage übrigens. ;-)
Dennis S. schrieb:> Stimmt, man könnte es irgendwie zwischen sichern. Aber eine von der> Sprache bereitgestellte Möglichkeit wäre vermutlich sicherer und> effizienter... vorausgesetzt man findet einen Use-Case. ;-)
WARUM wäre eine "von der Sprache bereitgestellte
Möglichkeit" sicherer und effizienter?
Es ist nicht in der Sprache enthalten, weil
das niemand verwenden will (bzw. sollte) -
und das aus gutem Grund. Ich werde jetzt
aber nicht einen guten Meter Literatur
zum Thema Software-Architektur bemühen
(welche ich gelesen habe), um das mit
entsprechenden Zitaten zu belegen.
merciless
Dennis S. schrieb:> Dirk K. schrieb:>> Oh doch. Und ganz nebenbei ist es auch noch>> schlechter Stil, den selben Namen für Variablen>> in verschachtelten Scopes zu verwenden.>>>> merciless>> Ähhm... neee, verlange ich kein Stück.
Hä? In deinem Ursprungsposting willst du doch genau das:
Dennis S. schrieb:> int a {10}; // (1)>> int main() {> int a {20}; // (2)> {> int a {30}; // (3)> Ich weiß ja noch nicht mal einen Use-Case in dem man das gebrauchen> könnte.
Es gibt keinen. Deshalb gibt's auch das, wonach du gefragt hast, nicht.
lichtstrahl schrieb:> Jobst Q. schrieb:>> Das Prinzip hat sich bei mir in der SPS-Programmierung vielfach bewährt.>> Ich befürchte Dein Prinzip verstößt gegen einige Regeln strukturierter> Softwareentwicklung und ist auch in der SPS-Welt bestimmt nicht gern> gesehen.
Es ist möglicherweise nicht gern gesehen von Programmierern, die sich
nach Zeilenzahl bezahlen lassen statt nach Funktionalität.
> Ganz einfach weil es schlecht nachvollziehbar ist!> Nur als Anmerkung zu den schon genannten Punkte werfe ich mal den> Begriff "race-condition" in Verbindung mit Deinen globalen Variablen in> den Raum. Soll heißen: was, wenn mehrere Pumpen gleichzeitig die Null> als NummerHauptpumpe lesen? Wer oder was regelt hier den Zugriff?
Es gibt kein gleichzeitig in meinen SPS-Programmen. Die Instanzen der
Pumpen werden nacheinander aufgerufen. Entweder übernimmt eine Pumpe die
Aufgabe, dann steht bei der nächsten keine Null mehr drin. Oder sie kann
die Aufgabe nicht übernehmen, dann wird die Null weitergereicht.
> Am Ende gibt es keine definierte Stelle, woher die Entscheidung zur> neuen Hauptpumpe kam, womit die Entscheidung schlicht nicht> nachvollziehbar oder gar zufällig ist.
Die Entscheidung kommt eindeutig immer von der Pumpe, die die Aufgabe
übernommen hat und deshalb ihre Nummer eingetragen hat. Daran ist nichts
zufällig.
Cppbert schrieb:> Was wäre wenn zusätzlich zu den Pumpenauswahl auch noch spezifische> Ventile geöffnet/geschlossen werden müssen (und manche Ventile auf 2> Pumpen gehen usw.), dann kommt man ganz schnell in die Situation das nur> die Station die Entscheidung treffen kann - noch weniger sinn das in die> Pumpe zu machen
Die Pumpe braucht zum Anlaufen sowieso die Information, ob ihre Ventile
offen und ohne Störung sind. Die bekommt sie natürlich von der Station.
Bei Störung der Ventile ist sie nicht bereit und übernimmt erst
garnicht. Ansonsten öffnet die Station die Ventile und meldet, wenn sie
offen sind. Zeigt sich dabei eine Ventilstörung, gibt die Pumpe die
Aufgabe wieder ab und eine andere springt ein, deren Ventile in Ordnung
sind.
Jobst Q. schrieb:>> Ich befürchte Dein Prinzip verstößt gegen einige Regeln strukturierter>> Softwareentwicklung und ist auch in der SPS-Welt bestimmt nicht gern>> gesehen.>> Es ist möglicherweise nicht gern gesehen von Programmierern, die sich> nach Zeilenzahl bezahlen lassen statt nach Funktionalität.
Oder bei Programmierern, die noch etwas mehr als nur den Trivialfall
abdecken müssen.
>> Ganz einfach weil es schlecht nachvollziehbar ist!>> Nur als Anmerkung zu den schon genannten Punkte werfe ich mal den>> Begriff "race-condition" in Verbindung mit Deinen globalen Variablen in>> den Raum. Soll heißen: was, wenn mehrere Pumpen gleichzeitig die Null>> als NummerHauptpumpe lesen? Wer oder was regelt hier den Zugriff?>> Es gibt kein gleichzeitig in meinen SPS-Programmen. Die Instanzen der> Pumpen werden nacheinander aufgerufen. Entweder übernimmt eine Pumpe die> Aufgabe, dann steht bei der nächsten keine Null mehr drin. Oder sie kann> die Aufgabe nicht übernehmen, dann wird die Null weitergereicht.
Und wenn alle Pumpen im Schnitt gleich viel genutzt werden sollen, damit
nicht eine komplett runtergeritten ist und die andern unbenutzt? Wie
entscheidet eine Pumpe dann, ob sie ran muss oder es doch der nächsten
überlässt?
Eine übergeordnete Komponente sollte die Entscheidung treffen, nicht die
einzelne Pumpe. Die ist nur ausführendes Element und hat keine eigenen
Entscheidungsgewalt. Und zwar nicht wegen der Zahl der Codezeilen,
sondern weil es einfach ein besseres und flexibleres Design ist.
Rolf M. schrieb:> Hä? In deinem Ursprungsposting willst du doch genau das:
Nee... ich habe gefragt ob das möglich ist. Ich habe nicht von der
"Sprache" verlangt, so eine Funktionalität zu implementieren.
Musste mal an einem SPS Programm eine Änderung machen.
Der gute nicht mehr anwesende Kollege hat es geschaft in einer
"Read Input" Funktion in einer der 2000 Zeilen versteckt Ausgänge zu
setzen.
Es war nur Glück dass nach der Modifikation nichts passiert ist...
Es hilft immer sich beim Design/Implementierung zu Fragen:
Wird mein Nachfolger (der nur halb so gut ist wie ich...) meinen Code
mit normalem Aufwand kapieren...?
Oder besser: blick ich Schnarchnase in 5Jahren noch meinen eigenen Code?
Jobst Q. schrieb:> Die Pumpe braucht zum Anlaufen sowieso die Information, ob ihre Ventile> offen und ohne Störung sind. Die bekommt sie natürlich von der Station.
und das ist dein Konzept-Problem - es gibt keine Notwendigkeit und
bringt auch keinen Vorteil die Verwaltung von egal was auf alle
irgendwie ein bisschen zu verteilen - es gibt in allen Software und
Hardware-Systemen klare Trennung von Master(Klug/Wissend)/Slaves(Dümmer
als Master) - dein Konzept ignoriert das einfach - keine Ahnung aus
welchem Grund, die Codeersparnis kann nicht so groß sein - also warum?
Es ist nicht logisch das die Pumpen-Komponente mehr versteht als
"Pumpen" - und sie muss es auch niemals - wie unsere 5-Zeiler deutlich
zeigen, und das sind auch absolut keine neuen Konzepte sondern 08/15
Standard-Patterns aus dem echten Leben
Falls du nur Code-Ersparnis als einzige Rechtfertigung für das Konzept
heranziehen kannst ist es schon mal per se dürftig
Rolf M. schrieb:>> Es ist möglicherweise nicht gern gesehen von Programmierern, die sich>> nach Zeilenzahl bezahlen lassen statt nach Funktionalität.>> Oder bei Programmierern, die noch etwas mehr als nur den Trivialfall> abdecken müssen.
Meine Programme sind alles andere als trivial,ich habe es nur als
Beispiel stark vereinfacht zur besseren Verständlichkeit. Je
nichttrivialer und komplexer,umso größer sind die Vorteile von
teamorientierter Programmierung gegenüber der hierarchischen.
> Und wenn alle Pumpen im Schnitt gleich viel genutzt werden sollen, damit> nicht eine komplett runtergeritten ist und die andern unbenutzt? Wie> entscheidet eine Pumpe dann, ob sie ran muss oder es doch der nächsten> überlässt?
Indem sie ihren Betriebsstundenzähler mit einem Durchschnittswert aus
der Station vergleicht. Und /oder sich danach richtet, wie lange sie
schon untätig war.
Übrigens ist die Maxime, dass alle gleich viel genutzt werden sollen,
umstritten. Denn es erhöht die Gefahr, dass sie gleichzeitig ausfallen.
Bei Systemen mit 2 Aggregaten empfehlen wir eine 2/3 1/3 Verteilung der
Betriebszeiten.
> Eine übergeordnete Komponente sollte die Entscheidung treffen, nicht die> einzelne Pumpe. Die ist nur ausführendes Element und hat keine eigenen> Entscheidungsgewalt. Und zwar nicht wegen der Zahl der Codezeilen,> sondern weil es einfach ein besseres und flexibleres Design ist.
Ein hierarchisches Design,in dem die ausführenden Elemente dumm und
ohnmächtig gehalten werden ist weder besser noch flexibler. Es ist
bestenfalls gewohnter, weil wir in einer hierarchischen Gesellschaft
leben.
In meinem Beispiel ist es sehr einfach, der Station zu erweitern auf
mehr Pumpen. Außer den Aufrufen der zusätzlichen Pumpen muss im
Stationscode nichts geändert werden und der Code für die Pumpen selbst
bleibt wie er ist. Die erfahrene Einfachheit bei Erweiterungen ist
wesentlich für die Einschätzung meines Designs als bewährt.
Jobst Q. schrieb:> Ein hierarchisches Design,in dem die ausführenden Elemente dumm und> ohnmächtig gehalten werden ist weder besser noch flexibler
Es geht mehr darum den richtigen Ort für die Zuständigkeit zu klären.
Wenn die Elemente auf Informationen der höheren Ebene zugreifen - und
diese modifizieren - müssen, ist die Zuständigkeit vermutlich falsch.
Oder gehst du auch zu deinem Chef ins Büro und schreibst in seinen Akten
herum? Wenn der Chef sein Ordnungssystem ändert, musst du und alle die
das ebenso tun darüber informiert werden...
Jobst Q. schrieb:> In meinem Beispiel ist es sehr einfach, der Station zu erweitern auf> mehr Pumpen.
Auch auf mehrere Hauptpumpen gleichzeitig? Zeig dein Beispiel doch mal
ganz konkret in Code, UML-Diagramm o.ä., damit wir wissen, worüber wir
reden.
Niklas G. schrieb:> Oder gehst du auch zu deinem Chef ins Büro und schreibst in seinen Akten> herum? Wenn der Chef sein Ordnungssystem ändert, musst du und alle die> das ebenso tun darüber informiert werden...
Ich habe keinen Chef,sondern nur Auftraggeber. Aber wenn ich einen Chef
hätte, würde ich es auch nicht mögen, wenn er in meine Akten schreibt
und darin herumschnüffelt.
Worum es geht, ist ein gemeinsamer Bereich zum Datenaustausch, also eher
etwas, was einem schwarzen Brett oder einer Mailingliste entspricht. Und
der Chef oder besser Teamleiter hätte sich vorwiegend darum zu kümmern,
welche Aufgaben zu erledigen sind. Wer was erledigt, kann das Team auch
unter sich ausmachen.
> Auch auf mehrere Hauptpumpen gleichzeitig?
Es gibt eine Hauptpumpe und je nach Bedarf eine Zweit- und Drittpumpe,
die je nach gewünschter Menge angefordert werden.
Jobst Q. schrieb:> Worum es geht, ist ein gemeinsamer Bereich zum Datenaustausch, also eher> etwas, was einem schwarzen Brett oder einer Mailingliste entspricht.
Dieses Brett braucht aber jemanden, der die Zugriffe koordiniert. Wenn
alle Teammitglieder ihre Dinge irgendwo anheften, gibt es ein Chaos.
Wenn man die Organisation des Bretts ändern möchte, sollte man nicht
alle Teammitglieder informieren müssen; das macht der Koordinator. Hier
ist das die Pumpstation - eine Entität, welche die anderen koordiniert.
Jobst Q. schrieb:> Wer was erledigt, kann das Team auch> unter sich ausmachen.
Dies bedeutet aber mehr Kommunikation und Abhängigkeiten für die
Teammitglieder, weil sie dann nicht nur mit dem Chef, sondern auch noch
untereinander reden müssen. Wenn man ein Mitglied dann in ein anderes
Team steckt, muss man ihm alle dessen Mitglieder bekannt machen, anstatt
nur den neuen Chef zuzuordnen. Üblicherweise möchte man die
Abhängigkeiten reduzieren - wenn jedes Teammitglied nur mit seinem Chef
redet, und dieser Chef auch noch ausgetauscht werden kann (zB. Observer
Pattern) kann man durch Anpassung dieses einen Datenkanals die
Gesamt-Organisation leicht ändern. Je weniger Kanten der
Abhängigkeitsgraph, also das Organigramm hat, desto besser!
Meinst du mit subjektorientierter Programmierung eigentlich das hier?
https://www.itwissen.info/Subjektorientierte-Programmierung-subject-oriented-programming-SOP.html
Niklas G. schrieb:>> Worum es geht, ist ein gemeinsamer Bereich zum Datenaustausch, also eher>> etwas, was einem schwarzen Brett oder einer Mailingliste entspricht.>> Dieses Brett braucht aber jemanden, der die Zugriffe koordiniert. Wenn> alle Teammitglieder ihre Dinge irgendwo anheften, gibt es ein Chaos.
Der Datenbereich bzw das Schwarze Brett braucht keinen Koordinator, es
ist ein Mittel zur Koordination. Die Daten selbst koordinieren. Da in
der Variable NummerHauptpumpe nicht mehr als eine Zahl stehen kann, kann
sich auch immer nur eine der Pumpen als Hauptpumpe verhalten.
Das Verhalten der Teammitglieder ist im Programm vorgeschrieben. Wo und
wann etwas zu lesen oder zu schreiben ist, ist festgelegt. Da ist nichts
mit "ihre Dinge irgendwo anheften".
>> Wer was erledigt, kann das Team auch>> unter sich ausmachen.>> Dies bedeutet aber mehr Kommunikation und Abhängigkeiten für die> Teammitglieder, weil sie dann nicht nur mit dem Chef, sondern auch noch> untereinander reden müssen. Wenn man ein Mitglied dann in ein anderes> Team steckt, muss man ihm alle dessen Mitglieder bekannt machen, anstatt> nur den neuen Chef zuzuordnen.
Das "unter sich ausmachen" heißt nicht, dass sie sich kennen müssen. Es
heißt nur, dass sich der Chef weniger darum kümmern muss. Kennen müssen
sie nur den gemeinsamen Datenbereich. Wenn ich eine Information ans
schwarze Brett hefte, brauche ich nicht zu wissen, wer und wieviele es
lesen.
> Meinst du mit subjektorientierter Programmierung eigentlich das hier?> https://www.itwissen.info/Subjektorientierte-Programmierung-subject-oriented-programming-SOP.html
Nein. Das kommt aus einem anderen Subjektbegriff.
Darf der gemeinsame Datenbereich eigentlich Setter/Getter-Methoden für
den Zugriff haben, oder ist es für die Subjektorientierte Programmierung
erforderlich, dass die einzelnen Objekte (Subjekte?) direkten Zugriff
auf die Variablen haben?
CppBert schrieb:> und das ist dein Konzept-Problem - es gibt keine Notwendigkeit und> bringt auch keinen Vorteil die Verwaltung von egal was auf alle> irgendwie ein bisschen zu verteilen - es gibt in allen Software und> Hardware-Systemen klare Trennung von Master(Klug/Wissend)/Slaves(Dümmer> als Master) - dein Konzept ignoriert das einfach - keine Ahnung aus> welchem Grund, die Codeersparnis kann nicht so groß sein - also warum?
Der Vorteil ist umso größer, je mehr untergeordnete Objekte mit
demselben Code arbeiten. In meinen selbstkonzipierten SPS-Programmen
haben alle Aktoren, Sensoren und zu überwachende Signale einen
gemeinsamen Funktionsbaustein FBControl, der umfangreiche Aufgaben auf
globaler Ebene erfüllt (Alarmierung, Signalisierung, Betriebszähler,
Schreiben und Lesen von Datenbausteinen für PLS und andere externe
Anwendungen).
Je nach Anlage wird er also um die 100 mal mit unterschiedlichen Daten
ausgeführt. Das macht meine Programme deutlich kompakter gegenüber
konventioneller Programmierung, bei denen in langen listenartigen
Bausteinen die einzelnen Daten nacheinander bearbeitet werden.
Codeersparnis heißt aber auch mehr Übersichtlichkeit und weniger
Anfälligkeit für Flüchtigkeitsfehler.
Wenn irgendetwas an den aufgezählten Funktionen geändert oder erweitert
werden soll, muss ich es nur an einer Stelle tun. Das Prinzip DRY (Dont
repeat yourself) wird bestens bedient und kann seine Vorzüge in der
Wartbarkeit zeigen.
Jobst Q. schrieb:> Je nach Anlage wird er also um die 100 mal mit unterschiedlichen Daten> ausgeführt.
Also doch 100 verschiedene Speicherbereiche, statt 1 geteilter?
Klingt irgendwie einfach nur nach IoC (Inversion of Control).
Niklas G. schrieb:> Jobst Q. schrieb:>> Je nach Anlage wird er also um die 100 mal mit unterschiedlichen Daten>> ausgeführt.>> Also doch 100 verschiedene Speicherbereiche, statt 1 geteilter?
Willst du mich unbedingt missverstehen? Nicht statt, sondern außerdem.
Die 100 verschiedenen sind jeweils private von verschiedenen Objekte,
auf die übergeordnete natürlich auch zugreifen können. Es ist bei
Instanzen so üblich, dass jede ihre eigenen Daten hat, aber alle
Instanzen desselben Objekts denselben Code.
Das Gemeinsame zwischen dem Pumpenbeispiel und dem FBControl ist das
Prinzip, den untergeordneten Objekten mehr zuzumuten und die
übergeordneten dadurch zu entlasten. Die Individuen haben einen
gemeinsamen Teil, um jeweils ihren Anteil an gemeinsamen Aufgaben zu
erledigen.
>> Klingt irgendwie einfach nur nach IoC (Inversion of Control).
Der Begriff wäre passend, wenn er nicht schon anders und fast
gegenteilig belegt wäre.
Niklas G. schrieb:> Darf der gemeinsame Datenbereich eigentlich Setter/Getter-Methoden für> den Zugriff haben, oder ist es für die Subjektorientierte Programmierung> erforderlich, dass die einzelnen Objekte (Subjekte?) direkten Zugriff> auf die Variablen haben?
Bei der praktizierten SPS-Programmierung ist das unerheblich, da es da
weder Setter noch Getter, sondern überhaupt keine Methoden gibt. Dafür
kann man auf jeden Datenbaustein zugreifen, wenn man seinen Namen oder
seine Nummer kennt. Es gibt also nichts wirklich privates. Ob man es
dürfen können sollte, darüber gibt es heftige ideologische
Auseinandersetzungen.
Nach meinen Idealvorstellungen sollte es Bereiche geben, auf die
untergeordnete Objekte unmittelbar zugreifen können, damit Umwege über
den globalen Scope nicht nötig sind und eine Kapselung auf Teamebene
möglich ist.
Jobst Q. schrieb:> Willst du mich unbedingt missverstehen?
Tatsächlich ist es sehr schwierig festzustellen, was du eigentlich genau
meinst. Meinen Beispielcode hast du ignoriert, eigenen zeigst du
nicht...
Jobst Q. schrieb:> Es ist bei Instanzen so üblich, dass jede ihre eigenen Daten hat, aber> alle Instanzen desselben Objekts denselben Code.
Also ganz normales OOP.
Jobst Q. schrieb:> Nach meinen Idealvorstellungen sollte es Bereiche geben, auf die> untergeordnete Objekte unmittelbar zugreifen können
Das ist mit OOP überhaupt kein Problem (siehe mein Codebeispiel), man
sollte nur den gemeinsamen Datenbereich über Getter & Setter ordentlich
kapseln.
Ich sage es mal einfach so: In der SPS gelten teilweise völlig andere
Regeln und Gesetze als in der "normalen" Software-Entwicklung - deswegen
haben Niklas, Ich und auch andere Probleme dir zu folgen warum dein
Vorgehen einfacher und besser ist
In der normalen Software-Entwicklung wären schon
alles-public-Schnittstellen (also allgemeine DB Zugriffe) ein massives
Problem für die Wartung, auch deine Zyklus-Orientiertheit d.h. kaum bis
keine Race-Conditions möglich - lässt sich so kaum (oder nur mit
Aufwand) auf normale Software-Projekte übertragen d.h. deine
SPS-Sprache, die Domäne und das hart vorgegebene Ablaufsverhalten sieht
bei uns normalerweise ganz anders aus und wird mit entsprechenden Mittel
unter Kontrolle gehalten
Was aber einfach nichts daran ändert das hier keiner erkennen kann warum
dein Weg einfacher und praktikabler sein soll - ich und Niklas würde
auch kaum mehr/weniger Code als du schreiben und es würde das gleiche
dabei rauskommen - wäre aber von der Konzept-Art aber auch auf einen
Multithreading oder komplexere Verteilungslogik (wo dann irgendwann das
Team-Eigen-Managment an seine Grenzen stößt) anwendbar - und es wäre
auch Wartungsarm und Zukunftsflexibel - deswegen verstehen wir hier
(glaube ich) alle nicht genau was an deinem Konzept besser sein soll -
ausser das es anders ist, sich ausserhalb (laut dir altbackender
Strategien bewegt) und garantiert nicht so gut skaliert wenn man so 10
Entwickler an unterschiedlichen Kontrollern arbeiten laesst - irgendwann
kennt dann einfach jeder indirekt jeden und dann fängt dann einer mal an
langsam einen echten Master zu formen weil es nicht mehr wartbar ist
Alleine wenn du dir deinen Station und Pumpen Kontrolle aus Unit-Test
Sicht anschaust sieht man sofort das meine und Niklas Tests viel kleiner
wären als deine - weil die Komponenten eben klar getrennte Aufgaben
haben
Wenn du keine Tests schreiben musst kann man sehr leicht ignorieren das
deine Komponenten zu komplex sind (es ist egal ob Komplex = 2 oder 200
Zeilen Code ist)
Ich teste das Verhalten der Station vollständig mit einem Pumpen-Dummy
und ich teste das spezifische Verhalten meiner Pumpen mit entsprechenden
Test - du musst einen Tests schreiben der beide Welten gleich gut kennt,
alle Schnittstellen versteht - dadurch wird dein Test sehr kompliziert
und Aufwendig - was im Normalfall der Beweis für zu hohe
Abhängigkeitskomplexität ist - aber wenn du keine Test schreiben
musst/willst/kannst dann ist das eben alles irgendwie egal
Niklas Gürtler schrieb:> Meinen Beispielcode hast du ignoriert, eigenen zeigst du> nicht...> Das ist mit OOP überhaupt kein Problem (siehe mein Codebeispiel), man> sollte nur den gemeinsamen Datenbereich über Getter & Setter ordentlich> kapseln.
Das ist in C++ kein Problem. Ich brauche objektorientierte Ansätze aber
gerade in der SPS-Programmierung, wo sie leider nur rudimentär
unterstützt werden. Da gibt es keine Methoden, also auch keine Getter
und Setter. Unterobjekte sind nicht als Array möglich, also kann man sie
auch nicht nacheinander in Schleifen bearbeiten. Vererbung gibt es nur
über Copy&Paste.
Cppbert schrieb:> Ich teste das Verhalten der Station vollständig mit einem Pumpen-Dummy> und ich teste das spezifische Verhalten meiner Pumpen mit entsprechenden> Test - du musst einen Tests schreiben der beide Welten gleich gut kennt,> alle Schnittstellen versteht - dadurch wird dein Test sehr kompliziert> und Aufwendig - was im Normalfall der Beweis für zu hohe> Abhängigkeitskomplexität ist - aber wenn du keine Test schreiben> musst/willst/kannst dann ist das eben alles irgendwie egal
Ich sehe die Pumpstation mit ihren Pumpen als eine Einheit. Also wird
das Team mitsamt seiner Kommunikation getestet. Da ist der Test dann
überhaupt nicht mehr kompliziert. Pumpen, die ich woanders einsetzen
will, bekommen einen anderen Baustein.
Jobst Q. schrieb:> Das ist in C++ kein Problem. Ich brauche objektorientierte Ansätze aber> gerade in der SPS-Programmierung, wo sie leider nur rudimentär> unterstützt werden.
Ach. Ich hatte das irgendwie anders verstanden:
Jobst Q. schrieb:> Was ich mir wünsche, wäre eine Sprache, die subjektorientierte> Programmierung unterstützt.
SPS enthalten doch auch nur Mikrocontroller. Die kann man auch in C++
programmieren.
Niklas Gürtler schrieb:> SPS enthalten doch auch nur Mikrocontroller. Die kann man auch in C++> programmieren.
Nein - die meisten SPS-Systeme sind super proprietär, maximal
Vendor-Lock-In-Syndrom - du arbeitest mit dem einen Entwicklungstool des
Hersteller und das war es dann auch an Möglichkeiten - die Sprachen sind
super rudimentär - verglichen mit C/C++/C# geradezu Steinzeit artig - in
Ausdruckskraft und Bedienung
Cppbert schrieb:> geradezu Steinzeit artig
Und warum benutzt man das dann, wenn einen diese Einschränkungen sogar
stören ?
Die Controller haben doch bestimmt einen JTAG/SWD/ISP/... -Anschluss.
Darüber kann man doch bestimmt mit dem entsprechenden
Programmierer/Adapter und ggf. Nadeladapter o.ä. die eingebaute Software
löschen und das ganz normal programmieren. Und wenn nicht - es gibt doch
SPSen die extra für Arduino, R-PI und andere selbstprogrammier-Systeme
sind...
Niklas G. schrieb:> Und warum benutzt man das dann, wenn einen diese Einschränkungen sogar> stören ?
Das ist der Markt-Standard - du verkaufst nichts im
Automations/Fertigungsbereich wenn du nicht die Produkte der 3 führenden
Hersteller (Siemens, Beckhoff, S3) verwendest - so einfach ist das
Da ist eine riesige Kette an Hardware-Zusatz-Komponenten und
Support-Garantie für 10 Jahre+ dahinter den man einfach sonst nirgends
bekommt
Das ist eine ganz eigene Welt die nach völlig anderen Regeln
funktioniert
Und der Prozessor ist wirklich ein Spezialteil? Nicht einfach irgendein
Cortex-M3 oder C166 oder so?
Witzig, dass gerade ein Ingenieurs-Konzern eine Software baut, mit der
das Baukasten/Wiederverwendungs/Komponenten-Prinzip nicht (gut?) nutzbar
ist.
Habe diesen Artikel gefunden
https://www.sps-magazin.de/?inc=artikel/article_show&nr=112569
und mich köstlich amüsiert :-)
Niklas G. schrieb:> Und der Prozessor ist wirklich ein Spezialteil? Nicht einfach irgendein> Cortex-M3 oder C166 oder so?
Standardprozessor, SoC, FPGA, irgendwas halt.
Völlig egal, wenn man die vorgefertigte Software nicht nehmen will, kann
man die Hardware auch gleich selbst entwickeln. Du setzt dich ja auch
nicht hin und betreibst Reverse Engineering bei dein Smartphone, weil
dir die von Android/iOS gebotenen Möglichkeiten nicht gefallen.
Und nicht anderes ist es bei einer SPS, der Hersteller bietet dir halt
ein Betriebssystem, welches dir komfortablen Zugriff auf die die
Hardware und alle möglichen Bussysteme bietet und möglichst viel
Komplexität wegoptimiert, dafür ist man in der Programmierung halt sehr
eingeschränkt. Im Gegenzug kannst du in 10 Jahren das gleiche Programm
einfach auf den Nachfolger draufspielen, ohne viel Portieraufwand.
Man muss aber auch sagen, dass schon seit vielen Jahren SPSen zumindest
halbwegs vernünftige Möglichkeiten zur Programmierung bieten, die
Entwickler aber diese auch einfach nicht verwenden. Viele sind auch mehr
Elektriker als Softwareentwickler.
Und von allen SPS-Herstellern ist Siemens der schlimmste, die anderen
sind da m.W. zumindest etwas offener. Deutsche
Qualitäts-Steinzeittechnik halt, deswegen gibts deren Handys und
Computer auch nicht mehr.
Jobst Q. schrieb:> Ich sehe die Pumpstation mit ihren Pumpen als eine Einheit. Also wird> das Team mitsamt seiner Kommunikation getestet. Da ist der Test dann> überhaupt nicht mehr kompliziert.
Natürlich wird der Test umso komplexer, desto mehr Funktionalität man in
einen Block rein packt.
Der Punkt ist vielmehr, dass du vermutlich kein Unittesting betreibst,
und keine Testcases definieren musst.
vn nn schrieb:> Du setzt dich ja auch> nicht hin und betreibst Reverse Engineering bei dein Smartphone, weil> dir die von Android/iOS gebotenen Möglichkeiten nicht gefallen.
Und was ist mit ROM's, Cyanogen Mod usw.?
vn nn schrieb:> kann> man die Hardware auch gleich selbst entwickeln
Man will doch den Vorteil der robusten SPS-Hardware haben...
Niklas G. schrieb:> Witzig, dass gerade ein Ingenieurs-Konzern eine Software baut, mit der> das Baukasten/Wiederverwendungs/Komponenten-Prinzip nicht (gut?) nutzbar> ist.
Damit bindest du deine Kunden für immer
Niklas G. schrieb:> Und was ist mit ROM's, Cyanogen Mod usw.?
Da gibt es leider nichts - auch wenn das bestimmt sehr lustig wäre
Niklas G. schrieb:> Und was ist mit ROM's, Cyanogen Mod usw.?
Sind ja auch keine komplette eigenentwicklung, sondern basieren immer
auf den Open-Source-Bestandteilen vom Stock-Android.
Und nochmal, eine SPS kauft man ja auch aufgrund der
Softwareunterstützung, man kann halt in 15 Jahren einfach das
Nachfolgemodell einbauen und das gleiche Programm läuft 1:1 wieder
drauf. Und man kauft es, weil es von Elektrikern programmiert werden
kann, die keine Ahnung von Softwareentwicklung haben müssen.
Leider führt das dann natürlich auch dazu, dass wir (Entwickler von
Industriekomponenten, die im Endeffekt von SPSen angesteuert werden)
regelmäßig Beschwerden von SPS-Entwicklern bekommen, bei denen sich dann
raus stellt dass die die Ansteuerung nicht im Griff haben.
Niklas G. schrieb:> Man will doch den Vorteil der robusten SPS-Hardware haben...
Und den der robusten SW. Das ist praktisch unmöglich, wenn jemand da
tief drin Prozessorzugriff hat. Und selber schreiben ist utopisch, da
Niklas G. schrieb:> vn nn schrieb:>> kann>> man die Hardware auch gleich selbst entwickeln
Eine SPS hat genau einen Zweck:
Das zu tun, was sie tun soll. Und zwar unter allen Umstaenden.
Fuer meine Gesellenpruefung (2008, Elektriker) brauchte ich auch eine
SPS, so die Vorgabe. Es sollte eine Hebebuehnensteuerung realisiert
werden.
Ich habe mich damals fuer eine "Easy" von "Kloeckner Moeller"
entschieden, andere fuer eine "LOGO" von Siemens.
Meine hatte ein Display und ein paar Knoeppe (aehnlich dem Bild).
Und wie man auf dem Bild auch sieht: Die Programmierung besteht aus
einfachem Verknuepfen durch AWL oder Logikgatter. (Bei grossen SPS mag
das anders sein, keine Ahnung. Hatte danach nie wieder mit SPS zu tun.
Schade eigentlich.)
Da muss ich mich "nur" um die Logik kuemmern. Ich muss mich nicht mit
einer Programmiersprache und deren Fallstricke (undefined behavior,
implementation defined behavior, overflows, Pointer, ...), Compilern,
Eigenheiten der Hardware usw. rumschlagen. Und bei so einer kleinen SPS
kommt man sogar ganz ohne Computer und Software zum Programmieren aus.
So eine kleine SPS zu programmieren haben wir in einem 5 Tage Lehrgang
(Teil der Ausbildung) gelernt, sowohl fuer die Easy als auch die Logo.
Und EIB war auch noch drin in den 5 Tagen. Versuch das mal mit einer
Programmiersprache in Verbindung mit Hardware.
Und bei der SPS kann ich mir sicher sein, das sie Funktioniert.
Versuch doch mal in einer beliebigen Programmiersprache auf einer
beliebigen Hardware eine entsprechende Steuerung zu programmieren, und
dann erbringe auch bitte noch den Nachweis, dass deine Steuerung unter
gar keinen Umstaenden abstuertzt.
Das ist bei einer SPS deutlich einfacher.
Und: Die SPS garantiert mir ein festes Ausfuehrungsfenster.
Auch hier duerfte der Nachweis ueber einhaltung von Timings in einer
beliebigen Programmiersprache auf einer beliebigen Hardware ziemlich
viel Aufwand bedeuten. Besonders wenn du diesen Nachweis erneut bringen
musst, weil du neue Hardware brauchst, einen anderen Compiler oder eine
andere Sprache verwenden willst.
Die Dinger sind in Sachen Hardware und Software so robust (und einfach
geil), da muss man schon viele Mannjahre an Zeit, Geld und Nerven
investieren um da mit einem uC und ASM, C, C++ oder Rust hinzukommen.
Fuer zu Hause fuer die eigene Heizungssteuerung mag das egal sein. Aber
in der Industrie, wo man gewisse Garantien geben muss (Gefahr von
Menschenleben), in einem Umfeld das so voller Stoereinfluesse ist,
verlasse ich mich lieber auf eine SPS.
An der SPS die ich hatte konnte ich an alle Kontakte mit 230V~ ran. Da
musst du erstmal mit einem uC hin. Und die SPS hat gerade mal etwas um
die 120 Euro gekostet (8 Eingaenge, 4 Ausgaenge).
SPS haben schon ihre Berechtigung. Aber das versteht man moeglicherweise
nur, wenn man mal mit den Dingern gearbeitet hat, und sei es nur fuer
eine Woche.
Niklas G. schrieb:> Und warum benutzt man das dann, wenn einen diese Einschränkungen sogar> stören
Weil es bestens Funktioniert: Never Change a running System!
Man soll mit einer SPS nicht alles moegliche Machen koennen, denn dazu
sind sie nicht gedacht. Auf einem uC kannst du gerne per WLAN und
Internet das Wetter und die Zeit abfragen, und noch deinen Toaster
steuern und das Ergebnis dann auf Facebook posten. Das ist aber nicht
die Aufgabe einer SPS. Deswegen stoeren gewisse Einschraenkungen einfach
nicht, was fuer einen Softwareentwickler moeglicherweise etwas sonderbar
wirken mag.
Bei deinem Fahrrad stoert es dich doch auch nicht, das du damit nicht
fliegen kannst, oder?
Prinzipien aus der Softwareentwicklung funktionieren im Bereich von SPS
mehr schlecht als recht. Weil eine SPS einfach anders Funktioniert.
Just my 2 cent
Gruesse
Eigentlich ging es nie um SPS vs uC. Erst hieß es, OOP sei zu
eingeschränkt und man solle da Prinzipien aus SPS-Programmierung
übernehmen. Was leider nicht schlüssig dargelegt werden konnte. Dann
hieß es, die SPS könne das leider doch nicht aber C++ schon. Jetzt wird
gesagt SPS sind doch ganz toll. Schönes Verwirrspiel.
Kaj schrieb:> Das ist bei einer SPS deutlich einfacher.
Wie denn, wenn man absolut nichts über die Funktionsweise weiß?
Kaj schrieb:> da muss man schon viele Mannjahre an Zeit, Geld und Nerven investieren> um da mit einem uC und ASM, C, C++ oder Rust hinzukommen.
Man muss bestimmt auch viele Mannjahre und viel Geld an Siemens
investieren, um mit SPSen die Dinge zu tun, die mit C++ einfach möglich
sind.
Kaj schrieb:> Da musst du erstmal mit einem uC hin
Kein Vergleich. Die SPS enthält einen uC. Du kannst ja auch nicht Autos
mit Motoren vergleichen und kritisieren dass der Motor keinen Laderaum
hat.
Kaj schrieb:> Weil eine SPS einfach anders Funktioniert.
Das ist eine Software auf einem Prozesssor in einem Plastik-Kasten. Was
funktioniert da anders als eine Android-App, welche auch eine Software
auf einem Prozesssor in einem Plastik-Kasten ist?
Niklas Gürtler schrieb:> Das ist eine Software auf einem Prozesssor in einem Plastik-Kasten. Was> funktioniert da anders als eine Android-App, welche auch eine Software> auf einem Prozesssor in einem Plastik-Kasten ist?
Die Umgebung ist stark eingeschränkt und zugeschnitten
z.B. Harte-Echtzeit, Programmablauf durch Zyklen (keine Threads oder
sowas)
- die Programmiersprachen die verfügung stehen (FUP,KOP,Strukturierter
Text,..) sind so stark eingeschränkt das ein Techniker damit
echtzeitfähige Software bauen kann, ansonsten geht das System in
Stop-Zustand
genau dafür ist auf der Plain Hardware noch eine Echtzeitsystem plus
viele Gimmicks mit drauf
Klar geht das auch mit FreeRtos oder anderen auf einem uController -
aber das bekommt dann eben kein E-Techniker mehr hin - oder ist nicht
Standartisiert genug um im Markt zu überleben
Niklas Gürtler schrieb:> Eigentlich ging es nie um SPS vs uC. Erst hieß es, OOP sei zu> eingeschränkt und man solle da Prinzipien aus SPS-Programmierung> übernehmen. Was leider nicht schlüssig dargelegt werden konnte. Dann> hieß es, die SPS könne das leider doch nicht aber C++ schon. Jetzt wird> gesagt SPS sind doch ganz toll. Schönes Verwirrspiel.
Ich sehe auch nicht wie man "praktikable" Beispiele - aka Konzept aus
der SPS Welt (egal aus welcher) als Konzept für allgem.
Software-Entwicklung hernehmen sollte - die Welten sind einfach zu
verschieden
Niklas Gürtler schrieb:> Tatsächlich ist es sehr schwierig festzustellen, was du eigentlich genau> meinst. Meinen Beispielcode hast du ignoriert, eigenen zeigst du> nicht...
Es ist halt ziemlich aufwendig,jedenfalls der Code, wenn der Master
alles tun muss. Ich hab es mal in C geschrieben, in AWL wäre schon das
Lesen fast unzumutbar und nur wenige kennen sich damit aus.
Im Teamwork sieht es im Code für jede Pumpe im Beispiel so aus:
Wären die Unterobjekte als Array verfügbar, ginge es natürlich etwas
kompakter, aber auf einer SPS mit AWL geht das leider nicht. Auf jeden
Fall wäre er aber auch größer als im Teammodell.
Ein kleiner Unterschied in der Funktionalität ist in der
Häufigkeitsverteilung der neuen Hauptpumpe. In dem hierarchischen Modell
kommen die ersten Pumpen immer wieder als Ersatzpumpen dran, während die
letzten ein geruhsames Leben haben, was auch nicht so gesund ist.
Im Teammodell wären es jeweils die nächstfolgenden, die bereit sind.
Wenn also Pumpe 4 ausfällt, wären erstmal die Pumpen 5 und 6 gefragt.
Wollte man eine solche Gleichverteilung im Mastercode nachbilden, wäre
es noch komplizierter.
Jobst Q. schrieb:> Auf jeden> Fall wäre er aber auch größer als im Teammodell.
Bei meinem Beispiel war's sogar kompakter. Deine ewige switch-case-Folge
ist natürlich weit von der Realität entfernt; nach der Logik musst du in
der Pumpe auch Hauptpumpe=1,2,3... abfragen. Wenn du deine Zugriffe auf
das "team" jetzt noch in Funktionen kapselst hast du ganz normales OOP.
Also kein wirklich neues Paradigma "Subjektorientierte Programmierung"
erkennbar. Mit so wenig bekannten Randbedingungen lässt sich nicht
eindeutig sagen von welcher Stelle die Ablaufsteuerung erfolgen sollte,
aber hier sind ein paar Gedanken dazu; im Allgemeinen sollte man im Kopf
behalten, dass kürzerer Code nicht immer besser ist. Die Wartbarkeit und
Wiederverwendbarkeit ist ein viel wichtigeres Qualitätsmerkmal.
Durch eine solche Team-Datenstruktur ist man natürlich versucht, von
verschiedenen Stellen in der Pumpenklasse darauf zuzugreifen. Dadurch
erstellt man sich schnell sehr komplexe und undurchschaubare Abläufe.
Macht man das zentral in einem Algorithmus in der Pumpenstation ist
dieser übersichtlicher - alle Änderungen am pumpenübergreifenden Zustand
sind an einer Stelle, man braucht nichtmal Getter/Setter.
Ich gehe mal davon aus, dass jede Pumpe eine Art von "run"-Funktion hat,
welche von der Station aufgerufen wird. Zwischen den Aufrufen dieser
Funktionen der einzelnen Pumpen ist der Zustand möglicherweise
inkonsistent; es könnte zwischenzeitlich keine Hauptpumpe existieren. Es
ist irgendwie nicht so schön, wenn es eine Funktion gibt, welche
ungültige Zustände erzeugen kann. Wenn ich jedoch eine "run"-Funktion in
der Pumpstation habe, welche von den Pumpen die Zustände abfragt und die
Hauptpumpe entsprechend aktualisiert, sind vor und nach jedem
Funktionsaufruf alle Daten dieser Aufrufebene konsistent.
i.A. sagt man dass auf je mehr globale Daten ein Algorithmus/Objekt
zugreift desto schwieriger er wartbar ist, weil mehr Verpflechtungen
auftauchen.
Jobst Q. schrieb:> Wären die Unterobjekte als Array verfügbar, ginge es natürlich etwas> kompakter, aber auf einer SPS mit AWL geht das leider nicht.
Dann verwend halt kein AWL (als Erklärung für diejenigen, die noch nie
eine SPS gesehen haben: eine Sprache auf Assemblerniveau), sondern ST
oder C++, da gibts auch Arrays. Wenn man in den 90ern festhängt, tut man
sich halt schwer.
Kaj schrieb:> Die Programmierung besteht aus> einfachem Verknuepfen durch AWL oder Logikgatter. (Bei grossen SPS mag> das anders sein, keine Ahnung. Hatte danach nie wieder mit SPS zu tun.> Schade eigentlich.)
Natürlich kann man Große SPSen auch halbwegs vernünftig programmieren
wenn man nur will, entweder in ST (Pascal-Abklatsch) oder in
abgespecktem C++.
Jobst Q. schrieb:> Im Teamwork sieht es im Code für jede Pumpe im Beispiel so aus:
Also quasi unleserlich, unstrukturiert, schwer zu warten, schwer zu
lesen.
Jobst Q. schrieb:> Im Teammodell wären es jeweils die nächstfolgenden, die bereit sind.> Wenn also Pumpe 4 ausfällt, wären erstmal die Pumpen 5 und 6 gefragt.> Wollte man eine solche Gleichverteilung im Mastercode nachbilden, wäre> es noch komplizierter.
Unfug, denn gerade dann brauchst du nur noch die Funktion
sucheNeueHauptpumpe() angreifen, anstatt im restlichen Code
herumzufuhrwerken und zu riskieren, dessen Verhalten zu beeinflussen...
vn nn schrieb:> Natürlich kann man Große SPSen auch halbwegs vernünftig programmieren> wenn man nur will, entweder in ST (Pascal-Abklatsch) oder in> abgespecktem C++.
Der strukturierte Text (ST) kommt der Hochsprache schon recht nahe, nach
IEC 61131-3 kann man dort auch objektorierentiert Programmieren. Die
Prinzipien sind ähnlich, es wird hauptsächlich aus Sicherheitsgründen
auf einige als potentiell unsicher geltende Features wie bspw.
Mehrfachvererbung verzichtet.
Da der Trend zur Soft-SPS geht (Industrie-PC mit
Echtzeitbetriebssystem), hat man z.B. auf den Beckhoff-Kisten sogar ein
vollwertiges Windows laufen, das dann natürlich jede Windows-Anwendung
in jeder beliebigen Hochsprache ausführen kann. Durch Mappen der
Prozessvariablen können diese Anwendungen dann in einfachster Weise auf
die robuste SPS-Hardware zugreifen.
Die Grenzen verschwimmen hier zunehmend, finde ich persönlich aber
positiv, da man so die Vorteile aus beiden Welten zusammenbringt.
lichtstrahl schrieb:> Der strukturierte Text (ST) kommt der Hochsprache schon recht nahe, nach> IEC 61131-3 kann man dort auch objektorierentiert Programmieren. Die> Prinzipien sind ähnlich, es wird hauptsächlich aus Sicherheitsgründen> auf einige als potentiell unsicher geltende Features wie bspw.> Mehrfachvererbung verzichtet
Ich weiß:
vn nn schrieb:> Natürlich kann man Große SPSen auch halbwegs vernünftig programmieren> wenn man nur will, entweder in ST (Pascal-Abklatsch) oder in> abgespecktem C++.lichtstrahl schrieb:> Da der Trend zur Soft-SPS geht (Industrie-PC mit> Echtzeitbetriebssystem), hat man z.B. auf den Beckhoff-Kisten sogar ein> vollwertiges Windows laufen, das dann natürlich jede Windows-Anwendung> in jeder beliebigen Hochsprache ausführen kann. Durch Mappen der> Prozessvariablen können diese Anwendungen dann in einfachster Weise auf> die robuste SPS-Hardware zugreifen.
Wunderbar, instabile Windows-Schrottsoftware steckt dann in
prozessrelevanten Echtzeitsystemen.
Hat denen noch keiner gesagt, dass Komplexität der Feind stabiler
Software ist?
lichtstrahl schrieb:> da man so die Vorteile aus beiden Welten zusammenbringt.
Eher die Nachteile... jetzt schafft es dann der instabile, unperformante
Müll der im PC-Bereich mittlerweile leider üblich ist, auch noch in
Industriesteuerungen. Am besten auch noch in Java, .NET oder - der
heißeste Shit - Node.js geschrieben. Das ganze nennen wir dann
"Industrie 4.0".
Von Blöcke zusammenklicken und AWL-Assembler auf 80er-Jahre-Niveau zu
den überladenen Frameworks im Jahr 2018 - Zwischenhalt "ordentliche
Software" wird ausgelassen.
vn nn schrieb:> Von Blöcke zusammenklicken und AWL-Assembler auf 80er-Jahre-Niveau zu> den überladenen Frameworks im Jahr 2018 - Zwischenhalt "ordentliche> Software" wird ausgelassen.
Definiere "ordentlich" - und finde dann 7 andere, die da zustimmen...
vn nn schrieb:> Wunderbar, instabile Windows-Schrottsoftware steckt dann in> prozessrelevanten Echtzeitsystemen.
Meines Wissens machen die das nicht erst seit gestern so. Und mit nicht
unerheblichem Erfolg.
vn nn schrieb:> Wunderbar, instabile Windows-Schrottsoftware steckt dann in> prozessrelevanten Echtzeitsystemen.> Hat denen noch keiner gesagt, dass Komplexität der Feind stabiler> Software ist?
Naja, Du musst es ja nicht so machen. Die "herkömmlichen" SPS-Sprachen
werden ja vollumfänglich weiter unterstützt.
vn nn schrieb:> jetzt schafft es dann der instabile, unperformante> Müll der im PC-Bereich mittlerweile leider üblich ist, auch noch in> Industriesteuerungen
Ich verstehe aber glaube ich, was Du meinst. Es ist sicher keine gute
Idee die "Skriptkiddies" auf die ehr konservative SPS-Welt loszulassen.
Das liegt meines Erachtens aber in der Verantwortung des Entwicklers,
das Tool und die Sprache auszuwählen, die für ein Projekt am
sinnvollsten hinsichtlich der Sicherheit, aber auch der
Leistungsfähigkeit ist.
Gerade im Zuge des vielgepriesenen Industrie 4.0 kommen halt eine ganze
Reihe an Anforderungen hinzu, an die man in den klassischen
SPS-Projekten wahrscheinlich nie gedacht hätte. Es soll ja heute jede
Kiste im Internet hängen und die Messdaten in ner SQL-Datenbank ablegen
(mal überspitzt gesagt). Ob die Daten jemals wieder ein Mensch anschaut,
steht auf einem anderen Blatt.
lichtstrahl schrieb:> Ich verstehe aber glaube ich, was Du meinst. Es ist sicher keine gute> Idee die "Skriptkiddies" auf die ehr konservative SPS-Welt loszulassen.
Ist nicht der SPS-Programmierer sowieso ein "Scriptkiddie"? Schließlich
nutzt er High-Level-Tools ohne die eigentliche Funktionsweise zu kennen
(bzw. ohne sie überhaupt in Erfahrung bringen zu können, weil die
Hersteller alles verheimlichen).
Dennis S. schrieb:> Meines Wissens machen die das nicht erst seit gestern so. Und mit nicht> unerheblichem Erfolg.
Nur weil etwas funktioniert, heißt das nicht, dass es auch sauber ist.
Oder die SPS läuft doch nicht auf Windows, sondern parallel dazu, was
auch erklären würde, die die Echtzeit unter Windows hinbringen.
lichtstrahl schrieb:> Naja, Du musst es ja nicht so machen. Die "herkömmlichen" SPS-Sprachen> werden ja vollumfänglich weiter unterstützt.
Würde die SPS tatsächlich auf Windows laufen, hätte man ja trotzdem den
kompletten Windows-Unterbau als Abhängigkeit drinnen, unabhängig davon,
wie man es programmiert.
lichtstrahl schrieb:> Es ist sicher keine gute> Idee die "Skriptkiddies" auf die ehr konservative SPS-Welt loszulassen.
Wobei konservativ da auch nicht unbeding von Vorteil ist, wenn man
deshalb in den 90ern hängen geblieben ist...
vn nn schrieb:> Dennis S. schrieb:>> Meines Wissens machen die das nicht erst seit gestern so. Und mit nicht>> unerheblichem Erfolg.>> Nur weil etwas funktioniert, heißt das nicht, dass es auch sauber ist.> Oder die SPS läuft doch nicht auf Windows, sondern parallel dazu, was> auch erklären würde, die die Echtzeit unter Windows hinbringen.
Das wäre ähnlich wie bei den "Echtzeiterweiterungen" für Windows, die im
Prinzip ihren eigenen Scheduler haben, der direkt auf der Hardware läuft
und Windows dann als Task in einer Art VM laufen lassen.
Rolf M. schrieb:> Das wäre ähnlich wie bei den "Echtzeiterweiterungen" für Windows, die im> Prinzip ihren eigenen Scheduler haben, der direkt auf der Hardware läuft> und Windows dann als Task in einer Art VM laufen lassen.
Also keine unmachbare Herausforderung, dass Schadsoftware aus Windows
heraus in den SPS-Code hineinpfuscht.
"Complexity is the enemy of security"