Archives

February 2010 (1)
September 2009 (1)
May 2009 (1)
April 2009 (1)
March 2009 (4)
January 2009 (3)

November 2008 (2)
October 2008 (2)
September 2008 (1)
August 2008 (5)
July 2008 (3)
June 2008 (1)
May 2008 (5)
April 2008 (8)
March 2008 (3)
February 2008 (1)
January 2008 (2)

December 2007 (2)
November 2007 (4)
October 2007 (17)
September 2007 (9)

Irony

Tuesday, October 30 2007

I was in Borders today looking for something interesting to use my 40% discount voucher on.

There was a new book in the computer section, on reverse engineering.

It was shink-wrapped.

no comments

Tags: funny

The most depressingly true thing I read today

Tuesday, October 30 2007

This post from Reginald Braithwaite sums up everything I always suspected was wrong with software project management. (It also has cautionary observations about startups that aren’t quite so universal).

 

…We have a really simple way of completing successful software projects: we put successful people on them. But we have a broken way of thinking about it: we don’t like to think of the people as being special, we think that what the people do is successful.

And by that logic, we can take anyone, have them do the same things as successful people, and our projects will succeed.

In a manager’s mind, the measure of whether information is good or not is, Does it measure whether people are doing the same things that successful people have done on projects I’ve been told were successful?

This is not the same thing as measuring whether the project is on its way to success at all. This measures the outward appearance of a project. Things that can be measured easily are rarely the most significant things. Behaviours that can be “gamed,” like how many hours a team is working, will be gamed.

And as above, even if a manger knows better, does her manager know better? If not, good information will be difficult to sell and she will be under a lot of pressure to serve Lemon Pie.

Off balance sheet transactions

There’s another important reason that projects have bad information: the best information is off balance sheet. That’s an expression meaning something a businessperson sweeps under the rug. Try Googling Off Balance Sheet Transaction. It’s never pretty.

In essence, project plans and reports never include the most important information about the likelihood of project success. Never. (I mean never in the same sense that Joel Spolsky means “nobody,” as in “fewer than 10,000,000 project plans”)…

 

Read the whole thing.

no comments

Tags: software ~ management ~ linky

Things I have learned about MySQL today

Monday, October 29 2007

This is one way to deal with it. Don’t forget to flush privileges after the restore if you want to have all your users working again. Then you can do a mysqladmin refresh, which flushes the database and starts new log files, making it safe to delete all the older ones (assuming that this is your workstation and you won’t need to replay them).

no comments

Tags: mysql ~ annoyance

The tale of the teddy bear

Thursday, October 25 2007

Years ago someone told me about the teddy bear, and I have never forgotten. It’s a story I tell people — or the programming subset thereof — and that they in turn pass on.

Imagine a university computer lab, full of students working on their programming assignments. (You can tell this is an old story, because these days no doubt all the students work on their own computers wherever they like). There are only two teaching assistants for the whole lab. They’re pretty busy. At their desk is a large teddy bear.

One of the students gets stuck, goes to the free teaching assistant and says “help! My program won’t compile!”

And the teaching assistant says “I’m happy to help you. But first, you must explain your problem to this teddy bear.”

The student hesitates, then starts to tell the teddy bear “well my code creates a pointer for the beginning of the list, and then …” (Blah blah blah).

And after about 30 seconds of explanation, the student says “oh shit! I know what it is!”, goes back to their console, and fixes their own problem.

Which is why my number one debugging strategy for intractable problems is to find someone else to explain it to. Not because I expect them to solve my problem for me, but because telling a coherent story about the problem, with all the information needed to explain it to someone else, helps you understand it yourself. And strategy number two, if I can’t find someone else to talk to, is to write things down as though I were sending a detailed bug report to someone else.

no comments

Tags: debugging ~ programming

My work here is done

Monday, October 22 2007

A few weeks ago I set out to write myself a blogging engine, which I have dubbed “Burble”. The motivation was partly to get off Blosxom, which I’d been finding pretty limiting, but mostly so I could come to grips with developing Python web applications.

And now I’m done. It was surprisingly easy. I’m even running on my own tiny frameworklet, which I have called Whisky, after WSGI. I’m going to put the code online soon, not because it’s ready for other people, but as an example (or a warning).

It’s pretty damned zippy too, even with all my old content from the other site. Network latency is by far the biggest factor in Burble’s performance. I’ve done my best to tweak that by turning on compression in Apache and minimising the markup. I have found YSlow invaluable for this.

(It’s worth a post on its own, but by judicious use of mod_deflate and mod_expires, guided by YSlow, I managed to get one of our indispensible extranet apps at work loading in less than 5 seconds, down from about 20, rendering it far, far more usable.)

 Now I have to find something else to do. I think the Ruminator is next. I have plans to use some stemming software and a bit of Bayesian analysis and a better visual representation that indicates links between stories.

1 comment

Tags: burble ~ web development ~ yslow ~ apache

Usability, or, Physician, heal thyself

Tuesday, October 16 2007

Burble has a nifty comment spam preventer, the details of which need not detain us here. But anyway, the spam-resistant comment process does require an extra step. This is partly to fool robots which mindlessly submit and then go away, and partly so I can do some magic.

I had Iabelled the buttons for the three steps Preview → Save → Confirm. That matched my mental model and the labels I had given these steps in my head.

A little log file inspection revealed that a couple of people had abandoned comments at the Save step. And I realised that by using the word “save” I had given the impression that the user’s comment was already persisted at the second step (it isn’t).

I have fixed the button labels to reflect what’s really happening. They are now Preview → Confirm → Save. And lo, now I have comments.

no comments

Tags: burble ~ usability ~ web development

A tiny WSGI framework in an hour or two

Sunday, October 14 2007

 I’m not sure whether the first story here is meant to encourage or dissuade, but I am writing my own WSGI framework to support Burble. Colubrid is holding me back, and its replacement Werkzeug is overkill for what I want. (To be fair, Colubrid has been a great help to me in getting started.) I’m really getting into the educational aspect of doing things from scratch where I can.

It turns out that putting together a very lightweight WSGI framework is very easy indeed, especially having made a small compromise by using a few pre-built things from Ian Bicking’s Paste. (Yeah, I contradict myself. I am large, I contain multitudes.)

It’s so easy that I’m almost done, so I present a tiny, noddy framework for your reading pleasure. It implements a regex-based URL dispatcher a la Web.py.


#!/usr/bin/python
from paste.request import parse_formvars
from paste.response import HeaderDict
import re

def attrsfromdict(d):
"""From Python cookbook s6.18 p 280"""
self = d.pop('self')
for n,v in d.iteritems():
setattr(self, n, v)

def simplerepr(obj):
d = obj.__dict__
members = ', '.join([n + '=' + v.__repr__() for n,v in d.iteritems()])
return '%s(%s)' % (obj.__class__.__name__, members)

class NoMatchingControllerException(Exception):
pass

class Request(object):
def __init__(self, environ):
self.environ = environ
self.fields = parse_formvars(environ)

class Response(object):
def __init__(self,
status_code='200',
response_phrase="OK", body="",
headers=HeaderDict({'content-type': 'text/html'})
):
attrsfromdict(locals())
def __str__(self):
return simplerepr(self)
def __repr__(self):
return self.__str__()
def status(self):
return ' '.join([self.status_code, self.response_phrase])

class Dispatcher(object):
"""
The Dispatcher maintains an internal list of regexes and controllers.
The Dispatcher accepts strings, and tries to match in turn against
the regexes. As soon as a match is found, the corresponding controller is
invoked.
"""
def __init__(self, regex_app_tuples):
self.dispatch_list = []
for k, v in regex_app_tuples:
p = re.compile(k)
self.dispatch_list.append((p, v))

def dispatch(self, request):
"""
Expects to call a Controller's instance method GET or POST
with the request and the groups obtained from the regex
as arguments.
"""
path_info = request.environ.get('PATH_INFO', '')
method = request.environ['REQUEST_METHOD']

for pat, app in self.dispatch_list:
mo = pat.match(path_info)
if mo != None:
args = [request]
                args.extend([i for i in mo.groups()])
if method == 'GET':
return app.GET(*args)
elif method =='POST':
return app.POST(*args)
raise NoMatchingControllerException, "No match for %s" % path_info

class WhiskyApp(object):
def __init__(self, dispatcher):
self.dispatcher = dispatcher
def __call__(self, environ, start_response):
request = Request(environ)
response = self.dispatcher.dispatch(request)
start_response(response.status(), response.headers.items())
return [response.body]

class NoddyController(object):
def GET(self, request, id):
r = Response(body="Noddy got %s" % id)
return r

class BigEarsController(object):
def __init__(self):
print "in init"
def GET(self, request, arg1, arg2):
r = Response(body="Big Ears got %s and %s" % (arg1, arg2))
return r

if __name__ == '__main__':
from paste import httpserver
dispatch_list = [
(r'/noddy/(\d+)/?$', NoddyController()),
(r'/bigears/(.*?)/(\d+)/?$', BigEarsController())
]
dispatcher = Dispatcher(dispatch_list)
app = WhiskyApp(dispatcher)
httpserver.serve(app, host='127.0.0.1', port='8080')

That’s pretty much all I need, to be honest. I’m happy using Beaker for sessions, and I’ll probably pull in cookie stuff from Paste. I bodged up an Etag cache manager for Burble, which I want to integrate. I want to write a nice base class for controllers. And that’s it. Whee!

no comments

Tags: python ~ burble ~ wsgi ~ paste ~ programming ~ web development

Shelly Powers: the Parable of the Languages

Thursday, October 11 2007

I love the ending.

no comments

Tags: programming ~ xml ~ linky ~ funny

On “helpful” frameworks

Thursday, October 11 2007

My colleague Christine just emitted this gem:

“Layers of cake are better than layers of abstraction.”

Indeed.

no comments

Tags: software ~ programming

Making life easy on yourself in Python with quick and dirty __repr__

Wednesday, October 10 2007

When I write Python, sadly my code often has bugs. One way or another I always end up dumping out variables to see what’s in them. If those variables refer to objects, Python’s default representation is not very helpful:

>>> class C:
... def __init__(self, arg):
... self.member = arg
...
>>> obj = C('foo')
>>> print obj
<__main__.C instance at 0xb7d363ec>

It would be nice to have something that lets you know what’s inside that object

Python lets you help yourself. If you define __str__ and __repr__ methods on your classes,  then they will have nice string representations when you want to print them, or when a debugger inspects them for you. This can be a bit laborious though, especially if you want to meet the requirement (see the docs) that __repr__ should  return “a valid Python expression that could be used to recreate an object with the same value.” And as a good Python citizen, of course you want to do that.

I have a solution that won’t always be the right thing, but saves a lot of typing for many simple classes. I find that often I write classes that are really glorified dictionaries with a few helper methods. In my day job, where we mostly write Java, we work where possible with POJOs or beans. This seems like a Pythonic way to emulate and improve on that idiom.

def simplerepr(obj):
d = obj.__dict__
members = ', '.join([n + '=' + v.__repr__() for n,v in d.iteritems()])
return '%s(%s)' % (obj.__class__.__name__, members)
def attrsfromdict(d):
"""From Python cookbook s6.18 p 280"""
self = d.pop('self')
for n,v in d.iteritems():
setattr(self, n, v)

class Foo(object):
def __init__(self, arg1="wstfgl", arg2="sneeb!"):
attrsfromdict(locals())
def __str__(self):
return simplerepr(self)
def __repr__(self):
return self.__str__()

>>> f = Foo('quux')
>>> f
Foo(arg1='quux', arg2='sneeb!')
>>> g = Foo(arg1='quux', arg2='sneeb!')
>>> g
Foo(arg1='quux', arg2='sneeb!')

This was inspired by and builds on a recipe in the Python Cookbook.

no comments

Tags: python ~ programming ~ good practice

Required reading for programmers

Wednesday, October 10 2007

Today’s xkcd is particularly good.

no comments

Tags: programming ~ funny

roads and trees

Tuesday, October 09 2007

(12:28:59) Stephen Judd: i don’t know why it disturbs me so much to think of apache having bugs
(12:29:01) Stephen Judd: but it does
(12:29:04) Julian Melville: turns out that’s some internal apache error code that was leaking out unintentionally
(12:29:15) Stephen Judd: i mean, its __apache__
(12:29:16) Julian Melville: yeah i reckon… apache is like roads or trees, it’s just there

1 comment

Tags: apache

Things I love about Firefox : view selection

Tuesday, October 09 2007

If you select a portion of a page and right-click, “View Selection” shows you the HTML for just that portion (or in some builds, the whole source, but with HTML corresponding to your selection highlighted). Invaluable to the developer, but not universally known.

no comments

Tags: firefox ~ web development

Flag day

Sunday, October 07 2007

It’s cutover time. I don’t think Burble is fully baked yet, but I need usage to smoke out bugs. This makes me anxious.

The old site is still around, but vital.org.nz is now backed by the same Burble instance that’s serving this.

Things I now have which I didn’t have with Blosxom:

no comments

Tags: burble ~ blosxom ~ i did it my way

not quite ready for prime time

Saturday, October 06 2007

A few things are still causing me headaches with Burble.

So near, and yet so far. It’s frustrating.

no comments

Tags: burble ~ mod_rewrite ~ hosting

Victory is mine?

Friday, October 05 2007

I think I did it. (update: I changed the path when I finally cut over, so I’m fixing it here too.)

But I’m going to be a little cautious and leave the full cutover until tomorrow. Because I’m just a wee bit too tiddly to be wrestling with mod_rewrite at this time of night.

Mind you, given my normal experience with mod_rewrite, being totally trollied first might actually help.

2 comments

Tags: mod_rewrite ~ burble ~ vital.org.nz

More things to do with Burble

Wednesday, October 03 2007

I’m committed now to using Burble for two sites. I’m about halfway through refactoring to make this possible, and I’ve discovered that my choice of framework is making this a tedious chore.

Colubrid is by the authors’ own admission based on a misapprehension about how best to use WSGI, and they recommend that you use Werkzeug now instead. Unfortunately, I didn’t realise this when I started using it.

The fundamental problem is that various important thingies are set up and torn down with each request, and various things done after instantiation, such that your init methods break. So I am forced to cut and paste where inheritance would be better, or monkeypatch.

So my very next thing to do is get off Colubrid. It would be top of the list now, but I really am desperate to get vital.org.nz off Blosxom and on to Burble. I just like my own blogging tool so much more.

no comments

Tags: burble ~ python ~ colubrid ~ wsgi

Recent comments

Rendered at 2010-03-14 17:54:49