February 15, 2011

Something is rotten at Nokia

As you probably have heard, Nokia and Microsoft recently announced a new partnership. Nokia will be delivering smartphones with Windows Phone 7 with it's first product release later this year, and Microsoft's Windows Phone 7 operating system has now become Nokia's primary platform.

Some of you may think this is just a bad move for Nokia, or some of you might even think this is really good news for both companies. Well, future will tell if it's a good or bad move, but I do think something is rotten here.

First, consider that Nokia owns Trolltech (creators of Qt, http://qt.nokia.com/), Symbian (which is open source) and they are also co-deveoping the mobile Linux distribution MeeGo with Intel. Sounds like a really open source friendly company, right? They clearly see the value in opening up their software and distributing it as free (as in speech) software.

Then something happened.

Late last year, Stephen Elop joined Nokia as President and CEO. Elop is a former Microsoft executive. He owns a lot of Microsoft stock, 174 000 to be exact.

Before Elop joined, there was an article on Nokia Conversations web site about his joining of Nokia. The article said:
"Nokia is transitioning from a hardware manufacturer of mobile devices to a software and solutions business."
Does the Microsoft partnership deal move Nokia towards being a software business? Not by any means. Instead, by placing Windows Phone software (developed at Microsoft of course) on most of their smartphones, Nokia remains a hardware manufacturer, instead of moving towards software. Sure, they will probably develop some Windows Phone apps at Nokia, but that would not be comparable to the commitment they previously had to MeeGo and Symbian. It's not even close. In fact, Nokia workers fear that there will be massive job cuts because of this deal.

Nokia's MeeGo partner Intel was also caught by surprise. They knew nothing of this change in Nokia's strategy, and say they will continue work with Nokia on MeeGo, but just not as close as before.

These are only a few of the things that proves this deal is a very sudden move. It was not planned (not by Nokia anyway) when Elop first joined, according to the Nokia Conversations web site. It is very easy to think that the man who owns 174 000 Microsoft shares is the brains behind this decision.

The Nokia employees are not the only ones who are disappointed, Nokia's share holders also took a stab when the partnership was announced. The Nokia stock dropped significantly, and in the last 3 days (10 feb-14 feb, excluding the weekend) it has gone down almost 25%. Doesn't seem like the market thinks this move is good for Nokia, right? Microsoft stock prices only went down 2,65% in the same period.

Nokia is of course a desperate company right now, Elop is not hiding that fact. And desperate times call for desperate measures. Giving up on all their investments in open technologies like Symbian and MeeGo and other promising projects such as the Ovi Store, and instead joining Microsoft with it's proprietary platform Windows Phone 7 is of course a desperate move, especially since the WP7 sales are not looking that good. Nokia is placing all eggs in the Microsoft basket, and if the market doesn't like WP7 Nokia will be history.

I think something is really rotten at Nokia, and the stench seems to come from the top floor...

February 11, 2011

My top 5 reasons not to comment out code

There are a lot of reasons that you shouldn't keep commented out code in your Version Control System. Still, it happens in almost every project. In my project at work, it is not uncommon to see files with 30-50% of the code commented out. I can't for the life of me understand what the developer that left it there was thinking. Especially when it comes to trivial lines like //int i = 0;. Is he keeping it in case he forgets how to define an int? Not likely. Then why? I have no idea.

But what I do know is why you should never leave commented out code in your source files. That's right, never. Ever. And here are my top 5 reasons.

1. Commented out code can never replace a good Version Control System. Your VCS keeps track of the changes in source files much better that you ever could with commented out code. By looking at the commented out code, you can't see when or in what order the code was commented out, much less why. You can't tell if two lines of commented code has any connection, or if they ever where active at the same time. You still need the VCS for that. Keeping commented out code is a very poor man's VCS. Very, very poor indeed.

2. It disrupts searching. When searching your project for a particular text, you are not interested in browsing through loads and loads of commented out code, simply because it's not relevant to anybody.

3. It distracts you when reading. When you quickly need to make out what the purpose of a class or method is, and how it does it's magic, you're not interested in what it doesn't do, or what it no longer does, right? You want to know what it does right now, without scrolling through pages of nonsense.

4. Be proud of what you commit (or in the git world; push). Whenever I am about to commit some piece of code, I always go through it line by line thinking "am I proud of this code?". If the answer is no, I go back an rewrite it. Beautiful code is also working code. Ugly code can surely be made to work, but it's much more vulnerable to future bugs, simply because it's harder to understand and edit.
No one can be proud of commented out code. Remember that software development is a craftsmanship. Take pride in what you do. Never commit crap.

5. It is misleading. If you're about to fix a bug in a function and you see chunks of commented out code, you probably think that the answer is in there somewhere. That's when you start analysing and maybe even testing the commented out code, only to find that it had absolutely nothing to do with anything. You could argue that commented code could never hurt anyone, but you would be wrong. Even commented out code can be very misleading.

If that didn't persuade you to go remove all your commented out code right now, please write a comment about your top 5 reasons to keep commented out code in your source files.

February 6, 2011

Git configuration in the cloud

When we started using git at work I also started a couple of open source projects on github in my spare time. I was configuring a lot of useful aliases at work which allowed me to work faster, but when I used git at home I kept getting errors trying to use the aliases I was used to from work, which was not added to my git configuration file at home.

I started thinking about a way to share the git configuration between all my computers, and I came to think about Dropbox. Dropbox is a smart and simple application that syncs a local folder to the cloud. This means that if you install Dropbox on several machines, this local folder will be syncronized across all those machines (there is even an Android client available).

Start by creating a git config file and save it somewhere in your Dropbox folder. Here we will use the path /home/user/Dropbox/gitconfig as an example.

Git reads configuration files from 3 different places; project specific config file in $GIT_DIR/config (e.g. /home/user/project/.git/config), user specific config file in ~/.gitconfig and the system wide config in /etc/gitconfig. To make git read from the config file in Dropbox, all we need to do is to make a filesystem link from ~/.gitconfig or /etc/gitconfig to the Dropbox file.

Since I have different user.name and user.email configurations on different systems, I chose to use /etc/gitconfig as my roaming git config file, which we will use in this example as well. In a multi-user environment it may not be possible och practical to change the system wide gitconfig file, and in that case you can probably use the ~/.gitconfig file instead.

On each of your machines where you want this roaming git config, open up a terminal and run:
sudo ln /home/user/Dropbox/gitconfig /etc/gitconfig -s

Now you're all set and you can put all your favorite aliases and configuration options into the git config file in your Dropbox folder, and they will be ready for you no matter which of your computers you're working on.

February 4, 2011

Git alias: prepare

The way we do development in git at my workplace is probably very similar to many others. When a new feature is requested, or when a bug is reported, we create a new local branch (or "feature branch") where we implement the required functionality. When the code is ready for deployment to the test environment we merge this local branch with the master branch which is then pushed to the central git server.

We recently moved to git from subversion, and even though we are very happy with it, the most common complaint about git is that it requires a lot of commands even when doing simple everyday stuff. For example, the most common work flow when pushing a local commit in a local branch to the server's master branch consists of the following commands:

# we are in local branch called "feature"
git checkout master
# to make sure we have the latest changes
git pull origin master
# then go back to our local branch
git checkout feature
# merge the latest updates
git rebase master
# then go back to master
git checkout master
# and merge the new feature
git merge feature
# and finally
git push origin master

As you can see, this requires quite a lot of typing. That made me think about creating an alias that can do all these things in one single command, and this is what I came up with:


prepare = !git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \\(.*\\)/\\1/' > /tmp/gitcurrentbranch && git checkout master && git fetch && git pull origin master && git checkout `cat /tmp/gitcurrentbranch` && git rebase master && git checkout master && git merge `cat /tmp/gitcurrentbranch` && rm /tmp/gitcurrentbranch

This alias does all things necessary until it's time to push the changes to the server. I have used it for a couple of weeks now, and I have had no problems whatsoever.

The biggest challenge here was to find a way to switch back to the branch we started in. I have found no way of doing that elegantly in git, but I solved it by writing the name of the current branch to a tempfile, and then retrieving the branch name from that file when I needed to switch back. I then finished with deleting the temp file.

If you prefer merging with the --no-ff flag (no fast-forward merge, always create a merge commit) you might want to tweak the alias a bit. We are actually in a discussion about the --no-ff flag right now, so I might add that myself later.

The above alias is obviously meant for Linux and will probably work in OSX too without modification, but if you're running another OS you are on your own.

Update 19 May 2011:
I recently discovered that you can switch to the last branch you were on by using @{-1}. That means my alias will get much simpler, and will also work on all operating systems:

prepare = !git checkout master && git pull --rebase && git checkout @{-1} && git rebase master && git checkout master && git merge @{-1}


I have also added "--rebase" to the pull command above to avoid having merge commits created if you pull when having local commits and someone else has updated the remote repo.

Git tip: push.default

When you have made local commits in git that you want to push to a remote repo, you use the command git push. However, the default behavior of git push might not be what you expect. If you have multiple remote tracking branches in your local repo, git push pushes all your local commits in all tracked branches on that remote (e.g. origin).

Personally I have no use for being able to push to several branches at once. The correct thing to do would of course be to include the remote name and the remote branch name in the command, like git push origin mybranch. But I know that if I'm required to always enter which branch I want to push to, I will eventually screw things up. It's simply a matter of time.

But there's hope. There is actually a git configuration option that makes git behave exactly like I would want it to, i.e. only pushing the commits that are in my current branch to the remote branch it's tracking, and nothing else.

Add the following to your git config file and you're safe(r):

[push]
default = tracking


Or issue the command:
git config push.default tracking
(include the --global flag to make this setting global)