Before we dive into the topic of this post, I would like to share with you the best possible advise I could ever give – never do everything by the book.
I know it sounds kinda odd and may appear to be irresponsible. After all, this series is about what to avoid and promote best practice. Am I not asking you do what I tell you? No, I am not.
I am asking you to think and to reason consciously why you chose to code something the way you did.
In the first post of this series, I wrote about how returning early improves code readability. It may appear so in the code snip presented in the post. It may seem to be appropriate in scenarios off the top of your head. However, I am most certain that there are contexts where returning early actually does the opposite – hurting code readability.
It is important that we understand a best practice is anything but the law. When circumstances change, it may not stand.
I ask you to think as you code.
Now, back to the topic. In this post, we will revisit a well known best practice from a less discussed perspective.
It is almost always a good practice to define variables where they are first needed, but not earlier. Doing otherwise is almost certainly asking for trouble. Take this WinMain() function from Miranda IM for example, and fast forward to line 649, the first line of interest of this post:
CreateServiceFunction(MS_SYSTEM_SETIDLECALLBACK,SystemSetIdleCallback);
CreateServiceFunction(MS_SYSTEM_GETIDLE, SystemGetIdle);
dwEventTime=GetTickCount();
myPid=GetCurrentProcessId();
for(;messageloop;) {
MSG msg;
DWORD rc;
BOOL dying=FALSE;
rc=MsgWaitForMultipleObjectsExWorkaround(waitObjectCount, hWaitObjects, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);
It is a for statement using the variable messageloop as its condition.
Depending on your preference to trace code forwards or backwards, visit Miranda IM’s source browser via either link, and try answering this – what are the possible values of messageloop when the for loop starts?
Before we go on, please allow yourself a minute or two to go through the code and find out the answer.
Okay, now that we know the variable messageloop was defined at line 546 as int with the value 1 at the beginning of WinMain().
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int )
{
DWORD myPid=0;
int messageloop=1;
HMODULE hUser32, hThemeAPI, hDwmApi, hShFolder = NULL;
And as it turns out, messageloop was never modified, in fact, it was never referenced elsewhere, except at line 649, as the condition of said for statement. That’s more than 100 LOC (lines of code) apart, and nothing relevant in between.
I don’t know about you, but I think it is pure annoying to make people going through more than a few LOC, and end up learning there was nothing of interest, it is a major waste of time and one of the best ways to upset people.
Mayers has been telling us to postpone variable definitions as long as possible for more than a decade. If you are not convinced by the book for whatever reason, think code readability, and make the lives of your fellow code readers easier.
One day, that reader of your code may very well be you.
« Function overloading by return type Why is Force Killing Threads a Bad Idea? »

這是慣C用法,寫慣了 C 的人會有的壞習慣。
是啊, 我知道. 但 21 世紀都已經過了 10 年了呢. XD
需要 define variable earlier 的情境:
http://www.jeffhung.net/blog/articles/jeffhung/1245/
XD