Hallo, aktuell möchte ich ein kleines Miniprojekt in C# erstellen und einen Temperatursensor auslesen - gerne würde ich hierbei auch OOP anwenden. In wie weit organisiert man alles in Klassen? Muss ich also eine Klasse "Temperatur" anlegen? (hier könnte man ja zwischen Fahrenheit und Celsius unterscheiden? Außerdem muss ich ja sicher eine Klasse Sensor anlegen. Wie weit würde man das ganze noch aufdroeseln? Vielen Dank, Kevin
Kevin schrieb: > (hier könnte man ja > zwischen Fahrenheit und Celsius unterscheiden? Brauchst du denn beides? Nichts ist schlimmer, als Klassenhierarchien "auf Vorrat" zu vervollständigen.
Das kommt auf das Projekt an. Aber prinzipiell hört sich das schon gut an. Eine Klasse Temperatur (könnte man auch von einer allgemeineren Klasse für Größen mit Einheiten ableiten, ist hier aber wohl zu viel des Guten). Die hat dann z.B. get/set unit und get/set value. Das Projekt scheint ja klein zu sein, da bringt OOP nicht viel. Interessant wird es, wenn du verschiedene Sensoren hast. Wenn du die Implementierungen von einer schönen Klasse "Sensor" ableiten kannst, dann wird es praktisch. Dazu musst du dir aber gut überlegen, was eine generische Sensor-Klasse können soll und was nicht.
super, vielen Dank für eure Antworten. Dann bin ich ja schon einmal nicht auf dem Holzweg. > > Nichts ist schlimmer, als Klassenhierarchien "auf Vorrat" zu > vervollständigen. Ist das wirklich so? Ich dachte gerade für sowas wäre OOP super?!
Kevin schrieb: > super, vielen Dank für eure Antworten. > > Dann bin ich ja schon einmal nicht auf dem Holzweg. > > Nichts ist schlimmer, als Klassenhierarchien "auf Vorrat" zu > vervollständigen. > > Ist das wirklich so? Ich dachte gerade für sowas wäre OOP super?! Over Engineering geht auch ohne OOP. "You ain't gonna need it" schon mal gehört? Flache Hierarchien sind besser denn Vererbung koppelt am stärksten, besonders wenn mann nicht nur die Schnittstellen sondern auch die Implementierung erbt.
Jan Hansen schrieb: > Die hat dann z.B. get/set unit und get/set value. Beeep, beep, beep, Anti-OO Alarm. Ein gutes Objekt macht seinen internen Zustand nicht von Außen erreichbar.
Kevin schrieb: > Ist das wirklich so? Ich dachte gerade für sowas wäre OOP super?! Ja, dafür ist OOP super. Sie verleitet dazu, Dinge vorzusehen, die kein Mensch braucht. Beispiel: Du entwickelst eine Software, um Zootiere zu verwalten. Dann hast du eine Oberklasse "Tier". Dabei fällt dir auf, daß du da erstmal Unterklassen "Mensch" und "richtiges Tier" bilden kannst, weil Menschen biologisch ja Tiere sind. Menschen mußt du zwar nicht verwalten, aber so ist es "ordentlicher". Einzeller hast du zwar im Zoo überall, aber verwalten mußt du die nicht. Trotzdem, warum nicht in Ein- und Mehrzeller unterteilen? Pilze sind zwar neben Pflanzen und Tieren ein eigenes Reich, aber manchmal zählt man sie ja eher zu Tieren. Also nochmal Pilze aufnehmen. All diese Klassen, die du für deine Anwendung nicht brauchst, kannst du alle noch x-fach weiter unterteilen. Ist ja richtiger so. Die werden zwar alle nie instantiiert werden, aber es ist doch schön, die Welt korrekt abgebildet zu haben. Erfahrene OOP-Entwickler machen solche Fehler natürlich nicht. Anfängern passiert das aber ständig. Deshalb nochamal: unterscheidet die Anwendung wirklich zwischen verschiedenen Temperaturskalen, oder ist das nur, weils den inneren Linnaeus befriedigt?
Mark 99 schrieb: > Beeep, beep, beep, Anti-OO Alarm. > > Ein gutes Objekt macht seinen internen Zustand nicht von Außen > erreichbar. Ich denke du hast das mit dem internen Zustand falsch verstanden. Wenn mir das Objekt weder Temperatur noch Einheit verrät, dann ist es nutzlos ;) Man muss die Getter/Setter ja nicht direkt auf die internen Variablen setzen. Zusatzlogik (Prüfung ob neue Einheit gültig ist, automatische Umrechnung der Temperatur, nicht weniger als absoluter Nullpunkt usw...) kann man ja vorsehen, oder auch später bei Bedarf dazuprogrammieren. Solange das alles über Getter/Setter läuft ist das kein Problem und auch richtig gekapselt. Und kann problemlos erweitert werden.
> Deshalb nochamal: unterscheidet die Anwendung wirklich zwischen > verschiedenen Temperaturskalen, oder ist das nur, weils den inneren > Linnaeus befriedigt? Jetzt leuchtet mir mehr ein, worauf die Aussage bezogen war. - Vielen Dank ;-) Nein, Celsius reicht eigentlich vollkommen aus.
Kevin schrieb: > Nein, Celsius reicht eigentlich vollkommen aus. Was aber nicht heißt, dass es nicht trotzdem schlau wäre ein Objekt daraus zu machen. Vererbung wird zwar meist als die primäre Nutzung von OOP gelehrt, in der Realität ist das aber anders. Gerade Kapselung ist sehr nett. Wenn du später einmal eine Überprüfung des Wertebereichs hinzufügen möchtest, dann geht das total einfach wenn die Temperatur ein Objekt ist. Wenn du die Temperatur einfach als Variable "herumliegen" hast, dann musst du die Logik überall vorsehen wo der Wert gesetzt wird, oder alle diese Stellen auf eine Validierungsfunktion umbiegen. Das hängt dann auch stark vom Projekt selbst ab was man als Objekt modelliert und was nicht.
Jan Hansen schrieb: > Kevin schrieb: >> Nein, Celsius reicht eigentlich vollkommen aus. > > Was aber nicht heißt, dass es nicht trotzdem schlau wäre ein Objekt > daraus zu machen. Vererbung wird zwar meist als die primäre Nutzung von > OOP gelehrt, in der Realität ist das aber anders. > > Gerade Kapselung ist sehr nett. Wenn du später einmal eine Überprüfung > des Wertebereichs hinzufügen möchtest, dann geht das total einfach wenn > die Temperatur ein Objekt ist. > > Wenn du die Temperatur einfach als Variable "herumliegen" hast, dann > musst du die Logik überall vorsehen wo der Wert gesetzt wird, oder alle > diese Stellen auf eine Validierungsfunktion umbiegen. > > Das hängt dann auch stark vom Projekt selbst ab was man als Objekt > modelliert und was nicht. Genau das war ja eigentlich meine Eingangsfrage. In wie weit macht es Sinn die Klassen aufzuschlüsseln? Kann man pauschal einfach sagen, dass man sich auf jeden Fall nach oben immer eine Vererbungsklasse Luft lassen sollte? - wenn man das so sagt^^
Vererbung ist gerade DAS Element von OOP, was man nur sehr vorsichtig einsetzen sollte. Wenn man große Vererbungshierarchien hat, sinkt die Übersicht enorm, und es wird immer schwerer herauszufinden, was das Programm da tatächlich eigentlich macht. Und jede Änderung an einer Klasse in der Hierarchie hat das Potential, Fehler zu verursachen. Nicht umsonst sagt man, dass Komposition der Vererbung vorzuziehen ist. Oft ist es auch besser, ein paar Zeilen Code zu duplizieren, statt Vererbung einzusetzen. Komplexität ist i.A. das größte Problem bei Softwareentwürfen, daher sollte man die Komplexität nicht noch künstlich erhöhen.
Kevin schrieb: > Genau das war ja eigentlich meine Eingangsfrage. In wie weit macht es > Sinn die Klassen aufzuschlüsseln? Klein und fein ist schon in Ordnung. Nicht zu viel in eine Klasse packen. > Kann man pauschal einfach sagen, dass man sich auf jeden Fall nach oben > immer eine Vererbungsklasse Luft lassen sollte? - wenn man das so sagt^^ Das ist ein anderes Thema. Nein, ich würde da keine "Luft lassen" (jemand weiter oben hat schon YAGNI genannt). Wenn du nur einen Sensor hast und kein anderer dazukommt, dann genügt eine Klasse und du kannst dir die Vererbung schenken. Wenn irgendwann einmal doch ein anderer Sensortyp dazukommen würde, dann kannst du noch immer eine Superklasse extrahieren und die jetzige davon ableiten. Da musst du nicht "auf Vorrat" arbeiten. Keep it simple.
Jan Hansen schrieb: > Ich denke du hast das mit dem internen Zustand falsch verstanden. Wenn > mir das Objekt weder Temperatur noch Einheit verrät, dann ist es nutzlos > ;) Man muss die Getter/Setter ja nicht direkt auf die internen Variablen > setzen. Zusatzlogik (Prüfung ob neue Einheit gültig ist, automatische > Umrechnung der Temperatur, nicht weniger als absoluter Nullpunkt usw...) > kann man ja vorsehen, oder auch später bei Bedarf dazuprogrammieren. > Solange das alles über Getter/Setter läuft ist das kein Problem und auch > richtig gekapselt. Und kann problemlos erweitert werden. Für alles Setter zu haben widerspricht der OO Natur, das macht man bei Datenstrukturen, in Java wären das die JavaBeans ;) Fowler nennt das "Anemic Domain Modell", führt dazu dass die Logik woanders implementiert werden als dort wo doie eigentlichen Daten, so wie man es vom Prozeduralen Ansatz her kennt. Ansosnten gibt es einen grossen Unterschied zwischen "Encapsulation" und "Information Hiding", wird oft durcheinander gewürfelt. Wenn man mit einem Getter ein mutable Objekt zurückgibt, war es das mit der Kapselung..
Kevin schrieb: > In wie weit organisiert man alles in Klassen? Gar nicht. Da du nur eine Instanz von Sensor und nur eine Instanz von Temperatur haben wirst, sind Klassen absolut überflüssig. Du wirst keinerlei objektorientierte Methode benötigen, wie Vererbung, Polymorphismus, und keine Objekte anlegen und verwerfen auf dem uC. Ein Programm ist dann optimal, wenn sich nichts mehr weglassen lässt, ohne daß dann die Funktion nicht mehr erfüllt wäre, unter weglassen versteht man die Maschineninstruktionen während der Abarbeitung, nicht die Anzahl der Kommentare. Zwar muss nicht jede Spielerei optimal werden, aber vorsätzlich den entgegengesetzen Weg einzuschlagen ist schon sehr realitätsverweigernd.
MaWin schrieb: > Ein Programm ist dann optimal, wenn sich nichts mehr weglassen lässt, > ohne daß dann die Funktion nicht mehr erfüllt wäre, unter weglassen > versteht man die Maschineninstruktionen während der Abarbeitung, nicht > die Anzahl der Kommentare. Na ja, das war vielleicht zu Zeiten der Lochkarten mal so. In dem vorliegenden Fall ist ein Programm dann optimal, wenn es mit möglichst wenig zusätzlichem Dokuemntationsaufwand leicht verständlich und testbar formuliert ist. Und ja, dabei helfen sinnvoll gestaltete Klassen ungemein. Oliver
> einmal doch ein anderer Sensortyp dazukommen würde, dann kannst du > noch immer eine Superklasse extrahieren und die jetzige davon ableiten. Das sehe ich eigentlich als den Hauptvorteil einer objekt basierten Herangehensweise an: man kann auch im Nachhinein oft noch neue Klassen einziehen, wenn sich die Forderungen im Programm verändern, ohne dass gleich alles zusammenbricht. Und ja. Ich hab in meinen OOP Anfängen auch genau den Fehler gemacht, viel zu früh viel zu viel 'Flexibilität' in das Klassendesign auf Vorrat einzubauen. Das Ergbnis war eine undurchschaubare Hierarchie, die zwar im Prinzip alle möglichen Stückerl gespielt hätte ... wenn sie denn je irgendjemand gebraucht hätte. Nach ein paar Jahren ist dieser Teil des Programms (es ging um Operatoren in einem CAD Programm und wie Mausmessages in diesem Konglomerat ihre Ergüsse an dieser Operatoren weiter geben, die dann wieder über Zeichenklassen den Cursor bzw. Hilfsgeometrie steuern) dann rausgeflogen und mit einem viel einfacheren Mechanismus ersetzt worden, der dann auch wesentlich fehlerunanfälliger war. Klassenhierarchien muss man immer im Kontext der konkreten Aufgabenstellung sehen. Was in der einen Aufgabenstellung sinnvoll ist, muss in einer anderen Aufgabenstellung keineswegs sinnvoll sein
:
Bearbeitet durch User
Oliver schrieb: > In dem vorliegenden Fall ist ein Programm dann optimal Nein, optimal ist definiert, besuche eine Informatik-Vorlesung. Du meinst vielleicht hübsch. Aber hübsch liegt immer im Auge des Betrachters.
Kevin schrieb: > Muss ich also eine Klasse "Temperatur" anlegen? (hier könnte man ja > zwischen Fahrenheit und Celsius unterscheiden? Wieso sollte man das tun? Deine Klasse (besser wäre sogar ein Interface) Temperatur kapselt einfach einen Wert (z.B. double, int o.ä.) und stellt einen Typ dar (am besten nicht veränderbar). Außerdem hat sie einen Getter, welcher den Wert in der normierten Einheit Kelvin zurückliefert. Eventuell hat sie noch Operatoren um Temperaturen zu addieren/subtrahieren/serialisieren o.ä. Wenn du nun aus irgendwelche Gründen in der Präsentationsschicht die Ausgabe einer Temperatur in °Celsius oder °Fahrenheit benötigst dann erstellst du dir einfach eine Formatierfunktion
1 | formatTemp(Temperatur t, Einheit e, int nachkommastellen); |
Diese kann dann jedwede Temperatur in den gewünschten Ausgabewert umwandeln. Und dann ist es auch egal ob es genau EINE Temperatur Implementierung gibt, oder eine SensorXYZTemperatur welche vielleicht immer live den Wert abfragt wenn der getter aufgerufen wird... oder oder ... Das muss man aber nicht zu dem Zeitpunkt entscheiden wo du die Designentscheidung triffst "mein System hat den Typ Temperatur mit den Eigenschaften....".
Kevin schrieb: > In wie weit organisiert man alles in Klassen? Bjarne Stroustrup widmet gleich einen ganze Teil seines Buches ISBN 3-8273-1660-X (Abschnitt IV: Design Aspekte mit drei Abschnitten und insgesamt 22 Kapiteln) dieser Frage. Ist zwar für C++, dürfte aber auf C# übertragbar sein. > Muss ich also eine Klasse "Temperatur" anlegen? (hier könnte man ja > zwischen Fahrenheit und Celsius unterscheiden? In http://www.boost.org/ gibt es eine Unit-Library, die das Abbilden von Einheiten ermöglicht. Ist sehr interessant, allerdings auch ein ziemliches Monster und alles andere als einfach.
Läubi .. schrieb: > Deine Klasse (besser wäre sogar ein Interface) > Temperatur kapselt einfach einen Wert (z.B. double, int o.ä.) und stellt > einen Typ dar (am besten nicht veränderbar) Ob mit oder ohne OO, verschiedene Temperaturen mitzuführen ist ohnehin der völlig falsche Weg. Beispiel aus der CNC-Technik: die Steuerung arbeitet grundsätzlich intern mit einer einzigen Masseinheit, z.B. 1/1000 mm. Inch kann man am Bildschirm sehen, wenn man denn will, oder als Bearbeitungsprogramm einlesen, die Maschine weiss nichts davon. Würde man die Positionieralgorithmen für verschiedene Masseinheiten auslegen käme man in Teufels Küche, was Fehler angeht, und der Aufwand ist auch völlig unnötig. Eine Temperatur ist eine Temperatur ist eine Temperatur und sollte vom absoluten Nullpunkt bis zu einer unereichbaren Obergrenze den physikalischen Wert mit ausreichender Auflösung darstellen können, das ist die primäre Designentscheidung. Ob sie in Kelvin, Celsius oder Fahrenheit ein- oder ausgegeben wird ist eine Frage des User Interface und nicht des Reglers. Georg
Georg schrieb: > Würde man die Positionieralgorithmen für verschiedene Masseinheiten > auslegen käme man in Teufels Küche, was Fehler angeht Das ist so nicht richtig. Wenn das System inch als Koordinaten bekommt, und inch ausgeben soll, treten wenn intern mit inch gerechnet wird keine Rundungsfehler auf, bei mm schon. Daher kann es sinnvoll sein, das zugrundliegende System umzuschalten, machen beispielsweise manche Leiterplattenentwurfsprogramme so. Bei CNC gibt es allerdings eine physikalische Auflösung der Achsen, damit sind Rundungsfehler beim Abbilden auf Positionen nicht zu vermeiden und es spricht nichts dagegen, mit denen zu rechnen. Wenn man aber Schrittmotoren mit 64 Schritten pro Millimeter hat, ist es blöd, erst die eingegebenen Koordinaten von inch in cm, und dann von cm in Schritte umzurechnen, das ergibt bei Schrägen plötzlich Streifenmuster an denen die Abbildung auf den nächsten Wert rundet, also von abrunden auf aufrunden springt.
Kollege schrieb: > Für alles Setter zu haben widerspricht der OO Natur, das macht man bei > Datenstrukturen, in Java wären das die JavaBeans ;) Gerade so ein einfaches Temperatur-Objekt ist doch ein perfektes Beispiel für ein JavaBean ;) > Fowler nennt das "Anemic Domain Modell", führt dazu dass die Logik > woanders implementiert werden als dort wo doie eigentlichen Daten, so > wie man es vom Prozeduralen Ansatz her kennt. Ist ja grundsätzlich nicht schlecht. Und welche Logik möchtest du denn bei einem simplen Temperatur-Objekt implementieren? Und warum kann man keine Logik implementieren wenn man Getter/Setter verwendet? > Ansosnten gibt es einen grossen Unterschied zwischen "Encapsulation" und > "Information Hiding", wird oft durcheinander gewürfelt. > Wenn man mit einem Getter ein mutable Objekt zurückgibt, war es das mit > der Kapselung.. Nein, wenn man aus dem internen Zustand ein neues mutable Objekt erzeugt und das zurückgibt, dann ist das kein Problem.
Georg schrieb: > Würde man die Positionieralgorithmen für verschiedene Masseinheiten > auslegen käme man in Teufels Küche, was Fehler angeht, und der Aufwand > ist auch völlig unnötig. Das Mitführen von Einheiten ist keinesfalls unsinnig, selbst wenn ich nur eine Einheit pro Größe im System verwende. Es steht ja nirgends in Stein gemeißelt, dass das immer so bleiben muss. Die oben zitierte http://www.boost.org/ -Library beweist auch, dass das grundsätzlich möglich ist, selbst ohne Laufzeit-Overhead. > Eine Temperatur ist eine Temperatur ist eine Temperatur ... Das hatten sich die Programmierer einer gewissen Mars-Sonde wohl auch einst gedacht. Dumm nur, dass eine Temperatur – bzw. in diesem Fall war es wohl eine Länge – in Amerika eben nicht gleich einer Temperatur in Europa ist. Ergebnis: Totalverlust von hunderten Millionen Dollar. Wenn das nicht Teufels Küche ist ...
Jan Hansen schrieb: > Gerade so ein einfaches Temperatur-Objekt ist doch ein perfektes > Beispiel für ein JavaBean ;) Naja, so gesehen ist das ein ganz mieses Beispiel für Obekt als auch Datenstruktur ;) float/double oder gar int passen da viel besser.. Jan Hansen schrieb: > Ist ja grundsätzlich nicht schlecht. Und welche Logik möchtest du denn > bei einem simplen Temperatur-Objekt implementieren? Und warum kann man > keine Logik implementieren wenn man Getter/Setter verwendet? "Nicht schlecht" sowieso, aber nicht OO! Schon mal eine JavaBean mit Logik gesehen? (Validierung zählt nicht) Schon mal eine JavaBean gesehen die die per Repository/DAO die DB abfragt? "Das darf man nicht.." heisst es dann nicht ohne Grund, echte Objekte dürften das. http://www.martinfowler.com/bliki/AnemicDomainModel.html Datenstrukturen wie JavaBeans leben eben davon, dass sie weder Kapselung noch Information Hiding bieten, sind eben nur Datenstrukturen, oft als DTO.
MaWin schrieb: > Wenn das System inch als Koordinaten bekommt, und inch ausgeben soll, > treten wenn intern mit inch gerechnet wird keine Rundungsfehler auf, bei > mm schon. Das war vielleicht mal richtig. Rundungsfehler sind aber irrelevant, wenn die rechnerische Auflösung deutlich höher ist als die mechanische - ich habe vor 25 Jahren 32bit Integer verwendet mit der Einheit 1µ, das hat Jahrzehnte ausgereicht, da die angeschlossenen Messmaschinen weniger als 4m gemessen haben und nicht genauer als 1µ positioniert, allerdings gibt es in Wirklichkeit schon Maschinen mit mehr als 4m und Messsysteme besser als 1µ. Macht heute aber nix mehr, da 64 bit kein Problem mehr ist, also kann man Nanometer auflösen und die Maschine kann so gross wie die Erde sein. Wenn ich mich nicht verrechnet habe, aber in jedem Fall langt es dicke und Runden ist kein Problem. Georg MaWin schrieb: > Daher kann es sinnvoll sein, das zugrundliegende System umzuschalten, > machen beispielsweise manche Leiterplattenentwurfsprogramme so. Meines nicht. CadStar löst 10nm auf, und mir ist noch kein Teil begegnet, bei dem Rundungsfehler eine Rolle gespielt hätten. Georg
MaWin schrieb: > Oliver schrieb: > Nein, optimal ist definiert, besuche eine Informatik-Vorlesung. Ja na, theoretisch optimal ist in den allermeisten Fällen praktisch unbrauchbar. Oliver
Oliver S. schrieb: >> Nein, optimal ist definiert, besuche eine Informatik-Vorlesung. > > Ja na, theoretisch optimal ist in den allermeisten Fällen praktisch > unbrauchbar. Und genau das lernt man in besagter Informatik-Vorlesung. ;-)
Kollege schrieb: > Naja, so gesehen ist das ein ganz mieses Beispiel für Obekt als auch > Datenstruktur ;) > float/double oder gar int passen da viel besser.. Es geht aber um OO. Ja, ein primitiver Zahlentyp kann auch sinnvoll sein, aber darum geht es hier nicht. > "Nicht schlecht" sowieso, aber nicht OO! Also für mich eindeutig schon OO. Warum denn nicht? > Schon mal eine JavaBean mit Logik gesehen? > (Validierung zählt nicht) Ja, Validierung ist auch Logik. Außerdem habe ich nicht mit den JavaBeans angefangen, dass die per Definition eingeschränkt sind hat nichts mit dem Thema zu tun. > "Das darf man nicht.." heisst es dann nicht ohne Grund, echte Objekte > dürften das. Reines Definitionsproblem. Und natürlich sind auch JavaBeans "echte" Objekte.
Oliver S. schrieb: > Ja na, theoretisch optimal ist in den allermeisten Fällen praktisch > unbrauchbar. Du meinst, praktisch kannst du es nicht und versuchst dich rauszureden. Davon gibt es tausende.
Ne, es gibt tausende davon, die übersehen, daß ein optimales Programm als allererstes einmal fehlerfrei sein muß. Nicht optimal, aber fehlerfrei ist praktisch erheblich besser als gedacht optimal, mit Absturz der Ariane als Folge... O.iver
Oliver S. schrieb: > daß ein optimales Programm als allererstes einmal fehlerfrei sein muß. Der Nachweis ist entschieden einfacher, wenn nur die tatsächlich real notwendigen Anweisungen programmiert werden. >, mit Absturz der Ariane als Folge... Scheiss Kapselung. Das SRI, das bei Ariane 4 funktionierte, wurde ungeprüft übernommen, kam aber mit den anderen Daten intern nicht zurecht. http://m.focus.de/digital/computer/chip-exklusiv/tid-14183/computer-fehler-die-groessten-software-desaster_aid_396628.html
greg schrieb: > Komplexität ist i.A. das größte Problem bei Softwareentwürfen, daher > sollte man die Komplexität nicht noch künstlich erhöhen. Das tut man aber, mit jeder neuen Hochsprache, jeder neuen Library, immer neuen Erfindungen, Verfeinerungen und Konstrukten der OOP. Was von der Intension her den Softwareentwurf vereinfachen sollte verkompliziert ihn letztlich nur. Kevin schrieb: > ein kleines Miniprojekt in C# ist besser in wenigen Codezeilen erstellt die genau das tun was nötig ist! Und wenn wir hier nicht just in der Rubrik PC-Programmierung wären würde ich sagen gleich in pure ASM.
Moby schrieb: > würde > ich sagen gleich in pure ASM. Endlich... Da habe ich schon seit gefühlten 300 Beiträgen drauf gewartet. Oliver
Hier auch mal mein Senf dazu. Gerade bei OOP ist viel Erfahrung nötig. Jahrelanges 'Spielen' ist da angesagt. Dann bekommt man mit, wo es notwendig ist und wo man es einfach beläst. Mach am besten 2 Versionen. Ein mit viel und eine mit wenig OOP. Und dann vergleiche mal die Vor- und Nachteile. Bei einem anderen programm sieht das dann wieder ganz anders aus. Zu den Einheiten. Ich mußte lange auch mit vielen physikalischen Größen umgehen. Da habe ich mir angewöhnt, immer alles in SI-Einheiten abzuspeichern. Da gab es dann nie die Frage, ob noch eine Kilo oder micro davor gehört. Umgerechnet wurde nur bei Benutzer Ein/Ausgabe. Programmintern war alles pure Meter.
PittyJ schrieb: > Gerade bei OOP ist viel Erfahrung nötig. Jahrelanges 'Spielen' ist da > angesagt. Und genau deshalb ist OOP auch nicht der Weisheit letzter Schluß... Oliver schrieb: > Endlich... > Da habe ich schon seit gefühlten 300 Beiträgen drauf gewartet. Kann man nicht oft genug sagen.
PittyJ schrieb: > Mach am besten 2 Versionen. Ein mit viel und eine mit wenig OOP. Und > dann vergleiche mal die Vor- und Nachteile. Bei so einem Micky Mouse Projekt kann OOP seine Vorteile doch gar nicht ausspielen. OOP kommt dann sinnvoll ins Spiel, wennn die Projektgrößen dergestalt sind, dass sie von den Team-Mitgliedern Disziplin erfordern. In klassischen prozeduralen Systemen (wie C) vertraut man darauf, dass die Programmierer diese Disziplin haben, was oft genug in die Hose geht. In OOP Sprachen (wie C++) hat man den Entwicklern Möglichkeiten in die Hand gegeben, diese Disziplin einzufordern bzw. das System so aufzubauen, dass es schwierig ist, am Gesamtkonzept vorbeizuprogrammieren und es leicht ist, es in der Funktionalität zu erweitern. Ja, bei kleinen Aufgabenstellungen sieht ein C++ Programm daher erst mal völlig überkandidelt aus. Das liegt daran, dass im Vergleich zu rein prozeduralen Ansätzen der Verwaltungsoverhead im Programmtext relativ hoch ist. Aber das verliert sich mit wachsenden Projektgrößen. > Gerade bei OOP ist viel Erfahrung nötig. Ein gewisses Mass an 'Beamtenmentalität' ist da sehr hilfreich. Die meisten vermurksten OOP Systeme, die ich bisher gesehen habe, drehten sich praktisch immer um die Frage "Welche Klasse ist wofür zuständig", bzw. eigentlich um das ignorieren dieser Fragestellung. Da wird dann auf Teufel komm raus mit Gettern/Settern gearbeitet und Funktionalität ausserhalb der zuständigen Klassen implementiert, die eigentlich ganz klar in die Klasse rein gehören würde.
:
Bearbeitet durch User
Jan Hansen schrieb: > Es geht aber um OO. Ja, ein primitiver Zahlentyp kann auch sinnvoll > sein, aber darum geht es hier nicht. Dann sind JavaBeans so ganz falsch, den JavaBeans sind eben nicht OO, steht schon in meinem letyzten Post warum und wieso, inkl. Link zur einer ausführlichen Erklärung. Jan Hansen schrieb: > Also für mich eindeutig schon OO. Warum denn nicht? Hab ich doch eigentlich schon erklärt. Jan Hansen schrieb: > Reines Definitionsproblem. Und natürlich sind auch JavaBeans "echte" > Objekte. Eben nicht, aber auch das hatte ich schon erklärt.
auf die Gefahr hin, dass ich da nur noch in kaltem Kaffe rühre und alle fragen geklärt sind: Das schöne an OOP ist, es gibt so viele möglichkeiten das zum implementieren, wobei flache hierachien meist sinnvoller sind. Da OOP-Tutorials meist die Konzepte vermitteln wollen, haben die oft irrsinnige Abstraktionstiefen. Oft macht es mehr sinn helperfunktionen einfach static in einer basisklasse unterzubringen, als noch eine noch vererbung mehr einzubaun. Als gute Grundlage zu den DOs und DONTs kann man sich mal die Coding guidelines des Qt-Projekts antun, die sind nicht zu umfangreich, geben aber ein paar schöne Beispiele, was sinnvoll ist, was weniger und warum welche Probleme in Qt wie gelöst wurden. Zurück zum Thema: Wenn ich davon ausginge, dass es mal mehr als ein sensor und typ werden könnten und dass ich vllt auch mal mehrere gleichzeitig haben will, beides ist ja realistisch möglich, wäre mein konzept wohl wie folgt Eine Baisklasse class tempSensor public getValue(unit); getUpdateRate() const; setUpdateRate(int); getType() const; sowie static convertUnit(value, fromUnit, toUnit); convertUnit kann temperaturen von einheit a in einheit b umrechnen, Dazu gibts dann eine Enum der gewünschten Temperaturskalen (Kelvin, Celsius, Fahrenheit). dem getter für die temperatur wird als standardwert für die einheit jene zugewiesen, die ich primär nutzen will. Ja, das könnte man als Klasse "temperatur" kapseln, halte ich aber nicht für nötig, weil YAGNI halt. Die Sensorklasse wird dann für jeden sensortyp abgeleitet, wenn ich generische schnittstellen wie I2C oder sowas habe, die mehrere sensoren nutzen könnten, wird das gekapselt. Der Konstruktor bekommt die nötigen argumente um den sensor auszuwählen. Fertig die laube. Jetzt kann man sich noch überlegen, ob die sensorklasse noch in der lage sein soll, den sensor im hintergrund zu lesen oder whatever. Klingt jetzt vllt nicht wie die hohe kunst der oop, halte ich aber für angemessene abwägung zwischen struktur und simplicity. Durch die Abstraktion des Temperatursensors als basisklasse kann es meinem restlichen code wurst sein, was da später dran hängt. Durch die static convertUnit kann ich temperaturen jederzeit in andere einheiten umrechnen. Das Tracking der Temperatureinheit muss dann zwar der den wert jeweils nutzende code machen, aber die umschaltung zwischen den einheiten ist ja auch eher selten. So ist es zum beispiel bei einer aufgezeichneten temperaturkurve nicht sinnvoll, pro wert die einheit zu speichern, vielmehr werden wohl alle messwerte die gleiche haben. Das ggf. nötige umrechnen kann der anzeigende code machen mit tempSensor::convertUnit, wenns sein muss.
Karl Heinz schrieb: > OOP kommt dann sinnvoll ins Spiel, wennn die Projektgrößen dergestalt > sind, dass sie von den Team-Mitgliedern Disziplin erfordern. Ach Karlheinz, DAS ist es eigentlich nicht. Objektorientierte Programmierung hat genau dort ihren Sinn, wo mehrere äußerlich gleichartig zu behandelnde, aber innerlich unterschiedliche Objekte existieren. Ein typisches beispiel sind die diversen Kringel auf einer grafischen Benutzeroberfläche. Aber all das ist hier nicht der Fall. Der TO will einen Temperaursensor auslesen und (vermutlich) dessen Temperaturwert auf irgend so einer grafischen Oberfläche anzeigen. Wenn er dazu ne grafische Klassenbibliothek benutzt, so hat es dort ganz gewiß genug passende Objekttypen, die er benutzen kann. Aber ne Klasse "Sensor" und ne klasse "Temperatur" ist schlichtweg albern und unsachgemäß. Allein schon aus der logischen Erwägung heraus, daß unterschiedliche Sensoren ja unterschiedliche Ergebnistypen liefern: ein Thermometer liefert was anderes als ne Waage odeer ein Zollstock. Die Ergebnisse sind nicht kommensurabel, also kann es keine zusammenfassende Klasse für sowas geben. Das Gegenteil liefert der Gedanke an eine Klasse "Temperatur". Hier ist es nicht die inkommensurable vielfalt, sondern die öde Einfalt: Temperaturen haben kein eigenes Innenleben, so daß man aus verschiedenen Temperaturen eine Klasse bilden könnte. Das ist also auch völliger Murks. Oh ihr grandiosen Programmierer, lernt vor dem In_Die_Tasten_Hauen doch um himmelswillen wenigstens ein klein wenig Logik. Das würde die Welt verbessern. W.S.
W.S. schrieb: > Das Gegenteil liefert der Gedanke an eine Klasse "Temperatur". Hier ist > es nicht die inkommensurable vielfalt, sondern die öde Einfalt: > Temperaturen haben kein eigenes Innenleben, so daß man aus verschiedenen > Temperaturen eine Klasse bilden könnte. Das ist also auch völliger > Murks. Die Temperatur als Klasse zu modellieren ist sogar sehr sinnvoll. Eine Temperatur hat einen (im Vergleich zu dem skalaren Typ int) eingeschränkten Wertebereich. Wenn Du keinen eigenen Typ für die Temperatur hast, müsstest Du korrekterweise bei jeder Zuweisung einen Range-Check machen. Weiter macht es überaus Sinn, dass die Temperaturklasse verschiedene Konvertierungen bietet, z.B. nach String, ... Clean-Code Koriphäen wie Robert C. Martin empfehlen dringend für Domains wie Währung, Geschwindigkeit, Temperatur, ... grundsätzlich eigene Klassen zu verwenden. Das macht den Code erstens leserlicher und zweitens leichter wartbar. Und das ist nicht nur bei großen Projekten sinnvoll. Aus eigener Erfahrung kann ich nur ins Feld führen, dass man irgendwann mal klein beginnt (kleines Programm), sich die Dinge aber unerwarteterweise plötzlich verselbständigen und schnell wachsen. Und dann steht man vor einem Chaos-Haufen. :-( Grüße Markus
Hallo, zusammen mit der "Erfindung" von OO kam eine Programmiersprache heraus, deren Name mir entfallen ist (irgendwas mit A), die von extremen Verfechtern der OO-Prinzipien konzipiert wurde. Die Sprache kannte keine Zahlen, sogar ein Bit war eine Klasse - mit Setter, um es wahr oder falsch zu setzen, getter, um es abzufragen, constructor, destructor usw., und Methoden für and, or, xor... Für mich kam das nicht in Frage, weil man sich den Aufwand im Embedded-Bereich mit den damaligen Prozessoren der Z80-Klasse überhaupt nicht leisten konnte. Ausserdem sehe ich das als fehlgeleitete Ideologie, ich schreibe zwar seit 20 Jahren OO-Programme, aber ich erwarte trotzdem, dass man 2 Ganzzahlen noch normal addieren kann. Georg
W.S. schrieb: > Karl Heinz schrieb: >> OOP kommt dann sinnvoll ins Spiel, wennn die Projektgrößen dergestalt >> sind, dass sie von den Team-Mitgliedern Disziplin erfordern. > > Ach Karlheinz, DAS ist es eigentlich nicht. Doch. Genau das ist es in der Praxis. Ein 300 Zeilen Spaghetti Code Programm kann jeder überblicken. Auch noch nach Jahren. NOch ein paar Nullen mehr hinten drann und dann geht das nicht mehr. OOP ist eine Methode, wie man Code strukturiert. Und das tut man, um den Code wartbar zu halten. > Objektorientierte Programmierung hat genau dort ihren Sinn, wo mehrere > äußerlich gleichartig zu behandelnde, aber innerlich unterschiedliche > Objekte existieren. Natürlich. Keiner sagt, dass es nicht mehrere Motivationen für OOP geben kann. Das eine schliesst das andere nicht aus. Und oft genug folgt das eine aus dem anderen bzw. bedingt es. Man kann auch mit C oder Fortran oder Pascal oder Algol oder Cobol oder ... riesige Systeme bauen. Das kann man und das wurde auch schon gemacht. Wenn die Entwickler diszipliniert genug sind, sich an einfache Prinzipien zu halten, dann ist das überhaupt kein Problem. Aber oft tun sie das dann eben nicht. Anstatt eine Funktion aufzurufen, die einen einfachen Sachverhalt berechnet, wird dann eben der Funktionsaufruf eingespart und an der Aufrufstelle direkt gerechnet. Funktioniert super ... bis sich dann irgendwann mal die Berechnung ändert und man plötzlich in der Situation ist, die 185 Stellen im Code zu finden, an denen die Berechnung direkt gemacht wurde (weil man ja 'optimal' programmieren will und ein Funktionsaufruf erst mal nur Zeit kostet) anstelle überall die eine Funktion aufzurufen, die diese Berechnung durchführt. Das meine ich mit Disziplin. C hat nichts zu diesem Thema zu sagen und vertraut einfach darauf, dass die Programmierer das schon richtig machen. Been there - seen that - took a long time to correct it. > lernt vor dem In_Die_Tasten_Hauen doch um himmelswillen wenigstens ein klein wenig Logik. Lern du erst mal, dass es in der Informatik nicht die eine, allein selig machende, Methode gibt. Ob und wie ein Klassenaufbau sinnvoll aussieht, hängt mehr als alles andere von der konkreten Aufgabenstellung ab. > Aber ne Klasse "Sensor" und ne klasse "Temperatur" ist > schlichtweg albern und unsachgemäß. Ach, ist es das? > Allein schon aus > der logischen Erwägung heraus, daß unterschiedliche Sensoren ja > unterschiedliche Ergebnistypen liefern: ein Thermometer liefert > was anderes als ne Waage odeer ein Zollstock. Und? Warum kann es dann keine gemeinsame Basisklasse SensorWert geben, die die Obermenge all dieser unterschiedlichen Werte darstellt? Wieso ist das albern? Gerade in so einem Fall, in dem man diverse unterschiedliche Typen unter einen Hut bringen möchte, ist das möglicherweise alles andere als albern. Wenn ich das brauche und sinnvoll nutzen kann, weil ich in meiner Applikation in einem Grid die Bezeichnung des Wertes, den Wert selber und seine Einheit darstellen muss UND ich die Dialogbehandlung unabhängig von den tatsächlich möglichen Einheiten der diversen Werte bzw. deren Typen haben will, dann ist so eine Basisklasse tatsächlich sinnvoll. Oder was denkst du, wie in den diversen IDE's die Anzeigen für die einzustellenden Properties eines Items in einem Resource Editor realisiert ist? Riesige switch-case Strukturen? Wieso soll ein geometrisches Item in einem CAD nicht eine PropertyList liefern können, in der die diversen Properties dieses Items versammelt sind, jedes nicht mehr als eine simple Einstellung (Breite, Höhe, Winkel, Beschriftung, Farbe, Name, ...), die vom Anzeigemodul einfach in der Form von Properties in die Controls eingebaut wird, indem zb jedes Property aufgefodert wird, sich in die Zeile eines Grids reinzurendern? Das kann sinnvoll sein. Hängt nur davon ab, welchen Aufwand ich treiben muss bzw. will. Wer sagt eigentlich, dass ein Sensor nur einen einzigen Wert liefert? Eine IMU liefert mehrere numerische Werte. Was ist mit denen? Genauso wie es nicht albern sein muss, unterschiedliche Sensoren unter einer gemeinsamen Basisklasse Sensor in einer Hierarchie zu sammeln. Wenn ich es sinnvoll nutzen kann, dann ist das alles andere als albern. Die Aufgabenstellung bestimmt was sinnvoll ist und was nicht. > Aber all das ist hier nicht der Fall. Der TO will einen Temperaursensor auslesen Exakt. Und genau deshalb kann man an so einem Micky Mouse Beispiel nicht sinnvoll festmachen, welche Vorteile OOP bringt. Diese Aufgabenstellung (und ich rede hier nicht von der Klassenbibliothek zur Anzeige) kann sowohl klassisch prozedural als auch mit OOP Methoden gelöst werden, wobei der OOP Ansatz erst mal nach einem riesigen Overhead aussieht, den keiner (in diesem Beispiel) braucht. Die Moral von der Geschichte ist dann oft, dass die Leute sagen, dass OOP nichts bringt, weil ja das gleichwertige C Programm um 2/3 kürzer und leichter zu überblicken ist - in dieser konkreten Aufgabenstellung. Was OOP tatsächlich bringt und leisten kann, sieht man erst in größeren komplexeren Systemen und das auch erst dann, wenn man eine zeitlang damit gearbeitet hat. Für einen OOP Neuling erschliesst sich der wesentliche Unterschied zwischen hierarchischer Ableitung samt virtuellen Funktionen auf der einen Seite und switch-case Leisten auf der anderen Seite nicht sofort. Für den ist die switch-case basierend auf einer Typangabe erst mal einfacher, da kürzer und weniger Tippaufwand. Das die auch fehleranfälliger ist, merkt er erst, wenn er zum dritten mal damit auf die Nase gefallen ist, weil er in einem der switches die Erweiterung um einen neuen Typ verpennt hat und natürlich keinen assert im default hat. Du warst doch der, der einem C-Programmierer Klassen und Ableitung (und damit C++) nahegelegt hat, um auf einem µC mit Touchpad Bereiche erkennen zu können. Dabei wollte der Fragesteller einfach nur simple Rechtecke haben und nicht mehr. Jetzt wäre eine ähnlich simple Aufgabenstellung (mit Potential für mehr) mit OOP Mitteln anzugehen plötzlich albern. Bischen inkonsequent, findest du nicht?
:
Bearbeitet durch User
Markus schrieb: > Aus eigener Erfahrung kann ich nur ins Feld führen, dass man irgendwann > mal klein beginnt (kleines Programm), sich die Dinge aber > unerwarteterweise plötzlich verselbständigen und schnell wachsen. Aus meiner (begrenzten) Erfahrung ist genau da der Punkt, wo man sinnvollerweise innehält und einen Schritt zurücktritt, um Programmaufbau + Strukturen der neuen Komplexität anzupassen, Basisklassen/Patterns einzuführen und alles soweit wie sinnvoll zu abstrahieren. Code darf dabei auch gelöscht und allgemein neugeschrieben werden. Am Anfang mit einem Sensor und einem Fenster mit einer Zahl ist es zu früh, weil man noch keinen Überblick hat, was gebraucht werden wird und sich zwangsläufig irgendwelche Architekturen zusammenwasserfallt, die später nicht funktionieren (alte Hasen ausgenommen). Bei 20 verschiedenen Sensoren, die über UDP/RS232/GPIB/Brieftaube ausgelesen und grafisch dargestellt werden, ist es zu spät, weil man einen Haufen switch/case/if/else-Spaghetti hat. Privat denkt man nicht immer rechtzeitig daran, weil das erstmal keinen Spaß macht und keine sichtbaren Ergebnisse liefert; beruflich brüllt einem vielleicht jemand ständig "Liefertermin! Das Zeug läuft, nicht mehr anfassen, mach neue Features!" ins Ohr.
Tom K. schrieb: > Aus meiner (begrenzten) Erfahrung ist genau da der Punkt, wo man > sinnvollerweise innehält und einen Schritt zurücktritt, um > Programmaufbau + Strukturen der neuen Komplexität anzupassen, > Basisklassen/Patterns einzuführen und alles soweit wie sinnvoll zu > abstrahieren. Code darf dabei auch gelöscht und allgemein neugeschrieben > werden. Kann ich unterschreiben. :-) Das Innehalten und Zurücktreten schaffen aber leider die wenigsten. :-( Auch Profis nicht. > Privat denkt man nicht immer rechtzeitig daran, weil das erstmal keinen > Spaß macht und keine sichtbaren Ergebnisse liefert; beruflich brüllt > einem vielleicht jemand ständig "Liefertermin! Das Zeug läuft, nicht > mehr anfassen, mach neue Features!" ins Ohr. Privat ist es auch annähernd egal, wieviel Zeit man in die Wartung von Spaghetticode steckt. Beruflich ist das von Dir beschriebene Verhalten zwar gängige Praxis, aber leider sehr kurzsichtig. In (Software-)Systemen, die über einen hinreichend langen Zeitraum gepflegt werden müssen, ist dieser Ansatz (Liefertermin, keine Zeit) langfristig das Todesurteil für das Produkt. Es ist recht schnell nicht mehr mit vernünftigem Aufwand wartbar. Grüße Markus
Markus schrieb: > Die Temperatur als Klasse zu modellieren ist sogar sehr sinnvoll. Eine > Temperatur hat einen (im Vergleich zu dem skalaren Typ int) > eingeschränkten Wertebereich. Wenn Du keinen eigenen Typ für die > Temperatur hast, müsstest Du korrekterweise bei jeder Zuweisung einen > Range-Check machen. Weiter macht es überaus Sinn, dass die > Temperaturklasse verschiedene Konvertierungen bietet, z.B. nach String, Das ist eine interessante Herangehensweise, die ich aber noch nirgends live gesehen habe. Hast du da vielleicht ein Beispiel irgendeines Open-Source-Projekts, wo das so gemacht wird? Das Problem, das ich dabei sehe: Würde man das konsequent durchziehen, müsste man ja für fast jede Variable eine eigene Klasse definieren, dazu kommen dann noch unzählige Überladungen für die dafür benötigten Rechenoperationen (vor allem Multiplikationen und Divisionen, bei denen die beiden Operanden i.Allg. unterschiedliche physikalische Größen sind und damit unterschiedlichen Klassen angehören). Was ich mir in dieser Richtung ganz gut vorstellen kann, ist die Verwendung unterschiedlicher Klassen abhängig von der Dimension der jeweiligen physikalischen Größe, da dafür generische Klassen, wie sie bspw. in der bereits angesprochenen Boost.Units-Bibliothek definiert sind, verwendet werden können. Auch damit lassen sich schon sehr viele Fehler in physikalischen Formeln aufdecken, und das sogar schon zur Compile-Zeit. Nur hat man dort eben keine Überprüfung des Wertebereichs.
Yalu X. schrieb: > Das Problem, das ich dabei sehe: Würde man das konsequent durchziehen, > müsste man ja für fast jede Variable eine eigene Klasse definieren Naja, für die Weltformel vielleicht. Für normale Projekte hat man doch ein gewisses Domainmodel und da gibt es nicht so wahnsinnig viele verschiedene Typen/Klassen. Yalu X. schrieb: > dazu kommen dann noch unzählige Überladungen für die dafür benötigten > Rechenoperationen Auch hier: Wie oft muss man JEDEN Typ mit JEDEM Multiplizieren, addieren etc? Gerade die physikalischen Einheiten (wenn man nicht jenseits des Teiches wohnt) sind doch überschaubar und wohldefiniert. Ein Beispiel findest du hier für Messgrößen (incl. Fehlerabweichung): http://www.osgi.org/javadoc/r4v42/org/osgi/util/measurement/package-summary.html oder für Zeiteinheiten: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/TimeUnit.html Es gibt nix blöderes als eine Funktion/Methode welche ein long/double/... akzeptiert, der in Wirklichkeit aber ein Datum oder Temperatur sein soll. Den da kommt man wirklich schnell hin, wenn viele an dem Code arbeiten das dann jeder wie er lustig ist das interpretiert, umrechnet und ausgibt, und ob der Wertebereich stimmt ist auch Fraglich. Und wenn man das konsequent durchzieht, gibt es sehr wenig Stellen (Erzeugung, Serialisierung) wo man tatsächlich sich um die internas kümmern muss. Hat man dann noch das ganze interfacebasiert aufgebaut kann man ein flexibles, wartbares und (modular) erweiterbares System schaffen was Fehler von vornherein verhindert und auch noch gut Testbar ist.
Karl Heinz schrieb: > Du warst doch der, der einem C-Programmierer Klassen und Ableitung (und > damit C++) nahegelegt hat, um auf einem µC mit Touchpad Bereiche > erkennen zu können. Richtig. Ganz genau. Aber siehst du denn nicht den logischen Unterschied? Wenn du auf einem Bildschirm verschiedene grafische Elemente unterschiedlicher Bauart hast, dann haben selbige zwar ein unterschiedliches Innenleben, aber sie sind in mehreren entscheidenden Punkten doch einheitlich: Sie haben alle irgendein Aussehen, was gezeichnet werden muß. Sie haben zum Teil auch die Notwendigkeit, auf Botschaften zu reagieren. Sie stammen also im Prinzip alle von einem Ancestor ab, der prinzipiell genau diese gleichen (virtuellen) Methoden hat: Darstellung und Reaktion auf Ereignisse. Ihre vom übergeordneten System sichtbaren Eigenschaften sind also kommensurabel (mit gleichem Maß meßbar und in gleicher Weise behandelbar). Bei solchen Dingen wie Sensor und Temperatur trifft das eben NICHT zu. Ein Sensor liefert zwar im Allgemeinen eine Zahl, aber das ist eben nicht einfach eine Zahl, sondern eine Größe also Zahl plus Maßeinheit. Und deshalb sind unterschiedliche Sensoren eben NICHT kommensurabel. Sie haben keinen gemeinsamen Ancestor. Das ist der grundlegende Unterschied - ich hoffe, daß du das begreifst. Bei der Temperatur sieht das zwar ganz anders aus, aber es ist auch nicht besser: Eine Temperatur ist ein Zahlenwert plus eine Maßeinheit, also eine Meßgröße. Daraus eine Klasse machen zu wollen, ist albern. Was soll eine Klasse Temperatur denn bieten? Man kann ihr nichts zuweisen, sie hat keine innere Struktur, sie ist eine Größe, die man messen und zur Kenntnis nehmen kann - nicht mehr. Wer das nicht versteht wie Markus kommt dann zu sowas: Markus schrieb: > Die Temperatur als Klasse zu modellieren ist sogar sehr sinnvoll. Eine > Temperatur hat einen (im Vergleich zu dem skalaren Typ int) > eingeschränkten Wertebereich. Wenn Du keinen eigenen Typ für die > Temperatur hast, müsstest Du korrekterweise bei jeder Zuweisung einen > Range-Check machen. Weiter macht es überaus Sinn, dass die > Temperaturklasse verschiedene Konvertierungen bietet, z.B. nach String, Der Range-Check ist Mumpitz, da man einer Temperatur nichts zuweisen kann. Sie ist - für Programmierer - eine ReadOnly Sache. Man kann sie mit einem Sensor erfassen (s.o.) und dessen Ergebnis zum Rechnen oder schlichtweg zum Anzeigen verwenden - jedenfalls dessen numerischen Wert unter Berücksichtigung der Maßeinheit - womit wir beim übergeordneten Programm wären: Weder ein Sensor noch die von ihm gemessene Temperatur können riechen, was mit ihrem Meßergebnis denn so geschehen soll. Das ist Obliegenheit des Programmes, was das Meßergebnis verwendet und dieses muß zwangsläufig Maßzahl und Maßeinheit bei der Verwendung berücksichtigen. Sowas könnte weder ein Objekt "Sensor" noch ein Objekt "Temperatur" leisten. Ich nehme mal an, ihr meint etwas ganz anderes: nämlich visuelle Objekte in einer grafischen Bibliothek, nennen wir sie mal TSensorDisplay und TTemperaturAnzeige. Sowas kann selbstverständlich von einem Ancestor TVisual abgeleitet werden wie z.B. TDropDown oder TButton. Sowas kann auch auf Botschaften reagieren (neuer Wert eingetroffen) und es kann sich zeichnen. Für sowas ist eine Klasse in Ordnung, wenn sie sich in den Rest der verwendeten Bibliothek einordnet. So, Leute, ich leg's euch ans Herz: Lernt das logische Denken und das analytische Denken und das naturwissenschaftliche Denken. Im Moment könnt ihr nur das Programmierer-Denken. Ist zwar auch was wert, reicht aber nicht aus. Guckt über den Tellerrand. W.S.
Wieso sollte eine Temperatur read-only sein müssen? Wenn ich eine Heizung softwaretechnisch regeln möchte, kann ich sicherlich auch eine Temperatur einstellen... Allein schon die Möglichkeit, dass ich mir ein und dieselbe Temperatur in verschiedenen Einheiten geben lassen möchte, bietet sich durch eine Klasse an.
1 | class Temperature |
2 | { |
3 | private decimal _valueInKelvin; |
4 | |
5 | public decimal InKelvin { get { ... }; set { ... }; } |
6 | public decimal InCelsius { get { ... }; set { ... }; } |
7 | public decimal InFahrenheit { get { ... }; set { ... }; } |
8 | } |
und so kann man auch mit Typen wie Länge, Fläche, usw. verfahren. Was Sinn macht, nötig ist und gebraucht wird bestimmt immer die Aufgabenstellung. Obiges stammt sogar aus einem realen Industrieprojekt ;) Da liegen die Typen die gebraucht werden im Domainmodel für alle Consumer verwendbar. Egal ob ShowTemperatureView1 den Wert nun in K oder DoSomethingWithTemperatureViewModelXY den Wert in °C braucht, das Model kümmert sich drum. Und es liest sich dann auch wie ein Roman:
1 | if ( mySensorValue.InCelsius > 0 ) { ... } |
besser als
1 | // sensor value given in K, 273.15 is zero for celsius |
2 | if ( mySensorValue > 273.15 ) { ... } |
Aber wie KH schon sagte, hängt viel davon ab bei welcher 10er-Potenz LOC man sich im Projekt bewegt, 10^2 oder 10^6.
D. I. schrieb: > Wieso sollte eine Temperatur read-only sein müssen? Wenn ich eine > Heizung softwaretechnisch regeln möchte, kann ich sicherlich auch eine > Temperatur einstellen... Weil es die Handhabung vereinfacht und "unerwartet" verhalten eliminiert. Wenn du die Temperatur "ändern" willst, erzeugst du ein Objekt mit der Wunschtemperatur und rufst z.B. setTemperatur(t) auf, also alles kein Problem. Der NUTZER einer Temperatur kann nun aber (da er weis das Objekt ändert sich nicht mehr) genau dieses hernehmen, er kann es eventuell auch als Identifikator für andere Werte hernehmen oder oder, ohne befürchten zu müssen das "irgendwer" die inneren Werte des Temperaturobjektes ändert. Kann er das NICHT müsste er streng genommen das Objekt jedesmal kopieren, auch dürfte er sein inneres Objekt nicht ohne weiteres an weitere an andere Funktionen weitergeben ohne es zu kopieren (der aufgerufen würde es ggf. wieder kopieren und so fort...). Auch hier gibt es garnicht so viele Fälle wo tatsächlich eine Temperatur "erzeugt" oder "geändert" wird, dafür aber viele die die Temperatur lesen und da die Temperatur nicht änderbar ist, kann ein Temperaturobjekt problemlos geteilt werden, was auch die frage der Synchronisation erheblich vereinfacht! D. I. schrieb: > dass ich mir ein und dieselbe Temperatur in verschiedenen Einheiten > geben lassen möchte, bietet sich durch eine Klasse an Nein, siehe mein Kommentar, so was gehört nicht in die Klasse/Interface! Denn das Ergebnis ist nicht von (privaten) inneren Zuständen abhängig sonder einzig und allein von den von außen zugreifbaren Werten, ene "TmeperaturConversion" Klasse ist hier also sehr viel sinnvoller und flexiebler falls morgen jemand eine Temperatur unbedingt als bytearray oder oder oder benötigt...
:
Bearbeitet durch User
D. I. schrieb: > Wieso sollte eine Temperatur read-only sein müssen? Wenn ich eine > Heizung softwaretechnisch regeln möchte, kann ich sicherlich auch eine > Temperatur einstellen... Nein, das kannst du nicht. Stattdessen kannst du einem Regler einen Sollwert vorgeben - das ist etwas anderes. Mag sein, daß du dafür das Wort "Temperatur" benutzt, aber das ist unexakt. Im Grunde hast du in deinem Beispiel eine Klasse TRegler, wo du einen Sollwert vorgeben kannst, vllt. SollTemperatur genannt. Aber du hast keine Klasse TTemperatur, die du einstellen kannst. Allenfalls hast du in deiner Regler-Klasse eine readonly Property namens MomentanTemperatur oder so ähnlich. W.S.
W.S. schrieb: > Bei solchen Dingen wie Sensor und Temperatur trifft das eben NICHT zu. > Ein Sensor liefert zwar im Allgemeinen eine Zahl, aber das ist eben > nicht einfach eine Zahl, sondern eine Größe also Zahl plus Maßeinheit. > Und deshalb sind unterschiedliche Sensoren eben NICHT kommensurabel. Sie > haben keinen gemeinsamen Ancestor. Darüber kann man jetzt lang und breit diskutieren, wie über alles andere auch. Was ein Sensor ist, kann und darf sich jeder selber definieren, und ob dann da eine Basisobjekt "Sensor" und davon abgeleitete Spezifizierungen sinvoll sind, oder nur gemeinsame Interfaces, oder sonst eine Lösung, ist nicht mit einem pauschalen Nein zu beantworten. Aber im Fall des TO ist das ja alles auch sowieos völlig egal. Der will EINEN Sensor auslesen. Ob das jetzt per OOP oder mit unabhängigen Funktionen oder in Assembler oder optimal oder suboptimal oder sonstwie gemacht wird, was solls. Wenn da eine Bedienoberfläche in C# für Windows dazu kommt, wird die sowieso 99% des Programmumfangs umfassen, und Struktur und Ablauf des Programms objektorientiert vorgeben. Ob die Sensorbehandlung dann auch in eine eigene Klasse wandert, oder nicht, ist völlig nebensächlich. Oliver
W.S. schrieb: > Ein Sensor liefert zwar im Allgemeinen eine Zahl, aber das ist eben > nicht einfach eine Zahl, sondern eine Größe also Zahl plus Maßeinheit. Man könnte es auch MESSWERT nennen (Zahl+Fehler+Einheit), das ist doch etwas was allen Sensoren eigen ist. > Bei der Temperatur sieht das zwar ganz anders aus, aber es ist auch > nicht besser: Eine Temperatur ist ein Zahlenwert plus eine Maßeinheit, > also eine Meßgröße. Daraus eine Klasse machen zu wollen, ist albern. Was > soll eine Klasse Temperatur denn bieten? Man kann ihr nichts zuweisen, > sie hat keine innere Struktur, sie ist eine Größe, die man messen und > zur Kenntnis nehmen kann - nicht mehr. Sehe ich nicht so, wenn ich eine Temperatur haben will, dann will ich eine Temperatur und kein beliebeigen double in Kilogram. Also wieso nicht temperatur von der generischen Klasse/Interface 'Meßgröße' welche ein double und eine Einheit liefert ableiten? Wer mit allgemeinen 'Meßgrößen' arbeiten kann kann diese ja nutzen, wer explizit wenigstens eine Temperatur benötigt kann dies in seiner Methode dokumentieren und der Compiler kann das im Vorfeld prüfen. Hier in "nicht-klassen-würdige" Objekte unterscheiden zu wollen ist nicht zielführend. Ob eine direkte VERERBUNG Sinn macht ist ein ganz andere Punkt, ich habe ja schon oben geschrieben, das man sowas eher interface-basiert machen sollte, und die entscheidung ob Vererbung oder nicht der implementierung überlassen.
Hallo, nach der (angeblich erstrebenswerten) MVC-Architektur (Model-View-Controller) gehören Umrechnungen der internen Temperatur in Fahrenheit, Reaumur oder sonstwas eindeutig nicht zum Model, sondern zum View (Ausgabe) oder Controller (Eingabe). Was der intern verwendete Wert darstellt, z.B. float Kelvin, müssen natürlich alle Beteiligten wissen! Es wäre ja absurd, wenn ein Temperaturregler mit einer anderen internen Grösse arbeiten würde, nur weil das Gerät nach Frankreich oder USA geliefert wird. Auch darf eine Erweiterung der Software um weitere provinzielle Masseinheiten überhaupt keinen Einfluss auf die Regelung haben. Georg
Läubi .. schrieb: > D. I. schrieb: >> Wieso sollte eine Temperatur read-only sein müssen? Wenn ich eine >> Heizung softwaretechnisch regeln möchte, kann ich sicherlich auch eine >> Temperatur einstellen... > > Weil es die Handhabung vereinfacht und "unerwartet" verhalten > eliminiert. Wenn du die Temperatur "ändern" willst, erzeugst du ein > Objekt mit der Wunschtemperatur und rufst z.B. setTemperatur(t) auf, > also alles kein Problem ... mh könnte meinen Vorschlag auch als struct realisieren und es kombinieren mit deinem: Regler.setTemperature(Temperature t) @MVC: Umrechnungnen sehe ich sehr wohl als Model-Logik, die View entscheidet lediglich was sie darstellen möchte. Maximal noch im Controller, aber bei MVC greift im Zweifel die Faustregel "thin controllers, fat models".
Läubi .. schrieb: > Sehe ich nicht so, wenn ich eine Temperatur haben will, dann will ich > eine Temperatur und kein beliebeigen double in Kilogram. Also wieso > nicht temperatur von der generischen Klasse/Interface 'Meßgröße' welche > ein double und eine Einheit liefert ableiten? Wozu, wozu, WOZUHUHUHUHU bloß? Als akademische Programmierer-Übung ohne Realitätsbezug? Als Selbstverwirrung? Kommt demnächst ein Programmierer auf die Idee, einem TKörper eine TMasse zuweisen zu wollen? Nun, die Schönheitsindustrie würde das ja begrüßen, man könnte damit sich selbst sein Idealgewicht zuweisen, auch dann, wenn man nicht ißt sondern frißt. Die Damen werden es den Programmierern danken. Ich hab das hier grad anderswo zitiert (aus dem Stroustrup): "Language shapes the way we think, and determines what we can think about" Ihr habt offensichtlich schon zuviel C++ verinnerlicht, so daß ihr aus dieser Denke nicht mehr herauskommt und den Wald vor Bäumen nicht mehr seht. Läubi .. schrieb: > wer explizit wenigstens > eine Temperatur benötigt kann dies in seiner Methode dokumentieren Ja, eben: An was für eine Methode hast du denn bei einer Temperatur gedacht? Ist es überhaupt denkbar, daß ein physikalischer Meßwert eingebaute Methoden oder Properties hat (eben außer seinem tatsächlichen Wert)? Nein, natürlich nicht. Das äußerste, was hier in Programmiererkreisen denkbar ist, ist eine API-Funktion des Betriebssystems, mittels derer man eine Aussage über eine Temperatur erfragen kann (Beispiel: aktuelle CPU-Temperatur). Das gibt ne Zahl und die Maßeinheit liest man in der BS-Doku nach. Wo bittesehr siehst du hier eine auch nur ansatzweise Möglichkeit, irgendwelche Methoden unterzubringen? Läubi .. schrieb: > Sehe ich nicht so, wenn ich eine Temperatur haben will, dann will ich > eine Temperatur und kein beliebeigen double in Kilogram. Nee, du kriegst vom BS eine Zahl und was die bedeutet - siehe oben. Mehr ist nicht drin in der Tüte. Jetzt kannst du dich natürlich hinsetzen und dir sagen: "Ich bau mir da jetzt ne Breitseite von allem ein, was mir grad einfällt und dann hab ich Methoden und Properties bis zum Abwinken." Aber wo bleibt da der eigentliche Sinn bei der derart kreierten TYaluTemperaturClass? W.S.
Zumindest dauert es jetzt 5 Tage, und bis sich die Experten über eine korrekte TemperaturKlasse einig sein werden scher noch mal 5 Monate, und innerhalb von 5 Minuten hätte man das Programm ohne OOP fertig geschrieben. Das kostet dann ein tausendstel (Aufwand, Geld), aber OOP ist ja SOOO arbeitssparend. Und nach 5 Monaten stellt dann die versammelte Programmierertruppe fest, daß der erzeugte Code leider nicht in den Programmspeicher des anvisierten Microcontroller passt, weswegen ein redesign mit refactornig für eine leightweight TemperaturKlasse notwendig ist, nicht ohne externe Beratung einzuholen obwohl man doch beratungsresistent ist. Die Branche ist so verkotzt inzwischen.
Nein, du bist nur in den 70ern stehen geblieben und bist wahrscheinlich frustriert weil du nicht mithalten konntest.
D. I. schrieb: > Nein, du bist nur in den 70ern stehen geblieben.. nanananana.. Ständig nur beleidigt (und dann beleidigend) zu reagieren, wenn die Argumente ausgehen und dann zu schreiben "du hast ja keine Ahnung" oder "du bist ja sooo doof" usw. hilft niemendem. Es legt auch beredtes Zeugnis ab davon, daß der Schreiber am Verstehen der ihm nicht schmeckenden Argumente gescheitert ist, aber seinen zu kleinen Horizont einfach nicht zugeben will. W.S.
W.S. schrieb: > Es legt auch beredtes Zeugnis ab davon, daß der Schreiber am Verstehen > der ihm nicht schmeckenden Argumente gescheitert ist, aber seinen zu > kleinen Horizont einfach nicht zugeben will. MaWin mag von Elektrotechnik große Ahnung haben, aber sein Softwarehorizont reicht nicht über 100 Zeilen Mikrocontroller hinaus, das hatten wir im Forum aber schon gefühlte 1000 mal. Da gibts mit KH, Läubi, Yalu etc. andere Kompetenzen. Natürlich kann man immer erstmal was zusammenhacken was irgendwie tut, so siehts dann hinterher auch aus und so wartbar isses dann auch. Btw. MaWin sollte der letzte sein, der sich darüber beschweren kann in einem ranzigen Ton angeredet zu werden. Edit: Du hast auch auch keine sonderlich ernstzunehmende Argumente gebracht, deswegen lohnt es sich nicht mit euch beiden weiter über dieses Thema zu diskutieren.
Andreas Lang schrieb: > [...] Die Sensorklasse wird dann für jeden sensortyp abgeleitet, wenn ich [...] Hier vermengst du doch Hardware mit Software. Klasse Temperatur sollte sich nur um solche kümmern. Dieser Teil ist Applikationsspezifisch komplett hardwareunabhängig. Genauso wie es eine I²C Klasse geben sollte, die sich nur um die Ansteuerung der Schnittstelle kümmert und der egal ist, was mit den geholten Daten passiert, oder wie sie zu interpretieren sind. Der Teil ist natürlich hardwareab- aber anwendungunabhängig. Klassischer Treibersoftware halt. Dazwischen sitzt eine Ebene, HAL (Hardware Abstraction Layer) genannt, die deine konkrete Application an die Hardware koppelt. Sie sagt dem I²C "hol die Daten" und rechet sie (bestenfalls in SI-Einheiten) um und übergibt sie der Applikation. Das ganze ist unabhängig von Programmiersprache oder OOP oder Nicht-OOP. Gehst du auf eine neue Hardware musst du nur passende Treiber suchen und den HAL anpassen. Bringst du eine andere Anwendung auf die bekannte Hardware, musst du nur den HAL anpassen. Schreibst du eine neue Anwendung für eine neue Hardware musst du halt alle drei Komponenten schreiben, aber meist finden sich zumindest Treiber schon irgendwo. Bastelst du ein µC Projekt, wo abzusehen ist, dass du die Hardware das erste und letzte mal siehst und das nicht sehr komplex ist und nicht gewartet werden soll, vermischt man halt Application und HAL. Treiber würd ich trotzdem immer extra halten.
Kevin schrieb: > In wie weit organisiert man alles in Klassen? Nun, Kevin - wie du hier lebhaft sehen kannst, ist es am Besten, du findest deinen eigenen Weg. Probiere aus, betrachte deine Loesungen selbstkritisch, verbessere sie. Schau hin und wieder ueber den Tellerrand und lasse dich inspirieren. Aber auf keinen Fall solltest du dir etwas von anderen Vorbeten lassen oder irgendwelchen Goetzen nacheifern. Finde deinen Weg.
D. I. schrieb: > Nein, du bist nur in den 70ern stehen geblieben und bist wahrscheinlich > frustriert weil du nicht mithalten konntest. Im Gegensatz zu dir ist mein Programm schon längst fertig und verkauft sich prächtig und bringt Millionen ein. Dein Geschwätz hingengen ist sachlich falsch, und das weiss ich, deutlich besser als du, denn du redest über mich. Und so weiß ich auch vieles andere deutlich besser als du.
D. I. schrieb: > Du hast auch auch keine sonderlich ernstzunehmende Argumente > gebracht Hast du irgend etwas Ernstzunehmendes dagegen zu setzen? Nein? Hast du wenigstens eine Ergänzung, eine Weiterführung, eine Präzisierung - kurzum irgend etwas Sachliches dazu zu sagen? Auch nein? Dann laß solche Bemerkungen und gehe das nächste Mal wenigstens ein wenig auf das ein, was ich geschrieben habe. Wie gesagt: einfach bloß "du bist ja doof" zu schreiben reicht einfach nicht aus. Gilt auch für dich. W.S.
MaWin schrieb: > schon längst fertig und verkauft > sich prächtig und bringt Millionen ein. Und warum fängst du dann hier im Forum einen blödsinnigen Streit nach dem anderen an, statt dich in St. Tropez auf deiner Yacht zu sonnen? Georg
Quack schrieb: > Kevin schrieb: >> In wie weit organisiert man alles in Klassen? > > Nun, Kevin - wie du hier lebhaft sehen kannst, ist es am Besten, du > findest deinen eigenen Weg. Probiere aus, betrachte deine Loesungen > selbstkritisch, verbessere sie. Schau hin und wieder ueber den > Tellerrand und lasse dich inspirieren. Aber auf keinen Fall solltest du > dir etwas von anderen Vorbeten lassen oder irgendwelchen Goetzen > nacheifern. > > Finde deinen Weg. Vielen Dank für deine Einschätzung. Aktuell sieht es ja so aus, als wenn das sowieso jeder völlig anders angehen würde. Gruß, Kevin
Es wird immer Leute geben, die alles Neue verteufeln und mit dem Alten "Millionen verdienen". Das ist ja nicht schlimm. Wenns so funktioniert, ist ja gut. Tragisch ist nur, wenn das für sie Neue schon bald fünfzig Jahre alt ist. eg
Fred schrieb: > Tragisch ist nur, wenn das für sie Neue schon bald fünfzig Jahre alt > ist. eg Und selbst wenns 200 wären... Eine gute Lösung bleibt eine gute Lösung. Insbesondere wenn sie einfach ist. Das "Neue" gibts leider oft nur im Bundle mit mehr, nur allzuoft unnötiger Komplexität.
Kevin schrieb: > Vielen Dank für deine Einschätzung. Aktuell sieht es ja so aus, als wenn > das sowieso jeder völlig anders angehen würde Da gibts eben die OOP Theologen, deren Lösung schön komplex sein muß, damit dieses Blendwerk ordentlich was hermacht und solche, die nur und genau das programmieren, was der Problemstellung tatsächlich angemessen ist.
Naja, kommen wir mal zum eigentlichen Kern der Sache zurück: Kevin schrieb: > Muss ich also eine Klasse "Temperatur" anlegen? (hier könnte man ja > zwischen Fahrenheit und Celsius unterscheiden? > > Außerdem muss ich ja sicher eine Klasse Sensor anlegen. Wie weit würde > man das ganze noch aufdroeseln? Es kommt drauf an, was du willst: a) üben, wie man ne Klasse anlegt? b) auf deinem PC auf der grafischen Oberfläche ein Fenster haben, wo dir die aktuelle Temperatur entgegengrinst? c) auf deinem PC ein Tool haben, also ein biederes Kommandozeilenprogramm von stdin nach stdout, oder den aktuellen Temperaturwert in eine Datei schreiben? d) der Frage nachgehen, was man sinnvoll in C++ oder auch in anderen Sprachen, die OOP bieten, in Objekte quetscht oder eben auch nicht? Ganz allgemein sag ich dazu, daß es zu allererst nötig ist, sich mit sich selber über die Begrifflichkeiten ins Klare zu kommen: Eine Klasse "Temperatur" ist albern, eine Klasse "Temperatur_Adapter" oder "Temperatur_Anzeiger" oder "Temperatur_Regler" hingegen nicht. es kommt auf den beabsichtigten Inhalt an, also was da innerhalb des Objektes 'leben' soll. Für ein stupides 'double' wäre eine eigene Klasse übertrieben bis zur Albernheit, für z.B. einen PID-Regler hingegen sieht das völlig anders aus. W.S.
Moby schrieb: > solche, die nur und > genau das programmieren, was der Problemstellung tatsächlich angemessen > ist. Ich stelle mir gerade so vor, wie dich beim Einstellungsgespräch der Personalchef fragt, ob du Erfahrungen mit OO hast, und du antwortest "ich programmiere nur das, was der Problemstellung tatsächlich angemessen ist"... Ich habe ja weiter oben das Beispiel gebracht mit einer Klasse Bit mit Getter/Setter für true und false und Methoden für and, or, xor, sowas macht einfach viel mehr her. War übrigens keine Fantasie von mir, das gibt es wirklich, sogar als verbindliche Lösung. Die Sprache hiess Actor, von Whitewater. Georg
Georg schrieb: > Ich stelle mir gerade so vor, wie dich beim Einstellungsgespräch der > Personalchef fragt... Der fragt aber nicht, Georg. Als Bastler hat man eben den einzigartigen Luxus, sich auf das tatsächlich notwendige beschränken zu können :-)
W.S. schrieb: > übertrieben bis zur Albernheit Genau das ist OOP- zumindest für alle jene Millionen Problemstellungen, die nicht über ein bestimmtes Maß an Komplexität hinausgehen. Hinter der softwaretechnisch eleganten Anmutung steckt allein unnötiger Overhead und Dokumentationsbedarf. Aber schee schauts aus- und trefflich akademisch diskutieren lässt sich darüber auch.
Moby schrieb: > unnötiger Overhead Ich habe mal versucht mich zu erinnern wie man OO-mässig addiert: aus der Gleichung s = x + y die man in "normalen" Programmiersprechen genauso eingibt, wird bei Actor: s.SetValue (x.AddValue (Y.GetValue)); supereindrucksvoll und sooo übersichtlich, nicht? Georg
Georg schrieb: > s.SetValue (x.AddValue (Y.GetValue)); > > supereindrucksvoll und sooo übersichtlich, nicht? Schon mal von Operatorüberladung gehört?
Ja, Spielzeug-Einzeiler sind immer eine gute Grundlage für einen fundierten Vergleich.
Georg schrieb: > Ich habe mal versucht mich zu erinnern wie man OO-mässig addiert: > > aus der Gleichung > s = x + y > die man in "normalen" Programmiersprechen genauso eingibt, wird bei > Actor: > > s.SetValue (x.AddValue (Y.GetValue)); > > supereindrucksvoll und sooo übersichtlich, nicht? Ich kenne Actor nicht, aber scheint ja eine reichlich antiquierte Sprache zu sein. Kein Wunder, dass du da keinen Spaß daran hattest. Außerdem ist das was du hier machst nicht wirklich der OO-Weg. Wenn ich mit objektorientiert-funktionalem Denken Assembler programmiere, kann ich auch nicht einfach Zeile für Zeile übersetzen. Zu deinem Beispiel: sollte man das wirklich so brauchen, dann gibt es dafür im Normalfall Operatorüberladung und primitive Typen. Dann bleibt es auch bei s = x + y. Je nach Aufgabenstellung hat man aber oft andere Fälle, z.B. addiere eine Länge zu einer anderen Länge: s = x.add(y) Das ist, finde ich, schon ganz nett. Sobald x und y nicht mehr die gleiche Einheit haben kann man die Umrechnung schön in der Add-Methode kapseln. Und wenn ich mich vertippe und zur Länge eine Temperatur addieren möchte schreit der Compiler.
Moby schrieb: > und solche, die nur und > genau das programmieren, was der Problemstellung tatsächlich angemessen > ist. Genau die, die immer nur das programmieren, was der Aufgabenstellung angemessen ist, haben überhaupt zur Entwicklung der höheren Programmiersprachen und danach zu deren Weiterentwicklung geführt. Warum wohl nur? Oliver
Peter schrieb: > Schon mal von Operatorüberladung gehört? Jan Hansen schrieb: > dann gibt es > dafür im Normalfall Operatorüberladung und primitive Typen. Da habt ihr garnichts verstanden. Actor war als streng OO konzipiert, d.h. Operatoren gibt es nicht. Punkt. Das hätten die Erfinder als Rückfall in die Primitivität abgelehnt (wie Jan sagt: primitive Typen. Die gab es natürlich ebensowenig wie Operatoren). Ausserdem wäre das ja inkonsequent: wenn man z.B. integer mit dem Operator + addieren kann, wozu muss ein integer dann noch ein Objekt einer Klasse sein? Was soll denn vererbt werden, wenn nicht Methoden wie Add? Actor wurde gleich nach den ersten Erwähnungen von OO als die ultimative Lösung mit vollständiger Umsetzung des OO-Gedankens propagiert, ist aber bald in der Versenkung verschwunden. Nach meiner Ansicht zu Recht, und das sollte mein Beipiel begründen. Ich würde das als fundamentalistische OO bezeichnen. Georg
Georg schrieb: > Da habt ihr garnichts verstanden. Actor war als streng OO konzipiert, > d.h. Operatoren gibt es nicht. Punkt. Warum widerspricht die Verwendung von Operatoren dem objektorientierten Programmierparadigma? Falls dich der Bergiff "Operator" stört: Benenne ihn einfach um, bspw. in "Methode mit 1 Argument" (wie in C++) oder "binäre Nachricht" (wie in Smalltalk). Falls dich die Schreibweise mittels Sonderzeichen ('+'. '-' usw.) stört: Das ist ausschließlich eine Frage der Syntax, nicht des Paradigmas. > Ich würde das als fundamentalistische OO bezeichnen. Wenn allgemein anerkannte und der Lesbarkeit dienende syntaktische Konstrukte wie die Infixnotation arithmetischer Ausdrücke sinnloserweise einem übertriebenen OO-Wahn geopfert werden, würde ich das schon eher als extremistische OO bezeichnen ;-)
Yalu X. schrieb: > Falls dich die Schreibweise mittels Sonderzeichen ('+'. '-' usw.) stört: > Das ist ausschließlich eine Frage der Syntax, nicht des Paradigmas. Das ist mir schon klar, dass das alles geht und auch gehen sollte, aber die damaligen Macher haben das im Interesse der reinen Lehre eben nicht vorgesehen. Könnte man die Addition mit + schreiben, wäre der beabsichtigte erzieherische Effekt hin zu OO ja nicht mehr gegeben gewesen. Aber lassen wir solche Verirrungen in Frieden ruhen, ausser mir erinnert sich sowieso keiner mehr an Actor (immerhin findet Google noch was). Georg
Georg schrieb: > Aber lassen wir solche Verirrungen in Frieden ruhen, ausser mir > erinnert sich sowieso keiner mehr an Actor (immerhin findet Google noch > was). Die Frage ist, warum du diese "Verirrung" dann gegen OO in Stellung bringst. Vielleicht solltest du dir eine modernere Sprache ansehen - vielleicht wirst du ja noch ein Fan :)
Oliver S. schrieb: > Genau die, die immer nur das programmieren, was der Aufgabenstellung > angemessen ist, haben überhaupt zur Entwicklung der höheren > Programmiersprachen und danach zu deren Weiterentwicklung geführt. Für komplexe Problemstellungen braucht es sicher neue Herangehensweisen. OOP ist ein mehr oder weniger gelungener Versuch dazu. Die Problemstellung des TO gehört wie Millionen andere sicher nicht dazu. OOP ist eben KEIN passendes Universalwerkzeug für alle Fälle. Aber wer einen tollen Hammer in der Hand zu halten glaubt neigt natürlich dazu, in jedem Problem einen Nagel zu sehen ;-) Der Begriff "Einfachheit" hat im übrigen auch etwas doppelbödiges an sich. Der sich entwickelnde Profi wird darunter etwas anderes verstehen als der Bastelamateur. Laufend werden Programmiersprachen weiterentwickelt und um neue Konstrukte erweitert, die dem Profi im konkreten Fall Vereinfachung versprechen, das ganze System aber letztlich aufblasen und dann doch immer komplizierter = lernintensiver machen. Egal. Wenn irgendwann kaum einer mehr einsteigt ist jedes System sowieso zum Untergang verurteilt. Georg schrieb: > im Interesse der reinen Lehre... und nach strikten pauschalen Regularien / Programmierideologien wird man selten zur passgenauen, einfachsten Lösung finden.
Moby schrieb: > OOP ist ein mehr oder weniger gelungener Versuch dazu. > Die Problemstellung des TO gehört wie Millionen andere sicher nicht > dazu. Der TO programmiert aus Spaß, hat bisher keine Erfahrung mit OOP, und möchte da einfach mal Erfahrung sammeln. Das macht das mir einer einfachen Anwendung. Ist doch völlig in Ordnung. Ja, das Problem lässt sich (als Konsolenanwendung) mit ein paar Zeilen Assembler erschlagen, aber darum geht es doch gar nicht. Oliver
Kevin schrieb: > Muss ich also eine Klasse "Temperatur" anlegen? (hier könnte man ja > zwischen Fahrenheit und Celsius unterscheiden? Eine Klasse "Temperatur" ergibt generell wenig bis gar keinen Sinn. Genau so, wie eine Klasse "Zeit" oder "Länge" oder "Stromstärke" oder "Volumen" wenig bis gar keinen Sinn ergibt. Physikalische Größen wird man in der OOP in aller Regel als eine "hat-ein" Beziehung antreffen. Also: -ein Fahrzeug hat eine Geschwindigkeit v -ein Gegenstand hat eine Masse m -ein Temperatursensor hat einen Temperaturwert ϑ (Theta) Eine "hat-ein" Beziehung wird man in den Member-Variablen wiederfinden, über die eine Klasse verfügt. Und in den Methoden, die darauf operieren. > Außerdem muss ich ja sicher eine Klasse Sensor anlegen. Wie weit würde > man das ganze noch aufdroeseln? Man kann eine Basisklasse "Sensor" anlegen, von der man dann alle anderen Sensoren ableitet. Das ist im Gegensatz zu oben eine "ist-ein" Beziehung. Die "ist-ein" Beziehung findet sich in der Klassenhierarchie wieder. Also: -ein Temperatursensor ist ein Sensor -ein Helligkeitssensor ist ein Sensor -ein Feuchtigkeitssensor ist ein Sensor und so weiter. Zu Übungszwecken: Warum nicht. In einer realen Anwendung auf einem Mikrocontroller, auf dem überhaupt nur ein einziger Sensor existiert: Unnötiger Mehraufwand. In einem Projekt, in dem es eine Vielzahl von unterschiedlichen Sensoren gibt: Kann sinnvoll sein. Ob es das ist oder nicht, hängt immer von der konkreten Aufgabenstellung ab.
:
Bearbeitet durch User
Mark Brandis schrieb: > Geschwindigkeit Eine Geschwindigkeit hat einen Numerischen Wert und eine Einheit > Masse Eine Masse hat einen Numerischen Wert und eine Einheit > Temperaturwert Ein Temperaturwert hat... Also wieso sollten diese nicht (von der gemeinsamen Basisklasse Messgröße) abgeleitete konkrete Klassen sein? Ob etwas "Sinn hat" ergibt sich nicht aus der Sache sondern aus dem Kontext. Ein µC mit 2x16 LCD für die Anzeige der Raumtemperatur hat ganz andere Anforderungen als eine Simmulationssoftware für Wetterphänomene.
Läubi .. schrieb: > Ein Temperaturwert hat... Ja, aber die Masseinheit mitzuführen ist unsinnig. Wann immer ich mit Temperaturen zu tun habe, verwende ich die absolute Temperatur in Kelvin, es gibt einfach keinen vernünftigen Grund, mit etwas anderem zu rechnen. Also brauche ich auch keine Eigenschaft Masseinheit, sondern nur den Zahlenwert. Noch krasser bei CAD-Systemen: alle mir bekannten Systeme haben eine interne Masseinheit, z.B. nm. Alle linearen Masse haben diese Auflösung, es wäre daher völlig unsinnig, bei z.B. Tausenden von Pin-Positionen auf einer Leiterplatte bei jeder einzelnen die Tatsache mitzuspeichern, dass es sich um nm handelt. Auf dem Bildschirm wird sowieso zwischen einer ganzen Reihe von Einheiten umgeschaltet, da ist die Anzeigesoftware für die Umrechnung zuständig. Falls man das überhaupt je braucht, kann man im Handbuch nachlesen, was die native Einheit des Systems ist. Natürlich kann ein Idiot etwas falsch interpretieren, aber gegen Idioten hilft auch OO nicht, die muss man halt vom Programmieren fernhalten. Ich weiss schon, dass es heute absolut uncool ist, Speicherplatz zu sparen, aber deswegen muss man ihn ja nicht vollkommen sinnlos einsetzen. Georg
Georg schrieb: > Ich weiss schon, dass es heute absolut uncool ist, Speicherplatz zu > sparen, und Rechenleistung noch dazu. Die Hardware muß immer fetter werden um die zunehmend ineffiziente Programmierung auszugleichen. Bis nix mehr geht und ein Systemwechsel unausweichlich wird ;-(
Läubi .. schrieb: > Mark Brandis schrieb: >> Geschwindigkeit > > Eine Geschwindigkeit hat einen Numerischen Wert und eine Einheit > >> Masse > > Eine Masse hat einen Numerischen Wert und eine Einheit > >> Temperaturwert > > Ein Temperaturwert hat... > > Also wieso sollten diese nicht (von der gemeinsamen Basisklasse > Messgröße) abgeleitete konkrete Klassen sein? Kann man machen, aber was genau bringt das? Intern wird man für gleiche physikalische Größen auch mit der gleichen Skalierung rechnen. Von daher sehe ich es so wie Georg, die Einheit wird für die Berechnungen an sich nicht als eine Eigenschaft in einer Klasse mit abgespeichert. Ein Meter pro Sekunde ist dann intern in einer Variablen nicht als ein Zahlenwert 1 gespeichert, sondern vielleicht als 10 oder 100 oder 1000. Also skaliert, damit man in Integer-Arithmetik mit ganzen Zahlen auch (sehr) kleine Geschwindgkeiten ausdrücken kann. Anders mag es bei der GUI aussehen. Hier stellt man vielleicht in Kilometern pro Stunde dar, was intern mit skalierten Metern pro Sekunde gerechnet wird. Das ist aber ein Problem der Anzeige, keines der Berechnung. Rechnen wird man alles in der gleichen, vorher festgelegten Skalierung, weil es anders wenig sinnvoll wäre. Läubi .. schrieb: > Ein µC mit 2x16 LCD für die Anzeige der Raumtemperatur hat ganz > andere Anforderungen als eine Simmulationssoftware für Wetterphänomene. Selbst bei Letzterer würde es mich wundern, wenn sowohl Windgeschwindigkeit als auch Niederschlagsmenge als auch Luftdruck als auch Temperatur alle von der gleichen Basisklasse abgeleitet sind. Falls es doch so ist, lasse ich mich gerne eines Besseren belehren.
:
Bearbeitet durch User
Mark Brandis schrieb: > Kann man machen, aber was genau bringt das? Weniger nötiges Spezialwissen (http://de.wikipedia.org/wiki/Truck_Number), (Dein Beispiel zeigt es doch gut, "vielleicht skaliert", "vielleicht 10, 100, 1000"... was interessiert die interne Repräsentation?), Flexibilität (Was wenn in Zukunft eben NICHT ein Zahlenwert ausreicht, sondern noch eine Fehlerabweichung benötigt wird?), Generische Methoden (ja, man kann auch mit Einheiten rechnen), Typsicherheit (Eine Temperatur ist keine Geschwindigkeit oder Gewicht oder Zeit...), Dokumentation (was soll ich 100 Zeilen Kommentar verfassen wenn es ein vernünftiger Typ tut um auszudrücken was Sache ist). Warum sollte ich all das verschenken (zumal der Aufwand minimal ist), und stattdessen darauf bauen das ich nächstes Jahr (oder mein Kollege morgen) noch weiß welche "ist-doch-alles-klar"-Annahmen ich getroffen habe. Ich habe ja oben schon ein Beispiel verlinkt wo es konkret um Messwerte geht, mit denen man auch rechnen kann, und die sogar den Messfehler berücksichtigen. Mark Brandis schrieb: > Rechnen wird man alles in der gleichen, vorher festgelegten Skalierung, > weil es anders wenig sinnvoll wäre Auch das muss nicht sein (und ist eher einschränkend) da die zu verwendende Genauigkeit ggf. einstellbar oder sogar dynamisch ist. Man sollte sich auch nicht zu arg an den Berechnungen festkrallen, diese sind in den meisten Programmen nicht der Hauptbestandteil oder gerade dort eher generischer Natur. Ansonsten wird hier immer schön argumentiert das es "keinen Vernünftigen Grund" für irgendwas gäbe, Argumente hört man leider keine.
:
Bearbeitet durch User
Läubi .. schrieb: > Ansonsten wird hier immer schön argumentiert das es "keinen Vernünftigen > Grund" für irgendwas gäbe, Argumente hört man leider keine. Ich denke mal das liegt einfach daran, dass viele Entwickler dafür weder im Studium noch im Berufsleben jemals ein Beispiel gesehen haben. Das heißt nicht, dass es keines gibt. Wenn es eines gibt, dann zeig doch bitte mal konkreten Code. Auszugsweise und beispielhaft reicht.
Mark Brandis schrieb: > Ich denke mal das liegt einfach daran, dass viele Entwickler dafür weder > im Studium noch im Berufsleben jemals ein Beispiel gesehen haben. Das heißt aber auch nicht, dass es nicht sinnvoll ist, nur weil viele es nicht schaffen, sinnvolle Konzepte umzusetzen und lieber "business as usual" betreiben, weil wir das ja immer schon so gemacht haben. Domainspezifische Klassen wie Temperatur, Masse, ... haben den Vorteil, dass man damit typsicheren Code schreibt. Jeden Fehler, den der Compiler findet, führt nicht zu einem Laufzeitfehler beim Kunden. Wobei das bei "Bastelprojekten" natürlich irrelevant ist. Grüße Markus
Läubi .. schrieb: > Ansonsten wird hier immer schön argumentiert das es "keinen Vernünftigen > Grund" für irgendwas gäbe, Argumente hört man leider keine. Dass es völlig unsinniger Aufwand ist, bei einer Leiterplatte mit 20000 Bohrungen zu jeder einzelnen Bohrung ein Objekt zu speichern statt einfach die X/Y-Koordinaten, ist für dich also kein Argument? 40000 mal die überflüssige Information, dass die Koordinaten in nm sind? Sowas ist bloss gut, um damit anzugeben, aber Lichtjahre von der Praxis entfernt. Natürlich ist meine Meinung für dich völlig irrelevant, aber komischerweise arbeiten reale CAD-Systeme so, ganz ohne mich gefragt zu haben. Wahrscheinlich haben sie einfach den natürlich unverzeihlichen Fehler gemacht, DICH nicht zu fragen. Allerdings müssten wir dann wohl immer noch auf CAD-Systeme warten, die auf einem normalen PC laufen. Georg
Georg schrieb: > 40000 mal > die überflüssige Information, dass die Koordinaten in nm sind? Offensichtlich fehlt es Dir an der nötigen Abstraktionsfähigkeit. Wo steht denn geschrieben, dass man beim Modellieren einer entsprechenden Klasse immer eine (konstante) Einheit mit ablegt. Jeder (halbwegs) vernünftige Entwickler käme wohl von alleine auf die Idee, dass diese Information redundant sein könnte und deshalb einfach implizit im Klassendesign enthalten ist. Und ganz ehlich: 40000 Objekte? Lächerlich! Wir sind heute nicht mehr in den Zeiten von C64 und Co., wo man mit jedem Bit rumgeizt (zumindest solange man sich nicht im embedded Bereich bewegt). Speicherplatz sparen ist sicherlich ganz nett, aber "Optimierungen" bringt man da an, wo es anfängt eng zu werden. Wesentlich wichtiger ist eine saubere Modellierung, sei es objektorientiert, prozedural oder sonst irgendwie. Grüße Markus
Markus schrieb: > Domainspezifische Klassen wie Temperatur, Masse, ... haben den Vorteil, > dass man damit typsicheren Code schreibt. Markus schrieb: > Wesentlich wichtiger ist eine saubere > Modellierung, sei es objektorientiert, prozedural oder sonst irgendwie. Schon recht. Nur wenn ich prozedural in C programmiere, habe ich halt keine Klassen. Viele Embedded-Projekte zur Steuerung von Maschinen, Anlagen, Fahrzeugen etc. sind nun mal in C geschrieben. Da gibt es dann halt keinen Prozesswert "Temperatur", der von einer Basisklasse "Messwert" abgeleitet ist.
Georg schrieb: > Dass es völlig unsinniger Aufwand ist, bei einer Leiterplatte mit 20000 > Bohrungen zu jeder einzelnen Bohrung ein Objekt zu speichern statt > einfach die X/Y-Koordinaten, ist für dich also kein Argument? 40000 mal > die überflüssige Information, dass die Koordinaten in nm sind? Sowas ist > bloss gut, um damit anzugeben, aber Lichtjahre von der Praxis entfernt. Mein 3 Jahre altes "Smartphone" hat einen Duo Core Prozessor mit mind. 1GHz Takt, dazu 16GiB RAM. 40000 Referenzen auf ein Immutable Objekt sind da gar kein Problem oder Faktor. Was war nochmal mit der "Premature Optimization", diesem Spruch aus den 70'er Jahren? ;)
Markus schrieb: > Wo > steht denn geschrieben, dass man beim Modellieren einer entsprechenden > Klasse immer eine (konstante) Einheit mit ablegt Das hat Läubi höchstselbst als der Weisheit letzten Schluss und als zwingenden Grund für eine Klasse propagiert: Läubi .. schrieb: > Eine Geschwindigkeit hat einen Numerischen Wert und eine Einheit Aber wie schon Adenauer (oder wars Strauss) sagte, was geht mich mein dummes Geschwätz von vorgestern an. Georg
Kolllege schrieb: > Mein 3 Jahre altes "Smartphone" hat einen Duo Core Prozessor mit mind. > 1GHz Takt, dazu 16GiB RAM. Beim RAM hast du dich wahrscheinlich um den Faktor 16 vertan. Sollte aber trotzdem kein Problem sein.
Georg schrieb: > Das hat Läubi höchstselbst als der Weisheit letzten Schluss und als > zwingenden Grund für eine Klasse propagiert: > > Läubi .. schrieb: >> Eine Geschwindigkeit hat einen Numerischen Wert und eine Einheit Er hat aber NICHT geschrieben, dass jedes Objekt die Einheit mitschleifen muss, oder? Das ist nämlich ausschließlich Deine Interpretation. ;-) Seine Aussage läßt durchaus zu, dass die Geschwindigkeits- oder auch die Temperaturklasse die Einheit implizit enthält. Grüße Markus
Markus schrieb: > Er hat aber NICHT geschrieben, dass jedes Objekt die Einheit > mitschleifen muss, oder? Das ist nämlich ausschließlich Deine > Interpretation. ;-) Seine Aussage läßt durchaus zu, dass die > Geschwindigkeits- oder auch die Temperaturklasse die Einheit implizit > enthält. Was ist dann der Unterschied zu einer Variablen? Wenn ich Variablen zum Beispiel so benenne: Battery_voltage Vehicle_velocity Converter_temperature dann dürfte wohl klar sein, dass die Einheiten nicht Sekunde, Ampere und Watt sind.
Die statische Typprüfung durch den Compiler. War das eine Fangfrage?
Jan Hansen schrieb: > Beim RAM hast du dich wahrscheinlich um den Faktor 16 vertan. Sollte > aber trotzdem kein Problem sein. Tatsache, meinte natürlich die SD Karte mit 16GiB, Ram hat es "nur" 1GiB, ist ja auch schon "alt" ;) Ansonsten finde ich es etwas schwer pro oder contra zu argumentieren wenn man den Kontext nicht kennt. OOP auf einem Mikrocontroller? Nun, der MC muss schon recht groß sein.. Assembler auf einem x86 um ein CRM zu implementieren? Nun, da muss jemandem recht langweilig sein um so ein Unterfangen zu starten.. "Einheiten", mit oder ohne? Je nachdem.. in OOP Sprachen würde ich eher mit "Ja" stimmen, als Immutable implementieren (in Java gar als Enum), dann reicht ein einziges Einheiten Objekt pro konkreter Einheit.
Ich habe spaßeshalber mal die Formel für den freien Fall
dimensionssicher in C++ unter Verwendung der Boost.Units-Bibliothek programmiert:
1 | #include <iostream> |
2 | #include <boost/units/systems/si/io.hpp> |
3 | #include <boost/units/cmath.hpp> |
4 | |
5 | using namespace std; |
6 | using namespace boost::units; |
7 | using namespace boost::units::si; |
8 | |
9 | int main(void) { |
10 | quantity<length> fallhoehe; |
11 | quantity<acceleration> erdbeschleunigung; |
12 | quantity<velocity> geschwindigkeit; |
13 | |
14 | fallhoehe = 3.00 * meter; |
15 | erdbeschleunigung = 9.81 * meter / second / second; |
16 | |
17 | geschwindigkeit = sqrt(2.0 * fallhoehe * erdbeschleunigung); |
18 | |
19 | cout << "Fallhöhe = " << fallhoehe << endl; |
20 | cout << "Erdbeschleunigung = " << erdbeschleunigung << endl; |
21 | cout << "Geschwindigkeit = " << geschwindigkeit << endl; |
22 | |
23 | return 0; |
24 | }
|
Ausgabe:
1 | Fallhöhe = 3 m |
2 | Erdbeschleunigung = 9.81 m s^-2 |
3 | Geschwindigkeit = 7.67203 m s^-1 |
Ändert man die Zeile
1 | geschwindigkeit = sqrt(2.0 * fallhoehe * erdbeschleunigung); |
in
1 | geschwindigkeit = sqrt(2.0 * fallhoehe / erdbeschleunigung); |
oder
1 | geschwindigkeit = 2.0 * fallhoehe * erdbeschleunigung; |
meckert der Compiler (wenngleich die Fehlermeldung schon etwas länglich und nicht sehr aufschlussreich ist). Auf jeden Fall lassen sich damit aber einige Fehler zur Compilezeit aufdecken, die ansonsten – wenn überhaupt – erst zur Laufzeit zutage treten würden. Da die Überprüfung komplett zur Compilezeit erfolgt, beinhalten die drei verwendeten Variablen keinerlei Information über Größe, Dimension oder Einheit. Jede von ihnen ist nur so groß wie der zugrundeliegende numerische Datentyp (in diesem Fall double). Der Speicherverbrauch kann also kein Argument gegen den Einsatz dieser Bibliothek sein. Insofern ist die Boost.Units schon eine sehr feine Sache. Das Ganze geht aber nur deswegen so leicht von der Hand, weil die Boost alle dazu benötigten Hilfsmittel bereits fertig zur Verfügung stellt. Würde man hingegen, wie hier von einigen propagiert, eigene Klassen für Weg, Geschwindigkeit und Beschleunigung schreiben, wäre das selbst in diesem primitiven Beispiel schon mit recht hohem Aufwand verbunden. In Java, das kein Operator-Overloading kennt, würde die obige Formel zudem ziemlich unleserlich werden. Ich kann mir deswegen kaum vorstellen, dass sich jemand in realen Anwendungen tatsächlich diese Mühe macht. Selbst fertige Bibliotheken, wie die Boost.Units oder die org.osgi.util.measurement, die die dimensionssichere Programmierung mit wenig Zusatzaufwand erlauben würden, scheinen von von den wenigsten Programmierern genutzt zu werden. Stattdessen werden in geschätzten 99,9% der Fälle für physikalische Größen ganz klassisch dimensionslose Doubles ohne jegliche Überprüfungsmöglichkeit durch den Compiler oder das Laufzeitsystem verwendet.
>Insofern ist die Boost.Units schon eine sehr feine Sache. Danke für den Hinweis. Yalu X. schrieb: > Selbst fertige Bibliotheken, > wie die Boost.Units [...] scheinen von von den wenigsten Programmierern genutzt zu werden. könnte an > wenngleich die Fehlermeldung schon etwas länglich > und nicht sehr aufschlussreich ist liegen. Ohne zwingenden Grund will sich niemand der Templatefehlermeldungshölle ausliefern. In der Zeit, die man braucht, um aus dem ganz simplen Beispiel im Anhang -- Dein Beispiel geändert auf das falsche v=sqrt(2*g)*h -- herauszufinden, dass irgendein Fehler in Zeile 17 ist, hat man schon einen Unittest geschrieben.
Tom schrieb: > Beispiel im Anhang -- Dein Beispiel geändert Nachtrag: Der Anhang ist für einen anderen Fehler als beschrieben, die Meldung sieht aber ziemlich gleich aus: 12kB Müll für "In Zeile 17 passen die Einheiten nicht."
Tom schrieb: > Tom schrieb: >> Beispiel im Anhang -- Dein Beispiel geändert > Nachtrag: Der Anhang ist für einen anderen Fehler als beschrieben, die > Meldung sieht aber ziemlich gleich aus: 12kB Müll für "In Zeile 17 > passen die Einheiten nicht." Zugegeben, lesbar ist das nicht. Aber wenigstens merke ich, dass in Zeile 17 ein Fehler steckt, und zwar schon während des Compilierens und nicht erst, wenn die millionenschwere Raumsonde den halben Weg zum Mars bereits hinter sich hat...
Yalu X. schrieb: > Stattdessen werden in geschätzten 99,9% der Fälle für physikalische > Größen ganz klassisch dimensionslose Doubles ohne jegliche > Überprüfungsmöglichkeit durch den Compiler oder das Laufzeitsystem > verwendet. Ich kenne da aus der beruflichen Praxis eher Integer (Stichwort Festkommaarithmetik) als Gleitkommazahlen, aber der Grundaussage stimme ich zu. Das wird sich im übrigen genau dann ändern, sobald ein solches Feature komfortabel zu benutzen ist und man nicht kryptischen Fehlermeldungen hinterherjagen muss. Solange wird es nämlich kaum jemand freiwillig nutzen wollen. Programmierer sind so. ;-) Ach ja, und der zweite Grund dafür, dass das kaum jemand macht ist dass das Projektmanagement kein Geld dafür herausrückt. Niemand wird Hunderttausende Zeilen an bestehendem und funktionierendem Code mal eben verboostisieren. Wenn man etwas von Grund auf neu entwickeln würde, dann wäre das schon eine gute Sache. Aber wie oft entwickelt man in einem realen Industrieprojekt die Dinge von Grund auf neu? Ganz genau. Meistens arbeitet man ja doch an etwas bereits Bestehendem und baut eine neue Funktionalität ein. A. H. schrieb: > Zugegeben, lesbar ist das nicht. Aber wenigstens merke ich, dass in > Zeile 17 ein Fehler steckt, und zwar schon während des Compilierens und > nicht erst, wenn die millionenschwere Raumsonde den halben Weg zum Mars > bereits hinter sich hat... Dazwischen sollten freilich noch ein paar Tests liegen. Wäre auch zu schön, wenn ein fehlerfrei kompilierendes Programm auch ein fehlerfreies wäre.
:
Bearbeitet durch User
Mark Brandis schrieb: > Dazwischen sollten freilich noch ein paar Tests liegen. Wäre auch zu > schön, wenn ein fehlerfrei kompilierendes Programm auch ein fehlerfreies > wäre. Stimmt natürlich. Mindestens genauso schön wäre es aber auch, wenn eine (vermeintlich) fehlerfrei getestetes Programm tatsächlich fehlerfrei wäre. Tests können die Fehlerfreiheit eine Programms bekanntlich auch nicht beweisen. Übrigens, wer immer noch glaubt, Einheiten seien überflüssiger Schnickschnack, der lese zum Beispiel mal hier nach: http://de.wikipedia.org/wiki/Mars_Climate_Orbiter
Mark Brandis schrieb: > Das wird sich im übrigen genau dann ändern, sobald ein solches Feature > komfortabel zu benutzen ist und man nicht kryptischen Fehlermeldungen > hinterherjagen muss. Solange wird es nämlich kaum jemand freiwillig > nutzen wollen. Programmierer sind so. ;-) Ist es nicht eher so, dass kaum jemand die kryptischen Fehlermeldungen zu Gesicht bekommen hat, weil er sich die Boost.Units-Bibliothek gar nicht erst angeschaut hat? ;-) > Ach ja, und der zweite Grund dafür, dass das kaum jemand macht ist dass > das Projektmanagement kein Geld dafür herausrückt. Niemand wird > Hunderttausende Zeilen an bestehendem und funktionierendem Code mal eben > verboostisieren. Man muss bestehenden und funktionierenden Code nicht nachträglich verboostisieren. Da der Code ja schon getestet ist, sollte er keine groben Fehler mehr enthalten. Deswegen ist es ausreichend, in seinen Schnittstellen nach außen dimensionsbehaftete Typen zu verwenden. Noch etwas zu den kryptischen Fehlermeldungen: F# unterstützt Maßeinheiten schon in der Kernsprache, was dem Compiler ermöglicht, wesentlich aussagekräftigere Fehlermeldungen zu generieren. Hier ist das obige Beispiel in F#:
1 | [<Measure>] type m |
2 | [<Measure>] type s |
3 | |
4 | let fallhoehe = 3.00<m> |
5 | let erdbeschleunigung = 9.81<m/s^2> |
6 | |
7 | let geschwindigkeit:float<m/s> = sqrt (2.0 * fallhoehe * erdbeschleunigung) |
8 | |
9 | System.Console.WriteLine ("Fallhöhe = {0} m", fallhoehe) |
10 | System.Console.WriteLine ("Erdbeschleunigung = {0} m/s^2", erdbeschleunigung) |
11 | System.Console.WriteLine ("Geschwindigkeit = {0} m/s", geschwindigkeit) |
In Zeile 7 wird geschwindigkeit explizit als float<m/s> deklariert, wodurch der Compiler mögliche Dimensionsfehler im Ausdruck rechts des Gleichheitszeichens erkennen kann. Ändert man diese Zeile in
1 | let geschwindigkeit:float<m/s> = sqrt (2.0 * fallhoehe / erdbeschleunigung) |
meldet der Compiler
1 | test.fs(7,58): error FS0001: The unit of measure 'm/s' does not match the unit of measure 's' |
was ganz klar auf die Fehlerursache hinweist. Es ist schade, dass nur die allerwenigsten Programmiersprachen von Hause aus über solche Features verfügen. Außer in F# habe ich das nur noch in Fortress gesehen, dessen Entwicklung aber leider vor ein paar Jahren eingestellt worden zu sein scheint.
A. H. schrieb: > Übrigens, wer immer noch glaubt, Einheiten seien überflüssiger > Schnickschnack, der lese zum Beispiel mal hier nach: > > http://de.wikipedia.org/wiki/Mars_Climate_Orbiter War das nicht im Pflichtenheft drin gestanden, dass man mit den richtigen SI-Einheiten rechnen muss und nicht mit dem Ami-Quatsch? ;-)
Mark Brandis schrieb: > War das nicht im Pflichtenheft drin gestanden, dass man mit den > richtigen SI-Einheiten rechnen muss und nicht mit dem Ami-Quatsch? ;-) Die Amerikaner können sich einfach nicht vorstellen, dass es ausserhalb ihres Landes auch andere Masseinheiten gibt. Dem kann man aber mit OO auch nicht beikommen, denn dazu müsste man dort einen Tankinhalt ja mit x Gallonen definieren, wofür ein US-Ingenieur aber garkeinen Grund sieht, weil man das ja immer in Gallonen misst. Das ist wie beim ASCII-Code: mehr Buchstaben als A..Z braucht niemand. Die spinnen die Europäer mit ihren Umlauten. Georg
A. H. schrieb: > der lese zum Beispiel mal hier nach: > > http://de.wikipedia.org/wiki/Mars_Climate_Orbiter Nachtrag: wenn erst das TTIP-Abkommen in Kraft ist, verklagt man die Europäer einfach auf Schadensersatz wegen Verwendung der SI-Einheiten. Georg
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.