Arun Tejasvi Chaganty about articles blog thoughts research

Maintainers, I Salute You!

For most of this past week, I have played the role of a maintainer for an obscure part of our college’s technical festival, Shaastra’s 1 website. I now respect the terribly difficult job a maintainer has to do. I also think I qualify as the worst maintainer ever. The portion of the website I’m working on is basically a portal where participants can pre-register for events, discuss on a forum and plot to take over the government. Nothing unusual as such really.  This year, we decided to make the whole thing with Django (except the forums, which is a customized UNB). I remember reading a quote 2:

The thing I’m most concerned about is how horrible the code produced by an average programmer will be in language X. I have maintained code written by average programmers in C++ (bad, but bearable), Java (not bad), Python (surprisingly bad) and Perl (kill me now). Most if not all languages are OF COURSE capable of beautiful code in the right hands. The problem is the scarcity of right hands. – JamesWilson

I assure you, all of us were less than average programmers. And we were using Python. The team was very small, just 3 of us. Still, I didn’t manage the show very well, and 3 was enough to cause chaos. To start with, I didn’t use a Version Control System (VCS), mainly because the other group members weren’t familiar with it. I instantly began to regret this decision, since we were throwing around tarballs, instead of patches.

Mistake 1: Not using a VCS.

To make things worse, the development on the project started with a distinct lack of coordination. Each of us was learning how to use Django, and we were doing this while building the application. I find this particularly bad practice, as it always leads to bad code, created at different stages of understanding the library (I prefer to experiment with a prototype or something first). Nevertheless, being the hypocrite, I built on the project while learning Django. At some stage, I released the first ‘version’ of our project (dubbed the Userportal). While one member accepted this code, the other still hung onto his code.

Mistake 2: Not forcing a central codebase.

Kinda results from Mistake 1. </modesty> When I submitted my first patch (it was to Tomboy. It hasn’t been accepted 3, I made sure it followed the existing code conventions (which was easy, since it was largely cut and paste). I took even greater trouble with the second one (this time for Anjuta.  This was a larger one, and also hasn’t been accepted yet :-( 4, making sure that it doesn’t break any changes to the rest of the code, was properly documented, etc. In other words, I put in a great deal of effort so that it might get accepted. My friend on the other hand, did everything possible to ensure that it would have to be re-written. <modesty>

I think I was being fair, I gave him a lot of polite nudges to name his variables sanely, and to use the code base I setup. Both were simple tasks, but the consistent disregard for these requests really got on my nerve. They also resulted in a constant reimplementation of the same thing by both of us. At some point, we had a deadline to meet, and I split up the various tasks among us. I tried to delegate the task of maintaining the project to another team member, so I could spend more time on my GSoC project, but that didn’t work out. Naturally, I was irritated to have to ditch some GSoC progress for this, and when I saw his code, I burst a vein.

Mistake 3: Losing your temper

After incessant requests, the variables are still jibberish, the codebase isn’t the accepted default.

Have a look:

def select_people(request): 
  if request.user.is_authenticated(): 
    if len(request.user.groups.all())==1: 
      usr=request.user 
      eve=request.user.get_profile().events.all()[0] 
      users=[] 
      h=[k.user for k in UserProfile.objects.all()] 
      for k in range(len(h)): 
        if eve in h[k].get_profile().events.all(): 
          users.append(h[k]) 
      if request.method=="POST": 
        y=request.POST.copy() 
        j="" 
        try: 
          obj=ChosenOnes.objects.get(event=eve) 
        except ObjectDoesNotExist: 
          pass 
        else: 
          obj.delete() 
          obj_new=ChosenOnes(event=eve) 
          obj_new.save() 
        for l in users: 
          try: 
            val=y[str(l.id)] 
          except MultiValueDictKeyError: 
            val=None 
          else: 
            j+=str(l.get_profile().name) 
            obj_new.users.add(l) 
            obj_new.save() 
          return HttpResponse(str(obj_new.users.all())) 
        else: 
          template=r"<tr><td></td><td></td><td><input type='checkbox' name=></td> " 
          t=Template(template) 
          done=r"<table border=2><tr><td>Name</td><td>College</td><td>Selected?</td></td> <form action='.' method='POST'> "
          for k in users: 
            que=Answer.objects.filter(answered_by=k, event=eve)
            c=Context({'m':k, 'n':k.get_profile()}) 
            done+=t.render(c)
            done += "</table><br><br><p><input type = 'submit' value='Done'>" 
          return HttpResponse(done) 
    else: 
      return HttpResponse("You sir, are no cord") 
  else: 
    return HttpResponse("Login")`

Perhaps I’m over reacting, but I was really pissed with the fact that it was made with the assumption in mind that I’d fix all the errors, typos and variable names. “You sir, are no cord” (Coord is institute slang for coordinator), not only doesn’t render as a template and inappropriate to show particpants, and slang, but also has spelling mistakes. This code was supposed to be production quality stuff, something I’m supposed to copy paste together, and upload onto the server. Yeah right.

I remember meeting Andrew Cowie at foss.in where he told me how horrible the patches he got were, and how at times, it’s easier to just rewrite the whole damn thing. I nodded my head then, obviously without the least clue about what he was talking about, but now I get it. I rewrote the whole damn thing from scratch. I figure in this case atleast, it would have taken me less time to edit his code into usuable form, but I was clearly beyond pissed at this point. I may also have been suffering from acute NIH.

To my credit, I didn’t reinvent the other guy’s code. But that was because he’d used the common codebase. All I had to do was diff -ur mydir hisdir > diff and make a few changes and patch the files. Took me 5 minutes. The entire thing ended in me flaming him in an email, followed five minutes later with an apology for losing my temper.

Mistake 4: Being easy to push around.

I feel extremely violated and used. There are few people easier to mollycoddle into doing work than me. And this is why I’m now behind on my GSoC project (and also the reason I’m doing something else alongside GSoC, despite my “stern” resolve to stick to just one things).

A brief update of what’s going on with my SoC

I am now working around Anjuta’s Document Manager, so that vim can handle multiple files with Anjuta’s knowledge of the same (right now, you can open files, but they won’t be parsed, etc., i.e. handled by Anjuta). The implementation however, is anything but straightforward. The way Anjuta handles editors is highly counter-intuitive; each editor is assumed to be a document. And even worse, every document is assumed to be a widget. This didn’t create much of an issue with the previous editors, Scintilla and GtkSourceView, because they’re widgets themselves. Each file is infact a widget and an editor in that case. But that doesn’t apply at all to the case of Vim (or Emacs. It’s easier to justify my actions when I can say it’s not just for my project). The whole interface and related code is written with those assumptions in mind. So every file opened through Anjuta is supposed to be added as a seperate widget. What I’m doing is creating a singleton widget, and maintaining a list of documents. Also, I’m creating a new interface to tell Anjuta that the document is part of a ‘document group’ as such, being handled by a common editor. Conceptually, it looks like it will work, but it seems like a hack to me.


  1. The main website is up. The userportal still isn’t.

  2. Quoted from: WriteOnlyLanguage

  3. This patch added a command line option to Tomboy to let you open a default notebook page. I also added some helper functions to make the process of creating a default notebook tab easier. I think it’s too trivial to be accepted, I don’t think my code looks bad…Bug #525199. This bug has sentimental value because it was the first patch I ever created.

  4. The Anjuta patch was to make it standards-compliant. I tested it rather extensively, and it works to the extent that on using anjuta in every crook and cranny (ok, I know which crooks to look at), it still doesn’t create a .anjuta/ folder, and all the files are neatly placed in the respective config/cache/data directories. I’m just guessing that the maintainers are either too busy to check. (I hope it’s just that). Bug #518594