20 Nov 2012

Improving someone else’s product

I spent a nontrivial amount of time writing code for uploading photos to Flickr from a web app of mine.  Flickr has apparently made it easier to upload pictures now, so my friend — the only user of my app — doesn’t upload pictures from my app anymore.

Lesson learned: By making your product a mere feature of someone else’s product, you’re giving up control over your own userbase.  (Related: Twitter and developers, a love story)

8 Nov 2012

Better tools, better results

Get the best tool you can get.  A lousy keyboard causes more grammar and spelling errors.

21 Oct 2012

Shying away from success

I wonder if I have been shying away from success.  I know I fear the unknown.  What happens after completing a task or project is probably “new and unknown”, and I subconsciously avoid it just so that I don’t have to face unknowns.

15 Oct 2012

No parentheses

I think the next improvement I should make to my writing is to drastically reduce the number of times I include notes in parentheses.  They make reading unnecessarily hard without adding much value.

7 Oct 2012

Bad writing

I was chatting with a friend and remembered something I had blogged about.  Naturally, I shared the link to the post.  That post was written two years ago, and it wasn’t the best of my writing.  After reading, she said I had come a long way from that point and I write much better these days.

I didn’t start writing because I wanted to become better at writing; I have always been a person who likes to write... it’s a way of self-expression for me.  English isn’t my first language, but my primary blog (this blog) is in English.  God only knows why.  My posts from years ago are nothing to be bragged about.  They are childish thoughts expressed in an awkward way.  Not that I have become a great writer now, but I have improved over time.

The way to improve writing is to exercise bad writing.  You know your writing is horrible, and yet you keep on writing.  Some day you’ll find yourself writing like a good writer.  I don’t know about others, but my takeaway from this is that there isn’t anything inherently good or bad.  Everything is equally good and bad.

Going back to writing well.  As I said, I like writing.  I think good writing should feel like the writer wrote it effortlessly... like words dancing together to make the text, and not like odd components stacked together.  If I were to wish, I’d say I want to write like Rob Pike or Bruce Eckel.  Those are two authors I loved reading... people from whom I have learned many things.

If you have been trying to become better at something, I think you’d like watching this video.  (Source: Daring Fireball)

Winning and losing

If you’re not willing to lose, you have a rather slim chance of winning.

29 Sept 2012

Don’t pay for web hosting if you don’t have to

A few months ago, I moved all my websites, including my personal homepage www.manki.in to Google hosting.  (That is, some Google product running on my own domain.)  However, there was one piece in the puzzle that was still with my web hosting provider: redirecting any requests to the naked domain manki.in to www.manki.in.  Once the request reaches www.manki.in, Google would take care of it from there on.

This was the setup of my site for several months, until yesterday.  Only yesterday I found out an awesome feature Google Apps has.  It can redirect requests to your naked domain to any subdomain you specify.  Precisely the one thing I was paying my web hosting provider for!   And Google would do this for free because I am on their free Google Apps plan.  That amounts to saving more than $50 a year.  Very cool!

Essentially, I had to set up DNS A records to point my domain name to Google’s IP addresses and tell Google Apps which subdomain I wanted the requests to go to.  Check Google’s help page for detailed step-by-step instructions.

One last thing you need to do is disconnect your domain name from your hosting provider’s IPs so your users are always sent to the right place.  Once you have added the A records to map your domain to Google’s IPs, delete all original A records so your domain is not pointing to your hosting provider anymore.  When your hosting contract runs out next year, you can simply not renew it :)

18 Sept 2012

Error-handling: Java vs Go

FotoBlogr is the first toy I wrote using Go.  As a part of FotoBlogr, I also wrote a Flickr client library, an App Engine helper library, (unpublished) Blogger client, and Picasa client, so I got to see some idiomatic Go.  One thing I really missed when writing Go was exceptions.  Many things that are one-liners in languages with exception support (Java, Python, etc.) become 3 or 4 lines in Go.  Let’s take parsing a string as an integer for example.  In Java, you’d write:
int n = Integer.parseInt(str);
and you’re done.  If you expect this conversion to fail, you’d catch NumberFormatException, but it’s not mandatory.  Compare this to equivalent Go code:
n, err := strconv.Atoi(str)
Of course, you can choose to ignore the error by using an underscore in the place of err, but it still won’t be as expressive like in Java.  For instance, you cannot write return math.Sqrt(strconv.Atoi(str)).  You must write that in two different statements:
n, _ := strconv.Atoi(str)
return math.Sqrt(n)
Of course, this is wrong, and it should actually be something like:
n, err := strconv.Atoi(str)
if err != nil {
  // Handle this error.
return math.Sqrt(n)
It was very annoying to get used to writing code this way... almost as if writing dumb code.

Fast forward a few months.  I had moved to a C++ project where the style guide prohibits using exceptions.  Existing code in this project ignored errors in several places, but when I was writing new code I always made sure I did something about errors... at the minimum log it and proceed.  I didn’t have to make a conscious effort to do that; writing Go code had trained me to naturally think about error handling.  It felt awkward to not check for errors, in fact.

Now, I am fixing a bug in a Java project.  This is an old project with design decisions independently made by hundreds of engineer over several years.  The change itself is fairly simple: instead of simply sending a request to an RPC server, now we have to first check whether it’s okay to send that request.  If this query fails, we’d show an error message to the user.  But the complication is this: I’m changing a void method that does not throw any exceptions.  (This method in effect promises all its callers that it can never fail!)  This method is being called by half a dozen classes, which are being called a few others, and so on.  Unless I touch a large number of files to handle the new error, I can’t get the code to compile.

I was discussing this issue with a teammate and what he said was remarkable.  He said, “Every method in every class should throw a checked exception irrespective of whether that method can fail or not.  If it cannot fail today, maybe it can tomorrow.”  He didn’t literally mean that, of course.  What he meant was we weren’t using checked exceptions as extensively as we should have.  If this method I am changing now threw some checked exception, I could simply use that in my client code without scratching my head too much.  This is precisely what Go does.  Almost all functions return an error status.  You can choose to ignore it, but when someone new to the codebase reads it, it’s obvious you’re ignoring an error.  I’m starting to think that Go’s way of error-handling is a much superior way than Java’s and C++’s.

SIDENOTE: The easy and obvious fix is to throw a RuntimeException and catch it in only the places I like to change now.  But that’s a really wrong way to fix a problem like this.  First of all, RuntimeExceptions are not meant for cases like this.  They are for things like division by zero, dereferencing a null pointer, etc.  Things that can happen in any code and thus are impractical to handle specifically.  Since they are rare and usually very serious, they are allowed to propagate through deep call stacks.  Defining application errors, input errors, etc. as RuntimeException can lead to severe debugging issues over time.  You really don’t want that.

16 Sept 2012

White headphones

At work, we can pick up headphones for free.  You just walk into the place where they’re kept, take one, and walk away.  You don’t have to ask anyone, and you don’t have to tell anyone.  I took a really nice Sennheiser pair a couple weeks ago.  Though they are expensive (about $60), it was painful to use them.  10 minutes into wearing them, my ears would be paining real bad.

I decided I’d just buy a better pair myself.  Being a predictable BoseSheep, I went to Bose (like iSheep buying Apple without thinking).  They had two different models: OE2 and AE2.  OE is on-ear while AE is around-ear.  AE2, when worn, doesn’t even touch your ears so they are more comfortable than OE2.

But I am not a rational buyer... I’ve never been one.  Very often I’d buy things for totally random reasons.  This time I decided to buy the OE2 because that was the only model available in white.  AE2 came in one colour and that was black.  I just cannot buy a black toy when there’s  a white alternative.

Within two days of usage, I don’t like the OE2 because it’s pushing on my ears almost like the Sennheiser.  Unhappily but with no other choice, I go to Bose Store again to return the OE2 and pick up an AE2.  To my surprise, they had white AE2s now!  Bose must have launched these in the two days I had the OE2!  Funny how lucky I get :)

11 Sept 2012

Slow = bad

Having to wait for machines repeatedly is one of the most demoralising things you can experience when trying to get something done.

9 Sept 2012

Understanding code

You don’t understand a piece of code until you can confidently add features to it.

Is screen the only advantage tablets have?

Quite often, I find myself wanting to read on my Nexus 7 than on my laptops.  Checking my Google Reader, reading any article that’d take more than a couple of minutes, reading Kindle books... I prefer the tablet for all these.  This is not surprising because the Nexus 7 has a 216-dpi screen while my laptop has an incomparable 96-dpi screen.

When it comes to doing some real work... work that involves multitasking and/or precision, touch devices are very inadequate.  Think of writing code, for instance.  I’d have 6+ browser tabs open with various manuals, one terminal for building and running the code, one or two more terminals for other random stuff, one editor/IDE window (usually GVim; occasionally Eclipse), and a few more browser tabs that are pure distraction (Gmail, Google+, etc.)  A touchscreen device without overlapping windows just won’t work for this use case.

Android’s multitasking UI would improve over time, but I doubt if it can catch up with current desktop OSes in the next two years.  On the other hand, it’s likely that before the end of 2013 there will be enough high-res monitors and laptops in the market.  When that happens, I may use the laptop a lot more frequently than the tablets.

While tablets may replace laptops for quite a few people going forward, I don’t see myself giving up the functionality I get from desktop OSes.

2 Sept 2012

Inspecting 302 HTTP headers

Let’s say you want to inspect the response header for an HTTP request.  But the response is a 302, so your browser immediately navigates to the new location and you never get to see the 302 response (and the headers).

One way to solve this problem would be to install a browser extension that would keep the headers for you even after the redirect has happened.  But I’m not a big fan of installing browser extensions for functionality that I very rarely need.  So I use the wget command instead:
wget -S -O/dev/null --max-redirect=0 'http://www.google.com/'
-S flag tells wget to print the headers to stderr
-O/dev/null discards the response body (by writing it to the null device)
--max-redirect=0 tells wget to not follow any redirects.

This is the 302 redirect google.com sends for redirecting users to country-specific Google domain:
--2012-09-02 09:54:33--  http://www.google.com/
Resolving www.google.com (www.google.com)...,,, ...
Connecting to www.google.com (www.google.com)||:80... connected.
HTTP request sent, awaiting response... 
  HTTP/1.1 302 Found
  Location: http://www.google.com.au/
  Cache-Control: private
  Content-Type: text/html; charset=UTF-8
  Date: Sat, 01 Sep 2012 23:54:33 GMT
Location: http://www.google.com.au/ [following]
0 redirections exceeded.

28 Aug 2012

Some monospace fonts

Being the monospace font freak that I am, I recently found PT Mono and have fallen in love with it.  Turns out, I’ve been liking the PT family of fonts for a while: I have been using PT Sans for this blog’s headings.  You can download PT Mono (and others) for free from ParaType’s web site.

If PT Mono is my newly found attraction, I have been really liking Envy Code R for its extreme readability.  If I had to pick a single monospace font to live with for the rest of my entire life, I’d choose Envy Code R.  You can download Envy Code R for free from Font Squirrel.

If you’re into serif monospace fonts, give Verily Serif Mono a try.  This used to be my favourite font until I stumbled upon Envy Code R.

30 Jul 2012

Poor battery life after Android 4.1 (Jelly Bean) update?

If your Android phone was recently updated to Android 4.1 (aka Jelly Bean) and you have been seeing really bad battery life ever since, read on.  It could be that Google+ sync has been enabled by the update and that’s using up a lot of power.  Go to your phone’s Settings > Accounts > Google settings screen.  For every Google account listed, deselect the Google+ option.  This should bring back sane battery life to your phone.

See Demystifying Android power usage for more generic tips on saving battery life on Android devices.

23 Jul 2012

Kovilpatti boy

It’s been 5 weeks since I came to India.  I have been living in our new house since my arrival, and it’s been pretty good.  Wide open sky with almost no light pollution.  This time of the year is usually windy, and I quite like the weather.  Being with my family has always made me happy.

Went out on my bike (a motorcycle) to a few places.  Even after seven years, I think my bike is pretty good and I like it the same.  The reason for the possessiveness I have about the bike and my riding gear has been unfathomable.  I just don’t want to share them with anyone!  Have a slightly longer ride coming up tomorrow; looking forward to it.  Want to take some pictures during the trip too; let’s see how that works out.

I would have liked to be a bit more productive at work, but the lack of productivity hasn’t made me very unhappy.  My mind keeps telling me that this is my place.  I really want to come back here and start living here again... like the Kovilpatti boy that I am.  There’s something magical about this place... maybe.

11 Jun 2012

Better than animals

“Even when they don’t know much—or not at all—about Americans, many Indians think that Indians are generally better than Americans.  Do you think it’s correct to think that way?”  When I ask people this question, they almost always say “No, it’s not appropriate to think ill of others without knowing them well”.  Or they’d say “It’s incorrect to generalise all Americans or Indians that way”.

However, when I discuss morality with them, an argument they love to put forth is that “We are humans, shouldn’t we be better than animals?”  I just don’t understand why.  Vast majority of us don’t know much about the lives animals live.  We don’t know why individual’s free will should yield to society’s morals.  We can’t be sure if we are actually better than animals to begin with.  But somehow we as a society have to live “better” than animals!

10 Jun 2012

Why I think new Android menus are broken

Up until Android 2.3, Android devices required a hardware “menu button”.  Pressing the menu button was the standard way of accessing the functions provided by apps.  Quite a few people  complained that this model is broken because sometimes users wouldn’t think that they can press the menu button to find actions they can perform.  Google “fixed” this problem in Android 3.0.
In Android 3.0, menu button became obsolete, and Google asked developers to use other on-screen UI elements to provide access to app features.  But the issue now is that actions are in two different menus.  Take Google Maps, for instance. If you want to check into a place, that option is available from the drop-down on the top-left:
But let’s say you want to change the Google account used for Latitude.  For that, you’d need to choose Settings from the bottom-right menu:
Similarly, Google+ app has its options split across two different menus.  Some options on the left:
And some on the right:
I know this is not plain madness, and there are reasons behind this UI change.  There are recommendations in Android Developer (or Design) Guide to help developers decide which options belong in the top-left menu and which options on the other one (called Action Bar).  But the issue is, any large app like Google Maps or Gmail or Google+ is going to have a large number of possible operations, and only when you know a good amount of it you can correctly guess which menu has the option you are looking for.  Expecting a common user to guess that correctly is unfair.

After having used my Android 4.0 phone for about 6 months, I’m giving a Thumbs Down to the new menus.

7 Jun 2012

Visible and invisible

This is a picture of earth from moon (source).  What I find interesting in this is that it’s all pitch-dark around earth.  But space on at least one side of earth must be filled with sunlight.
If we cannot see anything, it’s not always because there’s no “light”... sometimes it’s because there’s no dark, light-reflecting object.  In other words, all we see is contrast.

6 Jun 2012

Purpose, happiness, and Buddhism

Days with nothing to do are not always great.  Last weekend wasn’t great either.  There wasn’t anything specific that made me feel less-than-happy, but I wasn’t consciously happy either.  Monday morning, in the time between the start of my commute and the end of it, my mind had come back to its normal happiness.  Because there was work to do; something meaningful to do.  Looks like the mind needs to see some purpose in how I spend my time to decide to be happy in general.

This reminded me immediately of Poythevu, one of my favourite Tamil novels.  The title would translate to False God.  The crux of the novel is that each mind is seeking its own false god, and a minds that knows its false god is at peace because it has something to attain to.  My false god yesterday was the pending work I had to complete.

In sharp contrast is the Buddhist thought on purpose.  Alan Watts says “Fundamental principle in Buddhism is ‘no purpose’.  When you drop fart, you don’t say, at 9 o’ clock I dropped fart.  It happened of itself.”  If practising Buddhism means training oneself to renounce all purpose in life, that’s going to be a dramatic shift for someone like me.

20 May 2012

I like

I like light food that’s easy on the body.  I like machines that don’t make people wait.  I like machines that are predictable.  I like people who are happy.  I like people who think deep.  I like people who keep talking.  I like dogs... and cats, and monkeys, and wolves, and elephants too.  I like novels that are honest.  I like tunes that we wake up remembering.  I like long desert roads.  I like windy hill roads.  I like shady village roads.  I like girls who look pretty.  I like people who are beautiful inside.  I like sleeping on the floor.  I like sleeping 9 hours a day.  I like being awake for longer than a day.  I like repairing broken things.  I like buying gifts for people.  I secretly like walking to work in rain.  I am blessed, for blessed are those whose days are filled with things they like.

19 May 2012

Writing - 2

I just started writing a blog post supporting the restrictions Apple imposes on its products and users.  Halfway through, I rediscovered my disagreement to what Apple does.

This is why I write.  The fuzzy ideas in my head solidify as I write them down.  Often, I’d start writing with some opinion, and I’d have a different opinion when I complete the post.  Paul Graham says that writing is a tool for better thinking; he’s right.

13 May 2012

Indians and their arranged marriages

Just a random thought.  When so many Indians are fine with someone else deciding their wife/husband, how can we expect them to be assertive about other things in life that they’re less concerned about?

Criticisms like “we don’t care enough to vote for the right candidate in elections” are nothing new.  If we are willing to live with a partner that’s assigned to us, won’t we naturally be fine under pretty much any government that’s assigned to us?

28 Apr 2012

Bad choices

When you choose one from two suboptimal options, you will be unhappy irrespective of what you choose.  Thinking later that the option you didn’t choose may have been a better one is not productive.  You chose what you chose; just accept it.

23 Apr 2012

Predators and scavengers

Some people are of the “predator” class.  They do big stuff, and they don’t (and can’t) care about small stuff.  And there are people of the “scavenger” class who do the small stuff that the predators didn’t do.

Apple, for example, is a predator.  They make devices like iPhone and iPad that people want to buy.  But the devices often only go 90% of the way.  The remaining 10% needs are served by accessory manufacturers.  People who make hundreds of cases and speakers and all kinds of supplements.  In the system we have, all pieces are important: the predator, the scavengers, and the rest (those who buy things).

Whether you are a scavenger or a predator is determined by several factors, but I believe culture is an important one.  Countries like China or India don’t have as many entrepreneurs as we see in some other countries.  (Being a scavenger is not necessarily a bad thing... after all, their without their contributions the predators won’t have the success they have today.)

What I am wondering about is, how hard it would be for a scavenger to start playing predator.  All my life I have been focusing on small stuff, so I know I’m a scavenger.  But I have this desire to transform into a predator... someone that creates jobs for others rather than someone who finds jobs.  Until now I haven’t found any clue how I can make the switch.  But I’m kinda thinking I’ll eventually figure it out... by copying other predators.  I have a few around me :)

14 Apr 2012

How to add infinite scrolling to Blogger blogs

One nice thing I like about Blogger’s Dynamic Views is that they remove older posts/newer posts links from your blog and load more posts as you scroll to the end of a page.  (This is commonly referred to as infinite scrolling.)  Adding infinite scrolling to your Blogger blog with a traditional template is not that hard.

If you don’t care about the details and you only want to enable the feature on your blog, click on the button below and add the code to your blog.  Infinite scrolling should just work on your blog, in most cases.  If you have a custom template, though, you may need to tweak the code a little.  (Scroll down to “Frequently asked question” section for details.)

If clicking on this button does nothing, or it doesn’t work for some reason, you can add this code manually:
  • Add a HTML/JavaScript gadget to your blog.
  • Leave the gadget’s title empty.
  • Paste the following code as the gadget’s content:
    <script type='text/javascript' src='//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js'></script>
    <script type='text/javascript' src='//m-misc.appspot.com/js/blogger-infinite-scrolling.js'></script>
  • Save the gadget, and you’re done.
The code for the widget is available on GitHub.  Feel free to copy or adapt the code.  A few points worth mentioning:
  • This code uses jQuery library, so don’t forget to include it.
  • Custom template blogs may have to change the value of postContainerSelector variable in the code.
  • I have manually added +1 buttons to my blog.  Dynamically loaded posts won’t have the +1 buttons initialised; to fix that issue, I had to call gapi.plusone.go() every time new posts are added to the page.
  • _WidgetManager is a JavaScript object present in Blogger blogs.  You can query this object to find some page metadata.  This code uses _WidgetManager to determine if the current page is showing a single post.  Infinite scrolling is not meaningful when only a single post needs to be displayed.

Frequently asked question

  • Q: My blog uses a script/widget that adds post thumbnails or related posts.  When I add infinite scrolling, only the first few posts have thumbnails/related posts.  How to fix that?
    A: Simple answer is that this script doesn’t work well with other scripts that add content to posts.  But if you are willing to change the code, you can get both scripts to work together.  Right after new posts have been added — which is the line after $(postContainerSelector).append(newPosts); in the script — add the JavaScript that will make your other widget update itself.
  • Q: The script doesn’t work on my blog.  Can you help me debug it?
    A: While I really wish I could help everyone use this script, it’s practically not possible for me to look at everyone’s blog and see what’s wrong.  If I don’t respond to your comment quickly (or at all), it’s because I am just too busy with things like my day job.  I’m sorry I couldn’t help you with your blog.
  • Q: Why can’t I post a comment?
    A: Contact me through Google+ if you need to ask me anything. I believe you can send me a message even if you don’t have a Google+ profile yourself.

Change log

  • Mar 9, 2013: Moved the script to m-misc.appspot.com because Google Code is not setting the right content type.  This disabled the script completely in Google Chrome.
  • Nov 19, 2012: Version 1.6 was released with support for Automatic Thumbnail and Read More.
  • Oct 17, 2012: Version 1.5 was released with support for Facebook buttons and a fix for Disqus integration bug.  Thanks to Alex for sharing Facebook support code in a comment.
  • Oct 11, 2012: Version 1.4 was released with support for Disqus comments.  Do not use this version; Disqus integration is broken in this version.
  • Sep 20, 2012: Version 1.3 was released with support for Google Analytics.  If a blog uses Google Analytics, the script will register all automatic post loading as pageviews.  To Google Analytics, it will look like the reader clicked on the Older Posts link every time the script autoloads posts.
  • May 30, 2012: Version 1.2 was released with fixes for all known bugs.
  • Versions up to (and including) 1.1 have known bugs.

12 Apr 2012

Unfathomable decisions

This has happened to me several times.  I’d disagree with certain decisions other people make and complain about it.  Often I’d get to speak to the people involved in the decisions and they’ve been usually kind enough to explain the reasoning behind it.  When I see the broader picture, those decisions don’t look all that bad.  Once I know the reasons, I cannot be agitated about the current state of things.  With this context, I can make a better sense of what people mean by achieving world peace by making information freely available.

My experiences have mostly been with decisions about computer programs, because that’s what I do pretty much all the time.  I wonder, how different our lives would be if we could somehow know the reasoning behind all decisions our society has made over centuries.  And all the decisions our governments make.  And the reasoning behind every law we need to obey (including state laws, religious laws, etc).  Would Google or some other organisation or movement ever make this a reality?

10 Apr 2012

Why we like (or dislike) things?

One of the things I keep thinking about is what makes us like or dislike something.  We like certain things one day... and the next day we don’t like them.  Or vice versa.  One possible explanation is your current state of mind decides what you think about the things you’re currently thinking about.  When you’re frustrated, you tend to dislike most things you see, for example.  This is succinctly (and beautifully) expressed as உள்ளத்திலே உள்ளதுதான் உலகம் கண்ணா.  This line was very thought-provoking and I have been thinking it to be true ever since I heard that song.

I was on a road trip recently, and I thought all the pictures I took were sloppy.  That’s what I really thought.  Then a friend commented on one picture... and I looked at that picture again with fresh eyes.  This time somehow I liked it a lot.  Something similar happened during my Himalayas trip too.  I thought most of the pictures I took were mediocre... until I incidentally “re-saw” them months later.

For the reason behind liking or disliking things, there’s probably something more going on than just your “current mood”.  While I am tempted to come up with a theory to explain it, I guess I should be patient and observe a little more to see patterns.

9 Apr 2012

Random thoughts from a road trip to north NSW

I travel primarily for one reason: travelling lets me look into myself.  Some random thoughts from a recent 3 days long road trip:
  • I have always wanted to die in a road accident.  During this trip I could think of a (possibly stupid) reason.  Wide open roads are like gods: admirable, having a character, and fear-inspiring.  Dying in a road accident is, in a way, like surrendering to the roads.
  • Travelling in a car is a lot more tiring than travelling on a bike.
  • Being on the road alone makes me happy.  Third day of the trip was the happiest because I drove for about 750km.  Time spent on “touristy things” don’t add up to so much.
  • I really, really, really want to do a 6 to 8 weeks trip covering the full length of Australia Highway 1.
  • During the trip, I easily slept for 8 hours every night.  That’s the “normal” amount of sleep I used to get.  But increased computer time has shrunk it to 6 hours on average, which makes me :(
PS: I took some sloppy pictures too.

1 Apr 2012

Rolling back git commits without losing history

I sometimes introduce a buggy feature to a program and I want to roll it back.  If I had already committed the buggy feature into my git repository, I prefer to keep the buggy commit in revision history... just for posterity ;-)

Finding how to do this was a bit hard, so I’ll document it here.  I know I’ll need to look this up another time; it’s easier if it’s on my own blog :)  The command to roll back to a previous commit is:
git checkout <commit> <repository root>
For example, running git checkout ea2ff0a50 ~/d/prog would restore all files under ~/d/prog directory to the state they were at ea2ff0a50 commit.  Now I can commit the “new” rolled back state with a different commit message, for example “Roll back free penguins feature.  Penguins are too cute to be given away.”

The other approach for rolling back, where you lose the buggy commit for good is to use git reset.

29 Mar 2012

Generic solutions and specific solutions

From certain points of view, programming is fairly easy.  Most of the common problems have known solutions.  Often, programming is simply applying common solutions to specific problems.

I have a web app whose sole purpose is to create thumbnails of images whose URLs are given.  It took a few seconds for serving each request, so I applied a common solution to the “my program is too slow” problem: caching.  With two levels of caching, I brought down the average response time to around 150ms.  (Caching code is in boldface.)
if PICASA_URL_REGEX.matches(original_url):
  # Resizing Picasa URLs is child's play.
  # All we need is some URL tweaking.

if FLICKR_URL_REGEX.matches(original_url):
  original_url = mid_size_flickr_url(original_url)
# local_cache is a simple hash map.
if original_url in local_cache:

thumb_url = memcache.Get(original_url)
if not thumb_url:
  thumb_url = data_store.Get(original_url)
  if not thumb_url:
    image_bytes = http_client.Fetch(original_url)
    thumbnail_bytes = image_resizer.Resize(image_bytes)
    thumb_url = data_store.Store(original_url, thumbnail_bytes)
  memcache.Set(original_url, thumb_url)
local_cache[original_url] = thumb_url
Though 150ms isn’t too bad, I had been wanting to optimise this further for several months.  Only I couldn’t figure out how.  Yesterday, something dawned on me: I was using the caches all wrongly!  I was unnecessarily repeating a bunch of string operations and regular expression searches for every request before even touching the caches.  A better approach would be to hit the cache as early as possible.  I changed the algorithm to be like:
# response_cache is a a simple hash map.
if request.query_string in response_cache:

if PICASA_URL_REGEX.matches(original_url):
  # Resizing Picasa URLs is child's play.
  # All we need is some URL tweaking.
  thumb_url = resize_picasa(original_url)
  response_cache[request.query_string] = thumb_url

if FLICKR_URL_REGEX.matches(original_url):
  original_url = mid_size_flickr_url(original_url)
thumb_url = memcache.Get(original_url)
if not thumb_url:
  thumb_url = data_store.Get(original_url)
  if not thumb_url:
    image_bytes = http_client.Fetch(original_url)
    thumbnail_bytes = image_resizer.Resize(image_bytes)
    thumb_url = data_store.Store(original_url, thumbnail_bytes)
  memcache.Set(original_url, thumb_url)
response_cache[request.query_string] = thumb_url
Immediately the average response time came down to around 40ms.  Plus, it’s not unusual now to find requests that get served in less than 5ms!

Algorithmic difference between the two code snippets is subtle, yet the performance difference is substantial.  What makes programming interesting is the fact that knowing the solution is not always sufficient.  Ability to adapt a generic solution to specific problems is one of the things that makes one a good programmer.

Sample logs before code change:
Sample HTTP request log before code change
After code change:
Sample HTTP request log after code change

24 Mar 2012

Disable automatic updates for your crucial Android apps

Android Market has a per-app preference for automatically updating the app when a newer version is available.  It’s convenient, and is usually a good security measure to keep this option enabled for all your apps.  However, if there’s an app that’s “crucial” — i.e., if you cannot afford to have this app not running, you may want to disable automatic updates for that app.

I use Sleep as Android to track my sleep.  I turned on sleep tracking last night and went to sleep.  Woke up this morning and saw that the Sleep app wasn’t running.  Instead there was a notification from Android Market that it had updated the Sleep app overnight.  The app got killed when it was updated and was never started again.  Had it been a weekday, I would have missed my wake up alarm and could have slept longer than usual.

I have now disabled automatic updates for this app.  Disabling automatic update for this app would require that I manually update it every time there’s a new version.  It’s a pain, but it’s much better than oversleeping and being late to work.

16 Mar 2012

Generating data URIs in Go language

I wrote FotoBlogr to make blogging easier for a friend.  The main goal was to make it easy to add Flickr photos to Blogger blogs.  As time went by, I added support for adding recipe microformats to blog posts, since that’s what she primarily posts.

The app is fairly simple, it’s just one HTML file; but most of the UI is constructed at client side using JavaScript.  As soon as the page loads, it’d send out a number of AJAX requests to fetch the list of blogs, list of Flickr photos, any saved draft post, etc.  Adding features always implied adding more images (i.e. icons) to the interface.

At one point, rendering the UI needed more than 40 HTTP requests, all to the same domain.  The app that used to load instantly started taking a second or two to fully load.  I wanted to bring back the old speed while retaining all existing features.

I have seen data URIs generated by frameworks like Google Web Toolkit.  When you replace an <img src='/img/my-icon.png'> with something <img src='data:image/png;base64;image-data-inline'>, it cuts off one HTTP request from the load time[1].  I decided this is what I’d do, and this post is to document how I did it.

FotoBlogr is written using Go language and runs on Google App Engine.  One possible implementation is I can run my HTML files through some tool that will replace all (or selected) images with inline image data.  It could work, but I wanted something easier.  This is when I found out how powerful the Go language is.

Generating data URIs for images is literally one line of code:
func dataUrl(data []byte, contentType string) string {
  return fmt.Sprintf("data:%s;base64,%s",
      contentType, base64.StdEncoding.EncodeToString(data))
Now I have to connect this code with my HTML.  Enter Go’s template package.  Go’s templates can call functions[2].  If I can make this function callable from my templates, it’s job done.  I’ll first show you how this is used and then the implementation.

Instead of instantiating the template by parsing the file directly, now I need to call a helper function.  I.e., I had to replace calls like
  tmpl := template.Must(template.ParseFile("tmpl/home.html"))
  tmpl := gaesupport.NewTemplate("tmpl/home.html")
(gaesupport is the name of the package where I have some App Engine support code.)

To request inlining of images, I replaced HTML like
  <img src='/img/plus.png' width='16' height='16'>
  <img src='{{inline "img/plus.png" "image/png"}}' width='16' height='16'>
That’s all a caller has to.  It’s hardly any extra work, so I am happy with this solution.  Implementation of gaesupport.NewTemplate function is straightforward too.  It instantiates a new template.Template object, adds the inline function to its context so templates can call it, and then parses the template file as usual.  Here’s the full code:
package mgae

import (

// Encodes data into a 'data:' URI specified at
// https://developer.mozilla.org/en/data_URIs.
func dataUrl(data []byte, contentType string) string {
  return fmt.Sprintf("data:%s;base64,%s",
      contentType, base64.StdEncoding.EncodeToString(data))

func inline(fileName, contentType string) (uri string, err os.Error) {
  data, err := ioutil.ReadFile(fileName)
  if err != nil {
    return "", err
  return dataUrl(data, contentType), nil

func NewTemplate(fileName string) *template.Template {
  funcs := template.FuncMap(map[string]interface{} {
    "inline": inline,

  tmpl := template.New(fileName)
  return tmpl
[1] On the other hand, it bloats up your bootstrap HTML and makes it impossible for clients to cache your image.  FotoBlogr is tiny; even with all image inline, the bootstrap is only about 70kB, so this would work for me.
[2] I’ll be honest and admit that I first thought “wow, that’s like PHP!” when I first heard it.  But it’s actually cleaner than that.  Templates can only call functions that you explicitly export.

9 Mar 2012

When to get your eyes tested: before work or after?

Over the past few months, I have been observing something.  At mornings, when I enter work, my vision is blurred.  This usually means I need to change my glasses because the power has changed.  However, when I leave work at evenings, my eyesight would be like normal... as if I am wearing the right glasses.

I asked my optometrist today about this and he said it’s because my eye muscles are a bit too tired to squint enough at mornings.  As the day goes by, the body gets more energy and the eyes squint more easily.  What this means is I should always schedule my eye tests at mornings, when my eyes are more natural.

(All this while, I’d been scheduling the tests at evenings, after work.  And almost always I was a bit dissatisfied with new glasses.  This is probably the reason.)

3 Mar 2012

Being loved

Not being loved by anyone is probably better than being aggressively loved by people we can't like.

Scared and confused

I have an internal conflict.  I have committed to do something — something pretty big — that I don’t like one bit.  Every time I am reminded of it, I become afraid and angry.  Ain’t a great feeling to be angry and upset, so I changed my world slightly so that I can hide that terrible thing from my sight... and I can pretend as if everything is just normal.

I wonder now, what’s the path of lesser pain?  Postponing the real problem until last minute, or facing it today and finding a solution sooner?  The latter definitely sounds more honest... maybe that’s the better of the two?


Stateless is better than stateful.  Be it the objects you define in your computer programs, or how you live your life.  Statelessness is good.

25 Feb 2012


I was going to an Indian restaurant for dinner.  I was very happy on the streets as I was walking.  I really liked the buildings of London... they were beautiful.  I was making plans that I would live in Europe for a few years.  I can travel around all of Europe.

I reached the place I was going to, and bought myself some biryani.  The food wasn’t great.  I kept complaining inside my head about the food, and at one point I posted a mean comment on Google+ about the food I was eating.  I remember very well, I was laughing when I posted it.

Then two employees of the restaurant asked me independently if the food was good.  To the first person, I said “it’s okay”.  I said the same to the second person, but this person wasn’t happy with my answer.  He then asked “are you liking the biryani, is it good?” looking for a more definitive answer.  I really didn’t want to talk about the food.  It was a done deal; I had eaten more than half of it already.  If I complained now, they would want to “fix” the problem, and that would only mean more delays.  I didn’t want to return the food either.  So I said “yes, yes” only to make him go away.

That was it.  I couldn’t face the restaurant staff any more.  I felt as if I had disrespected them for no reason.  I was feeling very bad on the way back.  I thought I was feeling bad because of that mean comment I posted about the food on Google+.  I took my phone and immediately deleted that post... that felt like the “right thing” because I had started believing that the food wasn’t all that bad, and only I was overreacting.

After coming home, when I think about it now, I think it’s the lie that has made me feel so bad.  In my view, lying is a deep form of disrespect.  I think I still haven’t forgiven myself for having disrespected the restaurant staff.

4 Feb 2012

Speed Matters

I bought a Samsung N150 netbook in early 2011.  That’s a tiny little laptop with an Atom processor, 2GB RAM, and a 10” screen.  It was tolerable, but slow nevertheless.  A few months later, I bought a Galaxy Tab 10.1v.  From then on, I started preferring the tablet for any task, and used the laptop only for things that the tablet is not very good at.  (Anything that involves typing text or multitasking.)

In December 2011, I bought a Toshiba ultrabook, which is way faster than the Samsung laptop.  Now I see that I prefer to use the Toshiba over the tablet.  I guess it’s not the form factor that makes me like or dislike a device, but the speed.  I just hate waiting for machines.

Moving Eclipse installation to a different location

I recently changed my username on my laptop from manki to m.  I just had to rename /home/manki directory to /home/m and everything worked just fine, except one program: Eclipse.  For whatever reason, Eclipse writes absolute pathnames like /home/manki/whatever in its configuration files and when /home/manki disappeared, Eclipse could’t figure out what to do about it.

One nice thing about Eclipse is that, like all Unix programs, it keeps all its data in plain text files.  I just had to look for files that contained the string /home/manki and replace those strings with /home/m instead.  The directories I had to scan were:
  • workspace-root/.metadata
  • ~/.eclipse
I used this command to get a list of files that matched:
find ~/.eclipse ~/prog/eclipse-workspace-android \
    -type f \
    -exec grep -l '/home/manki/' {} \;
Once I had the list of files, an easy search-and-replace across all those files did the job.  Eclipse opened with no issues, and it was able to find all the plugins and such.  I think doing the same would be sufficient to move an Eclipse installation from one location to another.

2 Feb 2012

Grand plans for life

For a while, all I wanted from life was to just travel and see places.  Live in places that look “fancy”.  Then at some point I thought I wanted to do something for people of my town.  I wanted to start something like a new company and be useful to my society in some way.  Just now I had a thought: what’s the point of “being useful” to people anyway?  Also, I think I shouldn’t be planning my life so far in advance.  I’ll take life as it comes, and go with the winds.  At least that’s what I think now.

27 Jan 2012

Quotes from “I’m Feeling Lucky”

Some quotes from Douglas Adams’ I’m Feeling Lucky:
  • But you couldn’t work at Google without learning something new every day, even if you weren’t trying to.
  • Efficiency, I would learn very quickly, is valued highly among those who live to make things work better.
  • Among certain sets in Silicon Valley, your email address indicates more about you than the car you drive or the clothes you wear.
  • Larry and Sergey didn’t like renting intelligence when they could buy it.  There are only so many really smart people in the world.  Why not collect them all?
  • If search engines were faster and better, they could be integrated into your thought process.
  • “If we can’t win on quality,” [Larry] said quietly, “we shouldn’t win at all.”
  • Legend has it that Google grew entirely by word of mouth.  That’s not quite true.  We didn’t mind running online ads; we just didn’t want to pay for them.
  • Insecurity was a game all Googlers could play, especially about intellectual inferiority.  Everyone but a handful felt they were bringing down the curve.
  • Things could always be more efficient and cost less, in either time or money.
  • Google did that to you—made you challenge all your assumptions and experience-based beliefs until you began to wonder if up was really up, or if it might not actually be a different kind of down.
  • I needed to stop saying “Here’s my concern,” and start saying “Here’s what you need to do to make that happen.”
  • “You have to say both emotionally and intellectually, ‘I can only work so many hours.  The best I can do is make good use of these hours and prioritize the right way so I spend my time on the things that are most important.’  Then if I see something below the line that is broken and I can fix it, it’s important not to try to fix it.  Because you’re going to hurt yourself.  Either personally—because you add another hour and that’s not sustainable—or you’re going to hurt something that’s above the line that’s not getting the hours that it should.”
  • “Any technology can do a good job with a hundred thousand queries a day.  It’s a lot harder to do it with a hundred million.”
  • Google’s founders believed down to their DNA that simplicity was a benefit.
  • Neither Larry nor Sergey had been to business school or run a large corporation, but Larry had studied more than two hundred business books to prepare for his role running Google as a competitive entity.  He trusted his own synthesis of what he had read as much as anything he might have picked up in a classroom.
  • “It’s not an engineering personality to keep quiet when you feel things are going wrong... and being intimidated by people is not very productive.”
  • “Google engineers were so strong-willed,” [said] Matt Cutts, “that sometimes if we thought that Larry and Sergey were wrong, we just ignored them.”
  • “We can keep on discussing this for a long time and try to get agreement or we can just go ahead and do at least the part we know.”
  • “Once you start to see spam, the curse is, you’ll see it everywhere.”
  • “One thing I learned at Google,” [Matt Cutts] said to me, “is that you make your own cred.  If you propose your own initiative, you’re much more likely to do it than if you sit around and wait for someone to say, ‘What do you want to do with your life?’”
  • Any time you have that rate of growth, you basically have to make software improvements continuously because you can’t get the hardware deployed fast enough.
  • That’s the best definition of success: if a new system comes out and everyone says, ‘Wow, I can’t believe we put up with the old thing because it was so primitive and limited compared to this.’
  • ‘An order of magnitude is qualitative, not quantitative.’  When you go up by an order of magnitude, the problem is different enough that it demands different solutions.  It’s discontinuous.
  • Engineering lives and dies by its tradeoffs.
  • I was admitting I couldn’t get something done.  At Google, that was not a career-enhancing move.
  • “Don’t let anything hold you up for eventual delivery,” Cindy wrote in my six-month review.  “Figure out the fastest way to get it done.  And don’t let your signature high standards slip!”
  • Larry was so suffused with conviction that he simply brushed aside opposition and ran toward risk without fear or hesitation.
  • It’s hard to accept that everything you know is wrong, or at least needs to be proved right all over again.  [This is Douglas’ reaction when all of his experience seemed useless and/or rejected at Google.]
  • Search is cheap only when done right.
  • “What matters is whether we’re doing the right thing, and if people don’t understand that now, they will eventually come to understand it.”
  • Marissa’s desire to “fix things” as soon as they came to her attention was a common impulse among engineers.
  • We were the yin and the yang: marketing and engineering, glibness and geekspeak, a gracefully arcing comma in a classic Garamond font complementing a rigidly vertical apostrophe in fixed-pitch ASCII.
  • Product management gave [Marissa Mayer] a far wider playing field than she ever would have had as an individual contributor in engineering.
  • I was concerned about becoming “the guy who was always concerned,”
  • Larry and Sergey’s most sacrosanct commandment: Get it done on time.
  • Obvious solutions are not the only ones and “safe” choices aren’t always good choices.
  • Two smart guys working on complex technical problems, it turns out, can accomplish a hell of a lot.
  • Larry never wanted to give people more information than he thought it was useful for them to have.
  • We’re Google!  Let’s be outrageous and daring and have some fun.
  • It was our goal to make ads so useful that people would actually go out of their way to click them, even knowing that they were ads and not search results.
  • “Any chart that goes up and to the right is good,” [Eric Schmidt] assured us.
  • “You can’t get up and be an asshole about being smart,” Paul [Buchheit] explained, “because Jeff’s smarter than you and he’s not an asshole.”
  • But at Google the status quo was nothing more than an inconvenience to be improved upon as time allowed.
  • Scaling by adding staff instead of algorithms and hardware would be a mistake.
  • “Don’t be evil” is not the same as “Don’t consider, test, and evaluate evil.”
  • You need to understand how Google works.  We don’t have senior VPs.  We have Larry and Sergey and everybody else.  [This was during Doug’s time, of course.  Now Google has VPs.]
  • “We agreed not to do this,” [Marissa Mayer] insisted.  “And you went off and did it anyway.”
    “I don’t remember ever agreeing to that,” Paul [Buchheit] replied.  “Maybe you said not to, but I never agreed to anything.  I’m not really that agreeable a person that I would ever agree not to do something.”  [The conversation is about targeting ads based on email contents in Gmail.]
  • Experiencing something is much more powerful than just talking about it.
  • “Ultimately,” Paul [Buchheit] said, “that’s a really big advantage or liability for a project.  What Larry thinks of the people involved.”

26 Jan 2012

My experience with ‘meditation’

The first time ever I even heard of the name of Osho was when I saw this book called “மனதின் இயல்பும் அதைக்கடந்த நிலைகளும்” (The nature of mind and going beyond it).  This was almost 10 years ago.  The title was interesting, and so was the preface.  I immediately decided to buy it.  Soon after, I was known as an “Osho fan” among my friends, and I managed to read several books of his.

Soon I realised something: irrespective of how many ever books I read, I know what Osho is going to say: “mediate”.  That’s his primary (and arguably only) advice to people.  I tried sitting with my eyes closed and watching my mind.  It wasn’t easy... I just couldn’t stop the wandering mind.  As a believer of “if it’s too hard, you’re doing it wrong” theory, I stopped trying.  Though the desire to experience mediation never died down in me.

One thing Osho often repeats is “When I am pointing at the moon, don’t look at my fingers.  You’ll then mistake the pointing finger for the moon.”  I thought to myself that sitting with your eyes closed cannot be the only form of meditation.  I’ll find my own way... I’ll discover the meditation that works for me.
In the last two years, I have been catching myself doing stupid things.  Being angry with people who are helping me.  Expecting a fight and arguing with someone in my mind.  Thinking about some pointless loss and worrying about it for no reason.  And more stupid things like these.  Good thing is, once you have seen this stupidity, it’s easy to get rid of them.  This was probably the beginning of bringing in more consciousness into my day-to-day life.

Last week I happened to listen to a neuroscience professor’s lecture.  He was talking about how regulating your breath, being conscious of what you’re doing right now (precisely what Osho recommends you to do), etc.  That’s when I decided I’d try to regulate my breathing.  Anyone who have tried to regulate their breathing would know that you cannot really do anything else when you’re concentrating on your breath.  Someone in the crowd asked him how to effectively do your work and regulate your breathing.  The professor gave a tip: make it a habit that whenever you’re walking, you’d breath deeply; when you’re sitting on a chair working, you’d let yourself breath like you always do.

That was a very good tip... and it has been useful to me from the next day.  I practice deep breathing when I am walking to work.  First day was hard (obviously!) and my whole mind was occupied with breathing.  Within a few days it become easier... I can listen to music, think about random stuff while still breathing well.  I’m guessing this is going to be an interesting experiment :)

There’s a lot of online resources for learning deep breathing, if you’re interested.  Try Authentic Breathing or Wikipedia, for instance.

16 Jan 2012

Daylight savings time

Daylight savings time is good for one thing: it teaches our kids that time is just another arbitrary thing humans control.

12 Jan 2012

Blogger’s threaded commenting on custom template blogs

Update: Blogger has an official post about this.

Blogger today introduced the long-awaited threaded commenting feature.  It may not work for you even after enabling embedded comment form if you have manually customised your template.  Fear not, enabling threaded commenting on your custom template is not that hard :)

Go through your blog’s template and change all occurrences of
<b:include data='post' name='comments'/>
<b:if cond='data:post.showThreadedComments'>
  <b:include data='post' name='threaded_comments'/>
  <b:include data='post' name='comments'/>
(Make sure you have enabled the “Expand Widget Templates” check box; you may not see the text to be replaced otherwise.)  This change will add a “Reply” link after each comment on your blog.


The world is full of things we want to see.

10 Jan 2012

Opening a Toshiba Z830 laptop

Opening a Toshiba Z830 is fairly simple — just remove all the screws from the back of the laptop and the cover would come off with no effort.  But there’s one tricky part: there’s a hidden screw at the center of the laptop.

This is a Torx Security screw so you’d need an appropriate screwdriver.  This screw is also covered by a plastic piece that you’d have to remove first to even see this screw.  Once you have removed all 14 screws, the machine opens up very easily.

9 Jan 2012

Setting alarms on Android using Google Voice Actions

Do you hate this UI of Android’s alarm clock app?  I hate it too; fiddling with the dial to set the time correctly, and to get the am/pm correctly can be annoyingly hard.

There’s an easier way: Google Voice Actions.

Tap on the microphone icon of Google search widget and say something like “set an alarm at six thirty am tomorrow” and you’re done!  (Or just say “alarm six thirty am”... after all that’s all a computer needs to hear :-)

Samsung Galaxy Nexus: first impressions

I have been using a Samsung Galaxy Nexus for a few days now.  I have been an Android user since the G1 days; there isn’t much I have to say about the software in this post.  I like Android and I don’t think any other phone software is a good choice for my usage.

Talking about the Galaxy Nexus’s hardware, it’s an enormous phone.  Very wide, but it manages to fit in my hand by being very thin.  I like the feel of holding the phone in my hand (disclaimer: I have never held an iPhone for more than a few minutes).  Battery life is good; super fast camera doesn’t look like a big improvement, but I’ll know the difference only when I have to use a slower camera.  The phone is crazy fast in pretty much everything it does, and fast is almost always good.

One of the things I was excited about was the phone’s higher (than my previous phone, Nexus S) display resolution.  Text on the Galaxy Nexus is clearly crisper, and gives a better reading experience.  But I can still see “pixels” on the screen... more specifically tiny “holes” on white surfaces.  Apart from that I don’t really have any concern.

7 Jan 2012

How we accept gifts in my family

Since the time I remember, I have never seen people of my family use formal words in conversation.  By “family” I mean extended family: everyone who’d come down if there’s a celebration at my house, for instance.  If a relative gifts me something, I wouldn’t say “thanks”... that just isn’t the way you accept a gift.

This clip from Aadukalam movie reminded me of that way of accepting gifts.  Probably because I grew up seeing it, this seems like a more graceful way of accepting a gift than thanking for it.  Even today I avoid thanking people in my family... it just doesn’t feel that good to say thanks :)

(In the video, the guy is gifted a ring.  He accepts it just with a remark “it’s good”.)

5 Jan 2012

Fear of life

Everyone talks about fear of death.  But there’s another, likely more serious, fear: fear of life.  It’s astonishing how many of us are afraid to take ownership of our own life!