Design question - Globals and Naming Conventions

Started by
14 comments, last by lostincpp 16 years, 6 months ago
I'm starting a new project and im going to be releasing it open source. Si i have a few questions: 1) Gloabals - Say for example i have a class called CRenderer and its needed by other classes like the ui and player. I normally make it a global and use the extern keyword to access it in other classes. Ive read this is bad design so should i rather just create an object of CRenderer and pass it to the functions needed by the ui and player class eg

//1
void CUserInterface::UpdateAndRender()
{
  //do rendering with global 
}
//2
void CUserInterface::UpdateAndRender(CRenderer Renderer)
{
  //do rendering with Renderer passed as function paramater 
}

Which one is better? 2) Naming conventions say for example i have this class:

class CExample
{
private:
  int m_iInt;
public:
  CExample();
};

if i declare a member of a class i always put m_ in front of it to indicate its a member of the class. Also for an int i always put i in front of it to show its an int. Is this good practice? if so what should i put to indicate other data types like char, float, double whether its signed or unsigned etc? Thanks
Advertisement
I don't really have a strong opinion one way or another as far as the global-stuff goes, as I tend to just do the first way ( using external referneces to instances/data that are used throughout the program ). However, I think, the most important thing about notation is : consistency. The m_* and i/f/v etc prefixes are pretty common-place, and I use a similar, less-hungarian-inspired system... All-in-all : consistency.
Quote:Which one is better?


Using global variables tends to make for lousy object-oriented designs. You should design your systems without thinking about either global variables or global state.

Quote:if i declare a member of a class i always put m_ in front of it to indicate its a member of the class.


Initializer lists? Bar() : foo(10) {} : it's obvious that it's a member, no need to say it twice.

Member access? bar.foo : it's also obvious that it's a member, no reason to repeat it.

Member pointers? &Bar::foo : still obvious and not worth repeating.

Small functions? int Bar::Foo() const { return foo; } : either a member or a global but, since there are no globals in your code, you just know it's a member, so still not worth repeating.

Ambiguites? this -> foo : yes, this does take four more characters to write than the m_ prefix, but it's rare enough that it is largely offset by the lack of prefix in all other cases.

Quote:Also for an int i always put i in front of it to show its an int.


It's far better to use semantical denotation which implies that it's an integer (such as countFoo or numFoo or indexFoo or remainingFoo) or simply drop the type information because it's not relevant (fooHandle).
Quote:Original post by ToohrVyk
Initializer lists?
Member access?
Member pointers?
Small functions?
Ambiguites?
Large functions? It helps distinguish at a glace which variables are member variables and which are local variables. It also prevents name collision for local variables. Good for OOP. I recommend using the m_<type> prefix.

Sometimes I'm not sure what type prefix to use though. I use ones like s for a struct, e for an enumerated value, o for an object, p for a pointer, h for a handle, v for a vector of some sort, either mathematical or container... of course i for int and such. I get other ones sometime though.
Quote:Original post by Kimani
Large functions? It helps distinguish at a glace which variables are member variables and which are local variables.
It also prevents name collision for local variables.


Try to read my 'ambiguities' description.
People actually use this->foo to access member variables? Ew.

To each his own I guess.
For proponents of Hungarian notation I always feel the need to quote this from Microsoft (the originator of Hungarian notation).

Quote:from .NET Framework Developer's Guide

General Naming Conventions
...
Do not use Hungarian notation.
...


Nobody mentioned the 'C' on the front of class names. In my opinion, it is totally unnecessary and reduces readability. Don't do it.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
Quote:Original post by Kimani
People actually use this->foo to access member variables? Ew.


I didn't say it was pretty. In fact, any kind of name-mangling is ugly as hell, because it detracts from the actual problem-space semantics to specify some solution-space details. The advantages of this -> foo when compared to m_foo or _foo are that it doesn't mangle the name anywhere except where it's actually necessary (and yes, I tend to consider bar.m_foo an abomination, because it incorporates a perfectly useless m_ prefix), and that it interacts with intellisense approaches better (not only does the this -> prefix bring up intellisense, but it also doesn't alter alphabetical sorting like prefixes do, though there is certainly something that could be said about foo_).

I've been round and round on this question. In the end, just giving your classes, functions and data names that tell what they do is more important than putting 'c' in front of classes, 's' in front of structs, 'm' in front of methods, etc. For example, using 'count' for integer counting, 'cache' for temporary storage, etc. I found that when I used the little 'c' etc notation it soon became non-nonsensical because there were so many c's, m's etc in the code. The only notation that I do use emphatically is a small 'p' in front of pointers, because these are the most dangerous part of the programme and should stand out (be easily found), in my opinion, and I will use the suffix "_t" if a class is a fundamental type (such as int_t and real_t).

Being semantically accurate with names is extremely valuable because it requires you to think of a simple term that describes exactly what you want that function/class to do; if you have trouble with this then it is a signal that maybe you don't understand the problem domain anyway. To me, this means that functions and functors and class methods are for actions, so imperative naming forms are best (such as getBuffer()), whereas classes/structs are types, so use nouns for these (such as 'class buffer'). Then you can initialize as "buffer theBuffer". and if this is within a namespace, such as 'namespace string;' then you get very good semantics, ie 'string::buffer strBuffer;'. In this way your programme becomes very readable and clean. Because the namespace is so useful for modular development and semantics, I rarely use the term 'using namespace xxx;' because the namespace adds to the readability, plus it tells where things can be found within my source code. It also reduces the risk of name collisions.

--random
--random_thinkerAs Albert Einstein said: 'Imagination is more important than knowledge'. Of course, he also said: 'If I had only known, I would have been a locksmith'.
I don't like name mangling either. Hungarian stuff harms readability to imho. For naming:

Globals - all caps, underscore separated
ex: float MY_GLOBAL

Classes - capitalized, cap separated
ex: class MyClass

Member Functions - lower case, cap separated
ex: void MyClass::myFunction()

Class/Function Variables - lower case, underscore separated
ex: float rotation_x, rotation_y, rotation_z

This topic is closed to new replies.

Advertisement