Fork me on GitHub

Monday, January 18, 2010

Are we stuck in a Bratty Programming Model?

This is more of an essay or more of my thoughts than a blog post. So brace yourself to read some lengthy writing :).

Warning - Thoughts are evolving and so may not be complete as you think. If you can help it to move in the right direction, I welcome you.

Ever had your day spoiled by a kid who demands what he needs and doesn't budge until you give it to him (cries, pleads, rolls on the floor and on extreme cases punches and kicks :). The problem with him is he won't let you do anything else till he gets what he wants. But how does it relate to programming? I think most of our programs behave in the same way as the bratty kid.

Let's take a problem - Say we are working on some ticket reservation app. The need is - Given a ticket id, get the reservation info, do some processing on that and then go on to do some other important stuff.

Expressing the above spec in ruby:

reservation = remote_service.get_reservation_info(ticket_id)
#Program wishes to continue to do some other important stuff.

The above code is simple and we have all written this code at some point in time. But there seems to be a problem with the piece of code. It demands for some information from a remote service and doesn't move from there until it gets what it demands. Also it doesn't let rest of the code to execute as well until its demands are met. It is not just for service calls.. Think of using the same mode for network calls, database access, file system operations, long running computations. All of them can become bratty and stop your program from moving forward.

Are programs supposed to behave like this? Is this a better method of writing code? For simple code of not much serious use, the above model is acceptable. But when we start moving to systems which need to grow in scale this programming model is not sustainable.

Programs are supposed to be magnanimous in nature. A line of code should behave in a way that if it is not able to get something for moving forward, should move out of the line to let others execute and wait for its input. How would that actually work out in code?

Now lets jump into code which can give a hint of how to solve this. Below is the same ruby code written in a different way.

remote_service.get_reservation_info(ticket_id).addCallback {|reservation| process_ticket(reservation)} # I will get the input when it is available and process it
# other lines of code executing when above code waits for reservation info...

So the above lines of code does the same as above semantically. But the difference between the two is in this piece of code the retrieving of reservation information and processing it doesn't seem to block the program from moving forward. I know just adding a callback doesn't solve the problem. There must be an underlying infrastructure to handle this. And this is where event loops come in. But I think you get the idea of what I am trying to say.

Event loops are a bigger subject of discussion. But we have been using them most of the times. Take GUI programming as example.

The I/O or more importantly programing models we have been using till now have predominantly been focusing being imperative (Do this step, get the result, then do that and continue...) but I think it's time we understand that this model can't help us long. If we need our programs to scale or even be reasonable we need to move from bratty to a magnanimous programming model. Blocking other's from moving because we still need something is not a very scalable model both in real life and programming :).

This is my rant of current programming models. There may be better ways to do things and if you know any please let me know. A lot of this essay is inspired by node.js work done by Ryan Dhal and EventMachine which made non bratty programming so much easier for me to handle.

P.S. Using event loops has a different set of constraints like new way of thinking (inverted control), different way of exception handling as well using different frameworks which we may not be familiar with.

No comments: