Seite 1 von 1

Klassen Instanz

Verfasst: Samstag 5. Februar 2022, 15:22
von Xtremdiver
Hallo zusammen,

ich benötige ein paar Tipps von euch, da ich gerade einen logischen Hänger habe.
Ich habe 4 Module mit einem PCA9685 (16 Kanal 12bit LED PWM Generator) und 4 Module mit einem MCP23017 (16 Kanal Input und Output Portexpander).

Hierfür habe ich jeweils eine Klasse geschrieben und eine Instanz zur Steuerung der Hardware aufgebaut. Hier am Beispiel für das LED-Licht.
Bild

Mit der Instanz für LichtHardware und einer Referenzliste habe ich die Klassen HW_Ledtreiber und PCA9685 wie folgt aufgebaut und jeweils in einer Liste innerhalb der Initialisierungsphase gespeichert.
Bild

In der Klasse HW_Ledtreiber habe ich die Klasse PCA9685 als Instanz aufgerufen.

Code: Alles auswählen

self._hw_treiber = PCA9685(self._i2cbus_system, self._ledtreiber_adresse, self._treiber_option)
Nun habe ich in den letzten Tagen ein paar Tutorials zur Vererbung durchgelesen. Würdet ihr mir dazu raten mit dem Aufrufen der Klasse HW_Ledtreiber die Klasse PCA9685 zu vererben? Mir ist aber wichtig, das jedes Modul separat für sich ist und mit Aufruf initialisiert werden muss.

Wie auch immer, die Instanz von LichtHardware funktioniert und ich kann über diese auf die einzelnen Module zugreifen und somit auch die Hardware bedienen.

Nun habe ich mir überlegt eine weiter Instanz aufzubauen um die Steuerung des Lichtes zu gewährleisten.
Bild

Bild

Das sind nun 2 Instanzen nur für das Licht. Nach dem gleichen Schema würde ich 2 Instanzen für die Ein- und Ausgänge aufbauen.
Dann hätte ich also 4 Instanzen.

Wie kann man am Besten die Instanzen organisieren? (In Listen?)
Wie kann man Informationen in so einem Aufbau am besten verarbeiten und an die entsprechenden Instanzen verteilen?
Würde es Sinn machen eine Controller-Instanz aufzubauen?
Ich stehe gerade auf dem Schlauch und komme gerade nicht wirklich weiter.

Wenn ihr weitere Infos braucht, kann ich sie euch gerne geben.

Re: Klassen Instanz

Verfasst: Freitag 11. Februar 2022, 13:52
von LukeNukem
Xtremdiver hat geschrieben: Samstag 5. Februar 2022, 15:22 Das sind nun 2 Instanzen nur für das Licht. Nach dem gleichen Schema würde ich 2 Instanzen für die Ein- und Ausgänge aufbauen.
Dann hätte ich also 4 Instanzen.
[...]
Wie kann man am Besten die Instanzen organisieren? (In Listen?)
Verzeihung, ich verstehe nicht ganz, wie Du auf "2 Instanzen nur für das Licht" kommst oder warum das ein Problem darstellen sollte. Ich persönlich würde das eher so entwerfen, daß es für jede Lichtquelle eine Instanz gäbe, die einzelnen Lichtquellen in ihren Räumen organisiert wären und die Räume in einem Gebäude als Wurzel -- mithin also alles innerhalb einer hierarchischen Baumstruktur. Innerhalb der Lichtquelle gäbe es dann eine Instanz des Treibers für diese konkrete Lichtquelle, also etwa so:

Code: Alles auswählen

Haus
    Garage
        Deckenlicht         
    Schlafzimmer
        Deckenlicht         
        Nachttisch links    
        Nachttisch rechts
Eine solche Struktur ließe sich wunderbar zum Beispiel mit JSON oder IMHO noch besser mit YAML abbilden.
Xtremdiver hat geschrieben: Samstag 5. Februar 2022, 15:22 Wenn ihr weitere Infos braucht, kann ich sie euch gerne geben.
Mein Problem ist nicht ein Mangel an Information, sondern deren -- mit Verlaub -- etwas ungeordnete und chaotische Darstellung. Aus irgendeinem Grund habe ich den Eindruck, daß da ein Java-Entwickler die erlernten Konzepte mit Python umsetzen will, etwa mit Getter- und Setter-Methoden. Sowas macht man in Python gemeinhin nicht, und wenn, dann gibt es dafür Properties und / oder attrs [1]. Aus einem mit unerfindlichen Grund habe ich auch das Gefühl, daß Du irgendwie Instanzen sparen willst -- kann das sein, und wenn ja: warum? Und... kann es sein, daß Du mit "Instanz" eigentlich eine Klasse meinst?


[1] https://www.attrs.org/en/stable/

Re: Klassen Instanz

Verfasst: Freitag 11. Februar 2022, 19:25
von imonbln
Mit Verlaub,

gegenwärtig ist deine Lichtverwaltung eine glorifizierte Liste. Und die Klasse Lichtsystem hat gute Chancen, ein Gott-Antipattern zu werden. Schon mein Prof. hat gesagt, wenn eine Klasse System im Namen trägt, stimmt in 95% der Fälle das Design nicht, nach mehreren Jahren praktischer Erfahrung kann ich nur zustimmen.

Die ganzen Abarten von Lichtmodule, sehen für mich erstmal nach Datenklassen aus, solange diese keine Aktoren haben. Außerdem würde ich vermuten, dass du hier mindestens das D aus dem SOLID Prinzip verletzen wirst, da in diese Klassen unterschiedliche Property haben und Lichtsystem, Fallunterscheidungen braucht um zu wissen, mit welchen Lichtmodule es gerade arbeitet. Zwischen den beiden fehlt also noch irgendwelche Abstraktion.

Denn Namen PCA9685 finde ich auch nicht so toll, jemand der nicht im Thema drin steckt, wird nicht wissen, was die Klasse repräsentiert. Die Funktion pca9685_initialisieren, klingt von Namen nach etwas das __init__ schon gemacht haben sollte. Insgesamt würde ich mich meinen Vorredner anschließen und auch empfehlen, die einzelnen Lichter nach Standort in eine Art Baum zu implementieren.

Re: Klassen Instanz

Verfasst: Mittwoch 16. Februar 2022, 17:39
von Xtremdiver
Ich komme nicht aus der Java Welt - eher aus der C und Assembler Welt.
Irgendwo habe ich mal gelesen, dass man nicht einfach so ein Programmiersprache lernen sollte, sondern anhand eine Projektes.
Mein Projekt ist die Lichtsteuerung (erste Stufe). Hierbei habe ich mich entschieden von unten (also der Hardware Ebene) anzufangen.
1. Schritt: - Aufbau einer Klasse zur Kommunikation mit dem PC9685 -> erfolgreich
2. Schritt: - virtueller Aufbau der 4 PCA9685 Module. -> erfolgreich
Bild

Da nun die Nachbildung der Hardware-Realität funktioniert hatte und ich die volle Steuerung und Zugriff auf jedes einzelne Modul hatte, machte ich mich auf die Suche nach einer Lösung für die softwareseitige Lichtsteuerung. Hierfür entschied ich mich jede Lichteinheit als ein Modul zubetrachten. Es können mehrere Module zu einem System zusammengefasst werden.

Mein Problem besteht nun darin, dass die Instanzen vom logischen Aufbau her ungleich sind und ich keine direkt Zuweisung machen kann.

Leider finde ich auch keine passenden Beispiele - die meisten sind nicht Modular aufgebaut.
imonbln hat geschrieben: Freitag 11. Februar 2022, 19:25 die Klasse Lichtsystem hat gute Chancen, ein Gott-Antipattern zu werden.
-> das musst ich erst einmal googlen um zuverstehen was das ist. Ehrlich gesagt finde ich das nicht gerade passend und unverstanden was ich meinte.
Wie in den Abbildung zu sehen ist die Klasse Lichtsystem nur ein "Sammelbecken" zur Verwaltung der einzelnen Lichtmodule. Man könnte auch System durch ein anderes Wort ersetzen - das führt aber nicht zur Lösung des Problems.

Ich versuch es auf einem anderen Wege zu beschreiben. Auf der Software Seite hat ein RGBW-Lichtmodul die 4 Farbinformation (für Rot, Grün, Blau und Weiß). Auf der Hardware Seite hat ein Modul eine Adresse für den PCA9685 und ein "Register" der 16 Kanäle. Somit passen systematisch 4 RGBW Module an ein PCA9685 Modul.
Bild

Mir erscheint nun nur eins. Zu erst muss die Instanz der Hardware aufgebaut werden und dessen Link muss irgendwo gespeichert werden wie zum Beispiel

Code: Alles auswählen

class Controllers(object):
    mgmt_dict = {}
    mgmt_dict['lichthardware'] = LichtHardware(this_node_is, True)
    mgmt_dict['lichtsoftware'] = LichtVerwaltung(this_node_is)
Bei der Initialiserung der einzelnen Lichtmodule müsste ich dann über mgmt_dict['lichthardware'] die passende Verbindung in dem Lichtmodul in einer Variabel speichern. (Ist jetzt nur Therorie - ich versuch es in den nächsten Tagen)

Re: Klassen Instanz

Verfasst: Mittwoch 16. Februar 2022, 18:00
von __blackjack__
@Xtremdiver: Ich finde das alles auch zu unübersichtlich beschrieben und es erscheint mir auch übertrieben kompliziert. Da ich aber, wie wahrscheinlich jeder andere hier auch, nicht wirklich weiss das Du das hast und was Du machen willst, und weder Beschreibungen noch die ganzen Grafiken das wirklich vermitteln, kann da keiner wirklich was zu sagen.

Womit ich was anfangen kann ist Python-Quelltext und der gezeigte ist falsch. Man benutzt Klassen nicht als Behälter für globale Variablen die aus anderen globalen Variablen erstellt werden.

Davon mal abgesehen ist das auch komisch umständlich geschrieben, denn es gibt literale Wörterbücher. Und von `object` erbt man nicht (mehr) explizit.

Man sollte keine kryptischen Abkürzungen in Namen verwenden und Grunddatentypen haben da auch nichts verloren.

Das würde so aussehen…

Code: Alles auswählen

class Controllers:
    management = {
        "lichthardware": LichtHardware(this_node_is, True),
        "lichtsoftware": LichtVerwaltung(this_node_is),
    }
…aber wie gesagt, das ist so richtig falsch. Zumal Wörterbücher mit einem festen Schlüsselsatz ein „code smell“ sind, weil das eigentlich Objekte wären.

Re: Klassen Instanz

Verfasst: Mittwoch 16. Februar 2022, 18:39
von Xtremdiver
Mich würde es freuen, wenn mir jemand mal sagen könnte was genau unübersichtlich oder übertrieben kompliziert ist.
Es geht im einfachen nur um ein Modularsystem um Licht in Form von RGBW-Einheiten oder RGB oder nur Weiß anzusteuern.
Um es am Anfang einfach zuhalten kann man ja mit dem RGBW System starten. Das Licht (also die Farben) sollen verändert werden und über die Hardware PCA9685 ausgegeben werden.
Wenn ich auf so einem offensichtlichen Holzweg bin, dann muss es ja einen anderen "goldenen" Weg geben.
soll ich hier weiter in der Abteilung "Allgemein" weiter posten? oder gibt es eine Abteilung für Code Entwicklung?

Re: Klassen Instanz

Verfasst: Mittwoch 16. Februar 2022, 19:29
von pillmuncher
@Xtremdiver: Deine Vererbungsstruktur ist falsch. Sinnvollerweise verwendet man Vererbung, um Verhalten zu kapseln, das unterschiedliche Implementationen haben kann, nicht um eine Taxonomie (bunte LEDs und weiße LEDs) zu definieren. Sowohl ein Fahrrad als auch ein Auto können zB. beschleunigen, aber beim Fahrrad ist der Beschleunigungsmechanismus ein anderer als beim Auto. Das könnte dann etwa so aussehen:

Code: Alles auswählen

class Vehicle:
    def __init__(self):
        self.velocity = 0
    def accelerate(self, amount):
        pass
    ...

class Bike(Vehicle):
    def accelerate(self, amount):
        'pedal faster until new velocity == old velocity + amount'
    ...

class Car(Vehicle):
    def accelerate(self, amount):
        'push gas pedal until new velocity == old velocity + amount'
    ...
Wenn man eine Verkehrssimulation programmiert, muss man damit an einer Amplen nicht testen, was für ein Art von Fahrzeug gerade da steht, also statt sowas:

Code: Alles auswählen

def start_vehicle(vehicle):
    if isinstance(vehicle, Bike):
        'start pedaling and pedal faster until velocity == 50'
    elif isinstance(vehicle, Car):
        'release clutch and push gas pedal until velocity == 50'
    elif isinstance(vehicle, Rocket):
        ...
macht man einfach sowas:

Code: Alles auswählen

def start_vehicle(vehicle):
    vehicle.accelerate(50)
Wollte man eine neue Vehicle-Subklasse einführen - sagen wir Submarine -, müsste man also nicht den gesamten Code danach absuchen, wo man solche if-else-Kaskaden zur Typ-Unterscheidung stehen hat und dort überall eine neue elif-Klausel für Submarine reinschreiben, sondern kann diese Funltionalitäten einfach in der neuen Klasse bündeln und alles andere so lassen, wie es ist. Voilà, das ist schon der Kern der OOP. Alles andere ist Beiwerk.

Bei dir müsste man immer testen, ob es sich nun um eine bunte oder eine weiße LED handelt. Und was machst du, wenn du zusätzlich eine rote einführen willst? Da hättest du genau das Problem, das ich beschrieben habe und das OOP zu lösen versucht.

Wie das Design in deinem Fall tatsächlich aussehen sollte, kann ich dir leider nicht sagen, weil du versuchst, das anhand von taxonomischen Diagrammen zu erklären, bzw. glaubst, diese Diagramme würden als Erklärung genügen. Das tun sie nicht. Schreib einfach, welche Art von Verhalten du dir wünschst, also wie du deine LED-Steuerung verwenden willst.

Re: Klassen Instanz

Verfasst: Mittwoch 16. Februar 2022, 19:37
von Xtremdiver
@pillmuncher, vielen Dank für deinen Grundkurs der Vererbung. So ein ähnliches Beispiel habe ich schon in einigen Tutorial gelesen und getest. Das an sich ist nicht das Problem. Wie würdest du es machen, wenn man 50 Fahrzeuge hat und jedes einzelnes kontrollieren wollte.

Re: Klassen Instanz

Verfasst: Mittwoch 16. Februar 2022, 20:36
von pillmuncher
@Xtremdiver: Das kommt darauf an, was "kontrollieren" hier bedeutet. Wenn ich eine Verkehrssimulation programmiere, möchte ich soweit es geht jedes Fahrzeug einfach nur als Fahrzeug behandeln und nicht als Fahrrad, Auto oder U-Boot. Schwierig wird es natürlich, wenn ich mein U-Boot in einem Parkhaus abstellen möchte. Das nur nebenbei.

Wenn du mit "kontrollieren" meinst, jedes Auto als Auto und jedes Fahrrad als Fahrrad zu behandeln - wozu dann überhaupt eine gemeinsame Basisklasse? Wenn sich weder ein gemeinsames Interface noch eine gemeinsame Implementierung anbietet?

Deshalb nochmal: Beschreib doch mal, wie sich dein System verhalten soll, und nicht wie du meinst, dass seine statische Struktur aussehen soll. Du willst es doch verwenden und nicht nur wegen seiner schönen Struktur bewundern, oder?