I think (System) Hungarian notation is responsible for most of the "bad rap" that prefixes get.
This notaton is largely pointless e.g. "lpsz" to tell you that your string is a long pointer to a nul terminated string, when: segmented architecture is ancient history, C++ strings are pointers to nul-terminated char arrays, and it's not really all that difficult to know that "Name" is a string!
However, I do use prefixes to specify the usage of a variable (essentially "Apps Hungarian", although I prefer to avoid the term Hungarian due to it having a bad and unfair association with System Hungarian), and this is a very handy timesaving and bug-reducing approach.
I use:
- m for members
- c for constants/readonlys
- p for pointer (and pp for pointer to pointer)
- v for volatile
- s for static
- i for indexes and iterators
- e for events
Where I wish to make the type clear, I use standard suffixes (e.g. List, ComboBox, etc).
This makes the programmer aware of the usage of the variable whenever they see/use it. The most important case is "p" for pointer (because the usage changes from var. to var-> and you have to be much more careful with pointers - checking for NULL etc), but all the others are very handy.
For example, you can use the same variable name in multiple ways in a single function: (here a C++ example, but it applies equally to many languages)
MyClass::MyClass(int numItems)
{
mNumItems = numItems;
for (int iItem = 0; iItem < mNumItems; iItem++)
{
Item *pItem = new Item();
itemList[iItem] = pItem;
}
}
You can see here:
- No confusion between member and parameter
- No confusion between index/iterator and items
- Use of a set of clearly related variables (item list, pointer, and index)
Another great point of "iName" iterators is that I never index an array with the wrong index, and if I copy a loop inside another loop I don't have to refactor one of the loop index variables.
Compare this unrealistically simple example:
for (int i = 0; i < 100; i++)
for (int j = 0; j < 5; j++)
list[i].score += other[j].score;
(which is hard to read and often leads to use of "i" where "j" was intended)
with:
for (int iCompany = 0; iCompany < 100; iCompany++)
for (int iUser = 0; iUser < 5; iUser++)
companyList[iCompany].score += userList[iUser].score;
(which is much more readable, and removes all confusion over indexing)
The next benefit is that code snippets do not require any context to be understood. I can copy two lines of code into an email or a document, and anyone reading that snippet can tell the difference between all the members, constants, pointers, indexes, etc. I don't have to add "oh, and be careful because 'data' is a pointer to a pointer", because it's called 'ppData'.
And for the same reason, I can read a line of code, and I don't have to move my eyes out of the line of code in order to understand it. I don't have to search through the code to find if 'data' is a local, parameter, member, or constant. So programmers can read and understand the code significantly faster, because they don't waste time searching up and down.
The 'm' prefix also avoids the (IMHO) hideous and wordy "this->" notation, and the inconsistency that it guarantees (even if you are careful you'll usually end up with a mixture of 'this->data' and 'data' in the same class, because nothing enforces a consistent spelling of the name).
The last major benefit is with Intellisense and auto-completion. Try using Intellisense on a Windows form to find an event - you have to scroll through hundreds of mysterious base class methods that you will never need to call to find the events. But if every event had an "e" prefix, they would automatically be listed in a group under "e". Thus, prefixing works to group the members, consts, events, etc in the intellisense list, making it much quicker and easier to find the names you want. (Usually, a method might have around 20-50 values (locals, params, members, consts, events) that are accessible in its scope. But after typing the prefix (I want to use an index now, so I type 'i...'), I am presented with only 2-5 auto-complete options. The 'extra typing' people attribute to prefixes and meaningful names drastically reduces the search space and measurably accelerates developent speed)
I'm a lazy programmer, and the above convention saves me a lot of work. I can code faster and I make far fewer mistakes because I know how every variable should be used.