Trying something different, reformatting a binary search in C++
Thursday, 29 January 2015
Saturday, 17 January 2015
Whitespace, you're doing it wrong.
What if there was a scientific, objective way to format the whitespace in your current programming language?
Received wisdom tells us that choice of formatting styles is a purely subjective choice. The same as choosing a coffee blend, or finding the best way to paint your bikeshed.
What if they lied?
What if it was indeed possible to develop a framework to measure, compare and contrast formatting styles in a rational, objective way by applying the Scientific Methodtm?
As a community, we could then migrate towards a formatting style based on a series of measurable scientific tests, such that every competent programmer would agree on the outcome, even when that outcome differed from their own personal preference.
We might even then invoke Stigler's law and name such a formatting style “The Kolmogorov Style” for formatting programming languages.
What would you do if your favourite subjective choice turned out to be different from the Kolmogorov Style? What would you be forced to do, if I could scientifically prove that your whitespace choices, what you thought was your subjective preference, was objectively wrong?
Read on if you're genuinely brave enough to challenge your preconceptions...
TRIGGER WARNINGS : Unicode, indentation, tabs, newlines, braces, Kolmogorov complexity
Warning : This post requires unicode to read correctly. If your browser does not support unicode, please stop reading now.
- Note 1 : This blogpost will be continuously updated in response to reader feedback. Because Peer Review.
- Note 2 : Formatting conventions and other terminology follow wikipedia.
- Note 3 : I'm using C/C++ merely for convenience here. Obviously this extends to other (programming) languages in a natural way.
- Note 4 : It seems some brave souls are actually attempting research of this sort : http://ppig.org/sites/default/files/2015-PPIG-26th-Sarkar.pdf Way to go guys!
Existence proof
This is going to take a little bit of work, so I'm going to proceed in stages.
First up, I'm going to construct what theoretical mathematicians call an 'existence proof'. That's a standalone proof where I show it is possible to find an objective test of a formatting style, such that 100% of programmers will reach the same conclusion. The objective test won't be convincing! It's not intended to be convincing. The point of this section merely illustrates that it is possible to construct at least one objective test to make a decision between alternative formatting options. Only once we have our existence proof, will we be able start our search for the best objective tests to use.
As a pure hypothetical for this section, suppose we're starting a completely new project, purely for our own personal enjoyment, and we're trying to decide if we should indent using the TAB character, or indent using 4xSPACE.
For our objective metric, we will measure the disk space required to store the code, with smaller being better.
For our objective metric, we will measure the disk space required to store the code, with smaller being better.
We know that the TAB character ('\t') is 1 byte, and 4xSPACE, (' ') takes up 4 bytes.
Now, here's the part where I apply the scientific method! I select a representative source file from my hard drive, and prepare two versions, one with TAB indentation, and one with 4xSPACE indentation.
This particular file happened to have 2654 tabs, so we can cross-check :
RandomCPPFileTAB.cpp : 30,430 bytes
RandomCPPFile4xSPACE.cpp : 38,392 bytes
The results of my experiment showed the 4xSPACE version of this file is 26% larger than the TAB version.
I urge you to apply the scientific method and actually perform this experiment to determine if it is repeatable!
Extrapolating from this single data point(!), we expect that source files which use 4xSPACE would, on average, take up a larger amount of disk space, somewhere in the ballpark of 20% - 30% more.
Any competent C++ programmer can follow this chain of reasoning and agree that C++ files which use 4xSPACE are never smaller than the equivalent TAB version.
Crucially, my claim is that everybody who competently performs this particular objective test will obtain this same result (TAB beats 4xSPACE), even if they personally prefer 4xSPACE over TAB.
Now, before y'all start complaining that I chose an unfair metric, let me just repeat : This is an existence proof.
The entire point of this section is to establish the following hypothesis : “There exists at least one objective test which can be used to make a decision between alternative formatting options.”
Just to be 100% crystal clear, I'm not claiming this isolated test is sufficient for anyone to change spaces to tabs or vice versa!
The only point that I've proved is that it is possible for at least one objective test for whitespace stylistic concerns to actually exist, and therefore, by extension, it is meaningful to look for more.
(However, I feel obliged to point out that Kolmogorov Style does indeed use tabs instead of spaces for the C++ language. I certainly haven't proved it... But I think I can illustrate the fact by issuing the following challenge: If there exists even one objective scientific test against (i.e. 100% of competent C++ programmers would complete the test and choose 4xSPACE over TAB) then please post such a test in the comments below. I'll be sure to update this post if an objective scientific test does exist.)
Another example, Find in Files, :lgrep, Find in Workspace, M-x rgrep
Here's another motivating example, again purely for illustrative purposes. It's not intended to be convincing, the goal is simply to illustrate that it is possible to construct objective tests where 100% of competent programmers will reach the same conclusion about a formatting style, even if their personal preference is different.
Again, pure hypothetical, entirely new project, we're trying to decide between two ways to format a C++ class declarations:
class Allman
:
public Style
{
//...
};
class Stroustrup : public Style {
//...
};
Every programming environment provides some facility for matching lines within a codebase, so our objective test will be : Which formatting style gives us more information about the class hierarchy, as a result of performing 'grep class *.h'. (i.e. Look in all files which have a .h suffix, and print out any line which contain the string 'class')
Here's what the output might looks with the Allman style:
class Adams
class Jackson
class Garbo
class Greta
class Douglas
class Michael1
class Michael2
class Jackie
class Kennedy
class Sam
And the same code, formatted with Stroustrup style:
class Adams {
class Jackson {
class Garbo {
class Greta : private Garbo {
class Douglas {
class Michael1 : public Douglas {
class Michael2 : private Jackson {
class Jackie : public Kennedy, private Onassis {
class Kennedy {
class Sam : public Adams {
On this particular objective test, I claim that every competent C++ programmer will agree that the Stroustrup style gives more information, even if they personally prefer to use the Allman style.
Once again, if you're at all interested in the scientific method and have access to a C++ codebase, please do a 'find-in-files' or similar. Are you satisfied with the results? Would you have more or less information if your codebase was Allman/Stroustrup style? Please post your results below, especially if they are different!!
We're starting to get closer. We now have two examples of objective tests, and maybe we can even start to see a trend (remove redundant encodings).
We're also beginning to suspect there's probably many families of objective tests, and almost all of them are contradictory.
Take the famous painting the bikeshed problem, how many coats of paint should we use?
- Clearly 2 coats are objectively better than 1, because durability!
- Clearly 2 coats are objectively worse than 1, because cost!
Suddenly our objective tests are starting to look awfully subjective - given a universe of objective tests, how do we choose which are the best objective tests to apply?
To answer that, I'm going to need to introduce “Coding Atoms”.
Introducing Coding Atoms
Atom – indivisible
The smallest, indivisible constituent part or unit of something.
from Ancient Greek ἄτομος (átomos, “indivisible”)
Allow me to introduce a simple C++ coding atom:
✔ int
Just like in physics, we can look inside that 'atom', and see that it has 3 component parts, 'i', 'n', and 't'.
Let's look at the 6 possible permutations of those three parts, and verify that only one of them is valid C++:
✔ int
✗ itn
✗ nit
✗ nti
✗ tin
✗ tni
Here's another way of probing our atom, we'll insert a pair of brackets and confirm that only when the “i”, “n” and “t” are adjacent do we have valid C++.
✔ ()int
✗ (i)nt
✗ (in)t
✔ (int)
✗ i()nt
✗ i(n)t
✗ i(nt)
✗ in()t
✗ in(t)
✔ int()
The component parts of “int” are fused together in a special kind of way, we can't tear them apart, or insert things, or rearrange them and still have a meaningful C++ program.
That's what I'm talking about, when I use the term “coding atom”.
Coding Atoms : Variable Declarations
Allow me to present another atom, a variable declaration using the Resource Acquisition Is Initialization (RAII) principle:
✔ int adams = 42;
Or if we substitute {■ : adams, □ : 42}, we can rewrite our atom like this :
✔ int ■ = □;
Let's try permuting:
✔ int ■ = □;
✗ int ◻ = ■;
✗ ■ = int ◻;
✗ ; ■ int = ◻
✗ ■ int; = ◻
And inserting brackets:
✔ int ■ = (□);
✗ (int ■) = ◻;
✗ (int ■) = ◻;
✗ int (■ = ◻);
In the same way that 'int' is a coding atom, this declaration is 'fused' together. We can't insert or rearrange into it and still have a meaningful C++ program.
Look what happens when we break RAII and split our atom across two lines:
✔ int ■;
✔ ■ = □;
And permute:
✗ ■ = □;
int ■;
Or insert a pair of braces:
{
int ■;
}
✗ ■ = □;
Compiler errors for everyone!
OK, lets try two atoms, this time with comments
✔ int ▲ = △; // triangle
✔ int ■ = □; // square
Permuting and everything is awesome:
✔ int ■ = □; // square
✔ int ▲ = △; // triangle
Rock on! Now braces! All good!
✔ int ▲ = △; // triangle
✔ {
✔ int ■ = □; // square
✔ }
But what if we split the atoms and try to write our comments like this.. maybe that's okay? :
✔ // triangle
✔ int ▲ = △;
✔ // square
✔ int ■ = □;
Permuting, perhaps as a result of sorting the lines alphabetically :
✔ // triangle
✔ // square
✔ int ■ = □;
✔ int ▲ = △;
Whoa, what just happened?!?! Did you just feel the cabin pressure drop? We've produced valid C++ code that compiles just fine, passes all our unit tests, and runs correctly … but our comments are disconnected from their roots and have become actively harmful to our understanding of the code.
These are some of the longest lived families of software defects – the ones where the executable isn't affected and our automatic tools don't notify us when a new problem has been created. This only happened because we allowed a newline to be inside our coding atom.
I know what you're thinking.. “Such a silly mistake would never make it into shipping code”. Well, anecdotally, in the short time since preparing this blogpost as a draft and actually posting it, I've located and repaired defects of exactly this type (on a live production codebase) on at least 4 occasions.
The take home for this section is : At least on this somewhat contrived example (the “reducing defects as a result of random line permutations of variable declarations” test), every single programmer, regardless of their own personal variable declaration preference, who competently performs this experiment, will agree that the best way to declare a variable is with everything on the same line. i.e.:
✔ int ▲ = △; // triangle
Coding Atoms : Mandatory Braces
You're not going to like this one. Not one bit.
Here's the coding atom for an if statement.
✔ if(●){
✔ ◎
✔ }
What happens if we don't use braces at all?
✔ if(●)
✗ ◎
Disaster! Our ◎ atom has been torn apart! Observe:
#define ◎ print(“Hello, World“); log(“Hello, Log”);
As a consequence of not using braces, we've opened ourselves to the possibility of splitting an atom and introducing bugs. I'll formalise this principle more fully in just a moment. But for right now, I'm just going to blurt out:
For any given pair of C++ formatting styles which differ only in their usage of mandatory braces, the style using mandatory braces will be objectively better.
(Oh, you think I'm wrong on this one? First, go read about the gotofail bug Once you think you've understood that, let me know why you think $X is more important that having your code run correctly.)
Anyway, lets press forward! There's an alternate way of formatting conditionals, where the opening brace occurs on a different line from the conditional. I'll come back to the problems with this example very shortly, but for now, I just want to identify the coding atom and move forward.
✔ if(●)
✔ {
✔ ◎
✔ }
Coding Atoms (part 3)
Here's a short list of some of the frequently encountered (C++) coding atoms:
▵;//comment
int ▵=▵;
if(▵){▵}
while(▵){▵}
for(▵;▵;▵){▵}
class ▵:public ▵{▵};
int ▵(▵,▵,▵,...)const;
Hypothesis Time
So at this point, we hopefully have an intuitive feel for what a coding atom is (you can't split it up), and we have two examples of an objective test (100% of competent programmers reach the same conclusion, regardless of their personal preference) for formatting.
Allow my to present my central hypothesis:
Central Hypothesis:
For any given pair of formatting styles,
which differ only on the relative placement between the conditional and opening brace,
the style where they are on the same line will be objectively better.
If we could prove this hypothesis, with just a little bit of imagination, we could use it to predict that the single-line family of styles (Stroustrup, BSD KNF, Lisp style, Ratliff, K&R, 1TBS) are objectively better than the multi-line variants (Kernel style, K&R style, Allman style, Whitesmiths, GNU style, Horstmann)
Edit: An earlier version of this blog used 'Theorem' instead of 'Hypothesis' in this section. My apologies for any confusion this may have caused.
I suspect an actual proof for this hypothesis would make use of the following two observations :
Edit: An earlier version of this blog used 'Theorem' instead of 'Hypothesis' in this section. My apologies for any confusion this may have caused.
I suspect an actual proof for this hypothesis would make use of the following two observations :
Line-based world
We live in a line-based ecosystem. Find-In-Files, line numbers, the #line directive. In unixland, we have grep, sort, uniq etc.
In this section I'm going to use 'git' as an example of a source code control system, but the same principle applies to perforce, mercurial, subversion, cvs etc ad infinitum
Here's an actual real world diff from my local repository :
diff --git a/Source/Base/Optimize.cpp b/Source/Base/Optimize.cpp
index d827540..7cd13b5 100644
--- a/Source/Base/Optimize.cpp
+++ b/Source/Base/Optimize.cpp
@@ -258,6 +258,8 @@ void SWOptimize::FindMinimumBFGS(){
}
}
}
-// swlog(SWRoleMin,"iter=%d\n",iter);
+ if(Verbosity>1){
+ swlog(SWRoleMin,"BFGS iter=%d\n",iter);
+ }
CalcNumericJacobian(&jacobian);
There's nothing surprising about this, one line was deleted and 3 lines were added. That's how diffs work. There's nothing special about the choice of git here either.
Diffs are one thing. What happens when we merge?
Earlier, we looked at an objective test that took of the somewhat arbitrary form “reducing defects as a result of random line permutations”. Well it turns out, when we merge, that's exactly what is happening. We take two sets of line based changes (Adds and Removes) and we try to apply them both at the same time.
A pecking order for Merge Problems.
Suppose we're trying to merge two diffs. There's a number of outcomes that could happen, from best case to worst case, they are:
✔✔ Automatic merge succeeds, code compiles, all tests pass! everything works! Success!
✗ Automatic merge fails, manual fix.
✔✗ Automatic merge succeeds, code doesn't compile, manual fix.
✔✗✗✗ Automatic merge succeeds, code compiles, some tests fail, lengthy manual fix.
✔✔✗✗✗✗✗✗ Automatic merge succeeds, code compiles, all tests pass! dormant bug enters the system.
That last outcome is particularly insidious. Your tools told you everything was fine, but they secretly created a bug.
Lets take a look at our '4-line if' statement, with the conditional and opening brace on separate lines:
✔ if(●)
✔ {
✔ ◎
✔ }
You see where this is going right? That newline between the conditional and the opening brace? That's exactly the place where our merge tool will happily go ahead and insert new code.
✔ if(●)
! ▦
✔ {
! ◎
✔ }
This is just horrible. The merge reported success and our code compiles just fine – yet the bug exists! We're down to our last lines of defence now such as unit tests and peer review. If they fail to detect the problem, then we're silently putting bugs into our codebase, purely as a consequence of our C++ formatting style.
How often does this happen? When I've been working in active codebases that use this style, I probably see this type of “successful” merge at least once or twice per week. It takes time to clean up, and with any change, there's always the chance of making mistakes and introducing more problems.
Let's put this in context. Suppose github or bitbucket randomly inserted bugs into your code, but didn't notify you. Or if your IDE would occasionally insert extra characters into the middle of your file, and save it, and not tell you about it. Even if it was just once or twice a year per user, wouldn't you try hard to find some way to fix it?
Summary
Lets review:
- I gave an existence proof, a simple objective test that every competent programmer can perform and get the same answer, even when it conflicts with their own personal opinion.
- I highlighted coding atoms, and demonstrated why we should try hard to stop them spanning multiple lines.
So did I do it? Describe Kolmogorov Style, a profoundly new way of formatting programming languages, in a way that everyone can objectively agree on? Well of course not! Such a thing can't be done in just one tiny blogpost.
Instead, I managed to show that it is most likely possible to construct such a formatting style, and gave some hints in the direction I think that such a style might look like.
Keep in mind, even if such a style were to be fully enumerated and justified, there would still be many excellent reasons not to follow it. Maintaining consistency for one. Retraining for another. The existence of an objective standard does not require us to ignore subjective factors.
However, if this is you:
- Starting a new project.
- Preparing your team's coding standard for the first time.
- Developing the presentation layer of a text editor.
- Creating the syntax for a new programming language. (Especially this one!)
- Reduce redundant encoding.
- Don't split atoms across multiple lines.
- Convert optional syntax to mandatory.
Appendix A: Aesthetics? They matter right?
Absolutely! Whitespace is integral to the appearance of code when displayed on a computer monitor. It's fundamental to readability to have adequate white space around your code. I think it's a great thing to be able to isolate individual elements and examine them!
We need familiar whitespace because we're all pattern matching machines.
But the thing is, code doesn't live on computer monitors.
As I write this in 2015, the vast bulk of code lives in source code repositories. It's a collection of disembodied diffs and their associated merge histories.
We take a snapshot of that repository at an arbitrary moment in time and use that to construct a bytestream on our hard disk.
No one is asking you to interpret that raw bytestream directly. All of us use integrated programming environments, built on top of a graphical windowing system, which reformats that bytestream into an aesthetically pleasing onscreen presentation.
Take this bytestream : “””for(int i=0;i<10;i++){\n\tprintf("%d",i);\n}\n”””
Here's just a sampling of 3 different ways you might convert that byte stream into pixels:
Look, I don't care if your IDE uses proportional fonts, or monospace fonts, or wingdings or braille. I don't care about your color scheme, your choice of syntax highlighting, your latest emacs macro, oh-my-zsh github, which scrolling plugins you've got installed, or which keys on your DVORAK keyboard binds to autocomplete. #YOLO.
But here's the rub. All of those choices are local to your machine. None of your local choices can leak on to our team's shared perforce depot. None of your local configurations choices alter the bytestream that exists on my computer in any way.
Of course aesthetics matter to programmers. But don't let that blind you to the reality that any aesthetic quality of your whitespace doesn't matter in the slightest to your compiler, continuous integration server, merge utility, source code repository, build server...
...and especially not to the users of your software.
My problem is that your subjective notions about aesthetics open the possibility for software defects to creep in.
To use a bad analogy:
You're trying to make the blueprints more pretty by drilling holes in the life raft.
(The users won't notice the water coming in until it's too late.)
Appendix B: Some common objections (FAQ style)
Q) Why don't we get a bunch of programmers, randomize formatting styles, and measure how long it takes them to identify software defects?
A) Great idea! That's an excellent procedure for choosing presentation defaults for an IDE! On the other hand, when choosing a formatting style for transporting code between programmers, it makes more sense to use a style which is friendlier to automated tools and reduces the incidence of hidden software defects.
Q) Our ten million line code base already uses ABC style. Should we convert everything to QRS style?
A) Are you crazy? Every change has a cost, consistency has value! Stick with ABC style!!!
However, for any new code, and for any incremental changes you make to existing code, I strongly advise you to adopt the following two guidelines:
- Where braces are optional in your language ( if, while, do, ), make the usage of braces be mandatory.
- int raii = 7; // Declare a single variable, initialize it once, (add an optional comment), all self-contained on one line.
Sunday, 14 December 2014
Twenty years of Skidmarks
Lately I've been digging through the old Skidmarks archives, and I came across this wee gem from 1993, no doubt written with lots of help from Simon:
Function.q hite {di.q,dj.q,oset.l}
UNLK a4
MOVE.l d2,a0
MOVE.l d1,d2:SWAP d2:EXT.l d2:ASL.l #7,d2:ADD.l d2,a0
MOVE.l d0,d2:SWAP d2:EXT.l d2:ASL.l #1,d2:ADD.l d2,a0
MOVEM (a0)+,d2-d3 ;d0-d1 xy d2-d5 p0-p3
LEA 124(a0),a0:MOVEM (a0)+,d4-d5
MOVE d0,d6:MULU d1,d6:SWAP d6:MULU d6,d5 ; x. y.p3
NOT d0:MOVE d0,d6:MULU d1,d6:SWAP d6:MULU d6,d4 ;-x. y.p2
NOT d1:MOVE d0,d6:MULU d1,d6:SWAP d6:MULU d6,d2 ;-x.-y.p0
NOT d0: MULU d1,d0:SWAP d0:MULU d3,d0 ; x.-y.p1
ADD.l d2,d0:ADD.l d4,d0:ADD.l d5,d0 ;total
LSR.l#6,d0:RTS
End Function
For those not quite brave enough to decipher the 68000 assembly, here's what a strictly literal
translation might be:
float Height(float
x, float y, short *heightField){
//__asm{...}
heightField +=
int(x) * 64;
heightField +=
int(y);
short height2 =
*heightfield++, height3 = *heightField++;
heightField += 62;
short height4=*heightfield++, height5 = *heightField++;
float result5 =
frac( x) * frac( y) * height5;
float result4 =
frac(-x) * frac( y) * height4;
float result2 =
frac(-x) * frac(-y) * height2;
float result0 =
frac( x) * frac(-y) * height0;
float result = (result0 +
result2 + result4 + result5);
return result / 64;
return result / 64;
}
The motivation is that I've been working towards a new version for mobile devices, with a working title of "Super Skidmarks 2000" (hashtag #SS2K)
Here's what the modern version of that same function looks like, this time in C++ :
float
SKTrack::GetHeight(float axisI,float axisJ)const{
int
fi=(int)floor(axisI);
int
fj=(int)floor(axisJ);
if(fi<0||fi>=63){
return 0.0f;
}
if(fj<0||fj>=63){
return 0.0f;
}
int index=fi+fj*64;
float
v0=HeightField[index];
float
v1=HeightField[index+1];
float
v2=HeightField[index+64];
float
v3=HeightField[index+65];
float
s=axisI-floor(axisI);
float
t=axisJ-floor(axisJ);
float
v01=v0*(1.0f-s)+v1*s;
float
v23=v2*(1.0f-s)+v3*s;
float
height=v01*(1.0f-t)+v23*t;
return height;
}
As always, any questions / comments, or suggestion for a better name etc, please leave a comment below!
Labels:
Acid Software,
Attract Mode,
beta,
BlitzBasic,
circle,
coffee,
compression,
dot,
Filters,
interval,
Launch,
little,
Macho Programming,
math,
pants,
procedural,
Skidmarks,
SS2K,
zen
Saturday, 29 November 2014
Why he vertically aligns his code (And why you shouldn't)
Over on Terence Eden's blog, the latest post is about vertically aligning code : https://shkspr.mobi/blog/2014/11/why-i-vertically-align-my-code-and-you-should-too
The "bad" example looks like this:
Which is then "fixed" to make it look like this :
Just for comparison, I typed it into my regular text editor:
The point being, because I'm using a well designed syntax highlighting where the numbers (green) contrast with the operators. If you so choose, you can visually inspect just the green numbers and just as easily spot the outlier.
(Pro-tip: To concentrate on just one color, defocus your eyes slightly by staring "through" the plane of the monitor to engage your eye's cone cells. With a little practice, you'll find yourself doing this automatically when you want to focus on the structure of the code instead of the details. For best results, you might need to make the glyphs larger on screen....)
Note too, how the combination of proportional font and camelCase instead of under_scores keep the code density onscreen the same, but the individual glyphs appear larger in-place.
My code editor also uses syntax highlighting to hint the kerning. So for example, the kerning around the equals sign and the semi-colon are particularly loose to aid in their recognition. Similarly, the single space character (' ') has a width 50% larger than would be used for normal paragraph text.
But here's the big change that Terence missed, I've sorted all the variable declarations alphabetically to ensure there are no duplicates. This is a zero-cost policy that can simplify merges and conflict resolution when multiple variables (possibly duplicate) have been added upstream.
Lets take another code example from Terence's blog post, this time a function declaration :
extern int SomeDemoCode(int fred,
int wilma);
That's an atom right there - you can't split that up without changing its meaning. Watch what happens if I try to add a parameter in an excess white-space environment:
extern int SomeDemoCode(int fred,
+ int barney,
The diff splits our (atomic) function signature across 3 lines, exposing us to problems where a git merge might accidentally succeed, when really we need it to flag a merge conflict.
(For a real world case of how bad automatic merging can be, take a look at the Goto Fail Bug)
Now compare if everything had been on the same line, the diff would look like :
-extern int SomeDemoCode(int fred, int wilma);
+extern int SomeDemoCode(int fred, int barney, int wilma);
TL;DR: Using whitespace to control your code presentation is a hack from the '70s.. get a better editor.
p.s. Some formatting edits have been made to make this post clearer.
The "bad" example looks like this:
Which is then "fixed" to make it look like this :
Just for comparison, I typed it into my regular text editor:
The point being, because I'm using a well designed syntax highlighting where the numbers (green) contrast with the operators. If you so choose, you can visually inspect just the green numbers and just as easily spot the outlier.
(Pro-tip: To concentrate on just one color, defocus your eyes slightly by staring "through" the plane of the monitor to engage your eye's cone cells. With a little practice, you'll find yourself doing this automatically when you want to focus on the structure of the code instead of the details. For best results, you might need to make the glyphs larger on screen....)
My code editor also uses syntax highlighting to hint the kerning. So for example, the kerning around the equals sign and the semi-colon are particularly loose to aid in their recognition. Similarly, the single space character (' ') has a width 50% larger than would be used for normal paragraph text.
But here's the big change that Terence missed, I've sorted all the variable declarations alphabetically to ensure there are no duplicates. This is a zero-cost policy that can simplify merges and conflict resolution when multiple variables (possibly duplicate) have been added upstream.
Coding Atoms
The bigger problem is the coding atom is the line-of-code.Lets take another code example from Terence's blog post, this time a function declaration :
extern int SomeDemoCode(int fred,
int wilma);
That's an atom right there - you can't split that up without changing its meaning. Watch what happens if I try to add a parameter in an excess white-space environment:
extern int SomeDemoCode(int fred,
+ int barney,
int wilma);
(For a real world case of how bad automatic merging can be, take a look at the Goto Fail Bug)
Now compare if everything had been on the same line, the diff would look like :
-extern int SomeDemoCode(int fred, int wilma);
+extern int SomeDemoCode(int fred, int barney, int wilma);
TL;DR: Using whitespace to control your code presentation is a hack from the '70s.. get a better editor.
p.s. Some formatting edits have been made to make this post clearer.
Labels:
C++,
crunch,
Easy Mode,
ergonomics,
interval,
JSON,
little,
logo,
principle,
rectangle,
stunt programming,
VIC-20,
zen
Friday, 12 September 2014
Wi-Fi in Schools
A friend of mine asks :

Question : What's the effect on the human body, of 20 children in a classroom, each downloading a 3 minute youtube video over Wi-Fi?
As with all good science, let's start with an experiment. I happen to have a 3 minute HD video on my network, so I can time how long it takes to copy across to my laptop:
So a single 3 minute video (3:19 to be precise) will use about 6.5 seconds of Wi-Fi time to copy.
With 20 students, and rounding up a little to account for congestion..
... lets call it 200 seconds of Wi-Fi activity total.
The maximum 2.4-GHz transmission power is regulated by law, so lets assume it's 20dBm = 100mW = 0.1W ( source )
As we all learnt when we were in school, a watt is a joule per second, so 200 seconds at 0.1W is 20J.
Now we know that a class room of children downloading a youtube video results in 20 joules of microwave energy being emitted from the Wi-Fi router's antenna.
Now we need to make a pretty unrealistic assumption. Suppose that the entirety of those 20 joules of energy was somehow absorbed by one child. Of course, this can't happen in the real world for two fairly obvious reasons:
But just for fun, lets continue on anyway and figure out what would happen if all of those 20 joules were absorbed by one child.
An average 6 year old child weighs about 22 kilograms. (Of course, my 4 year old son also weighs 22 kilograms, but that's a blogpost for another day!)
The human body is about 65% water, so lets consider 14 kilograms of water.
The specific heat capacity of water is 4.18 J / gK
So we have 20 J / (14,000 g) / (4.18 J / gK) = 0.00034 K = 0.0004 °C
(That's 0.4 millikelvin for all you geeks out there.)
Answer : A classroom of children, all downloading a 3 minute youtube clip over Wi-Fi yields a maximum biological heating due to 2.4GHz microwave radiation of 0.0004 °C.
(0.4 millikelvin is about twice as small as it's possible to measure using a precision thermometer.)
We shouldn't really be too surprised. Wi-Fi signals are incredibly weak. Consider this, those 20 joules of microwave radiation is the same amount of chemical energy contained in one thousandth of a teaspoon of sugar.
There's no way to prove scientifically that microwave radiation from Wi-Fi is safe in the human body. Science doesn't work that way. You can't prove a negative.
But we can try and make smart choices about tiny risks.

For example, the exposure from a banana is about 0.1 μSv of harmful ionizing radiation because of their high quantities of naturally occurring radioactive potassium.
Yet who thinks twice about giving bananas to kids in schools?
Thoughts, questions or especially corrections? Please feel free to leave a comment down below!
Question : What's the effect on the human body, of 20 children in a classroom, each downloading a 3 minute youtube video over Wi-Fi?
An excellent question!
As with all good science, let's start with an experiment. I happen to have a 3 minute HD video on my network, so I can time how long it takes to copy across to my laptop:
missingbytes:$ time copy /NetworkDrive/HDVideo.mp4 .
real 0m6.550s
user 0m0.001s
sys 0m0.116s
So a single 3 minute video (3:19 to be precise) will use about 6.5 seconds of Wi-Fi time to copy.
With 20 students, and rounding up a little to account for congestion..
... lets call it 200 seconds of Wi-Fi activity total.
Transmit power
The transmission power for Wi-Fi signals is heavily regulated in the EU, the US and also in New Zealand where I'm performing the test.The maximum 2.4-GHz transmission power is regulated by law, so lets assume it's 20dBm = 100mW = 0.1W ( source )
As we all learnt when we were in school, a watt is a joule per second, so 200 seconds at 0.1W is 20J.
Now we know that a class room of children downloading a youtube video results in 20 joules of microwave energy being emitted from the Wi-Fi router's antenna.
A brief diversion : Ionizing and Non-Ionizing radiation
Electromagnetic radiation forms a spectrum, from low frequency and radio waves, up through the microwaves, visible light, X-rays and on to gamma rays which have very high frequencies indeed.
Those high frequencies are characterized as ionizing, they're very dangerous to humans and their ability to cause DNA damage and ultimately cancer is well known. This is the reason why we need to be so careful around medical/dental imaging devices, and need to take precautions such as wearing sunscreen and polarized sunglasses when we're outdoors on a sunny day.
It's not necessarily the amount of energy, it's more the frequency that's the problem. This high frequency ionizing radiation quite literally has the ability to rip electrons off their atoms. It's these "ions" which go on to cause damage to biological systems.
By contrast, the lower frequency non-ionizing radiation (such as used in Wi-Fi, or FM radio) doesn't have the same ability to affect us in this way.
By itself, non-ionizing radiation can only cause heating in biological systems. Indirectly, it's this heating which slows down or speeds up chemical reactions and/or signalling within the cell, and it's these secondary effects which has the potential to cause problems.
Intuitively, this is why the 1000 watt microwave oven in your kitchen makes food super hot in a few minutes using microwave energy, but it doesn't actually make your food radioactive. (You'd need an X-Ray oven for that!)
Anyway, lets continue, we've got 20 joules remember?
Absorption
Now we need to make a pretty unrealistic assumption. Suppose that the entirety of those 20 joules of energy was somehow absorbed by one child. Of course, this can't happen in the real world for two fairly obvious reasons:
- A router transmits energy in all directions. For all the energy to be absorbed by the child, the router would somehow need to be inside the child.
- Microwave energy interacts only weakly with the human body. That's one of the great benefits of Wi-Fi, it can pass right through walls and ceilings and straight through you and me.
But just for fun, lets continue on anyway and figure out what would happen if all of those 20 joules were absorbed by one child.
An average 6 year old child weighs about 22 kilograms. (Of course, my 4 year old son also weighs 22 kilograms, but that's a blogpost for another day!)
The human body is about 65% water, so lets consider 14 kilograms of water.
The specific heat capacity of water is 4.18 J / gK
So we have 20 J / (14,000 g) / (4.18 J / gK) = 0.00034 K = 0.0004 °C
(That's 0.4 millikelvin for all you geeks out there.)
Answers!
So there we have it, even with a wildly exaggerated assumption:Answer : A classroom of children, all downloading a 3 minute youtube clip over Wi-Fi yields a maximum biological heating due to 2.4GHz microwave radiation of 0.0004 °C.
(0.4 millikelvin is about twice as small as it's possible to measure using a precision thermometer.)
Conclusion
We shouldn't really be too surprised. Wi-Fi signals are incredibly weak. Consider this, those 20 joules of microwave radiation is the same amount of chemical energy contained in one thousandth of a teaspoon of sugar.
There's no way to prove scientifically that microwave radiation from Wi-Fi is safe in the human body. Science doesn't work that way. You can't prove a negative.
But we can try and make smart choices about tiny risks.
For example, the exposure from a banana is about 0.1 μSv of harmful ionizing radiation because of their high quantities of naturally occurring radioactive potassium.
Yet who thinks twice about giving bananas to kids in schools?
Thoughts, questions or especially corrections? Please feel free to leave a comment down below!
Labels:
cancer,
circle,
Fire Fighter,
infinite,
insurance,
Safety Inspector,
TV,
video,
Wi-Fi,
zen
Thursday, 7 November 2013
ScooterBoy Global Launch
Modka Games is very proud to launch ScooterBoy:
Need a little something extra? Why not buy a Pet from the store? These cute little helpers will fly along and collect coins and points to boost your score. You can even flick your pet to reach up even higher.
Meanwhile, in the PhotoBooth:
So what are you waiting for?
Download ScooterBoy Now!
![]() |
| ScooterBoy, free on the App Store, for iPhone, iPod touch and iPad |
![]() |
| ScooterBoy HD screenshot (click for full res) |
Gameplay First
ScooterBoy brings back the classic feel of the arcade, updated with one button touch controls. Of course you can jump and dodge to avoid obstacles, but in ScooterBoy you also swipe to change lanes, drop-boost to go faster, and there's loads of power ups and pickups to collect too.![]() |
| "Scooter Boy!" |
If you want to climb the high score ladder, you'll need to learn the mushroom's secrets. Or you can simply relax and explore ScooterBoy's amazing world at your own pace.
Upgrades
![]() |
| Marmot, jumping with the shark. |
Upgrade your scooter, choose new characters, hats, wheels and more..
Buy a friend!
Need a little something extra? Why not buy a Pet from the store? These cute little helpers will fly along and collect coins and points to boost your score. You can even flick your pet to reach up even higher.
PhotoBooth
| Bizzer in the PhotoBooth with his dragonfly. |
Meanwhile, in the PhotoBooth:
- Choose a background and a frame.
- Take a photo of your ScooterBoy.
- Share with your friends.
- Repeat!
Music
![]() |
| Download link for ScooterBoy |
Did I mention the music? ScooterBoy has nearly an hour of classic recordings from the 50s and 60s
Download, for free!
And the best part, ScooterBoy is free to download, and free to play!So what are you waiting for?
Download ScooterBoy Now!
Labels:
JSON,
Launch,
logo,
Mini-Game,
ScooterBoy,
ScreenShot,
zen
Saturday, 19 October 2013
Praise the Fire Fighter, Damn the Safety Inspector
There's a sickness eating our industry. It's a culture of Macho Programming. In it's simplest form, it's the idea that if we just push harder, longer, stronger, then we will win. Yet time and time again, experience shows that the way to win is by working smarter.
bool DetectCollision(Vector3 location, float radius){
...
radius * 1.2f;
...
}
So that line of code makes the collisions a bit fatter. It's what we call a 'Fudge Factor' - we don't know why a problem is occurring, so we fudge the numbers a little until it works.
But take a closer look. The statement as written has no side-effects. It doesn't actually modify the value of radius. When the programmer wrote:
radius * 1.2f;
they intended to write:
radius *= 1.2f;
Let's review the facts:
And we can safely assume that the programmer didn't verify the original bug in the first place.
That's right, not one, but two programmers, working together, managed to convince each other that this placebo changelist actually improved the game. Together, they marked the bug as fixed and sent it back to QA, fully confident they had made the game better.
What other trivial mistakes did those programmers make that night?
What a colossal waste of time and resources, simply because those two programmers had inadequate sleep. The project would have been much better off if those two programmers had just gone home at 18:00. Or 17:00. Or even 14:00.
[Edit: I just wanted to add, these are actually two really good programmers! I'd jump at the chance to have them on my team again. The equation here is crunch + good programmers = too many careless mistakes.]
To me, Macho Programming, is blundering onward in whichever way you possibly can, without regard to what's best for the project or the team, simply for the appearance of getting something done.
I think we can do better than that. In the true Agile sense, as a team, we need to make the best decisions based on the best information we have, right now, and move forward in the best direction we can.
Who's with me?
(1) Some details have been changed to preserve anonymity.
Side-effects
I was once working on a particular AAA title. The game was running late. We were in crunch, and had been for a while. There was no end in sight. I came across the following code:(1)bool DetectCollision(Vector3 location, float radius){
...
radius * 1.2f;
...
}
So that line of code makes the collisions a bit fatter. It's what we call a 'Fudge Factor' - we don't know why a problem is occurring, so we fudge the numbers a little until it works.
But take a closer look. The statement as written has no side-effects. It doesn't actually modify the value of radius. When the programmer wrote:
radius * 1.2f;
they intended to write:
radius *= 1.2f;
Let's review the facts:
- It's the wrong fix to begin with (fudge factors are generally a bad idea)
- It doesn't actually change the behaviour of the running program
- The programmer didn't verify that their "fix" worked
And we can safely assume that the programmer didn't verify the original bug in the first place.
Compound Fail
It gets worse. In this late stage of crunch, there were so many easily avoidable bugs coming in to the code, that the production team mandated every changelist required a second programmer to sign off.That's right, not one, but two programmers, working together, managed to convince each other that this placebo changelist actually improved the game. Together, they marked the bug as fixed and sent it back to QA, fully confident they had made the game better.
What other trivial mistakes did those programmers make that night?
What a colossal waste of time and resources, simply because those two programmers had inadequate sleep. The project would have been much better off if those two programmers had just gone home at 18:00. Or 17:00. Or even 14:00.
[Edit: I just wanted to add, these are actually two really good programmers! I'd jump at the chance to have them on my team again. The equation here is crunch + good programmers = too many careless mistakes.]
Praise The Fire Fighter ...
When you're deep in crunch, it's easy to see the heroic efforts, the mountains of caffeinated beverages, the change logs at 4am. It's easy to point to the person who's working the hardest and say "We all need to be more like that guy." Because when it's all falling apart, you need to do something.
(Hint: That something we need to do is to get more sleep.)
... Damn the Safety Inspector
And when you're at the beginning of the project, and the Safety Inspector is telling you that what you're building isn't up to code, that the schedules are unrealistic and will lead to crunch, slipped deadlines, hard-to-find bugs and adds unacceptable levels of risk to the project... Well they're easy to dismiss "We're trying to build something here! Why are you trying to stop us?"
(Hint: The Safety Inspector is probably right.)
Macho Programming
As an industry, we should be working smarter than that. We should be rewarding measurable results and hard evidence, rather than effort and posturing.To me, Macho Programming, is blundering onward in whichever way you possibly can, without regard to what's best for the project or the team, simply for the appearance of getting something done.
I think we can do better than that. In the true Agile sense, as a team, we need to make the best decisions based on the best information we have, right now, and move forward in the best direction we can.
Who's with me?
(1) Some details have been changed to preserve anonymity.
Subscribe to:
Posts (Atom)












