Sign in to follow this  

[.net] How do YOU code?

This topic is 4590 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm in the middle of my first BIIIIG C# project, porting over a lot of my old game-engine code to C#, making it all OOP and lovely. Now, in good old C++, you'd end up having a million get/set functions for each of your variables, but good old C# now lets you have properties! Also, theres a million different ways of naming your functions. I was just wondering what everyone else does... C++ Code
class FooBar
{
   private int d_height;
   private int d_width;

   public void setHeight(int height) { d_height = height; };
   public int getHeight() { return d_height; };
   public void setWidth(int width) { d_width = width; };
   public int getWidth()  { return d_width; };
}

USAGE:

Foobar temp = new Foobar();
temp.setHeight(250);
temp.setWidth(250);

Type 1 C# Code - The Encapsulated setData
class FooBar
{
   public struct FooBarSize
   {
      int Height;
      int Width;
   }

   private int d_height;
   private int d_width;

   public FooBarSize Size
   {
      get
      {
          FooBarSize _size = new FooBarSize;
          _size.Height = d_height;
          _size.Width = d_width;
          return _size;
      }
      set
      {
          d_height = value.Height;
          d_width = value.Width;
      }
   }
}

USAGE:

FooBar temp = new FooBar();
FooBar.FooBarSize tempSize = FooBar.FooBarSize();
tempSize.Width = 250;
tempSize.Height = 250;
temp.Size = tempSize;

C# Type 2 - The setSize function
USAGE:

FooBar temp = new FooBar();
temp.SetSize(250, 250);

That is a quick couple of ways I could think of - which way do you do it? Using the old "class.setSize(x, y)" is a bit C++'ish, but starting writing structs for every kind of data type is a bit of a pain, as is seperating "Width" and "Height" into two seperate properties... Just my 2 cents

Share this post


Link to post
Share on other sites
First of all, in C++ I never had a whole bunch of accessor methods. The entire point of OOP is that you shouldn't need a whole lot of accessor methods. A class does more than just encapsulate the data, it encapsulates how the data is used.

If you have a lot of accessor methods then you might want to see how much of that actually needs to be exposed. A careful evaluation of how the data is being accessed and used will reveal algorithms that would be better served as members of the class encapsulating the data.

Secondly, your example makes no sense to me. If you are going to return the structure, then store it in the structure. You don't need to convert to the structure just to return the data. It also means you can use the size structure to encapsulate access to the width and height, thus enabling constraints to be applied.

Share this post


Link to post
Share on other sites
Ok, that makes some sense, but the idea behind OOP is that you keep as much as you can private, and access the data through accessor functions, otherwise you might as well just make a whole load of variables in a class as public right?

Share this post


Link to post
Share on other sites
Define accessor?
If you mean get/set functions then no. OOP is not about get/set functions. They are a necessary evil however, since often times you do need to access the data that a class provides. OOP is about abstractions. Data-hiding is one technique used to achieve this, but if you expose that data via get/set methods, then you have not gained anything. Instead the object should encapsulate the access to the data by exposing algorithms to operate on the data.

Share this post


Link to post
Share on other sites
Get/Set functions that just return a member variable are useless and just take more time to type if you ask me (Then again I am an idiot).
However I use get/set if I want the user to only access part of something, for example:

class A
{
vector<int> foo;
public:
int GetSize()
{
return foo.size();
}
}

Share this post


Link to post
Share on other sites
What do I do?

Before writing any code, I decide on the interface of the classes I use (what I need to do with them), write that interface down, and go do something else (like have dinner). I force myself not to think of the internal properties of the object, or anything related to its implementation.

When I come back, I implement the interface without adding new members to it.

You'll find that quite often, after a bit of training, in the first step of this method, you think in terms of "what can I do with it", not "what is inside it". You can end up in functions that look like accessors: Resize instead of SetSize, for instance. But by thinking in terms of actions instead of properties, you end up naming your function as actions that are a little bit more deep than "Get the value, set the value", and also make the interface more consistent.

Share this post


Link to post
Share on other sites
if i notise i need to use get and set funktions i just make the variable public instead. easyer quicker. Might be dangerus but my projekt is small so far.
Largest is i think 13k lines.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
If I am adding a set/get member I ask my self a couple of questions:
1. Is it possible to access this object from multiple threads?
2. Should the caller know the internal storage structure of the object?
3. Is this a singleton holding Configuration or Resource information for the whole applications?

If I answer no to all 3 of these questions, I need to re-examine why the data member is not public instead of requiring a function member to access.

Share this post


Link to post
Share on other sites
For naming your functions and variables, searching for 'Design Guidelines for Class Library Developers' in your .NET Framework SDK docs is good.
Just a few excerpts:

Method/class/property/interface/enum etc names, pascal case.
Parameter names, camel case.

You can really do whatever you like with your internal variables since they are not exposed, but I use 'm_' prefix for class members and camel case for variables in functions. I don't like the style where some people use plain camel notation for class members because it promotes confusion with function parameters (at least for me [grin])

Just my humble opinion!

Share this post


Link to post
Share on other sites
I expose the routines that make sense to be exposed; if that means that I have to use a few get and set methods, that's fine, as long as it makes sense and is absolutely required. I suppose this sums up my way of coding:
Player.py

"""The player class"""


LEFT = -1
RIGHT = 1


class Player(object):
"""The player class.

See renderPlayer for the routine to render the player.

"""



def __init__(self, bounding_rect, run_speed, jump_speed, direction):
"""Create a player.

direction is either Player.LEFT or Player.RIGHT.

"""


# Copy boundingRect instead of just referencing it, because we'll be using
# it to store our current position.
import copy
self.bounding_rect = copy.copy(bounding_rect)

self.run_speed = run_speed
self.direction = direction

self.jump_speed = jump_speed


def move(self):
"""Move the player in the current direction by run_speed"""
self.bounding_rect.move_ip(self.run_speed*self.direction, 0)


def jump(self):
"""Move the player up by jump_speed"""
# Multiply jump_speed by -1 to make it negative, thus moving us up
self.bounding_rect.move_ip(0, self.jump_speed*-1)


def setDirection(self, direction):
"""Set the direction.

direction is either Player.LEFT or Player.RIGHT.

"""

self.direction = direction


def getBoundingRect(self):
"""Return the bounding rect of the player"""
return self.bounding_rect


renderPlayer.py

"""A routine to render a player to a given surface"""


def renderPlayer(player, surface):
"""Render the given player to the given surface"""
surface.fill((0, 0, 255), player.getBoundingRect())


player_signals.py

"""Routines dealing with registering player signals"""


import keyboard
import settings
import Player

def registerSignals(signal_manager, player):
"""Register signals with the signal manager dealing with the player"""

def movePlayerLeft():
player.setDirection(Player.LEFT)
player.move()

keyboard.onKeyDown(signal_manager, settings.player_left_key, movePlayerLeft)

def movePlayerRight():
player.setDirection(Player.RIGHT)
player.move()

keyboard.onKeyDown(signal_manager, settings.player_right_key, movePlayerRight)


Notice how the rendering routine is seperate from the actual class. This is because it doesn't belong there, mainly because it isn't required in order to use the given class.

Also notice the lack of an update method. Not only is this not present because it is not always needed, but because I don't have one at all! Instead, I use a signals-based update method. A signal-based approach is good for two reasons: it promotes heavy reuse of code, and it encapsulates complexity.

Finally, I should point out a few other things about the code listings above, which are actual files from a game project I'm working on. Error handling is quite a bit relaxed, mainly because I don't plan on anyone else using it. It is, also, a work in progress, as you will see with the renderPlayer routine (I haven't made the player sprite, yet).

Share this post


Link to post
Share on other sites
listen to the above advice. the whole point of having get/set is in beginner tutorials. instead of acting on the data (rather like fancy c data structures), you should be defining an interface to the structure.

to me, if I need a flag which has public access, usage of set/get doesn't outweigh making the variable just public (unless in the cases when other things need to be done when it is changed - i.e range checking).

Share this post


Link to post
Share on other sites
One reason for having Get/Set methods instead of having public data, is if you want the behavior of getting or setting a property, but you don't want to change the interface of the class. For instance, GetSize() may just return a variable today, but tomorrow it could compute it from a few values.

today:
int GetSize()
{
return size;
}

tomorrow:
int GetSize()
{
return h * w;
}

If you're using the variable size in 200 places, that's 200 changes you have to make. If you don't have access to all the files you need to change (ie, other programmers have the files locked out of source control), it can be a very hard thing to do! This applies more to large projects.

Of course, if you can avoid giving others access to your data, that's always better.

Share this post


Link to post
Share on other sites
Quote:
Original post by Washu
Define accessor?
If you mean get/set functions then no. OOP is not about get/set functions. They are a necessary evil however, since often times you do need to access the data that a class provides. OOP is about abstractions. Data-hiding is one technique used to achieve this, but if you expose that data via get/set methods, then you have not gained anything. Instead the object should encapsulate the access to the data by exposing algorithms to operate on the data.
Excellent advice, I suggest people take the time to digest that.
Actually it would be really cool if there was a code sample available where someone used too may get/set and then after they changed it. One of those before and after shot things.[smile]
A lot of people could be awakened by such a thing.

Share this post


Link to post
Share on other sites
1. You *rarely* loose out by using a simple get/set over using a public var. Even assuming that you never do anything other than just set or return the variable, adding break points to them can be invaluable for certain bugs. Typing time is irrelevant, you'll spend most of your time designing, maintaining or debugging anyway.

2. Often it's handy to provide only a 'get' or only a 'set'. get-only is great for immutable objects that you can pass around safe in the knowledge that someone's not going to tinker with them. set-only is handy if you want to force several vars to be set at the same time (ie. move to a completely different, yet still valid state).

3. Even simple get/set pairs can have error checking in them. You can always test new positions against level boundaries, referenced objects for null, etc.

4. Providing get/set pairs can also help if you ever want to extract an interface and provide a polymorphic substitute (which might do totally different things in response to get or set methods, like revalidating additional state or generating return values from existing state).

Of course, this assumes that getters and setters are actually appropriate in the first place...

Share this post


Link to post
Share on other sites
Quote:
Original post by iMalc
Excellent advice, I suggest people take the time to digest that.
Actually it would be really cool if there was a code sample available where someone used too may get/set and then after they changed it. One of those before and after shot things.[smile]
A lot of people could be awakened by such a thing.


Heh, I can't write code like that, so you'll have to look to someone else.

Share this post


Link to post
Share on other sites
get and set functions are helpful when you need to validate values or point out issues that could be a problem.


void setValue(int value)
{
if(value >= 100)
m_Value = value;
else
value = 100;
}

Share this post


Link to post
Share on other sites
Some interesting points, i generally try to use get/set pairs, even if it is just to access a variable - often cos i can inline profile the code and see how many times per frame a variable is accessed etc - plus, as someone already mentioned it may be a simple access today, but could be a whole lot more tomorrow.

Share this post


Link to post
Share on other sites
Quote:
Original post by SumDude
get and set functions are helpful when you need to validate values or point out issues that could be a problem.


void setValue(int value)
{
if(value >= 100)
m_Value = value;
else
value = 100;
}


I don't see why you can't code that into a property...although it would be a bit odd.

What I am currently implementing is a set / get method because I do not really want raw access to a property. I find it nicer to implement modifiers and accessors through my interfaces. Plus, not all my get methods have a set method. Like the ID, I never want to be able to change the object's ID because it is supposed to be constant.

Share this post


Link to post
Share on other sites
Quote:
Original post by Krisc
Quote:
Original post by SumDude
get and set functions are helpful when you need to validate values or point out issues that could be a problem.


void setValue(int value)
{
if(value >= 100)
m_Value = value;
else
value = 100;
}


I don't see why you can't code that into a property...although it would be a bit odd.

You can do that kind of stuff in a property. I've written a few properties that have bodies like that.
Quote:
What I am currently implementing is a set / get method because I do not really want raw access to a property. I find it nicer to implement modifiers and accessors through my interfaces. Plus, not all my get methods have a set method. Like the ID, I never want to be able to change the object's ID because it is supposed to be constant.

You can put properties into interfaces. Also, you can limit access by only defining a get or set block; the one that isn't declared can't be used.

Properties are also nice because they can easily replace variables. When I'm prototyping a class, I'll declare everything as public variables, get it working, then switch to properties accessing private variables.

Share this post


Link to post
Share on other sites
It's alright having properties that can throw exceptions isn't it? None of my properties do anything complicated, as they shouldn't, but I throw System.ArgumentNullException, System.ArgumentOutOfRangeException and System.ComponentModel.InvalidEnumArgumentException.

Share this post


Link to post
Share on other sites
Quote:
Original post by DrGUI
It's alright having properties that can throw exceptions isn't it? None of my properties do anything complicated, as they shouldn't, but I throw System.ArgumentNullException, System.ArgumentOutOfRangeException and System.ComponentModel.InvalidEnumArgumentException.


Properties are just functions internally, so you can do anything in a property that you can in a function (without changing the function definition).

Share this post


Link to post
Share on other sites
Quote:
Original post by nagromo
Quote:
Original post by DrGUI
It's alright having properties that can throw exceptions isn't it? None of my properties do anything complicated, as they shouldn't, but I throw System.ArgumentNullException, System.ArgumentOutOfRangeException and System.ComponentModel.InvalidEnumArgumentException.


Properties are just functions internally, so you can do anything in a property that you can in a function (without changing the function definition).

Cool, thanks. I was just wondering whether throwing exceptions for arguments (eg ArgumentNullException) when setting to properties was strictly accurate. Of course it is an argument internally but I was wondering from a design point of view.
Oh I wouldn't know what to change them to anyway so I probably won't bother. Still curious though [grin].

Share this post


Link to post
Share on other sites
Quote:
Original post by bytecoder
I expose the routines that make sense to be exposed; if that means that I have to use a few get and set methods, that's fine, as long as it makes sense and is absolutely required. I suppose this sums up my way of coding:
Player.py
*** Source code snippet removed ***


You don't need getter and setter methods in python. You can use the __getattr__ and __setattr__ methods. Just remember to raise an exception in __getattr__ if the object doesn't have the property being accessed, and to add the property to __dict__ in __setattr__ if they're setting a property that does not exist already.

Share this post


Link to post
Share on other sites
Washu and others made the point that sometimes properities are misused... sometimes they are just a way of breaking encapsulation.

They are useful though - if you are making form components then properities are necessary to store and retrieve state information.

Just take care though - structs are copied across on the stack and that can take up resources (so when you return a string using a getter you are returning a copy of that string, etc).

Though managed code makes things easier - there are impacts on the way you do things that a C++ programmer may not be aware of yet. Like the whole boxing thing, that can be very expensive.

Share this post


Link to post
Share on other sites

This topic is 4590 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this