Some people think that when scripting language abocates say “less code” is because they are lazy and that they are sacrificing performance over code. This article plans to counterpoint that with a small python/java program.
A little background first. We are working on a little project in which the server is written in python and we’ll have several clients (including one J2ME), also one of the people involve knows nothing about python. Anyway one of the proposals for server-client interaction is having the client pull every X seconds for updates. So I through of an algorithm for making this a bit more intelligent than just setting X to some value. The algorithm itself is very simple. it keeps track of the last Y plays, actually of the time they took, and then using a simple average calculation it will try to guess the next poll time. So basically if it’s a fast game (each player will play their turn fast) then the updates will be more frequent. it will also have a min poll time so clients won’t update way too often, and of course the server will have a timeout but that’s outside of the scope.
Below implementations written in python and java.
warning: sorry for the small code I’m still looking for a decent code highlighter for wordpress.
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
public class ClockTicker
{
private ArrayList data;
private final int MIN;
private final int SIZE;
public ClockTicker()
{
//this(10,20)
this.SIZE=20;
this.MIN=10;
data = new ArrayList(this.SIZE);
}
public ClockTicker(int min, int size)
{
this.MIN=min;
this.SIZE=size;
data = new ArrayList(size);
}
//not going to waste my time on the other 2 constructors
public void add(Float item)
{
if (data.size() == this.SIZE)
data.remove(data.size()-1);
data.add(0,item);
}
public float next()
{
float sum = 0;
Iterator i = data.iterator();
while(i.hasNext())
sum+=(Float)i.next();
float ave = sum/data.size();
return Math.min(MIN,ave);
}
public int len()
{
return data.size();
}
public static void main(String args[])
{
ClockTicker clock = new ClockTicker();
Random random = new Random();//or could have used (float)Math.random(), this seems less ugly
for (int i = 0;i<50;i++)
{
float value = random.nextFloat();
clock.add(value);
System.out.printf(”%s,%s,%sn”,value,clock.next(),clock.len());
}
}
}
class ClockTicker():
def __init__(self,MIN=10,SIZE=20):
self.data=[]
self.MIN=MIN
self.SIZE=SIZE
def add(self,item):
if len(self.data) == self.SIZE:
self.data.pop()
self.data.insert(0,item)
def next(self):
return min(self.MIN,sum(self.data)/len(self.data))
import random
clock=ClockTicker()
for i in range(50):
value=random.random()
clock.add(value)
print value,clock.next(),len(clock.data)
python total of 19 lines, and just 11 for the ClockTicker
java total of 55 lines and 39 for the ClockTicket class, but lets be fair I use the { in a new line (hi k&r fanatics) those don’t count. so it’s -1 line for each method and class. that leaves us with.
java K&R total of 47 lines and 33 for ClockTicket.
That means the python code is close 66% shorter then the java counterpart. One thing I should point out is that I wrote the python code first and the java one is a port but if you look at the java code, it follows java conventions and IMO it’s a fair competitor.
1. lossy data types, this is probably the most important one when I was writing the java code for some reason I wrote public void add(int item) and I didn’t notice that until the ave calculation in which the result was a float, which made me saw my mistake that I actually needed a bigger number to store time deltas, even worst I forgot that the time measured since epoch was stored in a long not a float. Anyway the python code works with int,floats,doubles,probably even strings. In the java counterpart I’ll probably have to write one class for each different datatype or just handle them in the same class with method overloading.
2. default parameters: the python’s init method
def __init__(self,MIN=10,SIZE=20)
is equivalent in java to
public ClockTicker()
public ClockTicker(int min, int size)
public ClockTicker(int size)
public ClockTicker(int min)
lets leave the fact that the last two won’t compile and think of all the boilerplate code that needs to be written just to have different ways to create a constructor. in java it can be minimized with calls to this() but that is at least 3 lines of code per constructor and a couple of curses from whoever is following that code. So we are looking at at least 10 more lines to achieve the same functionality.
3. named parameters: Back to the last two constructors issue. In java it will have to either be an ugly hack inside the two constructor parameter that if you call it as ClockTicker(null,size) min will be set to default. Or an even uglier one like ClockTicker(int minOrSize) and it will guess what you are passing in. But what most sane java programmers will do is something like ClockTicker c= new ClockTicker(); c.setMin(); or c.setSize(); which means adding even more lines of code and lets not get into the issue of fixing setSize so it won’t eat already present data. in python you just do what you need ClockTicker(MIN=100) or ClockTicker(SIZE=10) and done.
4. lists,dicts,etc as native data types and not API:
This is not really a feature that will directly make the size of the code smaller, but the fact that they are fundamental data types makes the developers of the std. api use them more often. Therefore functions like sum,min and len are prepared to handle Collections of data while in the Java counterpart they need to be hand coded outside of the std. api. Which is what is happening in the next method.
5. the fake access control (public,private,etc.)
One of the first things a good java programmer learns is to make class variables private and provide methods to access them,
• this is because setters should make sure the Object don’t gets corrupted.
• changes in the internals of a class will not affect client code.
• provide a clean API
• provide security of the object
Now in practice most setters don’t check anything, noone changes the name of a variable inside the class and if they do they normally do not keep the old setter/getter pointing to the new variable, until they compile everything crashes and they go back either in the name change or readd the old setter/getter pointing at the new name. About the clean API lets suggest an alternative lets say all “private” methods start with a symbol and and by convention (something the java crowd loves) lets say that symbol is _ . So in the event that you call a method that starts with _ it will crash with an access error? hell no if you really need my private method by all means use it, now don’t come crying to me when I break your code because I changed my private stuff, fair enough right? now think of all the setters and getter that are out there. All those millions of lame, useless lines of code, waiting to be strip out of existence to make tarballs,binaries, ISOs, backups, internet transfers and compile times smaller. ohh and about security just use reflection like this or this
6. primitives issue, this is more a language flaw in java than a real advantage in LOC. We have to admit that with autoboxing it makes code smaller, although official documentation states autoboxing is slow. Therefore this is not the optimal solution to fix the headaches of working with collections and primitives
7. And just to mess around with some people, time(1) says this
for the python code
real 0m0.083s
user 0m0.040s
sys 0m0.008s
and for the java code
real 0m0.117s
user 0m0.068s
sys 0m0.012s
so in this particular case python is faster, and just in case you where wondering neither program is optimized. They where both written for readability since after all the idea of this was to show a way the polling could be implemented.
Overall the python code is more readable, has more functionality, has less LOC and is faster