Forum: Mikrocontroller und Digitale Elektronik Variablen Benennung C++


von Anonymous U. (gastt)


Lesenswert?

Macht es Sinn die Einheit in den Variablennamen zu integrieren?

uint64_t frequency_is_1Hz;
anstatt
uint64_t frequency_is;

Oder anderes Beispiel, wo der Nutzen noch offensichtlicher wird:
uint32_t temperature_case_0C1;

Wie denkt ihr darüber?

: Bearbeitet durch User
von Dussel (Gast)


Lesenswert?

Wenn man mit Ländern mit imperialen Einheiten zusammenarbeitet sicher. 
Sonst geben die das noch in sqft*oz/psi an…
Allgemein würde ich aber in Basiseinheiten rechnen und die Einheit im 
Kommentar angeben.

von Oliver S. (oliverso)


Lesenswert?

Wenn es sinnvoll ist, ja, wenn nicht, dann nicht. Das gilt eigentlich 
für alle Variablennamen...

Wobei C++ zum Handling von solchen physikalischen Größen mit 
unterschiedlichen Einheiten benutzerdefinierte Literale bietet, die da 
sehr viel Sicherheit reinbringen. Aussagekräftige Variablennamen kann 
man dazu dann immer noch nutzen.

Oliver

von Stefan F. (Gast)


Lesenswert?

Bei einer Frequnez würde ich von Hz ausgehen, wenn nichts andere dran 
steht. bei Zeitspannen macht das eher Sinn:

duration_ms
timeout_minutes

Oder auch:

price_cent

Mir persönlich genügt es, wenn das in einem Kommentar direkt über der 
Variable bzw. Funktion (bei Parametern) dokumentiert ist.

von Wilhelm M. (wimalopaan)


Lesenswert?

Anonymous U. schrieb:
> Macht es Sinn die Einheit in den Variablennamen zu integrieren?

Nein.

Definiere Dir dafür eigene Datentypen. Es gibt genug Beispiele für die 
Modellierung physikalischer Einheiten im Netz.

von Einer K. (Gast)


Lesenswert?

Anonymous U. schrieb:
> Wie denkt ihr darüber?

Ich sage, denke und handle ....

Variablen immer klein beginnen.
KamelHöckerSchreibweise
Keine Unterstriche
Keine ungarische Notation (noch nicht mal in deiner abgeschwächten 
Version)
Geltungsbereich so weit wie irgend möglich einschränken.

Oliver S. schrieb:
> benutzerdefinierte Literale
Ja!

Beispiel(aus meiner kleinen Arduino Welt):
1
const Millis interval {25_ms};

von A. S. (Gast)


Lesenswert?

Wenn Du mehrere Formate für Frequenz hast, dann mache einen Typ daraus.

Bei nur einem wäre es dumm, da es keine Info birgt und das über den Code 
verteilt wird.

Bei mehreren wäre es unzureichend, da Du ja unterschiedliche Funktionen 
damit aufrufen musst.

von MaWin (Gast)


Lesenswert?

Anonymous U. schrieb:
> Wie denkt ihr darüber?

Beide verstehe ich nicht.

Eine Frequenz f in Hz könnte in einer Variablen namens frequency_Hz 
stecken.

Aber das frequency_is_1Hz bedeuten soll ? Ein boolscher Wert der nur 
dann tru ist wenn die Frequenz genau 1 Hz beträgt ?

Und temperature_case_0C1 soll 0C1 etwa 0,1 GradC bedeuten ? Wenn man die 
Temperatur mit Nachkommastellen erfasst, dann

temp_Zehntelgrad oder temp_tenthsofadegreecelsius

Also im Prinzip sinnvoll, aber eindeutiger gewählte Namen sonst weiss es 
der andere Leser doch wieder nicht.

von Zehpluplus (Gast)


Lesenswert?

Hier mal wie das aussehen könnte:
1
using Frequency = uint64_t;
2
3
Frequency operator "" _Hz(unsigned long long int val)
4
{
5
    return val;
6
}
7
8
Frequency operator "" _kHz(unsigned long long int val)
9
{
10
    return val * 1000;
11
}
12
13
Frequency freq1 = 1_Hz;
14
Frequency freq2 = 23_kHz;

Dokumentiert sich quasi selber der Code.

von Wilhelm M. (wimalopaan)


Lesenswert?

Zehpluplus schrieb:
> Hier mal wie das aussehen könnte:
>
>
1
> using Frequency = uint64_t;
2
> 
3
> Frequency operator "" _Hz(unsigned long long int val)
4
> {
5
>     return val;
6
> }
7
> 
8
> Frequency operator "" _kHz(unsigned long long int val)
9
> {
10
>     return val * 1000;
11
> }
12
> 
13
> Frequency freq1 = 1_Hz;
14
> Frequency freq2 = 23_kHz;
15
>
>
> Dokumentiert sich quasi selber der Code.

So macht man das sicher nicht: ein einfacher alias reicht nicht.

schlechte Fortsetzung:
1
using Bla = uint64_t;
2
    Frequency freq1 = 1_Hz;
3
    Frequency freq2 = 23_kHz;
4
5
    Bla b = 23_kHz; // Ups
6
    
7
    auto x = b * freq1; // What?
8
}

von Wilhelm M. (wimalopaan)


Lesenswert?

Wilhelm M. schrieb:
> Anonymous U. schrieb:
>> Macht es Sinn die Einheit in den Variablennamen zu integrieren?
>
> Nein.
>
> Definiere Dir dafür eigene Datentypen. Es gibt genug Beispiele für die
> Modellierung physikalischer Einheiten im Netz.

Ich bin ja erstaunt, dass ich hier nicht mit negativen Kommentaren 
beworfen worden bin. Habe ich doch vor ca. 3-4 Jahren noch dafür 
tiefsten Spott erhalten. Manche Dinge scheinen sich ja so langsam 
einzuschleifen ...

von TR.0LL (Gast)


Lesenswert?

Wilhelm M. schrieb:
> So macht man das sicher nicht: ein einfacher alias reicht nicht.

Hier ist ein besseres Bespiel:
https://www.geeksforgeeks.org/user-defined-data-types-in-c/

von Oliver S. (oliverso)


Lesenswert?

Für jemanden, der da weder in noch up signen will, ist der Link nutzlos.

Macht aber nichts, wer will, findet beliebig andere, die frei zugänglich 
sind.

Oliver
Edit: im zweiten Anlauf geht es. Aber trotzdem:
https://en.cppreference.com/w/cpp/language/user_literal

: Bearbeitet durch User
von Theor (Gast)


Lesenswert?

@ Anonymous U.

Ich denke, Deine eigenen Ansichten sind da der Maßstab. Falls Du Dir in 
einem konkreten Projekt Fälle vorstellen kannst, in denen Dir das von 
Nutzen ist, mach es so.

von TR.0LL (Gast)


Lesenswert?

Oliver S. schrieb:
> Für jemanden, der da weder in noch up signen will, ist der Link nutzlos.

Ich muss mich dort nicht Anmelden. Blockiere mal JS auf der Webseite 
(z.B.: mit uMatrix, NoScript).

von P. S. (namnyef)


Lesenswert?

Würde ich nicht machen. Das macht den Code wahnsinnig unleserlich.

Einfach beim Anmelden der Variablen bzw. bei der Definition des 
Datentyps per Kommentar das dokumentieren, was man wissen muss. In einem 
Kommentar hat man den Platz dafür und eben einen Ort wo man nachschauen 
kann. Das reicht völlig. Eine Variable muss mir nicht an jeder Stelle im 
Code, wo Sie steht, ihre Einheit im Namen entgegen plärren. Das ist 
redundante Information. Und je nach Variable bzw. Anwendung sind Dinge 
wie die physikalische Einheit, Wert eines LSB, Wertebereich, 
Vorzeichenkonvention, etc. von Interesse. Das kann man u. U. unmöglich 
alles sinnvoll in einen Variablennamen packen.

Jetzt mal von eher ausgefallenen Einheiten ganz zu schweigen... Mir 
fällt jetzt spontan nur "nV/sqrt(Hz)" ein, aber ich denke es ist klar 
was ich meine.

: Bearbeitet durch User
von Teo D. (teoderix)


Lesenswert?

MaWin schrieb:
> Aber das frequency_is_1Hz bedeuten soll ? Ein boolscher Wert der nur
> dann tru ist wenn die Frequenz genau 1 Hz beträgt ?

Sowas gibts bei mir nur als Makros und da machts auch Sinn.
frequency_Hz das gibts bei mir gern in Variablen.

von A. S. (Gast)


Lesenswert?

Ein 50 Jahre altes Zitat, mit dem Dimensionen/Einheiten aus 
Programmiersprachen herausgehalten wurden:

"“Numbers as invented by mathematicians are abstract and beautiful. This 
should not be spoiled by engineers".

von PittyJ (Gast)


Lesenswert?

Ich benutze meistens SI-Einheiten, dann ist klar, was z.B. unter 
BusSpannung gespeichert wird.
Muss ich die allerdings anders abspeichern, weil z.B Millivolt und 
Megahertz gespeichert werden, dann gebe ich die Einheit auch bei den 
Variablennamen an:
BusSpannungmV
CpuFrequenzMhz

Das kennzeichnet dann, dass die Einheit nicht die 'normale' Si-Einheit 
ist.

Damit lebe ich seit mehreren Jahren ganz gut.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Wenn irgendwie möglich, wähle ich als Einheit für Variablen immer die
entsprechende kohärente SI-Einheit. Dies muss dann genau einmal für ein
ein gesamtes Softwareprojekt als kurzer Vermerk dokumentiert werden. Bei
Verwendung von FP-Datentypen geht das praktisch immer.

Verwendet man aus Effizienzgründen Integertypen, möchte man oft die
Zahlenwerte skalieren, um entweder die Auflösung oder den Wertebereich
zu vergrößern. Da versuche ich dann, mit möglichst wenigen verschiedenen
Skalierungsfaktoren auszukommen, idealerweise mit maximal zwei pro
physikalischer Größe und Programmmodul (Bibliothek, Übersetzungseinheit
oder Klasse): Einen für das API und optional einen davon abweichenden
für die interne Darstellung. Beides wird an zentraler Stelle für das
jeweilige Modul dokumentiert.

Eine Dokumentation des Skalierungsfaktors für jede Einzelvariable ist
damit nicht erforderlich.

Nur in Ausnahmefällen, wo aus triftigen Gründen der Skalierungsfaktor
einer Variable von der programm- oder modulweit festgelegten Vorgabe
abweichen muss, dokumentiere ich diesen Umstand gesondert für die
entsprechende Variable, bspw. im Kommentar bei der Deklaration. Das es
sich hier um einen Ausnahmefall handelt, der besonderes Augenmerk
verdient, kann es aber auch sinnvoll sein, dem Variablennamen einen
entsprechenden Suffix anzuhängen, bspw. "duration_ms", "delay_ticks",
"distance_100m" oder "angle_2piDiv256". Der Unterstrich ist dabei als
"in" zu lesen.

Die Verwendung von benutzerdefinierten Literalen und größenspezifischen
Datentypen (bspw. Boost.Units) kann bei komplexen physikalischen
Berechnungen bei der Fehlervermeidung hilfreich sein, ist aber ein
Thema, das nur indirekt mit der Fragestellung des TE zu tun hat.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Man kann sich von std::chrono inspirieren lassen:

https://en.cppreference.com/w/cpp/header/chrono

Dort gibt es Datentypen wie std::chrono::nanoseconds und user-defined 
literale wie  operator""ns . Durch die Kodierung der Einheit im Datentyp 
vermeidet man Fehler und kann die Daten auch generisch verarbeiten.

Wie man es nicht macht kann man sich bei FreeType2 anschauen:

https://www.freetype.org/freetype2/docs/reference/ft2-basic_types.html#ft_pos

Es ist entweder "integer font units, or 16.16, or 26.6 fixed-point pixel 
coordinates". Statt FT_Pos16_16, FT_Pos26_6 und FT_PosFontUnit o.ä. zu 
definieren darf man raten was es jeweils ist.

von mh (Gast)


Lesenswert?

Niklas G. schrieb:
> Man kann sich von std::chrono inspirieren lassen:
>
> https://en.cppreference.com/w/cpp/header/chrono
>
> Dort gibt es Datentypen wie std::chrono::nanoseconds und user-defined
> literale wie  operator""ns . Durch die Kodierung der Einheit im Datentyp
> vermeidet man Fehler und kann die Daten auch generisch verarbeiten.

std::chrono ist nicht gerade das beste Beispiel.

Es gibt:
1
std::chrono::nanoseconds
2
std::chrono::microseconds
3
std::chrono::milliseconds
4
std::chrono::seconds
5
std::chrono::minutes
6
std::chrono::hours
7
std::chrono::days
8
std::chrono::weeks
9
std::chrono::months
10
std::chrono::years
als Alias für bestimmte std::chrono::duration Typen und es gibt
1
operator""ns
2
operator""us
3
operator""ms
4
operator""s
5
operator""min
6
operator""h
7
operator""d
8
operator""y
als Literals. Wer genauer hinschaut, wird feststellen, dass kein Literal 
für den Monat gibt. Und wer nachschaut, was diese Literale genau für 
einen Typ erzeugen, wird feststellen, dass die ersten 6 die 
entsprechenden std::chrono::duration Typen liefern. Die d und y Literale 
liefern die Typen std::chrono::day und std::chrono::year Typen, die 
nichts mit std::chrono::duration zu tun haben.

Interessant sind auch die Datentypen von t1 und t2.
1
auto t1 = 12s / 3;
2
auto t2 = 12m / 3;

Dann bleibt noch die Frage, welchen namespace man braucht, um die 
Literals zu nutzen? std::literals, std::chrono, 
std::literals::chrono_literals oder 
std::chrono::literals::std_chrono_literals?

Und wer etwas anderes als den "proleptic Gregorian calendar" (oder Jahre 
die außerhalb von ±2^15] liegen) benötigt, ist mit std::chrono eh 
verloren.

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