Thursday, October 26, 2017

Defining Objects

Earlier in my career, I loved browsing through the Linux kernel's source code. Mostly to satisfy my curiosity about how certain things are internally implemented. As I read through more and more files of code, I started noticing one common pattern. For the most part, the code was organised around  abstract concepts (spin-lock, work-queue, kthreads etc). And every abstract concept had

  • An object representation, a C structure that holds details about that structure
  • An init/alloc call, that initialises the object
  • The init/alloc call also returns a handle to this object
  • A number of operations that accept this handle as a parameter and then operate on that object
  • And finally a deinit/free call that destroys that object and also makes the handle invalid for any further use

Oh yes, you say, we had learnt it in our classes, no big deal! No, no, no. I mean, I had also learnt about it in my classes, but I had never ever used it practically in my code, apart from the stack example in my class assignment.

This was a good way to see it in practice in the Linux kernel, and that too used at multiple places. We even use it in our everyday programming lives. For example,

  •  File IO:
    • fd = open(...);
    • read(fd, ...);
    • write(fd, ...);
    • close(fd);
  • Socket IO:
    • socket_fd = socket(...);
    • bind(socket_fd, ...);
    • connect(socket_fd, ...);
    • send(socket_fd, ...);
    • close(socket_fd);
  • Pthreads: (pthread_create)
  • OpenSSL: (SSL_new)
  • Semaphores: (sem_init)
  • and numerous others

So what is really my point here? Thinking in this way, helps you focus on defining these objects. And thinking about these objects helps you have a more modular and cleaner approach to software development. Design your data structures first, and the rest automatically follows. 

Next time you add a global int/char variable, think if there is a relationship among those data structures. Do they belong into a structure together? Can you make things easier by defining an abstract concept/object and operations around that object?

Here is what Linus Torvalds (the founder of the Linux kernel and git) has to say about this:

I'm a huge proponent of designing your code around the data,
rather than the other way around, and I think it's one of the
reasons git has been fairly successful (*).
(*) I will, in fact, claim that the difference between a bad
programmer and a good one is whether he considers his code or
his data structures more important. Bad programmers worry
about the code. Good programmers worry about data structures
and their relationships.

Saturday, October 7, 2017


Let's do an experiment. I assume you have been working on a project (academic or professional) for some time now. Today, setup some realistic goal as to what you want to achieve at the end of this week. And in the morning, every day of this week, setup a sub-goal as to what you wish to finish at the end of that day. At the end of the week, evaluate whether you were more productive than the weeks before this. Repeat this exercise for another week and check if you were more productive.

To me, I find myself more productive when I do this. Moreover, I find that things just keep sliding when I do not do this. It just goes on and on, with no concrete outcome.

For one, setting milestones help you pace yourself through the day. Without it, its just work-in-work-out, a chore. With a target at the end of the day, your whole approach is different. You are focused on results, and achieving them is so satisfying.

Secondly, setting milestones helps you focus on the prioritisation and planning activity, which is particularly overlooked early in your career. Nothing fancy, just a small enough time frame to experiment and improve week over week.

It has so often happened to me, that I go: "Hmm, if I hadn't given it this thought, I would have continued pushing down a path that would waste so much time"

So, try it out, and let me know how it goes...

Thursday, October 5, 2017

In Pursuit of Efficiency

The first few years of your career you learn a huge amount. Make the best out of it, and develop an attitude to observe and learn from your own experiences. After every task, take a moment. Look back at what you did. How you did it. Feel good about it. And importantly, think how could you could have done it better and faster.

This look-back ends up becoming very critical, and helps you evolve much faster with each iteration. And act on, what you think, could have been improved upon.

Typical things you should think of:

  • Can I optimise the time spent switching windows
  • Could I save the build time by running multiple threads 
  • Could I overlap this activity with that
  • If a tool keeps taking most of my time, I should be a power-user of that tool
  • I got these code review comments, what was the rationale behind points 2 and 5? Search or ask the reviewer
  • Could I have done this faster if I had approached the problem differently?
  • Are there any recurring patterns across the tasks that I have done, and the deductions I have drawn so far?

What is important is having that perspective, almost like zooming out of your body and looking at yourself, trying to identify where could you improve your efficiency.