Ich wollte mal kurze Frage zum Design des Codens stellen. Da gibt es eine Funktion, die Daten schickt, wenn sie ausgeführt wird. Jetzt möchte ich dazu programmieren, dass die Daten nur geschickt werden, wenn sie sich auch wirklich geändert haben. Mache ich die if-Bedingung dann direkt in die Funktion rein oder führe ich sie in diesem Fall nur bedingt aus, sodass die if klar ersichtlich ist. Was ist der gängige Programmierstil?
Fragender schrieb: > Mache ich die if-Bedingung dann direkt in die Funktion rein oder führe > ich sie in diesem Fall nur bedingt aus, sodass die if klar ersichtlich > ist. Das kommt darauf an. Wie heißt die Funktion, was gibt sie vor zu tun, wie ist sie dokumentiert, was würde der Leser spontan erwarten wenn er das sieht, wie verhalten sich ähnliche Funktionen in anderen Teilen deines Codes, ist es naheliegend es so zu tun, wird es einfacher lesbar, führt es insgesamt zu weniger code?
Fragender schrieb: > Was ist der gängige Programmierstil? Egal, in welcher Progarmmiersprache, die Antwort auf solche Fragen ist immer 42. Oliver
Fragender schrieb: > .... > Da gibt es eine Funktion, die Daten schickt, wenn sie ausgeführt wird. > Jetzt möchte ich dazu programmieren, dass die Daten nur geschickt > werden, wenn sie sich auch wirklich geändert haben. > Mache ich die if-Bedingung dann direkt in die Funktion rein oder führe > ich sie in diesem Fall nur bedingt aus, sodass die if klar ersichtlich > ist. > Was ist der gängige Programmierstil? Mit anderen Worten: Du willst die function aufrufen und dann in der function prüfen ob sie was machen soll? Ruf die function dann auf, wenn Du sicher bist dass Du sie brauchst!
Sorry, ich bin kein fernsehgucker. Musste erst Wikipedia fragen, was 42 bedeutet. Kryptisches mit Kryptischem erklären? Hilft das?
wenn nur bei Änderung gesendet wird macht das Initialisierungen und Diagnosen schwer. i.d.R gibt es dann eine mindeste und einen maximale Updaterate. Was es immer geben sollte ist ein aussagekräftiger Betreff
Wenn es Dir irgendwie falsch vorkommt dann ist es wahrscheinlich falsch. Oder falsch dokumentiert. Oder falsch benannt. Scheib es so hin daß es offensichtlich wird und sich richtig anfühlt.
Wenn die Funktion in etwa "writeData()" heißt, würde ich als Außenstehender erwarten, dass die Daten immer geschrieben werden, sobald ich die Funktion aufrufe. "updateData()" oder "writeNewData()" klingen für mich eher so, dass nur geänderte Daten geschrieben werden. Je, nachdem, wie oft welcher Fall benötigt wird (alle Daten schreiben oder nur Neue) könnte man der writeData() eine Wrapper-Funktion schreiben, die dann eben writeData() nur aufruft, wenn neue Daten da sind. Was natürlich wieder Sprünge und Zeit braucht. Insgesamt ist es nicht festgelegt, wie man es umsetzt. Es sollte nur für andere ersichtlich sein, was eine Funktion tut.
Fragender schrieb: > Was ist der gängige Programmierstil? Je nach Komplexität kannst Du da auch 3 Funktionen draus machen: - Eine die Sendet - Eine die Daten vergleicht - und eine, die Daten vergleicht und Kopie / Hash der Daten erstellt und sendet.
Fragender schrieb: > Was ist der gängige Programmierstil? Als Gelegenheitsprogrammierer hat das imo mit Stil wenig zu tun sondern mit Funktion. Meiner einer bildet in der Software die Funktion ab (soweit möglich). Wenn das "nichtsenden" zum senden gehört (z.B. zum Stromsparen) mache ich es da, gehört es zu den Daten (Gegenseite erwartet nur geänderte Daten) prüfe ich da. Man kann natürlich auch eine extra Funktion schreiben und danach bedingt aufrufen. Das würde ich machen wenn es wichtig wäre und auffallen soll.
Ja, Je nach verwendeter Struktur (ist es ein µC oder eine PC-Anwendung oder die Steuerung eines Flugzeuges) gibt es halt mehrere Kriterien an Hand derer du deine Auswahl treffen kannst. Wenn das schreiben (oder Daten speichern...) zB innerhalb einer Interrupt Routine läuft, macht es Sinn das kontrollieren außerhalb und als eigene Funktion zu beschreiben. etc. [beliebeige Beispiele] In den meisten Anwendungen würde ich in der Konfiguration einen Flag setzen um diese Optimierung ein/ausschalten zu können (Testen / Fehlersuche) und bei Aktivierung das letzte gesendete Datenpaket immer im Speicher mit dem neuen Vergleichen vor jedem senden.
ausserdem schrieb: > Sorry, ich bin kein fernsehgucker. Musste erst Wikipedia fragen, was 42 > bedeutet. Kryptisches mit Kryptischem erklären? Hilft das? Zur 42: https://de.wikipedia.org/wiki/Per_Anhalter_durch_die_Galaxis Was dir der Schreiber damit sagen wollte: Ohne ein paar Code-Schnipsel ist es sehr schwer, darauf eine Antwort zu geben. Warum schreibst du den Code nicht so hin, wie du denkst und fragst uns dann hier um unsere Meinung? Wäre einfacher. merciless
Ich denke du suchst sowas in der Art:
1 | /* Hold the data that was sent the last time to check if it has been sent before */
|
2 | uint8 myLocalData[128]; |
3 | |
4 | /* Function that sends data only if it differs from data sent in the previous call */
|
5 | bool sendDataOnChange(uint8* data, uint16 length) |
6 | {
|
7 | bool returnValue = false; |
8 | |
9 | /* First check for valid input data before processing input data */
|
10 | if (data != NULL && length > 0) |
11 | {
|
12 | /* Check that our buffer is not compromized */
|
13 | if(&myLocalData[0] != NULL) |
14 | {
|
15 | /* Perform compare of the data sent the last time with the data requested to send */
|
16 | bool compare = memcmp( (void*)data, (void*)&myLocalData[0], length); |
17 | |
18 | if (0 != compare) |
19 | {
|
20 | /* In case the data differs, copy the requested data into our local buffer and sent the data */
|
21 | memcpy((void*)&myLocalData[0],(void*)data,length); |
22 | returnValue = sendData((void*)&myLocalData[0], length); |
23 | }
|
24 | else
|
25 | {
|
26 | /* Data already sent */
|
27 | returnValue = true; |
28 | }
|
29 | }
|
30 | }
|
31 | else
|
32 | {
|
33 | /* Invalid data passed to the function */
|
34 | returnValue = false; |
35 | }
|
36 | |
37 | return returnValue; |
38 | }
|
39 | |
40 | bool sendData(uint8* data, uint16 length) |
41 | {
|
42 | if (data != NULL && length > 0) |
43 | {
|
44 | /* Send data to a lower software module which performs the actual sending of data. */
|
45 | }
|
46 | [...]
|
47 | }
|
BTW: Wenn du eine Frage so hineinwirfst, kommen ganz viele Trolle und machen dir den Thread kaputt. Wenn das Beispiel dir hilft, liegt es daran, dass ich deine Frage richtig interpretiert habe und nicht weil du sie gut beschrieben hast. Ach und wenn jemand mit "Kommt drauf an" antwortet, brauchst du gar nicht erst weiterlesen. Diese Leute erwarten eine vollständige Spezifikation bevor sie sich herablassen eine Antwort zu geben. Wenn man allerdings alles im Detail spezifizieren kann, braucht man eine Antwort in der Regel auch nicht mehr. Solche Leute werden dann als erstes von Softwareentwicklern aus Low-Cost Ländern ersetzt. In meinen Augen dann auch kein Verlust. Ein guter Ingenieur hat soviel Erfahrung, dass er vor allem fehlerhaft oder lückenhafte Spezifikationen von sich aus füllen/berichtigen kann und dann sein Lösungsvorschlag mit dem Auftraggeber zusammen gegen seine Erwartungen evalutiert. Mit den Worten zum Donnerstag ein G4st PS: Kannst du kurz Feedback geben ob dir das Beispiel geholfen hat?
ausserdem schrieb: > Sorry, ich bin kein fernsehgucker. Musste erst Wikipedia fragen, was 42 > bedeutet. Kryptisches mit Kryptischem erklären? Hilft das? Jeder weiss, was 42 bedeutet. Das gehört zum Grundwissen und wird typischerweise von den Eltern vermittelt. Es sei denn, die kommen aus Bielefeld.
42 - die Antwort auf die Frage der Fragen : Was ist der Sinn von Allem. Siehe : "Hitchhiker guide through the galaxis", oder so Stellt die ultimaive Antwort auf fast alle Fragen dar. Die Frage der Fragen wurde dann anders gestellt. Die Frager im Buch haben dann die Erde gebaut und der Prozess zur Beantwortung laeuft immer noch.
Beitrag #5762258 wurde von einem Moderator gelöscht.
G4st schrieb: > Ach und wenn jemand mit "Kommt drauf an" antwortet, brauchst du gar > nicht erst weiterlesen. Diese Leute erwarten eine vollständige > Spezifikation bevor sie sich herablassen eine Antwort zu geben. Wenn man > allerdings alles im Detail spezifizieren kann, braucht man eine Antwort > in der Regel auch nicht mehr. Wenn ich jetzt frage, was ich für mein Auto tanken muss, ist, denke ich, die Aussage durchaus berechtigt, dass es auf mein Auto ankommt, dass ich habe. Die Randbedingungen zum Problem zu benennen ist niemals falsch und ja, oft ergibt sich die Lösung aus den Randbedingungen ganz von alleine. Der Spruch, dass es hilfreich sei, mal einen Schritt zurück zu machen und das ganze Bild zu betrachten, kommt nicht von ungefähr ;)
Also ich verstehe das so: 1) Es gibt Daten 2) Daten werden geändert 3) ??? 4) Geänderte Daten werden gesendet Wichtig wäre nun, wann und wohin werden die Daten gesendet? Fragt jemand nach Änderungen? Oder ist jemand dauerhaft verbunden, und in regelmässigen Abständen werden die Daten gesendet? Die Struktur und das Format der Daten ist auch wichtig. Und je nach Programmiersprache sind unterschiedliche Pattern einfacher umzusetzen. Zunächst muss herausgefunden werden, ob die Daten geändert wurden. Dann ist noch die Frage, ob man das erste mal alle Daten braucht, oder ob man bestimmte Daten Subscriben kann und man nur die dann braucht, oder ob man die am Anfang manuell holt, etc. Was sicher nötig ist, wäre eine Datenstruktur, z.B. eine Liste, aller Objekte, dessen Änderungen gesendet werden sollen. Bei einem subscriber Modell kann man das pro subscriber machen. Wenn alle alle beobachten kann man das auch global machen. Oder wenn es sonstige Kriterien je nach client gibt, kann man das zusammen mit den Infos über den Clienten speichern. Je nach Anwendungsfall können auch andere Strukturen sinn machen. z.B. Bäume bei verschachtelten GUI Elementen, etc. Ich denke das Erkennen geänderter Daten gibt es 6 wichtige Varianten, die mir spontan in den Sinn kommen: 1) Es gibt einen callback, der bei jeder Änderung sofort ausgeführt wird. Man hat dann z.B. immer einen Setter dafür. Oder man verwendet Transaktionen. 2) Dein Objekt mit den Daten, oder ein wrapper Objekt, hat ein flag, ob es geändert wurde. Von zeit zu zeit geht man alle einmal durch, sendet es an alle, und resettet das flag. 3) Jedes Objekt hat ein Hash. Der Client sendet alle seine Hashs, und der Server sendet alle Objekte, wo dieser nicht mehr übereinstimmt. Kann je nachdem etwas ineffizient sein, dafür wird so geprüft, dass tatsächlich eine Änderung vorliegt, und man muss keine sonstigen state Informationen synchron halten. Das ist super für Caches geeignet, und wird so bei HTTP E-Tags gemacht. Aber achtung, es kann zu hash collisions kommen. 4) Jedes Objekt hat einen Änderungstimestamp + einen counter. Bei jeder Änderung wird ein globaler counter erhöht, und der counter des Objekts darauf gesetzt, falls der Timestamp unverändert ist. Andernfalls wird der Timestamp des Objekts gesetzt, und der object counter sowie der globale counter auf 1 gesetzt. Der Client sendet nach dem Verbindungsaufbau den höchsten Timestamp + counter den er in seinen Objekten finden kann. Der server sendet dann alle Objekte, wo timestamp_client < timestamp_objekt || ( timestamp_client == timestamp_objekt && counter_client < counter_objekt ), sortiert so, dass das kleinste (timestamp, counter) paar zuerst kommt. Man könnte den Timestamp auch weglassen, und den server counter immer noch irgendwo persistieren. 5) Bei änderungen wird das Objekt an das ende einer Sendequeue angehängt. Oder nur dessen serialisierte daten. 6) Ne Kombination der anderen Optionen. Was ich jetzt oben noch nicht behandle, ist das Löschen von Objekten. Bei speziellen Formaten, wie z.B. Video Frames, muss man aber komplett anders vorgehen. Da kann man z.B. Bilder substrahieren, jpeg kommpressionsartige dinge machen, Translationsmatrizen berechnen, etc. Und dann kann man das immer noch auf viele weisen Implementieren. Auf jeden Fall muss man die Daten vor dem Senden noch irgendwie serialisieren. Idealerweise abstrahiert man dass noch irgendwie. Bei JavaScript reicht häufig ein JSON.stringify, bzw. in PHP ein JSON_encode. In C++ gibt es Templatemagie. In C kann man z.B. den Typ als enum mit speichern, und dann ne lookup Tabelle für Serialisierungsfunktionen usw. machen. etc. Eventuell nimmt man dafür auch ein Framework. Die Prüfung selbst macht man dann da, wo dies am einfachsten und möglichst einheitlich geht. Noch was zum Schluss: Versuche immer zusammenhängende Daten (Verbindungsspezifische Daten eines Clienten, Daten einer Serverinstanz, etc.) in je eine Datenstruktur zu packen. Sowas in globalen Variablen unübersichtlich herumschwirren zu haben, kann schnell zum Albtraum werden.
Fragender schrieb: > Ich wollte mal kurze Frage zum Design des Codens stellen. "Design des Codens" ... aua! > Da gibt es eine Funktion, die Daten schickt, wenn sie ausgeführt wird. Ähm. Die "Daten die eine Funktion schickt, wenn sie ausgeführt wird", nennt man üblicherweise Returnwert oder - wenn man zwanghaft eindeutscht - Rückgabewert. Und der Typ des Rückgabewerts ist fest. Er ist ein Teil der Funktions→Signatur, ebenso wie der Funktionsname. > Jetzt möchte ich dazu programmieren, dass die Daten nur geschickt > werden, wenn sie sich auch wirklich geändert haben. Eine Funktion kann nicht "nichts" zurückgeben. Wenn der Rückgabewert z.B. vom Typ int ist, dann muß sie einen int zurückgeben. Was du aber machen kannst: du kannst einen bestimmten Wert, z.B. 0 dahingehend festlegen, daß er "nichts geändert" bedeutet. > Mache ich die if-Bedingung dann direkt in die Funktion rein oder führe > ich sie in diesem Fall nur bedingt aus, sodass die if klar ersichtlich > ist. Man kann eine Funktion nicht "bedingt ausführen". Wenn du außerhalb der Funktion feststellen kannst, daß sich nichts geändert hat, dann brauchst du die Funktion natürlich nicht aufzurufen. Aber dann ist deine ganze Frage sinnlos. Wenn wir hingegen mal annehmen, daß die Entscheidung, ob sich etwas geändert hat, nur innerhalb der Funktion getroffen werden kann, daß mußt du die Funktion in jedem Fall aufrufen. Und brauchst dann natürlich ein if(), um auszuwerten ob die Funktion vielleicht "es hat sich nichts geändert" zurück gegeben hat. Und innerhalb der Funktion ein weiteres if(), damit sie das tut. Im Normalfall wird man diese Prüfung so früh wie möglich machen, damit man im Fall des Falles möglichst viel Code einsparen kann und die Sonderbedingung über möglichst wenige Aufrufebenen transportieren muß.
> Eine Funktion kann nicht "nichts" zurückgeben.
In C kann eine Funktion auch vom Typ "void" sein, dann gibt sie keine
Daten zurück.
Name H. schrieb: > der Prozess zur Beantwortung laeuft immer > noch. Nein. Die Erde wurde fünf Minuten vor Ablauf von den Vogonen gesprengt, um einer Hyperraumumgehungsstraße Platz zu machen.
Axel S. schrieb: >> Da gibt es eine Funktion, die Daten schickt, wenn sie ausgeführt wird. > > Ähm. Die "Daten die eine Funktion schickt, wenn sie ausgeführt wird", > nennt man üblicherweise Returnwert oder - wenn man zwanghaft > eindeutscht - Rückgabewert. Und der Typ des Rückgabewerts ist fest. Er > ist ein Teil der Funktions→Signatur, ebenso wie der Funktionsname. Ich denke eher, dass Fragender wirklich eine Funktion meint, die Daten irgendwo hinsendet. Da kann es durchaus sinnvoll sein, diese nur bei Änderung neu zu übertragen, wenn die Gegenstelle die Daten speichert.
svensson schrieb: >> Eine Funktion kann nicht "nichts" zurückgeben. > In C kann eine Funktion auch vom Typ "void" sein, dann gibt sie keine > Daten zurück. Dann gibt sie niemals irgendwas zurück. Und die Frage des TE erübrigt sich. Alex D. schrieb: > Axel S. schrieb: >> Die "Daten die eine Funktion schickt, wenn sie ausgeführt wird", >> nennt man üblicherweise Returnwert oder - wenn man zwanghaft >> eindeutscht - Rückgabewert. > > Ich denke eher, dass Fragender wirklich eine Funktion meint, die Daten > irgendwo hinsendet. Oh. DU meinst im Sinne von: "eine Funktion, die eine Ein-/Ausgabeinheit (z.B. UART) bedient, um Daten zu verschicken". Hmm, ja. So kann man das auch interpretieren. Fand ich angesichts der Wortwahl des TE jetzt nicht naheliegend. Aber auch dann gilt, was ich schrieb: > Im Normalfall wird man diese Prüfung so früh wie möglich machen, damit > man im Fall des Falles möglichst viel Code einsparen kann und die > Sonderbedingung über möglichst wenige Aufrufebenen transportieren muß.
Thomas E. schrieb: > Die Erde wurde fünf Minuten vor Ablauf von den Vogonen gesprengt, > um einer Hyperraumumgehungsstraße Platz zu machen. <Trump> So sad! </Trump>
> Dann gibt sie niemals irgendwas zurück.
Muß sie ja auch nicht, da sie Daten versendet.
Dann ist es streng genommen keine Funktion mehr, sondern eine Prozedur.
svensson schrieb: > Dann ist es streng genommen keine Funktion mehr, sondern eine Prozedur. In C gibt es keine Prozeduren.
Axel S. schrieb: > svensson schrieb: >>> Eine Funktion kann nicht "nichts" zurückgeben. >> In C kann eine Funktion auch vom Typ "void" sein, dann gibt sie keine >> Daten zurück. > > Dann gibt sie niemals irgendwas zurück. Meine Nachbarin ist dann auch eine Funktion. Die gibt auch nie wieder etwas zurück.
BabyYouCanDriveMyCar schrieb: >> Dann gibt sie niemals irgendwas zurück. > > Meine Nachbarin ist dann auch eine Funktion. Die gibt auch nie wieder > etwas zurück. Hat deine Nachbarin dann wenigstens Seiteneffekte? Hat sie irgendeine Wirkung auf Dich? Denn wenn nicht kannst Du sie ersatzlos wegoptimieren!
Schreib deine Daten in eine Variable und die lässt du dann vergleichen. wenn sich eine änderung ergibt, rufst du deine gewünschte subroutine auf.
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.