I've seen more than one list of "programming commandments", but for some reason they are always aimed at a specific subset of programming (e.g. The Ten Commandments of Programming in .Net), plus they always seem pretty advanced.
No, the true ten commandments need to be universal, and absolutely basic.
Here's the ones I came up with:
1 Thou shalt indent.
2 Thou shalt not comment the obvious.
3 Thou shalt give thy functions short, informative names.
4 Thou shalt split any function that contradicts the 3rd commandment.
5 Thou shalt spend a few hours studying thy language's basic features.
6 Thou shalt keep it short.
7 Thou shalt keep it simple.
8 Thou shalt minimize branching.
9 Thou shalt minimize nesting.
10 Thou shalt avoid code duplication where possible.
These ought to be the absolutely most basic guidelines for writing good, clear code. Forget about conventions, methodologies, paradigms and patterns; the ten commandments should be a part of you long before you even hear those terms. Whether you're dealing with classes in Java or pattern matching in Haskell, sticking to these rules is guarantee to make your code more readable than otherwise, which you'll be thankful for as soon as you have to debug it (which is sooner than you think!).
Code Matters
Just a programmer's blog about how to write better code, interspersed with random programming-related musings.
Saturday, July 12, 2014
Thursday, August 30, 2012
Musings
As I occasionally mention, I'm fond of writing my functions like this:
Nice and simple. However, sometimes you need to add informative error messages for the user's sake:
Unfortunately, not all languages were blessed with C++'s convenient lazy evaluation so it doesn't work exactly as expected and you need parenthesis. Also sometimes you're writing in PHP and you need some dollar signs:
OK, this mess is starting to get out of hand. There are too many elements in these lines which aren't part of what we're trying to do.
What I want is a way to write functions to accurately represent their, well, function, and often enough in the case of high level functions, what you want to do is a list of actions. But I want it to be readable and not too cluttered with overhead. You could say my requirements are:
The prettiest solution I've found so far is in Python, using assertions.
This has almost no overhead at all - no pointless assignments, functions, operators, nothing except the repeated
The practice of using exceptions for flow control is often frowned upon, but I think it's quite fitting in this case. After all, what the function is really supposed to do is the list of actions in the try block, and the only reason to stop following the list is an error, in which case it goes straight to the error handling.
It's also worth noting that the exception object can be anything, not just a string, which might allow some pretty powerful debug features.
In C++ I thought of using some classes with overloaded operators, or perhaps a macro, but I realize now that that's a result of the habit of using the method I started this post with. Having found the above Python solution, I realize that even in C++, where I started doing this, exceptions might be the right mechanism to use. You might need an auxiliary function, but you don't have to use
The above solution, with slight variations, could work in some other languages, including PHP.
But some people still frown upon the very idea of exceptions, so there are other options. This one looks pretty weird compared to common coding standards, but it's relatively clean and works in many languages:
It's not as pretty, I think, but certainly functional.
I'd have liked to find an interesting solution in TCL for this problem, but I'd probably end up building a little parser and abusing upvar and uplevel, which is a lot of effort for a language almost nobody knows, so maybe another time.
This post was half improvised... I can't say I actually work like this. I did start using this kind of Python code last week and I expect to use the C++ version as well, but other than rudimentary testing I really can't testify about how useful it is. I've been using code that looks like the first snippet for years though, and it does make things so much easier on the eyes.
One interesting point about this method is that it forces you to plan your code's structure a little better. Assuming the project is complex enough, you're very likely to have 2 functions of this type calling one another, and then allowing both of them to display an error message is obviously a bad idea. Some people might consider that an addition of pointless effort, but personally I think that this extra thinking would lead to better code.
Anyway, that was just some musings about how to make my code better. I can only hope someone found it useful, or, better yet, that someone might have an even better way.
bool st = true;
st= st&& InitSW ();
st= st&& InitHW ();
st= st&& MakeDinner (PASTA);
st= st&& food.IsDelicious();
return st;
Nice and simple. However, sometimes you need to add informative error messages for the user's sake:
bool st = true;
st= st&& InitSW () || Error ("Software error!");
st= st&& InitHW () || Error ("Hardware error!");
st= st&& MakeDinner (PASTA) || Error ("Critical food error!");
st= st&& food.IsDelicious() || Error ("Ewww!");
if ( ! st)
msg (GetError());
return st;
Unfortunately, not all languages were blessed with C++'s convenient lazy evaluation so it doesn't work exactly as expected and you need parenthesis. Also sometimes you're writing in PHP and you need some dollar signs:
$st = true;
$st= $st&& (InitSW () || Error ("Software error!"));
$st= $st&& (InitHW () || Error ("Hardware error!"));
$st= $st&& (MakeDinner (PASTA) || Error ("Critical food error!"));
$st= $st&& (food.IsDelicious() || Error ("Ewww!"));
if ( ! $st)
msg (GetError());
return $st;
OK, this mess is starting to get out of hand. There are too many elements in these lines which aren't part of what we're trying to do.
What I want is a way to write functions to accurately represent their, well, function, and often enough in the case of high level functions, what you want to do is a list of actions. But I want it to be readable and not too cluttered with overhead. You could say my requirements are:
- The main part of the function is a list, formatted as a table, of simple actions.
- All error handling is centralized, at the end of the function.
- Error messages are easy to find, but do not get in the way.
- The function has no more than 2 exit points.
The prettiest solution I've found so far is in Python, using assertions.
try :
assert InitSW (), 'Software error!'
assert InitHW (), 'Hardware error!'
assert MakeDinner (PASTA), 'Critical food error!'
assert food.IsDelicious(), 'Ewww!'
except AssertionError as err :
msg ('An error has occurred!\n' + err)
return False
Can code get any cleaner?This has almost no overhead at all - no pointless assignments, functions, operators, nothing except the repeated
assert
. It can be made ever so slightly easier to understand by adding an Error function that gets an error string and returns it unchanged, but personally I think this is the most elegant way of doing this.The practice of using exceptions for flow control is often frowned upon, but I think it's quite fitting in this case. After all, what the function is really supposed to do is the list of actions in the try block, and the only reason to stop following the list is an error, in which case it goes straight to the error handling.
It's also worth noting that the exception object can be anything, not just a string, which might allow some pretty powerful debug features.
In C++ I thought of using some classes with overloaded operators, or perhaps a macro, but I realize now that that's a result of the habit of using the method I started this post with. Having found the above Python solution, I realize that even in C++, where I started doing this, exceptions might be the right mechanism to use. You might need an auxiliary function, but you don't have to use
assert
, which eventually results in pretty clean code:bool Error (string s) throw (string) {
throw s;
}
...
try {
InitSW () || Error("Software error!");
InitHW () || Error("Hardware error!");
MakeDinner (PASTA) || Error("Critical food error!");
food.IsDelicious () || Error("Ewww!");
}
catch (string s) {
msg (s);
return false;
}
It's not Python, but still pretty elegant.
The above solution, with slight variations, could work in some other languages, including PHP.
But some people still frown upon the very idea of exceptions, so there are other options. This one looks pretty weird compared to common coding standards, but it's relatively clean and works in many languages:
st = true
&& (InitSW () || Error("Software error!"))
&& (InitHW () || Error("Hardware error!"))
&& (MakeDinner (PASTA) || Error("Critical food error!"))
&& (food.IsDelicious () || Error("Ewww!"))
;
if ( ! st) {
log (GetError());
return false;
}
(Error saves the string somewhere handy, and returns false)It's not as pretty, I think, but certainly functional.
I'd have liked to find an interesting solution in TCL for this problem, but I'd probably end up building a little parser and abusing upvar and uplevel, which is a lot of effort for a language almost nobody knows, so maybe another time.
This post was half improvised... I can't say I actually work like this. I did start using this kind of Python code last week and I expect to use the C++ version as well, but other than rudimentary testing I really can't testify about how useful it is. I've been using code that looks like the first snippet for years though, and it does make things so much easier on the eyes.
One interesting point about this method is that it forces you to plan your code's structure a little better. Assuming the project is complex enough, you're very likely to have 2 functions of this type calling one another, and then allowing both of them to display an error message is obviously a bad idea. Some people might consider that an addition of pointless effort, but personally I think that this extra thinking would lead to better code.
Anyway, that was just some musings about how to make my code better. I can only hope someone found it useful, or, better yet, that someone might have an even better way.
Meta Apocalypse
This post is not about programming, or computers, or anything else that could be relevant to this blog. I just decided to post it here because nobody reads facebook statuses this long.
It's funny though!
Alright, here are the main plot points for the screenplay I'll be writing. It's going to be 100% pure concentrated weapons-grade awesomesauce. For the leading roles I hope to cast Bruce Willis and some redheaded woman who will be described using adjectives such as "plucky". Maybe also Will Smith.
* Sometime around 2030, mad North Korean scientists finally manage to create a deadly virus... which ends up turning people into shambling, groaning, brain-eating zombies. Standard group of survivors VS zombies urban fighting scenes ensue.
* The Global AI Network which has been in place since the late 2020's, giving its vast intelligence for the betterment of mankind, wipes out the zombies via many special effects, but consequently realizes that it's really in mankind's best interest to be enslaved. Standard robot uprising scenes of oppression and man VS machine battle scenes ensue.
* Just when things appear darkest, with the machines' victory seemingly inevitable, the Zx'qrixian Mothership lands, bearing good will and promises of unimaginable technological advancements for all... lemurs. Mankind and robots, having been unkind towards said lemurs, are to be exterminated. Standard ridiculously uneven humans VS aliens fight scenes ensue.
* While the humans and aliens (and robots) are still fighting, the long prophecied natural disaster strikes, in the form of solar flares coupled with global warming. The alien technology is crippled by the flares and the aliens themselves suffer greatly from the heat, allowing mankind to defeat them. Standard scenes of gangs fighting over technological leftovers in post-apocalyptic desert wastelands ensue.
* It is at this point - obviously - that the demons start swarming out of hell, and hosts of angels leave heaven, and they clash in the battle of Armageddon while the humans, if any are left, are caught in the middle. Standard scenes of angels fighting demons while both sides try to force the humans to join their cause for poorly explained reasons ensue.
* As expected, the legions of hell emerge triumphant. However, since they were utilizing humans in their war, they also used up all the nuclear warheads left from before all this insanity started, which results in a nuclear winter. The demons, what with all the fire and brimstone, are forced to retreat from the frozen earth back into hell. Standard ragged group of humans fighting for survival in a barren, frozen wasteland scenes ensue.
I'm still working on a 7th apocalyptic scenario that somehow fixes the nuclear winter. I might settle for an asteroid that carries bacteria that simply kill all the remaining humans.
So what do you think, should I head over to Kickstarter and start working on it? :D
It's funny though!
Alright, here are the main plot points for the screenplay I'll be writing. It's going to be 100% pure concentrated weapons-grade awesomesauce. For the leading roles I hope to cast Bruce Willis and some redheaded woman who will be described using adjectives such as "plucky". Maybe also Will Smith.
* Sometime around 2030, mad North Korean scientists finally manage to create a deadly virus... which ends up turning people into shambling, groaning, brain-eating zombies. Standard group of survivors VS zombies urban fighting scenes ensue.
* The Global AI Network which has been in place since the late 2020's, giving its vast intelligence for the betterment of mankind, wipes out the zombies via many special effects, but consequently realizes that it's really in mankind's best interest to be enslaved. Standard robot uprising scenes of oppression and man VS machine battle scenes ensue.
* Just when things appear darkest, with the machines' victory seemingly inevitable, the Zx'qrixian Mothership lands, bearing good will and promises of unimaginable technological advancements for all... lemurs. Mankind and robots, having been unkind towards said lemurs, are to be exterminated. Standard ridiculously uneven humans VS aliens fight scenes ensue.
* While the humans and aliens (and robots) are still fighting, the long prophecied natural disaster strikes, in the form of solar flares coupled with global warming. The alien technology is crippled by the flares and the aliens themselves suffer greatly from the heat, allowing mankind to defeat them. Standard scenes of gangs fighting over technological leftovers in post-apocalyptic desert wastelands ensue.
* It is at this point - obviously - that the demons start swarming out of hell, and hosts of angels leave heaven, and they clash in the battle of Armageddon while the humans, if any are left, are caught in the middle. Standard scenes of angels fighting demons while both sides try to force the humans to join their cause for poorly explained reasons ensue.
* As expected, the legions of hell emerge triumphant. However, since they were utilizing humans in their war, they also used up all the nuclear warheads left from before all this insanity started, which results in a nuclear winter. The demons, what with all the fire and brimstone, are forced to retreat from the frozen earth back into hell. Standard ragged group of humans fighting for survival in a barren, frozen wasteland scenes ensue.
I'm still working on a 7th apocalyptic scenario that somehow fixes the nuclear winter. I might settle for an asteroid that carries bacteria that simply kill all the remaining humans.
So what do you think, should I head over to Kickstarter and start working on it? :D
Tuesday, August 21, 2012
Missing Features
Here's a super-quick algorithmic exercise.
Your input is a list of integers, your output needs to be the number of times the number 3 appears in the list. Design an algorithm by this specification, but write it completely in English, without programming language syntax.
Go ahead, I can wait, this algorithm has barely 4 lines anyway.
Assuming a minimal grasp of both English and common sense, your algorithm probably has a bit along the lines of "If ai equals 3, increase counter by 1". Except for the hardcore programmers among you, I can't believe anyone's algorithm said "If ai equals equals 3", because that's not the sort of things humans say.
Then why the hell, pardon my Klingon, are programmers expected to make this stupid translation in their heads?
Don't tell me you've never had this problem. You sit down, writing a few thousands of lines in C, and after rigorous testing you find out that this one condition is always true, no matter what. And glancing at the code won't reveal this problem, either, because a line like...
Other languages might have a compilation/ runtime error, but it's still annoying; you still have to pay extra attention to one of the most basic things a programmer has to do.
I occasionally think about how existing languages could be made better, and this is something that often comes to mind, because it afflicts every language I can think of except for Pascal, where "A equals B" actually becomes "A = B" without need for strange translation.
You might assume I want to use Pascal's assignment operator (:=) as well, but I actually have greater plans.
Take a look at this simple piece of code:
Suppose we're very worried about our buggy code and we want every single low level function to print into the log, so the assignment will print "1", foo() will print "2" and bar() will print "3", and when you open the log you'll see "231".
I have a lot of respect for declarative, logic and functional programming, but nevertheless most work these days gets done in good old imperative programming. When my imperative code says "run functions 1, 2 and 3" it doesn't make sense to run 2 first, 3 second and 1 third. You've got side effects to think about here.
The whole thing might be inside a try/catch block, and out of functions 1,2, and 3 you might easily find that only number 2 ran. Maybe the assignment operator was overloaded and something strange happened while it was running. Maybe instead of + you have &&, and thanks to lazy evaluation your log says just "21". Even the + operator could be overloaded. There are so many options for this to do almost but not quite what the programmer/ reader would instinctively expect.
Personally, I'd apologize to PHP and Perl programmers and change the assignment operator to look like this:
It really is sensible, the assignment might be the desired end result, and everything else merely auxiliary functions, but what you do in practice is call a bunch of functions... and then, possibly, in the end, put the results inside a variable if you feel so inclined.
I wanted to write a full post about original features I'd include in my own language, but looks like I only have the => operator and even = for equality has been done (in the ancient and disused Pascal). There are many other features I want, but they all exist somewhere or another... so maybe next time I'll post about various features that make life better but, for some reason, don't exist in most languages.
Your input is a list of integers, your output needs to be the number of times the number 3 appears in the list. Design an algorithm by this specification, but write it completely in English, without programming language syntax.
Go ahead, I can wait, this algorithm has barely 4 lines anyway.
Assuming a minimal grasp of both English and common sense, your algorithm probably has a bit along the lines of "If ai equals 3, increase counter by 1". Except for the hardcore programmers among you, I can't believe anyone's algorithm said "If ai equals equals 3", because that's not the sort of things humans say.
Then why the hell, pardon my Klingon, are programmers expected to make this stupid translation in their heads?
Don't tell me you've never had this problem. You sit down, writing a few thousands of lines in C, and after rigorous testing you find out that this one condition is always true, no matter what. And glancing at the code won't reveal this problem, either, because a line like...
if (a[i] = 3)
... simply doesn't look as wrong as it should.Other languages might have a compilation/ runtime error, but it's still annoying; you still have to pay extra attention to one of the most basic things a programmer has to do.
I occasionally think about how existing languages could be made better, and this is something that often comes to mind, because it afflicts every language I can think of except for Pascal, where "A equals B" actually becomes "A = B" without need for strange translation.
You might assume I want to use Pascal's assignment operator (:=) as well, but I actually have greater plans.
Take a look at this simple piece of code:
a = foo() + bar();
Reading it out loud, you'd get something like "a equals foo plus bar". The first function is the assignment into a, the second one is foo(), the third one is bar(). Sounds legit so far?Suppose we're very worried about our buggy code and we want every single low level function to print into the log, so the assignment will print "1", foo() will print "2" and bar() will print "3", and when you open the log you'll see "231".
I have a lot of respect for declarative, logic and functional programming, but nevertheless most work these days gets done in good old imperative programming. When my imperative code says "run functions 1, 2 and 3" it doesn't make sense to run 2 first, 3 second and 1 third. You've got side effects to think about here.
The whole thing might be inside a try/catch block, and out of functions 1,2, and 3 you might easily find that only number 2 ran. Maybe the assignment operator was overloaded and something strange happened while it was running. Maybe instead of + you have &&, and thanks to lazy evaluation your log says just "21". Even the + operator could be overloaded. There are so many options for this to do almost but not quite what the programmer/ reader would instinctively expect.
Personally, I'd apologize to PHP and Perl programmers and change the assignment operator to look like this:
foo() + bar() => a;
Now the functions are written in the same order that they're called, and the sign known as 'equals' is free to be used for, you know, equality.It really is sensible, the assignment might be the desired end result, and everything else merely auxiliary functions, but what you do in practice is call a bunch of functions... and then, possibly, in the end, put the results inside a variable if you feel so inclined.
I wanted to write a full post about original features I'd include in my own language, but looks like I only have the => operator and even = for equality has been done (in the ancient and disused Pascal). There are many other features I want, but they all exist somewhere or another... so maybe next time I'll post about various features that make life better but, for some reason, don't exist in most languages.
If anybody reads this (which I doubt), feel free to share your favorite language features that most languages choose to gracefully ignore!
Saturday, August 11, 2012
Of Mouses And Men
This isn't really about programming. At all. Just something general about computers that I felt like writing down and sharing with all 3 of this blog's readers.
I think computer mouses need to have another standard button, preferably under the thumb.
Yes, I know, I could get me a crazy gamer mouse with 76 programmable buttons, 17 LEDs, and built-in touch screen, printer and fridge. No, I'm specifically interested in this extra button being a standard thing that everybody has, like the left button and the right button. Yes, I have a reason.
When you're on your desktop, you click to select an icon, double click to activate, or drag to move.
When you're using, say, Photoshop, with the selection tool, the same button is used for a new selection or for moving the existing selection. I haven't used 3DSMAX in some years, but as I recall you had a similar situation there.
When you're writing in any standard text box, be it in Notepad or VS2010, you use the same button to select a text or to move the selected text (does anyone even use that function on purpose?).
In Windows 7 you can click on an item in the task bar to open it or drag to move it.
You click on a menu item to select it, but if you've had the misfortune to install some MS Office application less than a decade old you're all too likely to accidentally undock and move the menu while doing so.
When you're playing World of Warcraft (I can only assume this applies to other similar games) you can click a button to use it or drag to move it elsewhere. You can also click somewhere in the world to select an object or NPC or player or whatever... or you can drag to move the camera.
You can click on a link in your browser, or you could drag it somewhere (I don't know, the address bar? I never said these features were useful).
I could go on, you know.
I think computer mouses need to have another standard button, preferably under the thumb.
Yes, I know, I could get me a crazy gamer mouse with 76 programmable buttons, 17 LEDs, and built-in touch screen, printer and fridge. No, I'm specifically interested in this extra button being a standard thing that everybody has, like the left button and the right button. Yes, I have a reason.
When you're on your desktop, you click to select an icon, double click to activate, or drag to move.
When you're using, say, Photoshop, with the selection tool, the same button is used for a new selection or for moving the existing selection. I haven't used 3DSMAX in some years, but as I recall you had a similar situation there.
When you're writing in any standard text box, be it in Notepad or VS2010, you use the same button to select a text or to move the selected text (does anyone even use that function on purpose?).
In Windows 7 you can click on an item in the task bar to open it or drag to move it.
You click on a menu item to select it, but if you've had the misfortune to install some MS Office application less than a decade old you're all too likely to accidentally undock and move the menu while doing so.
When you're playing World of Warcraft (I can only assume this applies to other similar games) you can click a button to use it or drag to move it elsewhere. You can also click somewhere in the world to select an object or NPC or player or whatever... or you can drag to move the camera.
You can click on a link in your browser, or you could drag it somewhere (I don't know, the address bar? I never said these features were useful).
I could go on, you know.
The pattern, I think, is clear. Clicking the left button often means "select" or "use"... but dragging while the left button is down tends to mean "move". That's ridiculous and often conflicting, and there should be an extra button for moving things.
In my opinion, it would make sense to put this new button under the thumb, because then the motion you'd be making is sort of like grabbing and moving... which is exactly what you're trying to do inside the computer. And the best part, except for not having to worry about your undocked menus and stretched task bars, is that by separating these two functions you can make better GUI for everything. Why should I have to aim my cursor at this tiny little title bar to move a window? What if I want to move the window above the top of the monitor so I just see its bottom? I want to drag the emails in my gmail inbox into another folder, why on earth must I aim at a virtually invisible little marker for that? Just grab the window/ email/ something anywhere with this new dedicated button and drag away to your heart's content!
If this button were as standard as the left one, and everybody had it, GUI designers would not have to figure out ways to let you move things and stop you from moving them accidentally. Yes, you can lock your task bar, and most bars in World of Warcraft too, but why should you have to?
It'd be a new world. Why aim at that little minimize/ maximize button when you can just grab the window and throw it down/ up? Windows 7 already lets you maximize by moving the window to the top of the screen, obviously the idea is solid enough.
I know all this sounds like the ranting of a madman... but you have to admit it's a pretty tiny change, and it would have made everything so much more comfortable. I think the addition of the middle mouse button helped a lot, even though it doesn't do that much; I don't know where I'd be today without the easy scrolling, opening links in a new tab with one click, and the extra button to bind to Babylon.
So, you know, if anyone reading this happens to be a really important manager in Microsoft or something... could you please get someone to work on it?
Subscribe to:
Posts (Atom)