30 Aug 2011

Story of a failed software project

This happened in my second year MCA.  Through some friends, Mr TM got to know of me, and he said that one of his relatives wanted to computerise his business.  He proposed that he will take care of everything and I'd just write code.  He could write code himself, of course, but he didn't have the time for it.  So I agreed.  By this time I had had some bad experiences with MS Access, so I suggested that we'd use MS SQL Server as the database.  But TM wanted Access.  I agreed to that.  It was his project anyway.

Another thing TM was particular about, apart from using Access, was that we shouldn't be using any modern reporting solution.  All reporting tools used Windows' GDI to print the report on paper.  "We must do the DOS-style printing so that printing is really really fast", he said, though he wasn't sure if that was even possible.  I knew in theory how that could be done from a Win32 program, and this was a good opportunity to verify if my guess was correct.  So I agreed happily.

I defined my own reporting language and wrote a simple reporting system in Visual Basic.  The reporting system would generate plain text reports, which I'd just write to PRN file.  Worked like a charm.  (Later, this reporting language grew to include bold text, right-, center-, and left-aligned text, page breaks, cumulative totals, and all such funky features.  Even today, thinking about that system makes me feel good about myself.)

When it was mostly done, I showed him the working program and the reports.  He was happy with the way report was generated and printed.  He asked me how I'd done that.  I showed him the report definition .rpt files and the report generator code.  He didn't bother to see the code.  Only feedback he had was that having individual .rpt files was bad because you lose one file and your program stops working.  I had a solution for that too.  I baked in all .rpt files into the .exe as resources so the program effectively needed only one .exe file to run.  Again, he only wanted to know if I had fixed the problem; he didn't care how I fixed it.

He took a few days to use the app and see how it worked.  He called me and set up a meeting. He showed a few bugs he had found.  Then he gave the big news: the customer wanted to be able to keep some records "hidden" so that they don't have to pay taxes for all the money they were making.  But having anything in the UI that suggests that some records might be hidden was not acceptable.  Plus, the entire app needed to understand hidden records.  Search, reports, etc. should or should not include hidden records depending on which mode the system was in.  Effectively, there'd be two reports: one for the customer and one for the government.  Requirement itself was fair, but the timing was not.  I had to change the entire app to understand "white" records and "black" records.

It took a while, but I changed the app throughout to make it work.  After a few more days of testing, the customer test drove the app for a few hours.  That uncovered a number of flaws in the system that invalidated some fundamental assumptions the app was built on.  TM asked me to make changes again.  Without those changes there was no way the customer could use it, so we had no way other than changing the app to fit the new requirements.  It went on like this for a while, with random changes suggested to every part of the system.

With all these ad hoc changes, the code was becoming worse day by day and the number of bugs kept increasing.  What we thought would be a 2 weeks project was not complete after 3 months.  I love coding so much, so I don't usually fix my price before starting the work.  I hadn't talked about money to TM either.  One day I asked him how much he'd pay me.  He agreed to pay some 20% of what I had in mind.  (He even paid me a part of it then, I think.)  I told him that the actual work had been several times more than what we initially thought and demanded more.  His response was that he can't get a penny from the customer before the program goes live and he can only charge what he'd agreed to before starting the work.

I wasn't happy.  I told him that I can't work anymore and I came off.  I really don't think TM could have understood the code and fixed bugs.  The project might have been abandoned soon after I had left.  He probably didn't get any money from the customer either.

Thinking about it now, I think TM's fault was that he didn't know what PM-ing was, and did a sloppy job of it.  My fault, as a coder, was to trust the PM too much.  Even when I hesitated to do certain things -- like coding some mother of all hacks -- TM encouraged me to do it.  I think it was because he didn't understand the risks involved.  I never bothered to make him understand either.  (There's a reason for that: most people like TM look at how polite I am and conclude that I don't know what I'm doing.  Even when I say doing something may not be right, they'll "encourage" me like "oh not a problem, don't worry, go ahead".  One other person I have worked with knew I was good and he always respected my judgement.  Not coincidentally, all projects I worked with him made it to production.)

29 Aug 2011

What will I be remembered for?

Listening to Swarnalatha's songs always makes me think that I can listen to those songs just for her voice, even if I didn't like the tune or music or lyrics.  Just as I am listening to Muqabla from Kaadhalan, I am thinking that her songs are what people like me would remember her for.

That made me think – what would I be remembered for, if I were to die tomorrow?  I can think of a few.  The programs I wrote for a family friend's hospital.  FotoBlogr.  Maybe some post from one of my blogs, if a friend cared to look for it again.  Maybe two or three sessions I gave in my college, if it inspired at least one person to question their way of learning.  Maybe the Ladder magazine, if anyone still remembered it (even I don't think of it often).  Maybe the inventory program I wrote for Loyal Mills, though I am not sure if it's still in use.

I love Dido's line "you who loved to love, and believed we can never give enough", and I once wanted a friend to associate me with that line.  But now, I guess it'd be more appropriate if I was remembered for the code I write; for the few minutes my code saves for people.  Because, I think I put more of myself in my code than the love I have for people.

28 Aug 2011

Dog Day Afternoon

After a friend's recommendation, I saw Dog Day Afternoon.  (Warning: spoiler ahead.)  The movie is about a real bank robbery happened in Brooklyn in 1972.  After a very interesting sequence of events, the robber Sonny gets 20 years in prison.  When I saw it at the end of the movie, it didn't struck me how long 20 years actually is.

Today I was thinking about it again.  I tried to visualize how long 20 years in my life has been.  If the sentence was to start when I had just entered Madurai Kamaraj University for my masters -- before I had completed the course, before I had moved to Bangalore, before I had moved to Hyderabad, and before I had moved out of Hyderabad -- the sentence would have been almost half over by now. If the sentence were to end now, it should have started when I was in my 4th standard.  20 years in prison pretty much means you rob the convicted of his life.  Well, a huge part of it.  If someone commits a "crime" when he's 30, we deny him his life until he's 50.  And we expect him to lead a "normal life" after that.

Looking at these laws, I can't decide if we're cruel or dumb.  Maybe both.

Yellow everywhere

I have heard, and I believe, that we see only what we want to see.  Today I had a first-hand experience of the same.  A friend had shared Thomas Leuthard's book on street photography on Google+.  I take pictures now and then, but I am no photography enthusiast.  Nevertheless I am reading the book very very slowly.

One advice from the book is to train your eyes to see things on streets.  Thomas advises you to pick one colour -- any colour -- and try to see that colour throughout a day.  I tried that today.  I randomly chose red.  Suddenly it was red everywhere all around me!  I could see so much red that I thought I should pick a different colour.  So I told myself that I would see yellow.  Now I started seeing yellow everywhere, as much as there was red.  It's amazing how I don't see any of these colours when I don't want to see.

This exercise gave me a new experience, but my mind said this was just another variant of two different ideas I already have.  I could rationalise and see this experience as a proof to those ideas.  But I suspect that it's just my mind playing games with me and making me see only what I already know.  Maybe knowledge is, like everything else, both an asset and a liability.

26 Aug 2011

Remote debugging client side code

When I was learning to program, I was taught to use interactive debuggers.  Turbo C++ version 3 – the de facto DOS C++ IDE everyone used back then – had an interactive debugger.  That was the first debugger I ever used.  Then I used Visual Basic and Visual C++ debuggers as well, and loved them both.

When I learned Java, I tried to use jdb for some debugging but couldn't get my head around debugging from the "command line".  I never managed to learn that.  8+ years later, even today, I cannot connect the context from a jdb- or gdb-style debugger with code in an editor.

But I learned another way of debugging: System.err.println.  Just add a few print statements in the places you think are interesting and rerun your code.  (Some people are surprised when I say I find using print statements faster than using an interactive debugger.)  One thing I like about print statements is that it's so universal: I never have to learn how to use a new debugger.  It works the same way in all kinds of enviroments including Python, C++, and JavaScript.

The latest toy I've built, FotoBloger, has a mysterious bug that kicks in only when a friend of mine uses the app.  I have been trying to reproduce the bug from my account for a few weeks, but with no success.  Yesterday, I decided I had no way but to do some "remote debugging" when my friend is using the app.  My universal "print what's interesting" approach works really well in this bizarre remote debugging scenario as well :)

I added a /debug URI to the app which won't do anything apart from sending a 204 (no content) response back.  Next time the app is being used, it will make a bunch of /debug requests with the data I want to inspect in its query string.  The server logs all incoming requests, so I can look at the logs to see what those values were and maybe I can discover the bug.  (Can your interactive debugger do this? ;-)

22 Aug 2011

The importance of URLs

I have been a Blogger user for years. I still swear by Blogger for a number of reasons. One of them is that URLs are very important for the web, and Blogger understands that.

Try this: go to icanread.tumblr.com and click on "next" link at the bottom. You'll be taken to http://icanread.tumblr.com/page/2. Go to blog.fatema.in and click on "previous entries" at the bottom. You'll be taken to http://blog.fatema.in/page/2. Go to thewayialwayswas.blogspot.com and click on "older posts" at the bottom. You'll be taken to http://thewayialwayswas.blogspot.com/search?updated-max=2011-08-12T09%3A00%3A00%2B08%3A00&max-results=3.

Now, the designer kind might think that Blogger URLs are ugly while WordPress and Tumblr URLs are neat. But there's more than what meets our eyes.

Let's say you find the content in one of these links interesting, and you share it with some of your friends. Naturally you'd just grab the URL from the address bar and share it. If your friend happens to open your link only a few weeks later, they might be seeing content that is completely different from what you intended to share.

Why? Because both Tumblr and WordPress "page" URLs are not unique identifiers to content. The same /page/2 URL will be showing different content based on how many new posts are added after you copied the URL. Blogger's URL, on the other hand, fixes on published date, so the content is much more likely to stay the same over time.

PS: It might be possible to configure WordPress to generate good URLs like Blogger; I don't know for sure.

16 Aug 2011

Guru appears when the disciple is ready

Only this morning I figured this phrase can be interpreted in a different way:
  • We learn what we want to learn.
  • We like to take our learnings from someone else.  We want at least one person (or entity) to preapprove our learning.

7 Aug 2011

AJAX fie upload

Uploading a file from the browser can only be done by using forms.  Even then, you should remember to set enctype='multipart/form-data' attribute on your form.  Form submissions require a page refresh.  If your app is AJAX-heavy you probably wouldn't want to refresh the page just for uploading files.

Here's what you need to do to submit a form with file inputs without refreshing the page:
  1. Add an invisible iframe to your page.  Give the iframe a name.  For example, your iframe might look like: <iframe name='submit-iframe' style='display: none;'></iframe>.
  2. Set the target of your form so that the form submission goes to the hidden iframe: <form method='POST' action='/upload' enctype='multipart/form-data' target='submit-iframe'>.
  3. Add an onload event handler for your iframe.  This event handler will be called every time the form is submitted.  You can then read the response from the iframe's body.  A JQuery app might do it like:
    $(myIFrame).load(function() {
      var responseText = this.contentDocument.body.innerText;
      // Do something with response text.
Update: This can lead to some weird behaviour when a user navigates away from the app and then navigates back using the browser's Back button.  (Or if the page is refreshed.)  The iframe's onload event will be fired and your event handler will be called when you don't expect it to be called.  To work around this problem, I am clearing the iframe's content immediately after copying the text into a variable.  The event handler now looks like:
$(myIFrame).load(function() {
  var responseText = this.contentDocument.body.innerText;
  if (!responseText) {
  // Clear the content of the iframe.
  this.contentDocument.location.href = '/img/logo.png';

  // Do something with response text.


Do you:
- use Blogger for your blog,
- use Flickr for your photos, and
- want better integration between Blogger and Flickr?

Try FotoBlogr.  It's still a work in progress.  It has been functional only since this morning!  Try it out and let me know how it goes.

You can comment here, or you can comment on my Google+ post if Google+ is your thing.

UPDATE: This is how the main UI of the app looks:

FotoBlogr UI
See the picture in Flickr; I have added some annotations to mark different parts of the UI.