Laden...

Klasse mit gekapselten Variablen in XML serialisieren - Programmierstil

Erstellt von EyeTrackJack vor 5 Jahren Letzter Beitrag vor 5 Jahren 1.733 Views
E
EyeTrackJack Themenstarter:in
35 Beiträge seit 2019
vor 5 Jahren
Klasse mit gekapselten Variablen in XML serialisieren - Programmierstil

Hallo,

ich möchte gerne eine Klasse definieren, die die Parameter für eine Schaltfläche enthält, die mit einem Eyetracker betätigt wird. Da soll gespeichert werden: Farbe, Position, ein Tastaturcode, der gesendet wird, den Namen der Schaltfläche etc.

Das ganze soll dann in XML serialisierbar sein, damit ich diese Einstellungen leicht lesen und schreiben kann. Aber im Widerspruch steht, dass man doch Variablen kapseln soll.

Wie löse ich das? Verzichte ich in dem Fall auf die Kapselung und deklariere die Variablen als Public? Oder was ist der richtige Weg?

Grüße

Tobias K

T
156 Beiträge seit 2010
vor 5 Jahren

Hi,

Du könntest einen Custom-Serializer/ Deserializer erstellen, der dann aus privaten Feldern die Daten in die XML schreibt bzw. aus dieser in die privaten Felder schreibt.

Gruß, Marko

E
EyeTrackJack Themenstarter:in
35 Beiträge seit 2019
vor 5 Jahren

Hi,

Ich habe auch schon daran gedacht, aber ich möchte vermeiden, mich da um jeden Parameter einzeln kümmern zu müssen. Würde schon gerne einfach alles auf einen Schlag serialisieren.

Heißt das, dass der korrekte Weg nur über eine vollständige Kapselung läuft, auch wenn das viel mehr Arbeit ist? Weil mein Weg in einem anderen Programm gut funktioniert hat. Mein Ziel besteht aber schon darin, den korrekten Weg zu können.

Grüße

Tobias

4.931 Beiträge seit 2008
vor 5 Jahren

Benutze doch Eigenschaften (properties) dafür:


public string Name { get; set; }

Und wenn du dafür eine eigene (Daten-)Klasse erstellst, dann hast du ja Kapselung erreicht.

T
2.219 Beiträge seit 2008
vor 5 Jahren

@trashkid2000
Sowas macht man nicht.
Dafür gibt es, wie Th69 schon sagt, einfach Eigenschaften.
Diese stellen dann die öffentlichen Felder zum De-/Serailisieren dar.

@EyeTrackJack
Zum De-/Serialisieren von/nach XML gibt es in C# fertige Lösungen.
Im Link findest du dazu eine gute Einleitung.

Link:
https://docs.microsoft.com/de-de/dotnet/standard/serialization/introducing-xml-serialization

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

E
EyeTrackJack Themenstarter:in
35 Beiträge seit 2019
vor 5 Jahren

Danke für die Antworten. Dann werde ich mit den Eigenschaften arbeiten.

Wobei sich für mich beides etwa gleich anfühlt:


public int Feld1{ get; set; } = 100;
public int Feld2 = 100;

Wegen dem Verständnis frage ich mal so platt, wieso ist das eine besser?

Grüße

Tobias

T
156 Beiträge seit 2010
vor 5 Jahren

@trashkid2000
Sowas macht man nicht.
Dafür gibt es, wie Th69 schon sagt, einfach Eigenschaften.

Die dann aber auch public get set sein müssen...
Deswegen lasse ich es nicht so einfach stehen.
Und ja, manchmal ist für Sicherheit auch (viel) Mehraufwand nötig.

16.806 Beiträge seit 2008
vor 5 Jahren

Deswegen lasse ich es nicht so einfach stehen.

Trotzdem hat T-Virus Recht: dafür gibt es Eigenschaften.
Ein Custom Serializer ist der vollkommen falsche Weg.

Das Grundproblem ist, dass hier offensichtlich der Beschreibung nach keine Schichtentrennung erfolgt.
Es werden also Klassen zum Speichern verwendet, die UI- oder Businessmodelle darstellen. Eine Klasse, die nur für das Speichern und Lesen verwendet wird, hat i.d.R. keine Felder - sondern nur Eigenschaften.
[Artikel] Drei-Schichten-Architektur
Die Frage würde sich also bei einem saubererem Software Design nicht stellen.

Und private Elemente zu serialisieren gehört nicht nur zum Code Smell sondern ist Bad Practise. Sinnvoll nur in absoluten Ausnahmefällen 😉

Wegen dem Verständnis frage ich mal so platt, wieso ist das eine besser?

Ein Grundgedanke von OOP ist, dass die interne Umsetzung einer Klasse von Aussen nicht ersichtlich sein soll.
Das kannst Du mit einer Eigenschaft erreichen, aber nicht mit einem Feld.

Ein Feld ist nur ein "dummes" Klassenmember; also eine Variable.
Eigenschaften sind jedoch Abstraktionen; Du kannst beim Setzen (oder Lesen) noch zusätzliche Dinge tun (zB Lazy Loading, Events feuern..) - was bei einem Feld nicht geht.

Wenn Dir das alles neu ist, dann lohnt sich mind. 1 Tag Investition in die Doku ungemein Eigenschaften (C#-Programmierhandbuch)
Und zur Korrektur:

public int Eigenschaft { get; set; } = 100;
public int Feld = 100;
T
156 Beiträge seit 2010
vor 5 Jahren

Wenn Du **Json.NET **benutzt,
gibt es da noch die Möglichkeit von private Setters:


[JsonProperty]
public Guid? ClientId { get; private set; }

Nur mal so als Anregung 🙂

// Edit: jaa...
XML und kein JSON... passt dann gar nicht

T
156 Beiträge seit 2010
vor 5 Jahren

Sorry,
@Abt

Das Grundproblem ist, dass hier offensichtlich der Beschreibung nach keine Schichtentrennung erfolgt.
Es werden also Klassen zum Speichern verwendet, die UI- oder Businessmodelle darstellen.

Bzw. Businesslogik enthalten. Ja, da gebe ich Dir Recht. Das ist nicht gut.
Die DataModel-Schicht (Infrastructure, oder wie auch immer) soll also nur dumm sein. Und Daten halten.
Und im besten Fall die Daten nicht einfach von "außen" modifizierbar machen.

Ein Feld ist nur ein "dummes" Klassenmember; also eine Variable.
Eigenschaften sind jedoch Abstraktionen; Du kannst beim Setzen (oder Lesen) noch zusätzliche Dinge tun (zB Lazy Loading, Events feuern..) - was bei einem Feld nicht geht.

Das beißt sich meiner Meinung nach mit Schichtentrennung und dumme Datenklasse 😉

T
461 Beiträge seit 2013
vor 5 Jahren

Ein Feld ist nur ein "dummes" Klassenmember; also eine Variable.
Eigenschaften sind jedoch Abstraktionen; Du kannst beim Setzen (oder Lesen) noch zusätzliche Dinge tun (zB Lazy Loading, Events feuern..) - was bei einem Feld nicht geht.
Das beißt sich meiner Meinung nach mit Schichtentrennung und dumme Datenklasse 😉

Das sehe ich nicht so.

Ist klar, C# erlaubt dir soweit alles in der Richtung, nur hängt es vom Programmierer ab, ob er sich an gewisse Regeln hält und somit ein stabiles sicheres System zu erstellen.

Klar kannst du das alles machen und noch mehr, nur ist es weit von einer sauberen Lösung entfernt.

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

16.806 Beiträge seit 2008
vor 5 Jahren

gibt es da noch die Möglichkeit von private Setters:

Hab gewartet (und ein bisschen gewusst), dass das kommt - kenne natürlich auch Json.NET sehr gut.. 😃
.. und weil jetzt eine Bibliothek das unterstützt, gilt das als allgemein okay? Leider nicht.
Auch in Json.NET ist dies ein Workaround, um bestimmte Szenarien zu supporten - aber sicher keine allgemeine Empfehlung!

Das Gegenteil ist sogar der Fall: die meisten Serializer unterstützen keine Felder; vor allem keine privaten; sondern nur public Properties.

Und im besten Fall die Daten nicht einfach von "außen" modifizierbar machen.

.. was mit einer Eigenschaft funktioniert - aber nicht mit einem Feld.

Sorry,
Das beißt sich meiner Meinung nach mit Schichtentrennung und dumme Datenklasse 😉

Respektiere ich; verweise Dich an der Stelle dann doch mal in Richtung einem Software Design Buch 😉

C# ist Sprache, die durchaus für Enterprise und profesionellen Einsatz gedacht ist.
Daher ist sie natürlich entsprechend flexibel - was aber die Gefahr birgt gewisse Dinge falsch einzusetzen; wie nun hier.

T
2.219 Beiträge seit 2008
vor 5 Jahren

@trashkid2000
ThomasE. und Abts Aussagen halte ich hier schon für richtig und gewichtet.
Gerade wenn du dich beim Thema API Design und auch generell mit Software Architekturen befasst, wirst du schnell merken, dass solche Lösung alles andere als sauber und sogar bei falscher Anwendung auch Gefahren bergen.

Mal von den grundsätzlichen Vertoß gegen saubere OOP abgesehen, kannst du dir mit solchen Winkellösungen schnell ins Knie schießen.
Zusätzlich zu dem Mehraufwand auf deiner Seite um solch einen De-/Serialisierer umzusetzen bekommst du auch Probleme wenn du dann entscheiden musst welche privaten Felder nun serialisiert werden dürfen und welche nicht.

Genau dies kann man bei Eigenschaften schon durch normales Klassen Design mit öffentlichen und privaten Eigenschaften lösen ohne Sonderlösungen zu benötigen.
Und genau auf solche simplen Designentscheidungen achten alle gängigen De-/Serialisierer.
Hier reden wir schon von Grundsätzen die man hier einfach erwarten muss.

Es ist dir natürlich überlassen solche Lösungen umzusetzen.
Aber gerade als Entwickler der täglich mit unterschiedlichen APIs und auch Software Architekturen samt deren Umsetzungen/Anpassung zu tun hat, würde ich einen großen Bogen um solche Lösungen machen.

Das kann man nach mehr als 10 Jahren Erfahrung dann nicht mehr guten Gewissens machen.
Dafür gibt es einfach saubere und vorallem durchdachte Lösungen.
Hier wieder das Rad neu zu erfinden um es wieder einmal runder zu machen zeugt meistens von mangelhafter Erfahrung was generelle und grundsätzliche Lösungswege angeht.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

T
156 Beiträge seit 2010
vor 5 Jahren

Hier wieder das Rad neu zu erfinden um es wieder einmal runder zu machen zeugt meistens von mangelhafter Erfahrung was generelle und grundsätzliche Lösungswege angeht

natürlich 👍

Und nein, nach mehr als 10 Jahren damit vertraut keine mangelnde Erfahrung...
Vielleicht nur manchmal einfach (zu sehr) auf Sicherheit bedacht 😉