What makes code "readable"? (was Re: Python vs. Perl, which is better to learn?)

Alexander Jerusalem ajeru at vknn.org
Wed May 8 15:17:54 EDT 2002


I think lines of code or compressed source file size are both equally
bad at showing the complexity or readability of a langage. If one
language has a library for some task, you can achieve in one line in
that language what needs several thousand lines in another. But even
if you only measure the lines of code (or compressed size) of some
basic algorithm, it just doesn't mean anything. We all know the
infamous program in a line contests. That's probably what the
compressed file size measure intends to prevent but consider this:

In C++, when you want to call a method on an object, you have decide
if you use the . or -> operator.

obj.myMethod();
obj->myMethod();

There's no real difference in file size or lines of code but you have
to think and mybe search the code a lot more (Yes I know naming
conventions make this a lot better).

Or consider memory management. It's not that one line more that
matters:

delete obj;

It's the many hours you spend debugging your code if it has a memory
leak. It's the thinking and code browsing to find out if you need to
delete that object or not.

As to Perl: I don't use it because I'd have to remember too many
things. It's like VisualBasic which I think is one of the hardest
languages to learn and use. Both  require you to remember lots of
special ways to do things that are in fact very similar. But that's
not a question of lines of code or file size.

Imagine a language that has a rule that has two ways of calling a
method:

myMethod(obj)
obj.myMethod()

But then the rule would add that you have to use the first variant if
the objects class inherits X, Y or Z and the second variant if it
inherits P, Q or R. That'd just be silly and it would add complexity
but there wouldn't be any difference in line or file size.

I'm not very happy with some ideas of object orientation for the same
reason. At times it adds complexity and strange rules that obscure
things. If you  want to add a method to a class that you haven't
written yourself you can do that by inheriting from that class and add
the method. But if you are not in a position to control the creation
of the object, i.e you get the object from a library method, you
either have to wrap the object in another object, which obscures the
code as everyone can see with the Java or C++ io stream libraries or
you have to pass the object as a parameter to another method which
adds complexity because it is different from how you call other
methods that manipulate the same object. For example if I want to add
a htmlEncode method to the Java String class:

This is how I call a library method:

String s = ...
s = s.toLowerCase();

And this is how I would have to call my own string utilities:

String s = ...
MyStringClass ms = new MyStringClass(s);
ms = ms.htmlEncode();

or

String s = ...
s = MyStringUtils.htmlEncode(s);

In a non object oriented language there's no difference between
functions that come with the library and functions that you add:

s = ...
s = toLowerCase(s)
s = htmlEncode(s)


What OO does is to make one (the first) parameter special. The class
of that parameter will be searched to find the method that should
actually be called. The first parameter isn't passed in as all the
other parameters. Why? That just adds complexity. If you have a method
that manipulates the state of more than one object, you have have to
guess what class this method belongs to. Consider the a transation
that sells a house:

class House ...
class Agent ...
class Buyer ...

Is it 
house.sell(agent, buyer)
or
agent.sell(house, buyer)
or
buyer.buy(house, agent)
?

Where you put that method depends on where you expect other
subclasses, that is where you expect change in the problem domain. But
what if you expect change in all three respects? Of course a seasoned
OO designer would come up with some distribution sheme comprising many
methods in all of these classes that call each other. But I would
prefer:

sellHouse(house, buyer, agent)

And the language should dispatch this call to the right method
considering the types of all the parameters (multiple dispatch)

Another example where readability actually grows with code size:

<property
  address="1 some street ..."
  pricePerSquareMeter="100"
  squareMeters="100"
/>

That's a lot more readable than:

p = Property("1 some street ...", 100, 100)

In the first example you know what the numbers mean, in the second
example that's obscure (yes I like Pythons named parameters).

Regards



More information about the Python-list mailing list