programming.reddit’s top 10 posters (karma-whores?)

July 30, 2007

I wrote a quick script to see who submitted the most posts on programming.reddit.com (in the last 100 pages.) I was quite sure linuxer would come out on top, but I had no idea by how large a margin!

User Post counts
linuxer 930
dons 232
schwarzwald 66
queensnake 65
logistix 63
IbeeX 62
erikd 62
erikpiket 61
coffeemug 61
kaens 61

linuxer test

July 30, 2007

Hey linuxer, can you post this on Reddit? Thanks.


The power of memorized key strokes

July 29, 2007

I have just finished reading a post (found on programming.reddit.com) about how sometimes sometimes, it’s best to leave old software systems alone. The author reports of an anecdote where the curses-based data entry system of company running on an old Unix system was replaced by a new and shiny .NET web application. Now, even as a web developer I can see that it’s a bad idea. Here is the part of the article I was expecting to read:

What was perhaps the worst failure involved the in-house users and their productivity. Large portions of the old system were built around a curses-based UI. Although it apparently wasn’t very pretty, it did allow for a great deal of user productivity. One of the main complaints about the new Web-based software was that the keyboard support was quite poor, requiring the user to select input fields using the mouse, and at times even having to scroll the page to input or manipulate certain data. With the earlier system, the nagivation (sic) could rapidly be performed using just the keyboard. Some of the more experienced users were apparently so efficient with the older system that their productivity was reduced to 25% of what it was before the switch.

Anytime something like this comes up, I am reminded of a story of my own. I live in a small village and there are two places where you can rent movie: the movie rental shop (MRS) or the convenience store, known in Quebec as a dépanneur (DEP). The two establishments are on the same street, barely 50 meters away from one another and both have decent offerings.

As a computer geek, one thing I noticed was how much faster it was to get a movie at the MRS than at the DEP. The MRS rental computer system was (from what I saw of it) some sort of DOS-based program. Input of data was extremely fast, because the clerks had completely memorized the key strokes necessary to register a rental. They asked for your membership number, they entered it (if you didn’t know it, they asked for your phone number), pressed Enter, entered the numbers on the tokens you brought to the counter pressed a couple more keys and then they told you how much it was and went to fetch the movies while you were searching for your money. The entire process didn’t take them more than 10 seconds.

At the DEP, they had a Windows-based system (maybe Delphi-based) and it was much longer to input your rental. They would take the mouse, click on “New Rental”, select the phone number field, ask your for your phone number, input it, take the mouse, click on search, click in the input field for entering the number on the token, input it, take the mouse, press “Add”, select the input field again, enter the second movie number, click “Add” and so on… Eventually, the system at the DEP was replaced by a good ol’ paper and pencil system. I didn’t ask why they changed the system, but my guess is that it was just faster to write with a pencil than with their computer system.

Whenever I hear of a data entry system, I immediately judge of its efficiency by its interface: white text on a black background? Probably good. Flashy widgets? Not so much.


Funniest 5 seconds video ever

July 29, 2007

For more of those, check out this user’s profile :-D


Programming Erlang

July 21, 2007

I received my Erlang book yesterday! I’m really impatient to start learning this awesome language!


My 5 things I hate about Python

July 15, 2007

A couple of months ago, there were a few posts about five things people hated about Python. At that time I had posted five things I hated about Vim and Emacs, but today I want to steam off on a few things I hate about Python. I’ll try to keep my complaints on the language itself, not its implementation or its library.

  1. No get() method on lists: Dictionaries in Python have an extremely useful method called get() which tries to get an element and returns None (or any value of your choice) if that element doesn’t exist:
    In [1]: d = {'foo': 'bar', 'baz': 'quux'}
    
    In [2]: d.get('foo')
    Out[2]: 'bar'
    
    In [3]: d.get('chunk')
    
    In [4]: d.get('chunk', 42)
    Out[4]: 42
    

    That method isn’t available for lists however, so if you want to get an element from a list that may not exist, you need to use this code:

    try:
        val = my_list[index]
    except IndexError:
        val = default_value
    

    That’s really a pain in the neck to write. In Perl or Ruby, trying to access an inexistent key returns nil. It would be nice if Python either returned None for inexistent indexes, had a defaultlist class (similar to Python 2.5’s defaultdict) or had the get() method dicts have.

  2. (x)range() is exclusive of the upper limit: This one has bugged me since the first day I learned Python. When you write range(1, 10), you get [1, 2, 3, 4, 5, 6, 7, 8, 9]. Where’s the 10 gone? Nowhere, range never gets there, the upper limit is exclusive. I think (I have done zero research on this claim) is that to loop over a list, you can use this idiom:
    for i in range(len(list)):
        foo(list[i])
    

    That way you don’t have to substract one. If that’s the reasoning behind Python’s range() function, I think it should be changed for two reasons. 1) It would make calls clear like range(1, 10) much clearer, and 2) if you need the index nowadays, you’d better use enumerate() anyway.

  3. No static variables: For Project Euler, I wrote a fibonacci function like this:
    fibs = {0: 1,
            1: 1,}
    def fib(n):
        global fibs
        if n in fibs:
            return fibs[n]
        else:
            x = fib(n - 1) + fib(n - 2)
            fibs[n] = x
            return x
    

    I dislike the fact that I need to use a global variable. If there was a way to declare a static variable, it would be possible to declare the cache inside the function so that it would not depend on an external variable.

  4. The half ‘n half function/method deal: Sometimes to perform an operation, you do a “function call” such as len(L) and sometimes you do a “method call” like L.sort(). To make matters worse, some methods (sort and reverse) have both forms, but act differently depending on how you call them.
    n [2]: L = [1, 3, 2, 5, 4]
    
    In [3]: sorted(L) # Return a new, sorted list
    Out[3]: [1, 2, 3, 4, 5]
    
    In [4]: L
    Out[4]: [1, 3, 2, 5, 4]
    
    In [5]: L.sort() # Sort the list
    
    In [6]: L
    Out[6]: [1, 2, 3, 4, 5]
    
    In [7]: reversed(L) # Doesn't even return a frigging list!
    Out[7]: 
    
    In [8]: L.reverse() # Reverses the list (into an actual list this time)
    
    In [9]: L
    Out[9]: [5, 4, 3, 2, 1]
    

    Wouldn’t it be nice if it actually made sense? Please make everything method calls, and don’t modify in place. plzkthxbye!

  5. lambda: lambda should be able to perform statements and you should be able to do more than just one thing in them.

Unbreakable security at Experts Exchange

July 10, 2007

My colleague was looking for information about Javascript and cookies this morning. He Googled and found an Experts Exchange page. The problem is that Experts Exchange want you to register so that you don’t need to scroll to the bottom of the page to view the solution.

If you check this page, you’ll see that after the question the answers are blurred, then there’s the zones listing and then… the solutions in clear text.

But let’s imagine that the clear text solutions were not there at the bottom of the page, how might we get the solution? Turns out Experts Exchange doesn’t seem to be too concerned with security, so it’s actually trivial to get the solution you want.

First, let’s see what it looks like “encrypted”; when you look at a solution (or another post), they are blurred and when you bring your mouse over the text (in an attempt to copy it most likely), you get a sign up ad.


How might we defeat this seemingly unbreakable encryption? If you use Firefox (which you should!) and have Firebug loaded, simply inspect the text. You’ll get this in your console window:

Right click on the div with the “signUpSpace” class attribute and select “Delete Element.” The text will now be perfectly clear and that sign up ad won’t show when you try to copy the text.

But wait, what’s this jimble-jumble? It doesn’t look like Javascript? Right, it looks more like ROT13, and I’m sure geeks picked it up from a mile away. Copy the text, head over to www.rot13.com and…

TADAM! That was easy, right? Maybe Expert Exchanges’ programmers can ask their community how to improve the security of their site ;)


Ubuntu woes

July 5, 2007

I bought a new computer yesterday, because my old one was starting to misbehave, and I decided to replace it before it blew up in my face. I now have a computer with an AMD Athlon 4200 AM2 dual-core processor (that’s a mouthful), 1024 MB of RAM and an ASUS M2NPV-VM motherboard.

I installed Windows XP without problems (except the three reboots required to install all the drivers.) Feisty Fawn installed quite easily too, however I am now struggling with my X.org configuration. My monitor is an LCD Acer AL1916W (16:10) with an optimal resolution of 1440×900. With my old computer, I had no problems getting it to work. With this new PC however, I have the correct resolution, but the display is blurry/edgy/jagged/fuzzy. I exited Openbox and went into GNOME to try some fixes I’d read on the web, but nothing worked. Finally, I decided to use the GNOME screen resolution utility, and when I changed the refresh rate from 50 Hz to 51 Hz, the display became perfectly clear. A screenshot I’d taken when the fonts were blurry was suddenly perfectly clear too — no wonder a friend of mine didn’t understand what I was complaining about.

I tried to configure X.org to get a proper display, but so far, no dice. I have posted this problem on the Ubuntu forums, but no one has answered yet. If anyone has any idea, I would love to hear from you.

I’m not at home right now, so I do not have access to my xorg.conf file, but when I do, I can post the relevant sections.

Update: I got it, the culprit was the modeline.

Section "Monitor"
	Identifier	"Acer AL1916W"
	Option		"DPMS"
	HorizSync	30-82
	VertRefresh	56-76
    Modeline "1440x900" 106.5 1440 1520 1672 1904 900 901 904 932 -HSync +VSync
EndSection

No new job for me (for now)

July 3, 2007

I just got a call from an HR person from Astral Media. Although they liked me and my resume, they decided to go with another candidate. Oh well, that’s life. They didn’t say what I did wrong — and I’m I didn’t do anything wrong either — but they did say that they will hold on to my resume in case they need someone for another similar job.


Leah Culver and newforms

July 2, 2007

Someone on #grasshoppers mentionned Leah Culver’s blog, the lead developer of the (very useless) Pownce web service. In one post, she mentions that she is dumping Django’s forms library. Now, the very next post mentions that she’s going to give it a chance, because she found code snippets on djangosnippets, but. I’d still like to address one point she made:

And sometimes I need you to be able to validate my complex requests.

Hopefully, she’s aware now that validating data with newforms is very easy and powerful. Let’s look at it with an example: canadian postal codes have the format “letter digit letter space digit letter digit”. Let’s create a form that will ask for a postal code and validate it.

import re
from django import newforms as forms

class PostalCodeForm(forms.Form):
    postal_code = forms.CharField(label='Postal code', max_length=7)

    def clean_postal_code(self):
        postal_code_re = re.compile(r'^[a-z]\d[a-z] \d[a-z]\d$', re.I)
        if not postal_code_re.match(self.cleaned_data['postal_code']):
            raise forms.ValidationError(u'Invalid postal code format.')

        return self.cleaned_data['postal_code'].upper()

Well that was easy, wasn’t it? The hardest thing about newforms validations is finding how to do them for the first time: they are not yet documented. How did I find them then? At the bottom of the newforms documentation page, there is a link to the unit tests. Searching for “validation” will eventually bring you to a series of tests on the clean_XXX() methods. Just read the comments and you’ll have your answer.