Changing blog software (again)
Saturday, January 13th, 2007After a few months on typo I am going back to Wordpress, as it seems to work better on the shared host where I host this blog. Expect entries to reappear over the next little while.
After a few months on typo I am going back to Wordpress, as it seems to work better on the shared host where I host this blog. Expect entries to reappear over the next little while.
It is strange to think that it is year since I left India to helps start the ThoughtWorks Toronto office. After 18 months India was very definitely home - and I still get homesick for Bangalore, and miss my friends from our office there.
But that is not the point of this post.
While there I wrote an introduction for new arrivals, and Jake asked for a copy of it for the new group who are going to training there. I realised I have never posted it online.
So here it is:
Living and Working in Bangalore
Along with he rest of the World on Rails. This move was precipitated by a server crash on the machine that Damien was using to host my blog. I’ve been squatting on his server for way too long anyway, and with his new baby he is going to want to spend less time administering linux boxen, I am guessing.
I haven’t moved my past articles yet - I have to restore that from backups - and it may take a day or so.
So as of the weekend a a proud owner of a MacBook Pro. It is a great machine, although it looks disappointingly like the old PowerBook - except for the tiny (really really tiny) camera and a slightly wider trackpad.
I guess this similarity is a good thing, reinforcing memes of continuity and evolution rather than revolution and disruption. One of the things I have always found annoying in Windows world is the way that the new versions of the apps look different but still have the same old annoying quirks and bugs.
But it does have a slightly different feel - it is more like it used to be when I was using linux extensively - living on the bleeding edge and recompiling parts of the system every few days as new versions came out. I used to enjoy that, but one of the great things about the mac is the loss of the need or desire to do that so often. Everyhting is already beautiful and functional.
This feels a bit like those old days - googling for the latest beta versions of apps not yet universal. But I am loving it so far - TextMate is universal and I always run a compiled ruby anyway, and for that this thing rocks.
Ben is presenting a paper tomorrow which compares the language and interpretation of the Canadian Charter of Rights and Freedoms[link] with the codified Edict in Timothy Findley’s Not wanted on the Voyage.
And it got me to thinking¦
It struck me that the language of the law is rarely specific - it is couched in general terms - hedged about with ifs and buts - rarely couched in absolutes. In fact the language of the law is constructed carefully to avoid absolute or exact statements. Its all about nuance and relativity. This (I would suggest) is precisely because the law’s decisions are themselves so final and absolute - Guilty or Not Guilty. So since the decisions of the law are absolute, the “wiggle room” to allow for reality must be provided by a language that deliberately avoids commitment.
Section 27 - Canadian Charter of Rights and Freedoms : “This charter shall be interpreted”
This is not so in science however. Science is quintessentially relative and contingent - it is expected that today’s hypothesis might be disproved or changed on the basis of new discoveries and research. So to make it easier to test a hypothesis, it must avoid ambiguity and nuance. In fact hypotheses are constructed in absolute terms. Often it is the facts, the observations that are nuanced, hedged about with observational error bars and quantified sampling errors.
In my own field of software development, we are starting to move beyond the strictly typed mathematical languages of Java and C#, and becoming more comfortable with (lispers and smalltalkers would say re-discovering) the freedom and “wiggle room” that comes with untyped or dynamic languages such as ruby, python etc. Given these languages inherent flexibility, we constrain our solutions with the unit tests that we write - almost as legal interpretations are constrained by precedent - or scientific hypotheses are constrained by experimentation.
Don’t read too much into this - allegories can only go so far, and I’m not really getting at anything - but I found it an interesting train of thought.
I gave a presentation at XPToronto late last year on distributed agile, and how we went about transforming one of our own projects that had stagnated. This was an interesting project, not least because it is a large (at its peak about 40 developers, 35 in India, 5 in the US) long-running (5 years) agile project.
Goa Presentation - Even More Agile
This is a presentation that Deven Tolia and I gave at and Agile conference in Goa, India in 2005. Originally we did it with 2 projectors, one showing the photographs, and one the slides. We found then, and it was re-inforced when I did it in Toronto, that the photos are the most interesting aprt of the presentation. Many people haven’t seen an Agile project, and talking about theory is no substitute for seeing it done, even if the images are still.
And (re)-reading Tufte’s excellent The Cognitive Style of Powerpoint reinforces the observation that bullet points are not content. The content is in the conversation and the talking that accompanies the pictures, or the whitepaper that expands on the discussion. Deven and I plan to write this paper up in more detail this year, hopefully to present it at one of the Agile conferences this year. When we do that, I hope we will be able to rework it to address those issues.
Martin Fowler has blogged on a testing technique he calls TestInvariant.
This reminded me of a related approach that I have used is to refactor assertion methods onto the class under test. Here is how I got there.
Suppose you are was writing some tests on Martin’s bowler class:
public void testConcedingRunsAddsToRunsScore() {
Bowler botham = new Bowler();
assertEquals(0, botham.getRuns());
botham.concedeRuns(4);
assertEquals(4, botham.getRuns());
}
Now there are 2 code smells here to me.
First, the test has forced me to expose the internal implementation of the Bowler class - bleargh. It is bad enough in domain objects and it is worse when it is just for the purpose of testing. Even if we make the getter package protected it still ollutes the API. And sooner or later someone will come along who will make it public and start using it.
Second, the assertions are not very domain specific - and there is duplication. Lots of developers will make them a bit more informative with a message - like this:
public void testConcedingRunsAddsToRunsScore() {
Bowler botham = new Bowler();
assertEquals("Should have 0 runs", 0, botham.getRuns());
botham.concedeRuns(4);
assertEquals("should have 4 runs", 4, botham.getRuns());
}
I tend not to do this for assertEquals - it is already informative enough, and the message doesn’t increase readability, it increases duplication. So lets do something else:
public void testConcedingRunsAddsToRunsScore() {
Bowler botham = new Bowler();
assertHasRuns(botham, 0);
botham.concedeRuns(4);
assertHasRuns(botham, 0);
}
private void assertHasRuns(Bowler b, int runs) {
assertEquals(runs, bowler.getRuns());
}
That’s nice - we have a new informative assertion that is now making an assertion about the domain, not about the state of the object.
If you look at the testConcedingRunsAddsToRunsScore method, everyhting it does is expressed in the language of the domain - we have a mini domain language right here. Consider the assertion assertHasRuns(botham, 0) - that reads nicely.
But now there is one more code smell - feature envy. The assertHasRuns method is envious of the bowler, and following the precepts of refactoring - we should listen to what the code is telling us and move the method onto the bowler. so lets do that:
class Bowler {
public void shouldHaveRuns(int expectedRuns) {
Assertion.assertEquals(expectedRuns, this.runs);
}
}
I’ve done one extra step here, and renamed the assertion to make the domain language a bit clearer. Let’s look at the test now:
public void testConcedingRunsAddsToRunsScore() {
Bowler botham = new Bowler();
botham.shouldHaveRuns(0);
botham.concedeRuns(4);
botham.shouldHaveRuns(4);
}
There is one extra really nice thing now - since the assertion has moved onto the class under test, we no longer need to expose the getRuns method. So we can remove it and increase the encapsulation of the class.
This approach also fits quite nicely with the emerging approach of Behaviour Driven Development and Humane Interfaces.
Note though that as shown above, you need to distribute the JUnit classes with the production code, to make the assertion methods object available. I don’t mind this. If you do, you could use Java’s own assert support, or move the assertions onto a testing subclass of the original object.
This is a technique that I have used to “re-encapsulate†objects in legacy systems. Often there are objects that give all their information away through getters, initially for testing and then slowly people start using the methods rather than encapulating behaviour. This allows you to remove the getters incrementally.
So I was wondering what I would do if I was involved in the current court case in the US over Creationism (rebadged as intelligent design). And I thought I might do a bit of a stunt, that is, print out the scientific literature on Evolution for some period of time, and the scientific literature for intelligent design for the same period (if there is any).
So textbooks don’t count - I’m taslking peer reviewed journals. Oh, and only in english of course.
I used Google Scholar for the test. And here’s the results:
Evolution: about 17,400
Intelligent Design: about 13
Rather pokes a hole in the claim that ID is in any way a ‘real scientific theory’eh?
Just for fun, lets look at those 13 ID ones. Most are matches on like “Another important point is the intelligent design of peptide pools”. There is only one that isn’t an anti-ID review or commentary. That is in a crank journal and you can read it here: http://www.iscid.org/papers/DavisonPrescribedEvolution110804.pdf
Its a pretty pathetic paper, and we can see what the mainstream community has to say here and here. There are no citations of that paper in any journal google scholar knows about. But you can get a feeling for the scorn in the real scientific community by looking at the web
Still, lets count it. So that’s 17000 to 1. This year. So far.
By the way, if the average scientific paper is about 5 pages long, printing out this year’s evidence for evolution would end up with a stack of paper about 4.2m high (I would do it double sided to save at least some trees). That would compare to the two sheets of ID polemic.
And the proponents of ID want people to believe that there is some real controversy about evolution? Sigh.
It also struck me that many people don’t really get to see a real scientific paper. so lets have a look at one, randomly chosen from the first page of the evolution google page: Evolution of vertebrate steroid receptors from an ancestral estrogen receptor by ligand exploitation and serial genome expansions. It is obviously reasonably influential, since it has been cited 68 times by other articles.
Its an interesting paper, and includes discussion of DNA analysis and descriptions of the experiments and methodology that were used - so you can repeat it if you want. This is what science looks like.
Out of interest, you can go way down google’s list of pages to see the sort of work that is being done. Here’s a link to Page 99 of the query*. Notice that they are all still meaty real science reports.
Compare this with the full version of Davison’s article. His is simply polemic. No research, no evidence. Just a statement of opinion.
What is wrong with this code?
public class FooTest extends TestCase {
Random random = new Random(1000);
public void testSomething() {
Long primaryKey = new Long(Math.abs(random.nextInt()));
[create some objects]
...
[delete the objects]
}
public void testSomethingElse() {
Long primaryKey = new Long(Math.abs(random.nextInt()));
...
}
}
First problem, in every random library I have used, when you create a random number sequence with a seed, it gives you not a new sequence, but the same sequence. The numbers are pseudo-random, but the sequence will be identical.
So for a quick demonstration of this:
public void testRandom() {
System.out.println("First Sequence");
Random random = new Random(1000);
System.out.println(random.nextInt());
System.out.println(random.nextInt());
System.out.println(random.nextInt());
System.out.println(random.nextInt());
System.out.println(random.nextInt());
System.out.println(random.nextInt());
System.out.println("New Sequence");
random = new Random(1000);
System.out.println(random.nextInt());
System.out.println(random.nextInt());
System.out.println(random.nextInt());
System.out.println(random.nextInt());
System.out.println(random.nextInt());
System.out.println(random.nextInt());
}
gives
-1244746321 1060493871 -1826063944 1976922248 -230127712 68408698 New Sequence -1244746321 1060493871 -1826063944 1976922248 -230127712 68408698
Since JUnit enforces isolation by creating a new instance for each test*, each test will get the same number (actually -1244746321) for the primaryKey. So when it uses the primaryKey to create the objects for the test they will all have the same primaryKey. Almost certainly not the intent of the test author.
This is not such a bad thing if the tests clean up properly after themselves, but if they don’t, and the tests fail, from then on you will get primaryKey violation errors when you hit the database.
So, the second problem in these tests: the [delete the objects] is in the test. If the test fails, the objects are never cleaned up. Clean up belongs in tearDown(). That is what it is designed for.
*A subject of recent controversy, but IMHO a Good Thing
In my last post, I ranted about the behaviour of the Gnome calculator. But as Robert Watkins pointed out - not all calculators are equal. In fact their behaviour is all over the place. Here is my survey of OS systems within my reach:
| Calculator | Basic Mode | Scientific |
|---|---|---|
| MacOsX | CORRECT | CORRECT |
| Windows | WRONG | CORRECT |
| Gnome (Fedora Core 3) | WRONG | WRONG |
| Gnome (more recent) | CORRECT according to the website | CORRECT according to the website |
| KDE | CORRECT | CORRECT |
CORRECT = Obeys the laws of Mathematics. Ie 2 * 2 + 2 * 2 = 8
INCORRECT = Defies the laws of Mathematics. Ie 2 * 2 + 2 * 2 = 12
So next I have to dig out some mechanical and handheld calculators and try it on them. So far it seems that TI ’scientific’ calculators have been correct at least since the 1970s which makes sense and explains why I had the understanding that all calculators work that way - that is the sort of calculator I used in high school, and I would hope that is the kind used today - not TI necessarily, but something that is correct.
The Nokia phone that I use is wrong - but then I have never used it to do calculations.
Googling for recommendations about calculators for students, it seems that at least the Irish education authorities recommend: “If the calculator executes operations in the order in which they were keyed in, the answer displayed will be 14 - which is incorrect. If the calculator follows the conventional order of precedence for arithmetic operations, it will display the correct answer, 11. The first type of calculator is referred to as an arithmetic logic calculator. Many four-function and desktop business-style calculators are of this type. Virtually all scientific calculators, on the other hand, are of the second type. These are called algebraic logic calculators, and they apply the conventional rules of precedence to any sequence of arithmetic operations. Scientific calculators with algebraic logic are recommended for post primary students.”
I guess this is a lesson that the kind of usability that is basically lacking in the real world, the kind of problem that we often don’t notice until one day it bites us like it did me today. And how easy it is to overlook these problems
For an example of how easy it is to overlook basic usability like this, did you ever notice that calculators and keyboards have their keys in the opposite order to phones? Why is that? And why does an ATM match a phone not a calculator? What if you had to enter your PIN on a computer’s numeric keypad? Would you get it right?