Forum: PC-Programmierung C++: Zugriff auf nächsthöheren Scope


von Dennis S. (eltio)


Lesenswert?

Hallo zusammen,
in C++ kann mit :: auf globale Variablen zugegriffen werden. Ist es auch 
möglich auf den umgebenden Scope zuzugreifen? Beispiel:
1
#include <iostream>
2
3
int a {10}; // (1)
4
5
int main() {
6
    int a {20}; // (2)
7
    {
8
        int a {30}; // (3)
9
10
        // Folgende Zeile greift auf (1) zu.
11
        // Was tun um auf (2) zuzugreifen?
12
        std::cout << ::a << std::endl;
13
    }
14
    return 0;
15
}

Viele Grüße

von Vincent H. (vinci)


Lesenswert?

Nein, weil namespaces und scopes nicht das selbe sind.

von nfet (Gast)


Lesenswert?

:: greift nicht auf den globalen scope, sondern auf den globalen 
namespace zu.

Es gibt keine Möglichkeit auf andere scopes zuzugreifen.

von Dennis S. (eltio)


Lesenswert?

Verstehe, vielen Dank.

von Jobst Q. (joquis)


Lesenswert?

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.

von mh (Gast)


Lesenswert?

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.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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...

von Jobst Q. (joquis)


Lesenswert?

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.

von Dirk B. (dirkb2)


Lesenswert?

Du kannst vor der Definition von a (3) eine Referenz auf a (2) 
definieren.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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.

von Karl Käfer (Gast)


Lesenswert?

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.

von Dennis S. (eltio)


Lesenswert?

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. ;-)

von Dirk K. (merciless)


Lesenswert?

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

von mh (Gast)


Lesenswert?

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).

von Dennis S. (eltio)


Lesenswert?

Dirk K. schrieb:
> Du verlangst von der Sprache Mechanismen,
> um schlecht strukturierten Code umzusetzen.

Ganz und gar nicht.

von Hdudzevdjfd (Gast)


Lesenswert?

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.

von Jobst Q. (joquis)


Lesenswert?

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.

von Cppbert (Gast)


Lesenswert?

>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

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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:
1
class Station;
2
3
class Pumpe {
4
  public:
5
    Pumpe (Station& s) : m_station (s) {}
6
    void run ();
7
  private:
8
    Station& m_station;
9
};
10
11
class Station {
12
  public:
13
    Station () : m_pumpen { *this, *this, *this, *this, *this, *this, *this, *this }, m_haupt (nullptr) {}
14
    void run () {
15
      for (auto& p : m_pumpen) p.run ();
16
    }
17
    Pumpe m_pumpen [8], *m_haupt;
18
};
19
20
void Pumpe::run () {
21
  if (m_station.m_haupt == this) {
22
    // Ich bin Hauptpumpe ...
23
    
24
    if (false /* hier einfügen: Bin ich gestört? */) {
25
      m_station.m_haupt = nullptr;
26
    }
27
  } else if (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:
1
class Pumpe {
2
  public:
3
    bool run (bool istHauptpumpe, bool braucheNeueHauptpumpe) {
4
      if (braucheNeueHauptpumpe /* hier einfügen: Bin ich bereit? */) {
5
        return true; // Signalisiere dass ich Hauptpumpe werden kann
6
      }
7
      if (istHauptpumpe) {
8
        // Mache was wichtiges
9
        
10
        return true; // Bleibe Hauptpumpe
11
      }
12
      return false; // Werde nicht Hauptpumpe
13
    }
14
};
15
16
class Station {
17
  public:
18
    Station () : m_haupt (nullptr) {}
19
    void run () {
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
    Pumpe m_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.

von Dirk K. (merciless)


Lesenswert?

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

von Cppbert (Gast)


Lesenswert?

>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
class Pumpe (aka Pumpenkontroller)
2
  //das findet der Pumpenkontroller der Pumpe selbständig raus - eine Art "Sensor"
3
  void IchBinBeschaedigt(); //z.B. Callback oder Singal Interface, mit Queue oder direkt
4
5
Es kann x Varianten von Pumpen geben - solange sie das "IchBinBeschaedigt"-Sensor Callback/Signal Interface supporten
6
  
7
class Station
8
{
9
  Pumpen*[] // alle vorhandenen Pumpen, kaputte wie funktionierende
10
  Pumpen* aktive_pumpen[] // nur diese werden aktiv gesteuert
11
  
12
  die Pumpen "ichBinBeschaedigt"-Sensoren werden mit der Station verkabelt
13
  
14
  -->wenn eine Pumpe schreit dann
15
  WennEinePumpeBeschaedigt(pumpe_nr/Pumpe*)
16
  {
17
    //die Station sucht sich eine andere passenden aus veraendert die aktive_pumpen Liste
18
    //und arbeitet weiter damit
19
  }
20
}

wenn man keine aktive_pumpen Liste hat müssen die das unter einander 
ausmachen - aber das ist totaler Quatsch
- die Station ist der Master/Entscheider

von Cppbert (Gast)


Lesenswert?

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... :)

von Cppbert (Gast)


Lesenswert?

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

von lichtstrahl (Gast)


Lesenswert?

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.

von Dennis S. (eltio)


Lesenswert?

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.

von Dirk K. (merciless)


Lesenswert?

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

von Dennis S. (eltio)


Lesenswert?

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. ;-)

von Dirk K. (merciless)


Lesenswert?

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

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

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.

: Bearbeitet durch User
von Jobst Q. (joquis)


Lesenswert?

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.

von Jobst Q. (joquis)


Lesenswert?

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.

von Rolf M. (rmagnus)


Lesenswert?

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.

von Dennis S. (eltio)


Lesenswert?

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.

von Klaus H. (klummel69)


Lesenswert?

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?

von CppBert (Gast)


Lesenswert?

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

von Jobst Q. (joquis)


Lesenswert?

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.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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.

von Jobst Q. (joquis)


Lesenswert?

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.

: Bearbeitet durch User
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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

von Jobst Q. (joquis)


Lesenswert?

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.

: Bearbeitet durch User
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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?

von Jobst Q. (joquis)


Lesenswert?

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.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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).

von Jobst Q. (joquis)


Lesenswert?

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.

von Jobst Q. (joquis)


Lesenswert?

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.

von Niklas Gürtler (Gast)


Lesenswert?

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.

von Cppbert (Gast)


Lesenswert?

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

von Cppbert (Gast)


Lesenswert?

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

von Jobst Q. (joquis)


Lesenswert?

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.

von Jobst Q. (joquis)


Lesenswert?

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.

von Niklas Gürtler (Gast)


Lesenswert?

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.

von Cppbert (Gast)


Lesenswert?

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

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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...

von Cppbert (Gast)


Lesenswert?

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

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Diese Hardware kann man ja trotzdem benutzen, die ist ja nicht 
untrennbar mit der Software vereint...

von Cppbert (Gast)


Lesenswert?

Niklas G. schrieb:
> Diese Hardware kann man ja trotzdem benutzen, die ist ja nicht
> untrennbar mit der Software vereint...

Doch das ist sie - wird sogar pro aktiv gegen Fremdverwendung 
abgesichert
- ist kein offenes System sondern Spezialhardware, keine Kompiler 
verfügbar, keine Schnittstellen: sowas hier 
http://www.tpautomation.de/images/product_images/popup_images/6ES7515-2AM01-0AB0.jpg

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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 :-)

: Bearbeitet durch User
von vn nn (Gast)


Lesenswert?

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.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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...

von CppBert (Gast)


Lesenswert?

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

von vn nn (Gast)


Lesenswert?

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.

von A. S. (Gast)


Lesenswert?

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

von Kaj (Gast)


Angehängte Dateien:

Lesenswert?

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

von Niklas Gürtler (Gast)


Lesenswert?

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?

von CppBert (Gast)


Lesenswert?

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

von CppBert (Gast)


Lesenswert?

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

von Jobst Q. (joquis)


Lesenswert?

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:
1
//Aufgabe übernehmen
2
if(team.numHauptP == 0 && bereit && aufgabe==0 
3
&& zeituntaetig > zeitErholung){
4
  team.numHauptP=numMeine;
5
  aufgabe=1;  // 1:Hauptpumpe 2:Zweitpumpe ...
6
  }
7
  
8
if(team.numHauptP == numMeine){
9
  if( !bereit){ // Aufgabe abgeben wegen Störung
10
    team.numHauptP=0;
11
    aufgabe=0;
12
    anforderung=FALSE;
13
    }
14
  else anforderung = team.anforderungHauptP; //Anforderung übernehmen
15
  }

Etwa dieselbe Funktionalität, wenn der Master alles übernehmen muss:
1
errHauptp=0;
2
3
switch (numHauptp){  //Überprüfen auf Störungen
4
  
5
  case 1: 
6
  if ( ! P1.bereit) {
7
    P1.aufgabe=0;
8
    P1.anforderung=FALSE;
9
    errHauptp=1;
10
    }
11
  break;
12
  
13
  case 2: 
14
  if ( ! P2.bereit) {
15
    P2.aufgabe=0;
16
    P2.anforderung=FALSE;
17
    errHauptp=1;
18
    }
19
  break;
20
  
21
  case 3:
22
  if ( ! P3.bereit) {
23
    P3.aufgabe=0;
24
    P3.anforderung=FALSE;
25
    errHauptp=1;
26
    }
27
  break;
28
  
29
  case 4:
30
  if ( ! P4.bereit) {
31
    P4.aufgabe=0;
32
    P4.anforderung=FALSE;
33
    errHauptp=1;
34
    }
35
  break;
36
  
37
  case 5:
38
  if ( ! P5.bereit) {
39
    P5.aufgabe=0;
40
    P5.anforderung=FALSE;
41
    errHauptp=1;
42
    }
43
  break;
44
  
45
  case 6:
46
  if ( ! P6.bereit) {
47
    P6.aufgabe=0;
48
    P6.anforderung=FALSE;
49
    errHauptp=1;
50
    }
51
  break;
52
  
53
  case 7:
54
  if ( ! P7.bereit) {
55
    P7.aufgabe=0;
56
    P7.anforderung=FALSE;
57
    errHauptp=1;
58
    }
59
  break;
60
  
61
  case 8:
62
  if ( ! P8.bereit) {
63
    P8.aufgabe=0;
64
    P8.anforderung=FALSE;
65
    errHauptp=1;
66
    }
67
  break;
68
  
69
  default:
70
  }
71
 
72
if(errHauptp){ //Ersatzpumpe suchen
73
74
  if     (P1.bereit && P1.aufgabe==0 && P1.zeituntaetig > P1.zeitErholung){
75
    numHauptP=1;
76
    P1.aufgabe=1;
77
    }
78
  else if(P2.bereit && P2.aufgabe==0 && P2.zeituntaetig > P2.zeitErholung){
79
    numHauptP=2;
80
    P2.aufgabe=1;
81
    }
82
  else if(P3.bereit && P3.aufgabe==0 && P3.zeituntaetig > P3.zeitErholung){
83
    numHauptP=3;
84
    P3.aufgabe=1;
85
    }
86
  else if(P4.bereit && P4.aufgabe==0 && P4.zeituntaetig > P4.zeitErholung){
87
    numHauptP=4;
88
    P4.aufgabe=1;
89
    }
90
  else if(P5.bereit && P5.aufgabe==0 && P5.zeituntaetig > P5.zeitErholung){
91
    numHauptP=5;
92
    P5.aufgabe=1;
93
    }
94
  else if(P6.bereit && P6.aufgabe==0 && P6.zeituntaetig > P6.zeitErholung){
95
    numHauptP=6;
96
    P6.aufgabe=1;
97
    }
98
  else if(P7.bereit && P7.aufgabe==0 && P7.zeituntaetig > P7.zeitErholung){
99
    numHauptP=7;
100
    P7.aufgabe=1;
101
    }
102
  else if(P8.bereit && P8.aufgabe==0 && P8.zeituntaetig > P8.zeitErholung){
103
    numHauptP=8;
104
    P8.aufgabe=1;
105
    }
106
  errHauptp=0;  
107
  }
108
109
110
switch (numHauptp){  //Anforderung der Hauptpumpe
111
112
  case 1: 
113
  P1.anforderung=anforderungHauptP;
114
  break;
115
  
116
  case 2:
117
  P2.anforderung=anforderungHauptP;
118
  break;
119
  
120
  case 3:
121
  P3.anforderung=anforderungHauptP;
122
  break;
123
  
124
  case 4:
125
  P4.anforderung=anforderungHauptP;
126
  break;
127
  
128
  case 5:
129
  P5.anforderung=anforderungHauptP;
130
  break;
131
  
132
  case 6:
133
  P6.anforderung=anforderungHauptP;
134
  break;
135
  
136
  case 7:
137
  P7.anforderung=anforderungHauptP;
138
  break;
139
  
140
  case 8: 
141
  P8.anforderung=anforderungHauptP;
142
  break;
143
  
144
  default:
145
  }

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.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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.

von vn nn (Gast)


Lesenswert?

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...

von vn nn (Gast)


Lesenswert?

Weil wir mal nicht so sind:
Hier, deine Pumpensteuerung in schön, ohne Spaghetticode und wartbar.
1
#define AUSFALL_PROZENT  5
2
#define ZEIT_ERHOLUNG  5
3
4
typedef enum {
5
  NixTun,
6
  Hauptpumpe
7
} pumpe_aufgabe_t;
8
9
typedef struct {
10
  pumpe_aufgabe_t    aufgabe;
11
  bool        anforderung;
12
  bool        bereit;
13
  unsigned int    zeit_untaetig;
14
} pumpe_t;
15
16
typedef struct {
17
  pumpe_t        *pumpen;
18
  unsigned int    anzahl;
19
  pumpe_t        *hauptpumpe;
20
  bool        anforderung;
21
} station_t;
22
23
void pumpeAnfordern(pumpe_t *pumpe, bool anforderung)
24
{
25
  pumpe->anforderung = anforderung;
26
}
27
28
void pumpeDeaktivieren(pumpe_t *pumpe)
29
{
30
  pumpe->aufgabe = NixTun;
31
  pumpe->anforderung = false;
32
}
33
34
void pumpeAktivierenAlsHauptpumpe(pumpe_t *pumpe)
35
{
36
  pumpe->aufgabe = Hauptpumpe;
37
}
38
39
bool pumpeHatNixZuTun(pumpe_t *pumpe)
40
{
41
  return pumpe->aufgabe == NixTun;
42
}
43
44
bool pumpeIstBereit(pumpe_t *pumpe)
45
{
46
  return pumpe->bereit;
47
}
48
49
bool pumpeWarLangGenugFaul(pumpe_t *pumpe)
50
{
51
  return (pumpe->zeit_untaetig > ZEIT_ERHOLUNG);
52
}
53
54
pumpe_t *stationFreiePumpeSuchen(station_t *station)
55
{
56
  for (pumpe_t *pumpe = station->pumpen; pumpe < &station->pumpen[station->anzahl]; pumpe++) {
57
    if (pumpeIstBereit(pumpe)
58
        && pumpeHatNixZuTun(pumpe)) {
59
      return pumpe;
60
    }
61
  }
62
63
  return NULL;
64
}
65
66
void pumpeTask(pumpe_t *pumpe)
67
{
68
  // immer mal wieder ausfallen lassen
69
  pumpe->bereit = (rand() % 100) > AUSFALL_PROZENT;
70
71
  if (pumpe->aufgabe != NixTun) {
72
    pumpe->zeit_untaetig++;
73
  }
74
  else {
75
    pumpe->zeit_untaetig = 0;
76
  }
77
}
78
79
void stationTask(station_t *station)
80
{
81
  if (station->hauptpumpe) {
82
    if (pumpeIstBereit(station->hauptpumpe)) {
83
      pumpeAnfordern(station->hauptpumpe, station->anforderung);
84
    }
85
    else {
86
      pumpeDeaktivieren(station->hauptpumpe);
87
      station->hauptpumpe = NULL;
88
    }
89
  }
90
91
  if (station->hauptpumpe == NULL) {
92
    pumpe_t *neue_hauptpumpe = stationFreiePumpeSuchen(station);
93
    if (neue_hauptpumpe != NULL) {
94
      pumpeAktivierenAlsHauptpumpe(neue_hauptpumpe);
95
      station->hauptpumpe = neue_hauptpumpe;
96
    }
97
  }
98
}
99
100
void pumpeInitialisieren(pumpe_t *pumpe)
101
{
102
  pumpe->anforderung = false;
103
  pumpe->bereit = false;
104
  pumpeDeaktivieren(pumpe);
105
}
106
107
void stationInitialisieren(station_t *station, pumpe_t *pumpen, unsigned int anzahl)
108
{
109
  station->pumpen = pumpen;
110
  station->anzahl = anzahl;
111
  station->hauptpumpe = NULL;
112
}

Hausaufgabe: Schreibe die Pumpstation so um, dass die von dir geforderte 
Verwendung unterschiedlicher Pumpen forciert wird.

von lichtstrahl (Gast)


Lesenswert?

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.

von vn nn (Gast)


Lesenswert?

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.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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...

von Dennis S. (eltio)


Lesenswert?

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.

von lichtstrahl (Gast)


Lesenswert?

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.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

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).

von vn nn (Gast)


Lesenswert?

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...

von Rolf M. (rmagnus)


Lesenswert?

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.

von vn nn (Gast)


Lesenswert?

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"

von Vn N. (wefwef_s)


Lesenswert?

Negativbewertungen, ohne selbst Argumente vorzubringen, haben durchaus 
was faszinierendes.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.