I need your oppinion setters/accessor functions

Started by
7 comments, last by EnigmaticCoder 14 years, 11 months ago
I've got a class that has several pieces of data that can be altered and I'm wandering what is the prefered way to do things. There can be up to 10-20 parameters at one time so im just looking for your prefrences. 1: I force everything to be set in the constructor ie Function( param1 p1, param2 p2, param3 p3, param4 p4... ) 2: I add separate functions for each parameter ie Param1( p1 ) { param = p1 }; Param1( p2 ) { param = p2 }; Param1( p3 ) { param = p3 }; ... 3: Or I can group them ie SetParams1( param1, param2 ); SetParams2( param1, param2); ... Typically I'd do the #3 option and group parameters just to lessen the amount of calls. he's an example of the type of class I'm using and how I use it;

// create the class
class *MyClass;
MyClass = new MyClass();

// set the data how you want it
MyClass->SetParams1();
...

// create the class
MyClkass->Init();

[ dev journal ]
[ current projects' videos ]
[ Zolo Project ]
I'm not mean, I just like to get to the point.
Advertisement
Tell us about the actual class, what is it really?

Sometimes you can split a class into smaller parts that each deal with more manageable chunks of data. This would be the preferred method IMO.
You'd want individual accessors/mutators, but for initialization, probably grouping initialization functions, or maybe groups of related information can be put into structs? That would keep it clean looking, while still passing in all your nessessary data. You definatly don't want a single function taking 20 parameters.

so say you have a game class. say you have graphics, audio, and input systems.

you could have a graphics_info, audio_info, and input_info, then fill each struct with related info, and have an init function

Game game;
game.init(graphics,audio,input);


or, have individual init functions

Game game;
game.initGraphics(graphics variables..);
game.initAudio(.....);
etc....



--------------------------------------Not All Martyrs See Divinity, But At Least You Tried
Quote:Original post by freeworld
I've got a class that has several pieces of data that can be altered and I'm wandering what is the prefered way to do things. There can be up to 10-20 parameters at one time so im just looking for your prefrences.


Segmenting it into smaller bits. One class solves one problem.

Quote:Original post by Telastyn
Quote:Original post by freeworld
I've got a class that has several pieces of data that can be altered and I'm wandering what is the prefered way to do things. There can be up to 10-20 parameters at one time so im just looking for your prefrences.


Segmenting it into smaller bits. One class solves one problem.


I was going to say something similar, to solve the problem by implementing more aggregation, but I decided that it was a bit out of the scope of the question.


But yes, if you can, try to break your data into self-sufficient classes, and then have an init method for each class within the class that holds them, kind of like what I suggested with the structs, but more in the vain of data and operations on that data.

For instance, instead of having a graphics struct, you can create a graphics class with its own mutators and accessors, and use them through the "Game" class's accessors and mutators.


That is why i've gained a new found respect for java/C# since I started school, they, for the most part, force you to learn and use better OO practices.
--------------------------------------Not All Martyrs See Divinity, But At Least You Tried
Some tips:

1. Don't write a single class with that many parameters.
2. Don't design classes that are in an undefined state until some Init() method is called. Especially if that Init() method requires an arbitrary set of properties in the class to be assigned beforehand, to which Init() gives no indication.
3. Do all initialization in the constructor. If parameters are neccessary for initialization, or for certain methods to work, pass them in the constructor. Completely eliminates the risk of calling a method with uninitialized fields.
4. If construction of a class is too complex (which it shouldn't be), use the builder pattern to allow for a checked step-by-step construction, eg.

struct MyClassBuilder {  MyClassBuilder(int requiredProperty1, int requiredProperty2);  void AddSwizztle(int swizzleProperty1, int swizzleProperty2);  void EnableHoop(int hoopProperty1, int hoopProperty2);  auto_ptr<MyClass> CreateInstance() const;}

Professional C++ and .NET developer trying to break into indie game development.
Follow my progress: http://blog.nuclex-games.com/ or Twitter - Topics: Ogre3D, Blender, game architecture tips & code snippets.
Quote:Original post by freeworld
I've got a class that has several pieces of data that can be altered


1) Why does it have several pieces of data?
2) Why can those pieces of data be altered? Meaning, what are the circumstances under which they are altered?

When you use a class, you are not supposed to think in terms of what pieces of data an instance contains, and how you want to alter them. You are supposed to think in terms of the class interface - what the class advertises that it is capable of doing. The instance is responsible for looking at, and possibly altering, its own data in order to perform whatever action was requested of it.

Quote:and I'm wandering what is the prefered way to do things.


I assume you mean wondering.

Anyway, don't write functions with names like Init(). That is what constructors are for.
As several posters have already said, that best solution (if existing at all) depends on the circumstances.

In the OP it isn't clear what "parameter" actually mean. E.g. the 4 components of a 4D vector can be passed one by one, or they can be grouped in a Vector class. Whether it would be senseful to pass the scalars or the whole vector depends on the circumstances.

I don't see why providing setters with more than a single parameter should be a problem in general. Assume for example a quaternion class used solely for representation of rotations. Such quaternions are required to have unit length. If you provide 4 setters for the real and the 3 imaginary parts, resp., then it is not a problem for a client to violate the unit length constraint. Moreover, the client is enforced to violate it (temporarily), since it is enforced to set the values one by one. The quaternion class has no chance to check for the violation sensefully. But when you provide a setter with all 4 scalar parameters at once, the quaternion can check the unit length condition and preserve the object from entering an invalid state.

Assume for example a graphics rendering engine that collects graphics rendering jobs in a list to have the ability to sort them before performing the actual rendering. One don't want the jobs to be memory allocated again and again, due to performance reasons. When working with a pool allocator instead, the objects need some kind of post-creation initialization, be it called init() or reset() or an assignment or whatever. In such a case it isn't always possible to have objects in a well defined state. Sure, encapsulating that in a kind of factory may hide that bad situation from the public.


Many words to say just that: The suggestions made in the above posts are the general guidelines, but they may be useless under special circumstances. So, freeworld, tell us more details if you want a more specific answer.
Quote:Original post by Zahlman
Anyway, don't write functions with names like Init(). That is what constructors are for.


What about a "working" Init(...) function? A function that sets all the class' data?

By the way, Zahlman, your perspective on object oriented programming seems/is unique -- and right too. A few months ago you posted that accessor and mutator pairs should be avoided in place of methods that actually do something. It's a brilliant idea!

[Edited by - anothrguitarist on April 22, 2009 3:06:35 AM]
--------------------Enigmatic Coding

This topic is closed to new replies.

Advertisement