The Evils of Global State and Singletons
In this Google Clean Code talk, Miško Hevery presents the evils of global state, how this relates to Singletons, testing and what to do about it.
Questions starting at 31:20 are pretty interesting.
Using SQLite in Python
Python has had support for SQLite built-in since version 2.5.
This is a very convenient pairing as SQLite is an excellent lightweight SQL implementation that I find very useful for a variety of tasks e.g. data mining. Or any task involving manipulating complex data sets where I’d otherwise end up resorting to using a full blown SQL server like MySQL.
Here is a simple example of using SQLite in Python using it’s built-in sqlite3 module:
import sqlite3
# craete a connection
con = sqlite3.connect('test.db')
# create a cursor
cur = con.cursor()
# create a test table
cur.execute( "CREATE TABLE testTable (myKey INT, myValue INT)" )
# insert some data
for i in range(0,10):
cur.execute( "INSERT INTO testTable VALUES ( %d, %d )"%(i,i*i) )
# select the data
for row in cur.execute( "SELECT * FROM testTable" ):
print row
# destroy (drop) our test table
cur.execute( "DROP TABLE testTable" )
# close the connection
con.close()
As you can see Python makes handling SQLite (a C language library) much easier, less error prone, and the resulting code much more compact than SQLite’s native C.
Fail to succeed!
The more experienced I become the more aware I become of what I don’t know and the more I come to terms with the fact that I make mistakes.
The awareness of what I don’t know helps keep me humble, humility makes working as part of a team easier: as there is no pressure to have to know everything or not make mistakes. In fact I tend to expect to make mistakes more now than when I first started programming. Perhaps it is the years I have spent shipping games that finally proved to me that I too write software that contains bugs (the horror!).
I remember a professor at university telling me that the main difference between a professor and a first year student working on a programming task is that the student will start working immediately and also start making mistakes immediately, the professor will think for a while then start work and start making mistakes as well. I have found this observation to have a surprising amount of truth in it,:whether it is at university, work or even sports.
Mistakes are healthy: without mistakes we would have not reason to every really think about what we are doing e.g. why didn’t that work? By continually pushing (or stretching) ourselves to failure we discover our boundaries, once we know where are our boundaries are we can then start to work on pushing them further. However if we always play it safe and never push ourselves (which can be scary) we will never discover our boundaries which makes improvement much harder and also makes approaching those boundaries harder due to fear (typically of loss of control).
An excellent example of this is people learning to ice skate: young children will tend to fling themselves around the rink with wild abandon falling all over the place (as failure is expected but irrelevant due to lack of social stigma), yet adult beginners typically skate in a much more conservative fashion taking less risks (as there is social stigma against falling as an adult: falling is seen as failure). Interestingly when observing ice hockey players, it is noticeable that those with the best skating technique are typically falling more than the other the non-beginner players on the ice, as they do not fear falling.
As most of us are not engaged in high risk activities on a daily basis we can easily begin to revise how we think about failure and to learn to embrace it as a powerful tool for self improvement.
No bad programming languages
I encountered some truly hideous source code today in a programming language in which I wouldn’t have thought hideous obscure code was possible: C#. It was my first real experience of abject horror when looking at the source code of a C# application. Obviously with hindsight it would seem that you can write hugely, dense, brittle and hard to understand programs in any programming language. And yet I would not expect a C# source code to be this obtuse or brittle but I would expect a Perl script to be dense and hard to read.
It is not that I have anything against Perl as a programming language: it is a fine language. I find that Perl’s motto of `There’s more than one way to do it.’ means that it is a programming language with (you guessed it) more than one way to implement most operations. This flexibility is a double edged sword: it allows a lot of creativity in program implementation, yet it also means that a dozen Perl coders will produce a dozen radically different scripts for the same problem. This makes Perl quite hard on beginners or infrequent maintainers of Perl scripts: as to understand any given Perl script requires an understanding of much more of the Perl programming language than it would for most comparable programming languages.
I digress.
I’ve known for years that it is possible to write awful obscure code in low level languages like C and C++ but it really hadn’t occurred to me that a high level language like C# could be abused to the same degree. Thinking about this some more, it is not the fault of the programming language itself but of the programmer that is using it.
So, brittle obtuse code is the result of a bad programmer not a bad programming language: well except maybe Brain Fuck (but thats kinda the point).
You Aren’t Gonna Need It!
A very common trap to fall into while implementing a new system or feature is to add functionality to ‘future proof’ your code for a use case that you imagine in may be required in the future. The future for the purposes of this post is any time that is not in your current development iteration.
This may seem harmless but consider that the future use cases you are imagining are not something you fully understand yet: as most of us will admit we are pretty bad at anticipating the future. So how can we hope to implement future functionality successfully? The most likely outcome is that whatever you implement now not be sufficient when you actually try to use it in the future. This will mean more time will have to be invested in the future to refactor or replace the functionality with what is actually required.
Unless you also plan to implement a full set of tests for this new functionality then you are adding extra code to your program that will not be correct and will not stay correct. This can also lead to really weird run time behavior if the flow of program execution goes into your new ‘future proof’ functionality unexpectedly: which can be very hard to debug. Adding functionality for future use without corresponding tests also means that as the rest of your program evolves the future functionality does not evolve with it, this means by the time you actually try to use it that it is most likely hopelessly out of sync with the rest of the code base.
The future functionality is also expanding the size of the source code of your program which leads to unnecessary code bloat. In some compiled languages (e.g. C++) code bloat will lead to increased memory usage and decreased program performance which is highly undesirable.
Another thing to consider from a business stand point is that you are spending time and money implementing future functionality when you are not being paid for it. This is a strong indication to me that implementing future functionality makes little business sense. As it means spending money now paying developers to implement functionality that you can’t sell right now.
There is a handy acronym for this: it is YAGNI which stands for ‘You Aren’t Gonna Need It’. The essence of this concept is to only implement the functionality you need right now and to implement in as simple and robust a fashion as possible. As simple robust code (preferable with acompaning unit tests) is code that can be easily refactored in the future to meet future needs and that is cost effcient!
Fail fast, fail cheap!
I was explaining this to some junior programmers the other day and it’s worth repeating. Failure is fine in software engineering, in fact it is expected: I get nervous if something works first time these days as I know my limits and expect to make mistakes. However I think that new programmers don’t always realise that failure is acceptable and in some cases failure is preferred, this is especially true during research and development tasks. Consider the following diagram representing three programmers A, B and C working on a task over a period of time, each arrow represents one attempt at a solution.

Assume the task that has been set is complex and contains some degree of uncertainty which means that the first few attempts will probably fail. Which programmer would you want working on the task? If the task is actually impossible then programmer A will be the cheapest from a business standpoint as they fail earliest followed by programmer B and finally programmer C. Also, programmer A will have five attempts at a solution compared to programmer B’s two and a half attempts and programmer C’s single attempt. As iteration leads to improved quality (Boyd’s Law) this means that programmer A is also likely to hit on a more superior solution than programmer B or programmer C in the same time period.
The interesting thing here is that in my experience new programmers tend to work like programmer C: they will attempt a single solution working diligently to overcome any hurdles they encounter, no matter how severe the hurdle. This sounds harmless but remember that few things are impossible in programming, so the more a programmer hammers away at a problem the more likely they are to fudge a solution and that solution (in my experience) is not often of a high quality. The counter point to this is that more productive programmers will rapidly discard attempts early in each attempt when it becomes clear that the solution though possible is not actually desirable e.g. the dog is hungry and solutions include: A) feed the dog B) kill the dog.
This can also be observed by monitoring how long a programmer will remain stuck for before asking for assistance. The most productive programmers will get help within minutes of becoming completly stuck. However the least productive (and often least experienced) programmers will often struggle with the problem for days before actually asking for assistance and this delay is expensive in terms of money, deadlines and product quality.








