Make your source code readable
by Konrad Kiss · 10/14/2008 (12:04 pm) · 10 comments
Beauty is in the eye of the beholder they say. So forgive me if I use the term beautification of code. This is what this article is all about.
For long, I've been having a problem with code that looks like this:
This is not easy to read. I like code that has blocks even if it's just one command in there - or even none at all. It's a lot easier to understand where a block begins and where it ends, plus it's easier to expand the contents of a block when brackets are always used.
Also, I like code where indentation is telling me something about the depth of the block. Since in the source, in many places this is not as it should be, I'd decided to beautify my code.
Right away, I came to realize, that this will probably not help when I want to merge code in through following a resource, or when I want to port the changes to a new version of the engine. However, I've made peace with that. I am hoping to learn enough just by being able to read code faster, and I believe that I am going to save much time in the following months or years - definitely more than what I'd need to merge.
First of all, I backed everything up, and if you are following this, you better do it as well! This is important because 3-4 files will break after the conversion, and need to be copied over by the originals from your backup! I did this at my own risk, and you do it at your own. This can really mess up your source if you are not careful!
I've found Universal Indent GUI ( http://universalindent.sourceforge.net ) that helped me to set rules through which the code was changed. I've used the crustify indenter, and created a config file that you can download here in case you like the following syntax more:
That's more like it. The software can even create a batch file that can be used to replace all files of a certain extension (second param) in a specific directory (first param) and all subdirectories. So you can issue something like this:
Before running the conversion, make sure that you remove math/mMathAltivec.cpp from the directory that you wish to beautify. I've found that the converter does not like that one and probably gets into an infinite loop.
After running the conversion, you will need a clean rebuild. You will see that a few files report errors. You should replace these files with the original ones that you have already backed up.
I've ran tests to see if everything was behaving as it should, and for now, I have not found anything that's out of the ordinary, but this of course needs a lot more testing. It is possible that syntax is broken in a way that is not recognized by the compiler, and eventually results in weird runtime behavior. Well, hopefully not. Uncrustify did a pretty good job converting the code to a format that I find more readable when working with C++.
If you want to give it a try, go ahead, but make sure you keep your backup around, it will be useful when you are debugging some new error that just came up after the conversion. :) Hehe. Just kidding. (You wish.)
Good luck! (really)
For long, I've been having a problem with code that looks like this:
stream->write(body.restitution);
stream->write(body.friction);
for (i = 0; i < Body::MaxSounds; i++)
if (stream->writeFlag(body.sound[i]))
stream->writeRangedU32(packed? SimObjectId(body.sound[i]):
body.sound[i]->getId(),DataBlockObjectIdFirst,
DataBlockObjectIdLast);This is not easy to read. I like code that has blocks even if it's just one command in there - or even none at all. It's a lot easier to understand where a block begins and where it ends, plus it's easier to expand the contents of a block when brackets are always used.
Also, I like code where indentation is telling me something about the depth of the block. Since in the source, in many places this is not as it should be, I'd decided to beautify my code.
Right away, I came to realize, that this will probably not help when I want to merge code in through following a resource, or when I want to port the changes to a new version of the engine. However, I've made peace with that. I am hoping to learn enough just by being able to read code faster, and I believe that I am going to save much time in the following months or years - definitely more than what I'd need to merge.
First of all, I backed everything up, and if you are following this, you better do it as well! This is important because 3-4 files will break after the conversion, and need to be copied over by the originals from your backup! I did this at my own risk, and you do it at your own. This can really mess up your source if you are not careful!
I've found Universal Indent GUI ( http://universalindent.sourceforge.net ) that helped me to set rules through which the code was changed. I've used the crustify indenter, and created a config file that you can download here in case you like the following syntax more:
stream->write(body.restitution);
stream->write(body.friction);
for (i = 0; i < Body::MaxSounds; i++) {
if (stream->writeFlag(body.sound[i])) {
stream->writeRangedU32(packed ? SimObjectId(body.sound[i]) :
body.sound[i]->getId(), DataBlockObjectIdFirst,
DataBlockObjectIdLast);
}
}That's more like it. The software can even create a batch file that can be used to replace all files of a certain extension (second param) in a specific directory (first param) and all subdirectories. So you can issue something like this:
call_Uncrustify.bat c:\Torque\TGEA_1_7_1\engine\source cpp
Before running the conversion, make sure that you remove math/mMathAltivec.cpp from the directory that you wish to beautify. I've found that the converter does not like that one and probably gets into an infinite loop.
After running the conversion, you will need a clean rebuild. You will see that a few files report errors. You should replace these files with the original ones that you have already backed up.
I've ran tests to see if everything was behaving as it should, and for now, I have not found anything that's out of the ordinary, but this of course needs a lot more testing. It is possible that syntax is broken in a way that is not recognized by the compiler, and eventually results in weird runtime behavior. Well, hopefully not. Uncrustify did a pretty good job converting the code to a format that I find more readable when working with C++.
If you want to give it a try, go ahead, but make sure you keep your backup around, it will be useful when you are debugging some new error that just came up after the conversion. :) Hehe. Just kidding. (You wish.)
Good luck! (really)
About the author
Lead Developer at Bitgap Games (www.bitgap.com) currently working on Xenocell (www.xenocell.com) a massively multiplayer action strategy game based on Torque 3D technology.
#2
for example i'm a huge fan of lining stuff up in columns:
10/14/2008 (6:58 pm)
my problem with code beautifiers is that they invariably destroy formatting inside the line,for example i'm a huge fan of lining stuff up in columns:
Line up everything possible! // bad: int RenderInit(); void RenderGo(); unsigned char* RenderUpdate(); int RenderDeinit(); // better: int RenderInit(); void RenderGo(); unsigned char* RenderUpdate(); int RenderDeinit(); // best: int RenderInit (); void RenderGo (); unsigned char* RenderUpdate (); int RenderDeinit ();
#3
10/14/2008 (11:51 pm)
The internets ate my post, so to summarize... visual assist is a nice plugin for visual studio (has a hefty price after the trial though), its formatting does make it easier to pick out return type / function name / parameters so (for one thing) taking the time lining things up isn't necessary.
#4
@Orion: There are rules to do just that and only that in Universal Indent. There are really numerous indenting and new line rules that you can use. So for example in class constructors, I have now all the default value assigns done just the way you described. I didn't do it for variables though, but even the format you described as best is possible.
@James: Sounds cool, but I was looking for something that's indie budget friendly. The coolest thing would be if it would not modify the source, but present you with an indented version when working, optionally. So any code written the old way could be viewed as it is or indented. t would make merging a lot easier.
10/15/2008 (12:44 am)
@Scott: I can understand how compact code can make for readable code, but the indenting with the first example is way messed up. You must be wanting to change at least that, right? :)@Orion: There are rules to do just that and only that in Universal Indent. There are really numerous indenting and new line rules that you can use. So for example in class constructors, I have now all the default value assigns done just the way you described. I didn't do it for variables though, but even the format you described as best is possible.
@James: Sounds cool, but I was looking for something that's indie budget friendly. The coolest thing would be if it would not modify the source, but present you with an indented version when working, optionally. So any code written the old way could be viewed as it is or indented. t would make merging a lot easier.
#6
10/15/2008 (7:52 am)
I agree with Scott - if you're picky about formatting, it makes more sense to me to have the opening bracket on its own new line. But meh. I'm not that way - I like simplicity, so I often leave off brackets in one-liners. Though I agree, the indenting in your first example is pretty wacked. I find that Ctrl+k, Ctrl+f in VS2005 suits my needs - it just fixes indentation.
#7
consistent. I've done much contract work over the years and have found
that you can work with anything given a short time. I believe in all
code formatting religions.
The first "horrible" example has a simple formatting rule. Indent the target
of control statement. Nothing really messed up about that, just not your
cup of tea.
10/15/2008 (11:00 am)
I personally believe that (almost) any style is acceptable as long as it'sconsistent. I've done much contract work over the years and have found
that you can work with anything given a short time. I believe in all
code formatting religions.
The first "horrible" example has a simple formatting rule. Indent the target
of control statement. Nothing really messed up about that, just not your
cup of tea.
#8
I actually liked the first example more. Granted I would have indented the word wrapped lines more, or even maybe made it all one line. It's only the word wrap that throws off the "readability" there.
In the end it's all just a matter of personal preference. It's consistency in style/formatting that counts.
But thanks for the pointer about Universal Indent GUI.
10/15/2008 (12:14 pm)
Other than increasing the indent, adding the unnecessary brackets, and indenting/lining up the word wrap you didn't really change anything from that first example. I make a point of removing brackets from one line blocks, I prefer "tighter" indentation, and I too dislike the open bracket at the end of a line.I actually liked the first example more. Granted I would have indented the word wrapped lines more, or even maybe made it all one line. It's only the word wrap that throws off the "readability" there.
In the end it's all just a matter of personal preference. It's consistency in style/formatting that counts.
But thanks for the pointer about Universal Indent GUI.
#9
Quit commenting my style already! :) I've been using this for more than 16 years, and I will do so for the rest of my life. But that's not the point. The point is that with Torque, I was forced to read (and write) in a style that made developing a bit harder for me. This is to make reading and writing code easier for everyone, but not necessary in the same way.
I'm used to look at code, and when I see an if or a for, I know that that begins a block. Because it always does, even with a single line of code in the block - according to my style. So there's no need for a bracket below, it just takes space. Ah, I'm not wanting you guys to change religion, just wanted to show a way to those who feel like I did. If you are not missing a style change, consider yourself lucky! ;)
Changing it has already paid off. I've noticed that I'm progressing faster - a lot faster. I now have every function's name at the function's closing bracket in a comment, and that just saved me the time to scroll up and find what function I'm viewing. I've not used this before, but it certainly is very useful.
Regardless of style, if you fit the code to your style the best you can, you will be able to work better and faster - and the single aim of this how-to is to help you there.
10/15/2008 (12:46 pm)
Through my personal preference, I tried to show the process through which coding style and format can be changed to be unified and fit each devs personal preference. Quit commenting my style already! :) I've been using this for more than 16 years, and I will do so for the rest of my life. But that's not the point. The point is that with Torque, I was forced to read (and write) in a style that made developing a bit harder for me. This is to make reading and writing code easier for everyone, but not necessary in the same way.
I'm used to look at code, and when I see an if or a for, I know that that begins a block. Because it always does, even with a single line of code in the block - according to my style. So there's no need for a bracket below, it just takes space. Ah, I'm not wanting you guys to change religion, just wanted to show a way to those who feel like I did. If you are not missing a style change, consider yourself lucky! ;)
Changing it has already paid off. I've noticed that I'm progressing faster - a lot faster. I now have every function's name at the function's closing bracket in a comment, and that just saved me the time to scroll up and find what function I'm viewing. I've not used this before, but it certainly is very useful.
Regardless of style, if you fit the code to your style the best you can, you will be able to work better and faster - and the single aim of this how-to is to help you there.
#10
we use
10/17/2008 (11:14 am)
I woulds also encourage marking all changes with a special start and end tag. It might seem tedious at first but if you get into a habit of it you will find that porting your code to a more recent version of the engine or to another code base entirely will be less cumbersomewe use
// > pg description // new code here // < pg descriptionat Plastic Gamee
Employee Scott Burns
GarageGames
However, I see this tool as being rather useful when comes to people on a team who have problems following a set coding standard.