Datenkapselung

Design Patterns, Erklärungen zu Algorithmen, Optimierung, Softwarearchitektur
Forumsregeln
Wenn das Problem mit einer Programmiersprache direkt zusammenhängt, bitte HIER posten.
Antworten
Benutzeravatar
Jonathan
Establishment
Beiträge: 2374
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Datenkapselung

Beitrag von Jonathan »

Ich habe eine Objektklasse (Für allgemeine Objekte in der Spielwelt), die eine Reihe von Komponenten besitzt, welche das Objekt quasi 'definieren'. Jetzt müssen diese Komponenten aber auf das Objekt zugreifen und es verändern können. Natürlich würde ich Attribute wie die Position in der Objektklasse gerne private machen, aber dann könnten die Komponenten nicht mehr direkt darauf zugreifen. Ich würde ja gerne mit friend arbeiten, aber das wird nicht vererbt, weswegen ich sämtliche Komponenten einzeln eintragen müsste, was dann auch keinen Sinn macht.
Im Moment tendiere ich dazu, die Attribute einfach public zu machen, denn quasi leere Getter/Setter sind ja eigentlich auch nichts anderes. Aber es fühlt sich irgendwie auch "böse" an, weil es ja irgendwie ein Grundsatz ist, Attribute private zu machen. Es ist ja auch toll, wenn man z.B. die Implementierung getrennt vom Interface ändern kann, aber in meinem Fall würde das wohl nie Sinn machen, da Objekte und Komponenten ja sehr eng zusammen arbeiten müssen.
Irgendwelche Vorschläge?
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
Brainsmith
Establishment
Beiträge: 109
Registriert: 04.09.2009, 13:52
Echter Name: Fabbo

Re: Datenkapselung

Beitrag von Brainsmith »

Ich weiß ja nicht, wie du es implemetiert hast, aber kannst du den Components nicht einfach nen Pointer auf die Owner-Entity geben?? (im Konstuktor)
Benutzeravatar
Jonathan
Establishment
Beiträge: 2374
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Datenkapselung

Beitrag von Jonathan »

Ja, das mach ich ja. Aber über diesen Pointer kann man ja trotzdem nur auf öffentliche Attribute des Entity zugreifen.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Despotist
Establishment
Beiträge: 394
Registriert: 19.02.2008, 16:33

Re: Datenkapselung

Beitrag von Despotist »

Warum keine public-Methoden die die private Members in gewünschter Weise verändern?
Also statt:

Code: Alles auswählen

class test
{
public int count;
}

test.count = test.count + 1;
lieber

Code: Alles auswählen

class test
{
private int count;
public IncrementCount() {count++;}
}

test.IncrementCount();
Ist zwar mehr Schreibarbeit ist aber ordentlich gekapselt. Weiterhin kannst du in den Methoden auch komplexere Abfragen einbauen, Exceptions werfen, Log schreiben usw. und du kannst für verschiedene Zwecke verschiedene Methoden implementieren die auf demselben Member operieren. Kapselung heißt, dass sich Objekte nur selbst verändern (durch die methoden) und nicht direkt von außen verändert werden können. So kann die Konsistenz des Objektes besser gewährleistet werden.
Benutzeravatar
Brainsmith
Establishment
Beiträge: 109
Registriert: 04.09.2009, 13:52
Echter Name: Fabbo

Re: Datenkapselung

Beitrag von Brainsmith »

Entweder Set/Get-Methoden oder so, wie Despotist sagt..

Wenn die Komponente was verändern muss, braucht es auch die erforderlichen Daten.
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4260
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: Datenkapselung

Beitrag von Chromanoid »

Bei Spielen, die von einem kleinen Personenkreis entwickelt werden, halte ich solche Konzepte für eher vernachlässigbar. Datenkapselung ist dann sinnvoll, wenn man auch spürbare Vorteile davon hat. Wenn man bei einem kleinen Spiel, an dem man vielleicht ein halbes Jahr arbeitet, Variablen und Funktionen gerne public machen möchte und man dadurch bugfreiheit nicht signifikant gefährded, sollte man das IMO ohne schlechtes Gewissen tun. Das ist einfach zeitsparender, bequemer und wesentlich sauberer als immer kompliziert um irgendwelche Architekturkonzepte herum zu bauen.
zwergmulch
Beiträge: 91
Registriert: 07.12.2009, 16:42
Echter Name: Fabian R

Re: Datenkapselung

Beitrag von zwergmulch »

In dem Zusammenhang sind C#'s anonyme Properties (public int foo {get; set}; oder so) sehr interessant.
Man kann erst mal seine Variablen vollkommen public machen und spart Schreibarbeit, aber später noch Prüfungen einbauen die Werte testen, ohne dass sich die Benutzung ändert.

Schade, dass es das nur da gibt. ;)

Edit: Generell würde ich also Setter/Getter vorziehen, da man so halt einfach später noch Kontrollen einbauen kann und moderne IDE's die auch automatisch generieren.
Zuletzt geändert von zwergmulch am 27.06.2010, 11:52, insgesamt 1-mal geändert.
Bild
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4260
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: Datenkapselung

Beitrag von Chromanoid »

ja die empfinde ich auch als königsweg für dieses problem...
Benutzeravatar
Krishty
Establishment
Beiträge: 8250
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Datenkapselung

Beitrag von Krishty »

Ich würde auch zu dem tendieren, was Despotist vorgeschlagen hat … also quasi Move()-Methoden statt auf dem .Position-Member zu arbeiten oder Getter und Setter zu implementieren.

Das krasse Gegenteil davon, was mir aber auch legitim vorkäme, wäre, alle komponentenspezifischen Objekteigenschaften in ein struct zu packen (Daten von Logik zu trennen) und das den Komponenten über einen einzigen Getter und Setter zur Verfügung zu stellen.
Chromanoid hat geschrieben:Bei Spielen, die von einem kleinen Personenkreis entwickelt werden, halte ich solche Konzepte für eher vernachlässigbar.
Sowas ist nie vernachlässigbar. Genau sowas hält den Verstand fit für das nächste Mal, wenn man so ein Problem für einen „großen Personenkreis“ lösen muss.

Gruß, Ky
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4260
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: Datenkapselung

Beitrag von Chromanoid »

Krishty hat geschrieben:
Chromanoid hat geschrieben:Bei Spielen, die von einem kleinen Personenkreis entwickelt werden, halte ich solche Konzepte für eher vernachlässigbar.
Sowas ist nie vernachlässigbar. Genau sowas hält den Verstand fit für das nächste Mal, wenn man so ein Problem für einen „großen Personenkreis“ lösen muss.
Naja man sollte auch immer abwägen inwiefern der Aufwand seinen Verstand in diesem Sinne fit zu halten gerechtfertigt ist... Solange man sich darüber bewusst ist, dass das so in anderen Projekten vielleicht nicht geht, sehe ich da nicht immer eine Notwendigkeit. So eine Entscheidung seinen Geist für vernünftige OOP Programmierung fit zu halten ist ja auch immer eine Frage der Zeit/des Geldes...
odenter
Establishment
Beiträge: 207
Registriert: 26.02.2009, 11:58

Re: Datenkapselung

Beitrag von odenter »

Der Vorteil von extra Methoden ist ganz klar die Wartbarkeit, der Nachteil ganz klar der Aufwand.

Ich würde Methoden bauen, da Du heute ja nicht weisst welche Erweiterungen Du in Zukunft vornehmen willst, Du willst ja nicht überall in Deinem Code rumgraben nur weil z.B. beim setzen der Position eine zusätzliche Prüfung her muss. Bei den "public" Variablen müsstest die Prüfung dann überall beim Zugriff auf die Variable einbauen, oder spätestens dann anfangen alles zu kapseln, also kannst das auch gleich machen. :)
Benutzeravatar
exploid
Establishment
Beiträge: 146
Registriert: 21.08.2005, 18:33

Re: Datenkapselung

Beitrag von exploid »

...
Zuletzt geändert von exploid am 04.11.2010, 12:18, insgesamt 1-mal geändert.
All your base are belong to us! Justice
dronus
Establishment
Beiträge: 114
Registriert: 11.01.2010, 01:53

Re: Datenkapselung

Beitrag von dronus »

zwergmulch hat geschrieben:In dem Zusammenhang sind C#'s anonyme Properties (public int foo {get; set}; oder so) sehr interessant.
...
Schade, dass es das nur da gibt. ;)
Ich finde das ist eher eklig. Ähnlich wie die Möglichkeit, dass = überladen ist. Ich muss sagen dass ich selber bei Wenige-Leute-Projekten meine getter/setter Zeit überwunden habe. Wenn man z.B. in Java Ding.eigenschaft=5; schreibt, dann hat man immerhin im Griff was in diesem Moment passiert. Bei C++ Überladung und C# Properties muss ich an jeder =, += etc. Stelle genauso argwönisch sein was ich damit eigentlich auslöse. Bei kleinen Projekten verzichte ich mittlerweile auf getter/setter soweit es geht, ich habe auch kein Problem damit wenn es denn doch notwendig wird eine Stunde umzubauen. Letzlich gilt das aber alles nur weil ich den kompletten Code in der Hand habe bzw. auf alle Beteiligten Einfluss nehmen kann. Bei externe Libs ist das nat. nicht zu machen, hier kenne ich aber auch die ganze Palette an Ekelkram: getter + setter die blocken, getter deren Rückgabe nicht dem gesetten gleicht, getter und setter die manchmal unkalkulierbar lange dauern etc.
Benutzeravatar
Jonathan
Establishment
Beiträge: 2374
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Datenkapselung

Beitrag von Jonathan »

@exploid
Es geht hier um ein Spiel und nicht um eine Bibliothek die potentiell von vielen anderen benutzt wird, daher denke ich nicht, dass getter/setter hier Sinn machen. Sollte ich irgendwann eine Überprüfung einbauen wollen, muss ich nur die entsprechende Funktion erstellen und die 50 trivialen Compilerfehler abarbeiten, was im Zweifelsfalle mit suchen/ersetzen geht. Das dauert dann ungefähr 5 Minuten. Aber bis dahin habe ich eine übersichtliche und aufgeräumte Klassenschnittstelle weniger Tipparbeit und übersichtlicheren Code (weil weniger () durch Funktionsaufrufe).
Letztendlich geht es mit dem ganzen Kapseln ja darum, dass man keine Daten von außen verändern kann, sobald man einen setter hat, der den Wert einfach so übernimmt, hat man mit ein wenig Arbeit einfach mal gar nichts erreicht. Weil man immer noch genauso von außen zugreifen kann, nur umständlicher.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Benutzeravatar
Krishty
Establishment
Beiträge: 8250
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Datenkapselung

Beitrag von Krishty »

dronus hat geschrieben:Ich finde das ist eher eklig. Ähnlich wie die Möglichkeit, dass = überladen ist. Ich muss sagen dass ich selber bei Wenige-Leute-Projekten meine getter/setter Zeit überwunden habe. Wenn man z.B. in Java Ding.eigenschaft=5; schreibt, dann hat man immerhin im Griff was in diesem Moment passiert. Bei C++ Überladung und C# Properties muss ich an jeder =, += etc. Stelle genauso argwönisch sein was ich damit eigentlich auslöse.
Das Überladen von Operatoren kann nicht mehr versteckte Gefahren bergen als jede andere Funktion auch (siehe [url=ttp://james-iry.blogspot.com/2009/03/operator-overloading-ad-absurdum.html]hier[/url]). Und ich finde sogar ganz im Gegenteil, dass Properties die einzige Möglichkeit sind, bei der man sicher weiß, was passiert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
joeydee
Establishment
Beiträge: 1044
Registriert: 23.04.2003, 15:29
Kontaktdaten:

Re: Datenkapselung

Beitrag von joeydee »

Leider noch mehr Tipperei und Kopfarbeit, aber eine gute Möglichkeit dass nur die registrierten Komponenten und niemand sonst z.B. an der Objektposition was ändern können, sehe ich im Observer-Pattern: das Objekt registriert einen Listener zum Event "ChangePosition" bei seiner Komponente. Diese löst nur Events aus statt Eigenschaften des Objekts direkt zu beeinflussen. Das Objekt selbst kümmert sich bei gefeuerten Events dann selbst um die Ausführung und ändert seine Eigenschaften, welche dadurch auch private bleiben können.

Das wäre im allereinfachsten Fall eine private Funktion im Objekt, deren Referenz gezielt an die Komponente weitergegeben wird, welche sie dadurch bei Bedarf aufrufen darf. Wer die Referenz nicht hat, darfs auch nicht. Und da die Referenz in der Komponente ebenfalls private bleiben kann, bleibt diese auch hier nach außen geheim.

Ich habe hier gerade nur AS zur Verfügung, aber ich glaube damit wirds klar:

Code: Alles auswählen


	public class PLObject{
		
		private var x:Number;//private position
	
		//add a new component to this object	
		public function registerComponent(component:PLComponent){
			component.changePositionX=setPositionX;//register event listener for event "changePositionX"
		}
	
		//event handler for event "changePositionX"
		private function setPositionX(value:Number){
			x=value;
			trace("PLObject: position x is set to "+x);//log output
		}

	}


	public class PLComponent{
		
		private var _changePositionX:Function;//event handler for event "changePositionX"
		
		//register a handler function for event "changePositionX"
		public function set changePositionX(handler:Function){
			_changePositionX=handler;
		}
		
		//test changing a private value in parent object
		public function updateX(anyValue:Number){
			if(_changePositionX)_changePositionX(anyValue);// fire event "changePositionX" if it has a handler
		}
		
	}

//test it!

var myObject:PLObject=new PLObject();
var myComponent:PLComponent=new PLComponent();

myObject.registerComponent(myComponent);//add component to object

myComponent.updateX(15);// --> "PLObject: position x is set to 15"

//other ways to acces the PLObject property "x" will fail:
//myObject.x=8;//error
//myObject.setPositionX(8);//error
//myComponent.changePositionX(8);//error


odenter
Establishment
Beiträge: 207
Registriert: 26.02.2009, 11:58

Re: Datenkapselung

Beitrag von odenter »

Jonathan hat geschrieben:@exploid
Es geht hier um ein Spiel und nicht um eine Bibliothek die potentiell von vielen anderen benutzt wird, daher denke ich nicht, dass getter/setter hier Sinn machen. Sollte ich irgendwann eine Überprüfung einbauen wollen, muss ich nur die entsprechende Funktion erstellen und die 50 trivialen Compilerfehler abarbeiten, was im Zweifelsfalle mit suchen/ersetzen geht. Das dauert dann ungefähr 5 Minuten. Aber bis dahin habe ich eine übersichtliche und aufgeräumte Klassenschnittstelle weniger Tipparbeit und übersichtlicheren Code (weil weniger () durch Funktionsaufrufe).
Letztendlich geht es mit dem ganzen Kapseln ja darum, dass man keine Daten von außen verändern kann, sobald man einen setter hat, der den Wert einfach so übernimmt, hat man mit ein wenig Arbeit einfach mal gar nichts erreicht. Weil man immer noch genauso von außen zugreifen kann, nur umständlicher.
Naja bei den set/get Methoden, bauste halt nur Deine zusätzliche Prüfung und brauchst keine 50 Compiler-Fehler abarbeiten.
Ist aber ja letztlich Dein Code, und wenn Du mit suchen/ersetzen arbeiten willst, mach das. :)
Antworten