Das richtige Design Pattern: I2C - ADC - Temperatur



  • Hi,

    bin gerade mit meinem Raspberry Pi beschäftigt und wollte eine Temperatur-Regelung implementieren. Bevor ich aber wild loslege wollte ich mir aber ein paar Gedanken über das Design machen. Folgender Ablauf:

    1. Ein Temperatursensor wird über einen AD Wandler Baustein eingelesen.
    2. Dieser Wandler wird über den I2C BUS angesprochen(lesen/schreiben).
    3. Eine Thermistor-Klasse wandelt den gelesenen Rohwert in Temperaturwerte um.
    4. Eine High Level Reglerklasse verarbeitet den Wert.

    Regelung <-> Thermistor <-> I2C Bus <-> AD-Wandler

    AD-Wandler und I2C sind eigentlich eine Einheit, denn der Baustein funktioniert eben nur via I2C.

    Die Idee ist es generisch und modular zu halten, sprich, wenn sich der Temperatursensor, der ADC Baustein oder der BUS ändert möchte ich auch nur Änderungen an der entsprechenden Klasse vornehmen.

    Eine Idee wäre, von jeder Klasse eine abstrakte Base-Klasse zu erstellen und jede andere Klasse die mit der konkreten Implementierung interagieren möchte eine Referenz zu übergeben.

    Was denkt ihr?



  • Halte ich fuer eine schlechte Idee. Abstrakte Basisklassen sind nur fuer verschiedene Typen zur laufzeit sinnvoll, du wirst aber wohl kaum weahrend der Laufzeit einen neuen bus festloeten.
    Einfach per Dokumentation ein Interface mit bestimmten Eigenschaften und Methoden garantieren und dann per preprozessor oder build-script anderen Code mit gleichem Interface reinschalten. Ein Beispiel waere boost::thread. Dort werden auch verschiedene, plattformunabhaengige Implementierungen ohne vererbung umgesetzt.



  • wanderameise schrieb:

    Was denkt ihr?

    Ich empfehle dringend, das Problem zu vertagen, bis es akut wird. Dann liegt mehr Erfahrung vor, was wirklich gebraucht wird.

    ~Upps, guter Spruch für die Sig.~



  • Ich sehe das wie volkard.

    Ich würde hier die einzelnen Zuständigkeiten schön in einzelne Klassen packen. Also...
    Eine I2CLink Klasse die I2C plaudern kann...
    Eine I2CThermistor Klasse die das Protokoll des Thermistor plaudern kann und sich der I2CLink Klasse bedient...
    Eine Regelung Klasse die sich wiederrum der I2CThermistor Klasse bedient.
    Und vermutlich noch ein paar andere Klassen für andere Dinge, denn die Regelung wird ja z.B. auch irgendwas ... regeln (also irgendwelche Werte irgendwohin schreiben).

    Schön auf das "single responsibility principle" achten, das macht sich fast immer bezahlt.

    Aber erstmal alles konkret und ohne gross vorzuplanen. Weil YAGNI und weil das was volkard jetzt in seiner Sig. stehen hat 🙂



  • Eine Klasse hält eine Referenz auf die Nächste? War das so gemeint?

    class CThermistor
    {
        CMCP3424 *m_ADC;
    
        float read()
        {
            float val = m_ADC->read();
            // .. do stuff
            return val;
        }
    };
    

    1. Der name der ADC Referenz ist konkret. Würde er wechseln müsste ich den typ der Referenz ändern.
    2. Wer garantiert das bei einem anderen ADC das Inerface immernoch read heißt und die selbe definition hat? Ich müsste es ja überall ändern...

    Etwas mehr Abstraktion wäre doch sinnvoll oder?



  • wanderameise schrieb:

    1. Der name der ADC Referenz ist konkret. Würde er wechseln müsste ich den typ der Referenz ändern.

    Ja.

    wanderameise schrieb:

    2. Wer garantiert das bei einem anderen ADC das Inerface immernoch read heißt und die selbe definition hat? Ich müsste es ja überall ändern...

    Ja *

    wanderameise schrieb:

    Etwas mehr Abstraktion wäre doch sinnvoll oder?

    NEIN
    Nicht für die 2 1/2 Zeilen, nicht wenn du noch gar nicht weisst was sich wirklich ändern wird und wann und warum.

    EDIT:
    *
    Wenn du willst kannst du ruhig das ADC Interface in eine Klasse einpacken (wrappen), die quasi dafür zuständig ist ein einfacheres und "einheitliches" (auch wenn es erstmal nur eine Implementierung gibt) Interface anzubieten. Eine klassische Wrapperklasse halt.
    Nur zerbrich dir nicht allzusehr den Kopf darüber wie man das jetzt abstrakt und allgemein und wiederverwendbar und blub machen könnte.

    Und so lange es nur eine Implementierung gibt, macht es auch sicher keinen Sinn eine abstrakte Basisklasse zwischenzuschieben oder ähnliches.

    Falls du es später einmal brauchst ist das auch in wenigen Minuten nachgezogen. Sich mehrere Stunden Arbeit zu machen indem man sich den Kopf zergrübelt was man später mal brauchen könnte und es dann zu implementieren...
    Und das nur um sich möglicherweise (man weiss ja noch gar nicht ob man es jemals brauchen wird) in der Zukunft ein paar Minuten Arbeit zu sparen...
    Macht finde ich keinen Sinn.

    Den Gedanken "ich will den perfekten Code schreiben, den ich dann später nie mehr ändern muss" kenne ich zwar gut. Aber ich weiss mittlerweile auch dass das meist viel mehr Schaden anrichtet als nutzt. Wenn ein Programm halbwegs sauber strukturiert und implementiert ist, dann ist es auch später kein schlimmes Problem Dinge zu ändern. Anstatt beim Versuch Code für die Ewigkeit zu schreiben wilde overengineerte Moster zu schaffen lieber versuchen sauberen verständlichen Code zu schreiben der bei Bedarf einfach geändert werden kann.


Anmelden zum Antworten