Nim's braindump Swords, code and a dirty mind!

8Apr/120

Symfony2 and Jenkins

I was a bit surprised to see that Symfony2 doesn't come with an ant build file for Jenkins by default, so I spent a bit of time whipping one up for you (well, for me, really):you can get it here.

Maybe it'll work for you, maybe it won't. The project I'm working on has the complete SF2 distribution in version control and all of our bundles in the src folder. It's easier to test & ship the code this way. If you want to test a specific bundle or don't want to have SF2 in version control, then you're on your own :-) .

flattr this!

Tagged as: , No Comments
7Dec/110

On donating to open source

Some time ago, Gabriel Weinberg, the guy behind the excellent Duck Duck Go search engine, started a bit of a discussion about open source donations. He set up a website where companies can make a pledge to donate x% of their profits to worthy projects. I donated 15% of my company's estimated profit this year. Half went towards an individual hacker who will remain nameless and genderless. The other half went to the OpenBSD project, because face it, where would you be without OpenSSH?

FOSS Tithe.org

flattr this!

Tagged as: , No Comments
20Aug/110

On name & address madness

A long time ago, in a university far far away, I had a crazy Relational Database professor. This man was under the impression that data should be normalized at any and all cost, to infinity and beyond. In some cases, he had a point. When he started talking about normalizing names and addresses, I had to suppress murderous tendencies. You see, he seemed to be under the impression that it's always a Good Idea to split an address into different chunks. You know the drill: street, post code, city, country. Or worse, add a house number. Or worse, states, counties & provinces. Maybe regions, too. And before you know it you end up with a monstrosity of a data model that's broken beyond repair. There are many different addressing systems out there. To the point that Wikipedia has a page devoted to them, some of which are too complex to explain on that single page. The Japanese one is particularly interesting. I'm sure someone out there is nuts enough to create a model that encompassess all of these many & varied possibilities, but not I.

Generally speaking, addresses are used to send snail mail. If that's the only reason you need them in your application, then a simple text string will do. I'm sure users from Country X are quite capable of entering their address in a sensible format. When people want stuff delivered, they'll make sure the address is properly formatted. If you need to do silly things like calculate shipping costs, then there's no harm in asking the user for their country seperately, or even their locality within that country. Instead of having a dozen fields, you'll have 2 or 3, which is much simpler to work with for users, and it won't drive developers insane.

And then there's names. They're even worse. "First name", "last name". If I had a penny for every time I came across a form asking me for two parts of my name, I'd be bleedin' rich. Let's start with the obvious: not everyone has two names. In fact, until relatively recent in history, most western people only had one name. Only when Napoleon decreed in 1811 (!) that everyone under his rule ought to have a last name did people take on "actual" last names. Before then, John was simply John. If you didn't know which John exactly, then "John son of the butchers by the church". Not every culture uses the same sort order for first name & last name. In Japan, the family name comes before the given name. If you want to use the first name to send informal communications along the lines of "Jack, we have a wonderful new offer", then you're out of luck in China. They use the full name for those types of things.

Just like with the addresses, the only sensible thing to do is stop trying to fit everyone in the same box, in a manner of speaking. Because what you actually need is *one* box for a name. Your users are perfectly well aware of their own name, so they can enter it in whatever order or format they're used to. If you really insist on being the cool kid by sending messages with personalized greetings, then I suggest you ask the user "how should we address you?". And for goodness' sake, DO NOT try and validate the length of a name. 2 characters is perfectly common in Asian languages, whereas the longest official name is -- according to Guinness World Records -- 799 characters long.

KISS is the golden rule, as always. If you don't need need the "standard" granularity for names and addresses, then don't bother with it. It's a waste of everyone's time and it will only frustrate users who don't fit in any of your boxes.

flattr this!

Tagged as: No Comments
21Jul/110

Git pre-commit hooks

Git's pre-commit hooks are pretty useful. You could use them, for instance, to run your tests and abort the commit if there are failures. All you have to do is write a simple shellscript. The example below runs a php syntax check on all php files and aborts the commit if it detects anything invalid. It's based on a script that was going around at $work, no idea who the original author is, but kudos!

Save this as .git/pre-commit, and make sure you make it executable (chmod u+x)!

 #!/bin/sh

syntax_errors=0
error_msg=$(mktemp /tmp/error_msg.XXXXXX)

if git rev-parse --verify HEAD >/dev/null 2>&1
then
        against=HEAD
else
        # Initial commit: diff against an empty tree object
        against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

# Get a list of modified php files and run php -l against them.
for indexfile in `git diff-index --diff-filter=AM --name-only --cached $against | egrep '\.(php)'`
do
    # Don't check empty files
    if [ `git cat-file -s :0:$indexfile` -gt 0 ]
    then
        case $indexfile in
            *.php )
                # Check php syntax
                git cat-file blob :0:$indexfile | php -l > $error_msg ;;
        esac
        if [ "$?" -ne 0 ]
        then
            echo -n "$indexfile: "
            cat $error_msg
            syntax_errors=`expr $syntax_errors + 1`
        fi
    fi
done

rm -f $error_msg

if [ "$syntax_errors" -ne 0 ]
then
    echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
    echo "@@   Error: syntax errors found, aborting commit.   @@"
    echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
    exit 1
fi

Extending or modifying this script to suit your needs is pretty trivial. You can expand the egrep and case to include any other filetype you want to perform magic on, or you can run your unit tests after the loop, or send an e-mail, or make coffee, etc.

flattr this!

Tagged as: , No Comments
21May/110

On Ruby & PHP

So I quit my job. That was a relatively big change for me, after spending 3 years sat on the same chair working with the same team. But I felt it was time for a change. The new job is quite a bit different from the old one. One rather obvious difference is the programming language .. I've gone back to my proverbial roots and am now churning out PHP on a daily basis. And because I'm such a programming nut, I'm working on some after-hours Ruby projects as well.

PHP and Ruby are both obviously very different from Java - and very different from each other. Sometimes in good ways, sometimes in bad ways. Syntax wise, PHP and Java are very similar. The dollar sign on my keyboard is definitely seeing a lot more action now, but other than that not many dramatic finger changes are required. PHP doesn't have have a bunch of things I like, like final method arguments, multit-hreading or a half decent collection of standard classes. What it does have is excellent documentation and easy & interesting meta-programming. That, and it's obviously much more tailored for the web than Java. For the first time in 3 years I *don't* actually need a whole armada of frameworks just to get something simple done. Still .. I miss my (Concurrent)HashMap, ArrayList, and most importantly my trusted BigDecimal.

And then there's Ruby .. Even after a couple of months of Ruby, I have very mixed feelings about it. The documentation sucks. Don't argue with me, it really does suck big fucking donkey balls. RDoc (especially online) is to JavaDoc what Spam is to nice and tasty Prosciutto. Then there's the lack of backwards compatibility (granted, Java may take this a bit too far, but still).

And then ... there's the syntax. This is where my feelings are mixed, rather than plain negative. There's too much choice. You can mix and match a bunch of styles, do..end, curly brackets, semicolons or no semicolons, method arguments with or without braces, and the list probably goes on. This leads to code that's hard to read (and thus hard to maintain), especially when different people stick to different styles. On the other hand, it also leads to nice syntactic sugar. Clever use of methods can make it look like you're defining your own keywords, which is very nice for creating your own DSLs. It's also rather nice to have Operator Overloading, and being able to treat everything like an object also has its benefits.

Still .. my feelings remain mixed. And in spite of everything, I feel like Java is still the only choice for Serious work. Not only because of the amazing documentation, the excellent standard library or even the massive community, but also for the amazing JVM, its security model and its thriving ecosystem.

Java ain't dead, folks.

flattr this!

Tagged as: , , No Comments
9Mar/111

On naming Interfaces

Just about every programming book or OOP example I look at has the annoying habit of prefixing interface names with an I. Yes, IInterface, ICar, IWallet, IMoney, IIAmStupid. It's one of my pet peeves, I admit, but every time I come across code like this I find myself suppressing murderous tendencies.

Why oh why would you do this? "To clearly indicate that it's an interface". Why the hell do I need to know that it's an interface in the first place? If I want to use your library, I really don't give a toss whether I'm talking to an interface or a concrete class. If I do want to know (because I'm extending or initialising it) then I'm quite capable of figuring out for myself whether I'm dealing with an interface, abstract class or concrete class. The only thing this random I does is make it harder to look for suitable classes. I want to search for Car, or Wallet, or Money. Not to mention that I don't want to type that extra letter every single time I'm assigning an instance to a variable.

Seriously, how ugly is this
IFoo foo = IFooFactory.createIFoo();

The irony here is that I used "I" 32 times in this post. But for crying out loud, pick a meaningful name, not some silly prefixed monstrosity.

flattr this!

Tagged as: , 1 Comment
20Feb/112

The Agile Samurai: Mini book review

The Pragmatic Programmers have published quite a few books over the years. My bookshelf contains nearly a dozen of them. The latest addition being The Agile Samurai: How Agile Masters Deliver Great Software.

It's essentially a high level overview of agile practices, with a focus on the why and the how. Unlike some other books on Agile, this one tries to remain pretty neutral when it comes to methodologies. XP, Scrum, Kanban are all briefly mentioned, but the author managed to boil Agile down to its essentials: common sense, being goal oriented and having a willingness to improve.

The chapter on Agile Planning is a particularly excellent treat. It could have easily been called "the idiot proof guide to agile planning", because really, it's that good. Concepts like velocity and burndown are illustrated with pretty graphs. Not only does the book explain how to apply agile planning, but by the end of the chapter you'll also know why it's a good idea. The phrase "Why does reality keep messing with my Gantt chart!?!" sums it up pretty nicely.

I have just one problem with the book. The Samurai theme could've been explored a bit better. For starters, this here Samurai is wearing his swords on the wrong hip. Second, his name, Master Sensei is a bit silly. Ō-sensei would've been much more appropriate. But in all seriousness, the whole Samurai theme could've been expanded on. There are many similarities between software development and martial arts in general. Mostly when it comes to drive and focus, a bit less so when it comes to actual sword wielding. Still, it doesn't detract from the book, so all is well.

All in all, a pretty good book. If you're an Agile Veteran, you won't need it, but maybe your pesky manager or team leader could benefit from it ...

flattr this!

Tagged as: , , 2 Comments
25Jan/110

Automating Maven Releases

Automating maven releases should be pretty straightforward in non-interactive mode. A bug in the release plugin made it impossible in my situation. Every time I would provide the release version(s) as command line arguments, the release plugin would choke on me with the following error message:

Error parsing version, cannot determine next version: Unable to parse the version string

The following shellscript works around this problem, by redirecting input to the maven execution.

Note: I'm releasing a project with a parent and 2 child modules, which is why I have to specify three versions ( + 1 SCM tag). If you're not using multiple modules, or are using more, you'll have to adjust the script accordingly.

#!/bin/sh

releaseVersion=AmazingRelease1
nextVersion=AmazingRelease2

mvn \
    release:prepare -P production &>> /tmp/build.log << EOS
$releaseVersion
$releaseVersion
$releaseVersion
$releaseVersion
$nextVersion-SNAPSHOT
$nextVersion-SNAPSHOT
$nextVersion-SNAPSHOT
EOS

mvn release:perform -P production &>> /tmp/build.log

This is an abridged version of our full release script. The full version asks the user to enter the release version once, then releases several versions using different profiles and creates a distribution set with all versions and a bunch of documentation. This works in my situation, but if your release procedure is more complicated then you can just expand on the script :-) .

flattr this!

Tagged as: No Comments
24Jan/110

Test design – Equivalence Classes

During a recent job interview, I was asked to write some code -- I know, shocking! The idea was that several test cases had been defined, and that I was to implement a relative simple class that would make the tests pass. The problem was pretty simple, so I won't bore you with it.

What was shocking, however, was how poorly designed the tests were. Boundary cases were largely untested, and it seemed like someone spent an inordinate amount of time writing useless tests. When I brought this up during the interview, the person who wrote the tests seemed surprised that they weren't very good, because he got nearly 100% code coverage on the implementation he created.

While code coverage is all fine and dandy, it doesn't actually say anything about the quality of your tests. Maybe his implementation would've worked perfectly, even with strange values and edge-cases. Maybe not. We'll never know.

Equivalence Partitioning is one of the simplest test-design techniques. As the name pretty much implies, the idea is to partition possible input values into equivalent classes. Sounds like a bunch of gibberish? Let me illustrate with a classic example. Liquor laws.

As you can tell from the image, if you're under 16, you're not allowed any alcoholic beverages. Once you turn 16, you're allowed to have beer and other non-spirits. Once you turn 18, you hit the jackpot and can drink whatever tickles your fancy.

The red, yellow and green areas are the three Equivalence Classes for this problem. Whether you're newborn, 5, 11 or 15, it doesn't matter, you're not getting a drink. And once you're older than 18, your age stops mattering entirely.

Once you have this information, you can design a couple of test cases. In this case, you could start off by designing a test case for each class. The exact age for each test you pick doesn't matter, as long as it's in the class you're testing – or outside of it if that's what you're testing.

So that's three easy tests. Then it's time to apply a bit of Boundary Value Analysis. After all, it's so very easy to create off-by-one errors.

Boundaries are the areas where equivalent classes meet. The boundaries in this case are 16 and 18. When you look at the boundaries you've defined, you'll want to look very carefully at your specifications again. Someone's just turned 16 on this very day. Does that mean they can have a drink? Or not? Once you have the answer, create a test case. Then do the same for all other boundaries.

With five test cases, one for each boundary and one for each equivalence class, you'll have tested this very thoroughly. Additional test cases can be made to test invalid input. What happens if you try to pass a person with a negative age? What if the age is a million years old?

flattr this!

Tagged as: No Comments