Spot any errors? let me know, but Unleash your pedant politely please.

Wednesday 25 November 2009

Disconnection doesn't necessarily mean Broken Web App

I was wrong about something yesterday…

Peter-Paul Koch unambiguously sets this straight

Let’s debunk one argument. It is perfectly possible to write an offline Web app for Safari iPhone. The browser supports appcache and local storage for storing the application and its data, respectively.

Both Web apps and native apps can work offline. Thus this argument has no value.

I still think web apps suck. They suck on a desktop. Running them on a phone, with a fraction of the clock speed, a fraction of the cores, a fraction of the RAM, and they're going to suck an order of magnitude more.

Tuesday 24 November 2009

iPod Touch, iPhone, Native vs Web Apps and pinch of ChromeOS

I'm prompted to write this by John Gruber's iPhone Web Apps Alternative post.

I pretty much agree with Gruber on this, but he neglects to consider the iPod Touch. Most apps, unless they use the camera, compass or GPS, are iPod Touch apps too. Apple screwed up by not having a common name for the two devices (No, I can't think of a good one), and I don't think they expected or planned for the iPod Touch to be such a success.

Many apps require connectivity to work because the data is in the cloud. Most of the apps that rely on data in the cloud could be written as web apps. They would probably be slow and suck, and suck more life of the 3G network, but they'd do the job. It's the difference between www.twitter.com and Tweetie or Twitterific. Twitter sucks in a desktop browser. It sucks really badly in the mobile optimised version on the iPod/iPhone. (Thinks: "iApp" as a common name?)

An app that doesn't need data from the cloud should be written as a native app. It'd be faster, not suck as much, and not require any wifi/3G bandwidth at all. Most importantly, it would work on an iPod Touch where there was no accessible Wi-Fi. (And on an iPhone where there was no 3G or edge).

An app that lives in the cloud and uses data from the cloud is sometimes necessary, such as a webmail client. These still suck compared to native clients, but needs must when the devil vomits into your kettle.

I have no problem not using Mail, Twitter, Safari, NNW, Facebook, linked etc when I'm on a bus or a train. To not be able to play Bpop or boxed-in or Bones or Reversi because of no connectivity makes no sense whatsoever.

Apps and data in the cloud break when connectivity breaks.

It's why ChromeOS makes little sense to me.

Friday 30 October 2009

Defying Gravity Series 1 Episode 2 'Natural Selection'

I'm really rather enjoying this series so far. I'm kind of waiting for it to jump the shark, which it seems in danger of doing quite early on if they're not careful. That'd be a shame. There are unscientific/supernatural things in the series, and that's fine, it's TV, they're necessary and entertaining devices. If it doesn't need to be wrong though, it really needs to be right.

In episode 2, ('Natural Selection'), an experiment is performed by one of the astronauts that she describes as 'natural selection'. Anyone with a passing knowledge of evolution knows immediately that it's bullshit TV science rearing its ugly head yet again.

An external actor, selecting randomly is about as far from natural selection as you can get. The survivors won't be the fittest / most appropriate, they'll simply be lucky.

Two things required for evolution are (random) mutation and natural selection. What the stupid experiment in Defying Gravity does is 'Random Selection'.

Darwin's finches are the result of evolution by natural selection. The ones that remain are best suited to their environment.

The pigeons he studied are the result of selective breeding. That is taking two birds with particular characteristics and letting them get it on (repeat to freak). Same with domestic dogs. Their suitability is not governed by nature, but by man. This unatural selection yields significant changes quickly.

I have a very basic understanding of this stuff, gleaned from TV and getting halfway through The Blind Watchmaker 10 years ago. If I was writing a scene with this stuff in, I'd run it by a biologist. I'd check. I'd really not want to look this foolish on TV. And that's just me. One person. Nobody. Not one single person noticed when this was being written and rehearsed and recorded, that it was bullshit ? What astounds me about this Defying Gravity nonsense is this carelessness.

If you work on this show and told your boss that this scene was bullshit, show them this blog. Tell them I said they were idiots and they should listen to you next time. People notice this shit. Mmmkay ?

Saturday 15 August 2009

Filmmakers and musicians having a “credit score”

I often think about writers and filmmakers and musicians having a “credit score” with my bureau. The currency is the amount of faith I have that a certain project will be great or even good. Some creators rate so low that if the currency were actual money, I won’t loan them $50 if they left behind a $100 bill as collateral. Whereas the Coen Brothers could tell me “Our next movie is going to be a static, 90-minute shot of a bowl of Cheerios getting soggier and soggier over time” and I’d still mark Opening Day on my calendar.


So says Andy Ihnatko.

He's right. This is how I feel about Tarantino. I can't imagine him ever making a bad movie. I sometimes worry that I'm blindly accepting of anything that he does, but really, is that such a bad thing?

Wednesday 24 June 2009

Fax machines : Oh how I hate thee.

Fax machines and washing machines. The both confuse me. Are both designed to be operated by a female brain, perhaps ?

Reminder to self: to use the fax machine at work successfully, feed the paper face down and upside down. Put the paper in before dialling the number, or it won't work. It'll pretend to go through the motions, but it'll fail. The fax machine's printer will not begin to warm up until the faxing is complete, despite needing to print whether the operation was a success or not.

Washing machine : I haven't quite figured it out yet. Anyway: fabric conditioner is for wimps.

Friday 19 June 2009

from x import *

Damn. I instinctively knew this was was bad, but it was in the examples I was given before I got stuck in, and before things got complicated, and stupidly without looking to find out if there was a better way.

I have from x import * and from x import name1, name2 all through my code.

It hasn't actually bitten me yet, but I know that I need to change this. Everywhere.

In some languages, there would be no better way. This kind of import is the way things work, and if there's an ambiguity, it's a compile time issue, where things need to be made explicit/qualified when names are used, or it simply won't work.

There's a similar thing in Ada, where with x; is essentially the same as import x, but everything must be qualified. There's a use x; statement that exposes everything in x. It's not dangerous, like Python's *, but it does make it a bastard to find things. The first rule of Ada was "Never use use".

Note to self: next time I try a new language and something looks like a use, figure out how to not use that 'feature'.

Wednesday 17 June 2009

Code Like a Pythonista: Idiomatic Python

Code Like a Pythonista: Idiomatic Python by David Goodger.

It's a must read. I was surprised at how much I already knew, but it's a great reference, and it has lots of good links at the bottom too.

I wish I'd read this a few months ago, when I started dabbling in Python. I didn't realise how deep I'd get. I though just up to the ankles, but I'm maybe up to my knees by now.

Things I've done right :
  • Used 4 spaces for indents. I always have, in all languages that allowed it. (Though possibly not in examples on this blog, for reasons of laziness)

  • Tried to stick to 80 chars. This is just a habit from my days (and nights) on a VT220.

  • StudlyCaps for classes.

  • Avoided single line compound statements.

  • Practicality beats Purity. Always believed this. Some people try to write optimised code. I try to write readable code, and if it needs to be optimised, refactor later, and litter the code with comments explaining why.


Things I'm naturally graduating toward:
  • I love whitespace. I use tons of it. Always have. It really helps readability. So I may have as many as 10 blank lines between functions. Gradually, this has been reducing. While I'm using Python, the excess whitespace has become annoying. I'm not quite at the 1 line between functions, 2 between classes guideline, but I think I'll naturally get there soon.
    Used None for many default parameters, initialising new objects inside functions. (I didn't really know why, but now I do, and I can fix it where I've got it wrong at the moment)


Things I've done wrong:
  • Used camelCase where I should be using joined_lower. I prefer camelCase, but if joined_lower is more Pythonic, I'm willing to yield this. Not sure if I'll change all the code that I already have though.

  • Not used spaces after , and : in lists and dicts

  • Not used docstrings much (My excuse is that I'm in a mixed Java/Jython environment, and I don't know how to make the docstrings useful).

  • I have some unnecessary "== True" or "== None" gubbins. The linked doc has a table explaining how the Truth Values work.

Lovely MISO font from omkrets

Don't know much 'bout typography, I quite like Papyrus, for example, which is probably wrong, but I do despise Comic Sans, so my eyes must work a bit…

There's a lovely looking free font available from omkrets called Miso:

Picture of MISO font

There are different weights, but they're equally spaced, so you can have normal and bold fit into the same space. The technical terms from the PDF descibing the font are 'Equal stroke height, varying baseline' and 'equal glyph width'. Maybe lots of fonts do this, but it looked like genius to me.

I think I'd like a monospaced version for coding with, but there are probably very good reasons why this won't work. Are there any good sans serif monospaced types ? Would the 'i's would look all wrong ?

Tuesday 16 June 2009

New MacBook Pros and the missing ExpressCard slot

I'm in full agreement with Matt Davis, that replacing the ExpressCard slot on the MacBook Pros with an SD card slot makes little sense.

Some people love that they now have an SD card slot. I get that. I still think it sucks.

The pros need connectivity, and while the unibody enclosures and battery life are superb, the compromise has been connectivity.

Audio people use firewire drives and firewire audio devices. At the same time. They use express card to connect to pro equipment

Video people use firewire drives and firewire audio devices at the same time too. They use the expresscard slot for reading and writing SxS at high speed, and also for specialist pro equipment.

If people really wanted an SD card reader, they could've just bought one for the expresscard slot.

The real test, though, is if people switch to Windows, or go for the 17", which still has expresscard. Is it really the hardware that matters, or is it software. If it's hardware, they'll switch. I'm not switching any time soon.

Tuesday 9 June 2009

Python: Finding out if a class is a subclass of a class

I needed to find out whether a class was a subclass of another. Googling, I found a message by Armin Rigo on the Python-Dev mailing list with this line :
    for basecls in type(obj).__mro__:

A quick look squizz at __mro__, enough to see that it represents 'method resolution order'. (I'll look in more details at some point, but that phrase was enough for now). A bit of a distillation at the Python command line, and I end up with this simple test/condition:
    <ParentClass> in <ChildClass>.__mro__

Monday 1 June 2009

Determine current stack depth

If anyone knows of a better way to do this, do let me know...

The test harness I'm writing produces a lot of logging information. It's necessary to record what test are doing, where they fail etc, so that we can investigate and not just produce yet more useless metrics. One of the things I found myself doing was adding indentation so that the test cases, sub tests and test steps etc were shown with increasing indentation. As with source code, it makes the scope of the test results easier to follow.

The more I was adding this by hand, the more I though that maybe there was a better way to do things. I'm probably going to so something a little more intelligent, but for now I've gone with indenting my logs according to the call depth of the function that writes the log string.

At a fairly high level, there is a routine to print to the console and to a log file. References to this cascade through the code, so that this one function is the one that actually gets called when logging :

def printAndLog(self, logText):
print logText
self.log(logText)


All I need to do is determine the stack depth:
def callDepth():
depth = 0
while True:
try:
sys._getframe(depth)
depth +=1
except:
return depth - 1

and use it to add indentation...
def printAndLog(self, logText):
logText = ' ' * self.callDepth() + logText
print logText
self.log(logText)

Not sure that it's entirely legit to be calling _getframe, but it's working at the moment, and I'm not doing anything with the returned frames anyway.

Friday 29 May 2009

Exploiting Python's logical evaluation order for conditional evaluation in list comprehensions

My head is hurting slightly over this one. First I'll show the experimentation (edited!)
>>> if 'arse':5
...
5
>>> if '':5
...
>>>
>>> if 'arse'==True:5
...
>>> 'arse' and 'arse'
'arse'
>>> 'arse' and 'flange'
'flange'
>>> 'arse'==True
False
>>> a = [1,2,3,4,5]
>>> b = [4,4,4,4,5]
>>> c = [x==y for x,y in zip(a,b)]
>>> c
[False, False, False, True, True]
>>> a = [(x<y and x+1 or y) for x,y in zip(a,b)]
>>> a
[2, 3, 4, 4, 5]
>>> a = [(x<y and x+1 or y) for x,y in zip(a,b)]
>>> a
[3, 4, 4, 4, 5]
>>> a = [(x<y and x+1 or y) for x,y in zip(a,b)]
>>> a
[4, 4, 4, 4, 5]
>>> a = [(x<y and x+1 or y) for x,y in zip(a,b)]
>>> a
[4, 4, 4, 4, 5]

I then spent a little time reading about logical operator and precedence in my Python Pocket Reference, because this was messing with my head. In x and y, if x is false, y is not evaluated. If x is true in some form, then y gets evaluated. If y happens to be a string, then the evaluation of y is returned, which is a string.

What we have then is a sort of trick if:else: statement. By writing…
condition and x or y

…we're achieving the same as…
if condition:
x
else:
y

This is remarkably handy stuff. Especially (as shown above) when used in a list comprehension. I'm not sure that it's particularly readable, but it's certainly more concise than the code I had previoulsy. More importantly, it works too (the previous code did not). The result is this (names changed to protect the innocent), which increments the values in a list, but only up to the corresponding limits specified in another list:
counters = [counter<boundary.upper and counter+1 or counter for counter,boundary in zip(counters,boundaries)]

The code I had in place prior looked something like this:
newList=[]
for counter,limit in zip(counters, limits):
if counter < limit.upperLimit:
newList.append[counter+1]
else:
newList.append[counter]
counters=newList

Python: str * int … WTF!? … Thinks … Ah!

I was reading Guido's History of Python blog this morning. In it he mentions this :
Passing an invalid argument, for example a string, is generally caught quickly because few operations accept mixed string/numeric operands (the exception being multiplication)

WTF!?
Rushes over to Terminal...
>>> 'string' *2
'stringstring'

Why the hell would _anyone_ want to do that ?

…Thinks…

…Realise that I have some code that can be simplified with this…
indent=''
for space in range(level):
indent += ' '

…quick check for zero case…
>>> 'string' *0
''

…changes code…
indent = ' ' * level

Python lesson 1 learned for the day.

Thursday 28 May 2009

Wolfram|Alpha. I guess this explains the 'Alpha' part

Today I wanted to convert something, and thought maybe it was the sort of thing Wolfram|Alpha would be good at, and a better starting point than Google. Converting from European shoe sized to UK shoe sizes, to see if some shoes I like the look of (but will probably not buy if I'm honest), are made in my size.

If you type a query about shoe sizes in, it probably won't know what to do with it, but it will have a link to shoe sizes and some example queries.

One of the examples happens to be "U.K. men's size 11 shoe in Japanese size". I clicked this and then changed it to "European men's size 47 shoe in U.K. size". It borked (Wolfram|Alpha isn't sure what to do with your input). Changing it to "U.K. men's size 11 shoe in European size" also made it bork.

I guess this explains the 'alpha' part of the name.

BTW, I really want to like Wolfram|Alpha, but their natural language parser just doesn't work well enough yet to allow people to get at the data.

Wednesday 27 May 2009

Blogger, spaces, &nbsp; and <pre>

OK, So I've been posting bits of code of late, and Blogger buggers up the spacing. It removed leading spaces and trims multiple spaces to single spaces. This is probably good for the average blog post, but really, really bad for indent dependent Python.

I finally got around to Googling the problem. I'll repeat it here, just in case this helps someone else.

This is how I was doing it until today:

<code>
def double(x):
&nbsp;&nbsp;&nbsp;&nbsp;return x*2
</code>

But now I know about <pre></pre> and I can write this instead:

<pre>
def double(x):
    return x*2
</pre><
To show this:

def double(x):
return x*2

Much better !

Python : Using **arg and setattr to create instance variables at runtime

I found that I need the generic/extendable **args, but I also needed those args easily visible to a method in a subclass. Initially I just passed the **args dctionary into a named parameter, but that seemed messy when I actually came to use it. Plus I need this usable by (even) less able programmers.

Here's in essence what I've done:
>>> class A(object):
... def __init__(self, **args):
... for key,value in args.iteritems():
... setattr(self,key,value)
...
>>> a=A(first = 1, second = 2, name="Monty")
>>> a.first
1
>>> a.second
2
>>> a.name
'Monty'

There's a little more to it. I have checks against the existing names in case I overwrite something, for example.

Tuesday 26 May 2009

Python : Instantiate nested classes in a superclass, not the direct containing class

I'm using classes for parts of the test harness that I'm writing for some functional testing. I'm writing I want the tests themselves to be fairly clean, fairly free of boilerplate etc, because some of the people writing the test have not done much or any coding before.

I have a TestCase class and I have a TestStep class. When a new test step is written, TestStep is subclassed and included in a subclass of TestCase.

One of the things I wanted to avoid doing was having to get the test writer to instantiate the TestSteps. I don't think this is possible in many languages, but Python lets me do it with its ludicrous ability to introspect and add stuff to objects at runtime.

class NewTestCase(TestCase):
    class NewTestStep(TestStep):
        def body(self):
            ...test step code goes here...
    def body(self):
        stepNewTestStep() #call instance of NewTestStep

Note that there's no stepNewTestStep = NewTestStep() anywhere, and I can add as many TestSteps as I like to the class. stepNewTestStep is not hard coded into the TestCase.

I'd considered naming the NewTestStep objectsas newTestStep rathe than stepNewTestStep, but I was already getting duplicate names in the tests that I'd written, so decided to add the explicit 'step' prefix.

To a Python newbie like me, this is a bit WTF!?, but stick with me. As ever, real Pythoneers, feel free to tell me of better, more Pythonic ways to do this. Here's how it was done…

import types
class TestCase(object):
    def __init__(self):
        for name in dir(self):
            attribute = self.__getattribute__(name)
            if type(attribute) = types.TypeType: # ignore any non classes
                for base in attribute.__bases__:
                    if 'TestStep' in base.__name__: # only interested in TestStep classes
                        setattr(self, 'step%s' % attribute.__name__, attribute())

In plain English, get the names of all the things in TestCase/NewTestCase. For each, make reference to the object of that name (__getattribute__), see if it derived from TestStep and then create a new instance of it (setattr), called 'step[ClassName]' as part of TestCase/NewTestCase.

Note that NewTestCase inherits the __init__ of TestCase, so dir(self) returns the names of everything in NewTestCase.

Friday 22 May 2009

Python : Iterating Multiple Lists

I did this a few times...

for index in range(len(aList)):
    doSomethingWith(aList[index], blist[index])
    doSomethingElseWith(cList[index])

Or even...

for a in aList:
    doSomethingWith(a, blist[aList.index(a)])
    doSomethingElseWith(cList[aList.index(a)])

And at some point, it felt wrong. It felt, I have come to understand, unPythonic.
Google was my friend, although I didn't really look or read enough, and I ended up with something like this:

a=0
b=1
c=2
for abc in zip(a,b,c):
    doSomethingWith(abc[a], abc[b])
    doSomethingElseWith(abc[c])


And I was happy. But putting it in a few more places, it also felt like unPython. So I decided to take a better look (actually just a better more explicit simple search for exactly what I wanted), and found the Pythonic way...

for a,b,c in zip(aList,bList,cList):
    doSomethingWith(a.b)
    doSomethingElseWith(c)

Refactoring to use this idiom has been wonderful. Lines of code disappearing and the code becoming more readable too. Marvellous !

(I think I found my answer at testing reflections

Pythonic

I'm not a very Pythonic Python programmer yet, but it's getting better. The web has oodles of useful hints and tips. I'm adding stuff here that I find useful as much for me as anyone else.

I don't think yesterday was the first time I came across the term 'Pythonic', but it's the first tie it really registered. It's a nice landmark on my journey.

'Pythonic' just means doing things in Python the way a real Python programmer does them, rather than doing it Python in the way that it's normally achieved in another language. I've mentioned before that I'm a couple of degrees of separation from being a real Python programmer. I'm from an Ada background, and came to Python via Java.

Ada is a superb language. It's like a polar opposite of Python, and that's fine. I wouldn't use Python for safety critical, and I wouldn't use Ada to write automated functional tests. Right tools for the job and all that.

Edit: worth a read : What is Pythonic ?

Monday 18 May 2009

Example of an exception class in Python

If I'm going to suggest that you define your own exceptions, I really ought to give an example:

class PlayerError(Exception):
    pass

class PlayerIsNotPlayingInExpectedDirectionError(PlayerError):
    def __init__(self, direction):
        """direction parameter should be 'forwards' or 'in reverse'"""
        if 'rev' in direction : direction = 'in reverse'
        self.direction = direction

    def __str__(self):
        return "Player was not playing %s as expected." % self.direction

Define and raise exceptions liberally.

It does the job, but this doesn't really feel like it's enough:

  if not playerIsPlayingForwards():
      raise "Player is not playing forwards'

I'm using this structure instead, liberally raising my own verbose exceptions :

  try:
      assert playerIsPlayingForwards():
  except AssertionError:
      raise PlayerIsNotPlayingInExpectedDirectionError('Forwards')

It takes a bit more time, but it's worth it. You get it back in debug time saved. You also get a nice warm fuzzy feeling when one of your explicit exceptions gets raised, highlighting a very specific problem.

Finding the name of the current function in Python. nameOfThisFunction()

As part of my testing, I need to create logs that give me some traceability for when things go wrong, evidence of testing whatever the result. Kind of like permanent debug text. I'll look at differences between log files of the same tests run on previous and new versions. It's ad-hoc testing when it's first written and it's regression testing thereafter.

One of the ways to show trace is simply to show which methods/functions are being called. Being lazy, I simply want to cut and paste something, I don't want to also have to change it. I would prefer to use the actual function name rather than hard coding into a string for printing / logging. The name might change in the future. I might forget to alter the name after pasting it.

This is what I don't want:

def testStepA(param):
    writeToLogFile('Reached function 'testStepA')
    ...

def testStepB(param):
    writeToLogFile('Reached function 'testStepB')
    ...

I want something like this instead:

def testStepA(param):
    writeToLogFile('Reached function '%s', nameOfThisFunction())
    ...

def testStepB(param):
    writeToLogFile('Reached function '%s', nameOfThisFunction())
    ...

Fortunately, inspect gives me the information I'm after:

import inspect

def nameOfThisFunction (offset=0):
    return inspect.stack()[1 + offset][3]

Handling exceptions and printing a useful trace in Python

In writing a test harness for functional automated testing, I'm expecting things to fail. In writing some of the tests, I'm trying to get things to fail, poking around the boundaries etc. WhenI have a test suite that takes 50 hours to run, that I kick off on a Friday night, what I don't want is for it to stop running five minutes after I leave the office.

I want it to carry on with the rest of the tests, but I also want some information about these failures. What exceptions were raised and where they were raised. This is how I'm doing it:

import sys
import traceback

try:
    myTestCase.executeTestSteps()
except:
    # handle and log exceptions
    exctype, value, trace = sys.exc_info()[:3]
    extracted_tb = traceback.extract_tb(trace)
    printAndLog("**********************');
    printAndLog(str(exctype) + ':' + str(value))
    for tb_line in extracted_tb:
        printAndLog(str(tb_line[0]) + 'line ' + str(tb_line[1]) + ' in ' + str(tb_line[2]) + ' (' + str(tb_line[3]) + ')')
    printAndLog("**********************');

    del trace

( Where myTestCase is the thing I want to run and printAndLog (you'll have to roll your own) sends to the console and to a log file)

Profit per head. Tech stock

The $210K profit per head at Google figures are interesting (as John Gruber points out).

Apple's not known for talking small profits and Microsoft pride take pride associating themselves with cheap so what's going on here ?

I have a few initial thoughts…

1 - Microsoft doesn't have stores. Although the Apple stores must bring in lot of revenue, they're also a massive overhead.

2 - Apple isn't in enterprise, and this is where Microsoft gets its profit. Money for old rope with Office and Exchange and Windows volume licenses.

3 - The data is based on 'employees', but that's not the same as staff. It probably excludes contract staff. Those companies using lots of contractors might be showing artificially high numbers using this measurement. I've no idea whether Microsoft, Google or Apple uses a lot of contact staff (I suspect not), but I bet a few of the companies listed do.

Sunday 17 May 2009

Python: count of parameters in a function

I recently had a problem with a that class had several ways to populate one of its instance variables. An instance method was called in each case, either with a parameter, (using the method provided by the class), or without a parameter, (in the case of the same method overridden in a subclass). I've since realised that there was a simpler/better way to achieve this, but no matter, Python allowed me to figure out which one to call by being able to count the parameters in the method, and then call

import inspect

def parametersInMethod(method):
    return len(inspect.getargspec(method)[0])

Allowed me to do this...

if parametersInMethod(self.populateInstanceVariable) == 0:
    self.populateInstanceVariable()
else:
    self.populateInstanceVariable(withValue)

This give a little insight into 'inspect' and also shows how methods being objects allow them to be passed as parameters into functions.

Saturday 9 May 2009

More on Python and a bit on Objective C

I can't quite put my finger on it, possibly because I've not used ObjC in anger yet, but it seems to have a similar ethos to Python. I'm probably going to ignore ObjC for a while longer, but I may dabble with PyObjC instead. Learn some Cocoa through the increasingly familiar Python, then apply that knowledge to an ObjC project.

What I love about Python so far is that just trying things seems to usually just work. It's a language that does what you want it to. It's a little dangerous, because so much is checked and can be manipulated at runtime. It's the least nanny-ish language I've come across, trusting the programmer to do the right thing and allowing the programmer to break convention when it is appropriate. It's counter-intuitive, perhaps, but the responsibility given to the programmer seems to lead to responsible programming. Treat me like an adult and I will behave like an adult kind of thing.

Wednesday 15 April 2009

Why "The dumbest 'Macs are better than PCs' post, ever" wasn't dumb at all.

Ian Betteridge, former Mac User (UK) editor and recent switcher from Macintosh (for perfectly good and valid reasons), usually gets it right, but gets it wrong in his The dumbest “Macs are better than PCs” post, ever post.

The post to which he refers says this :

“Apple never, ever expresses battery life based on the number of cells that make it up. The ThinkPad I have at work is available with a 4, 6, and 9-cell option. And I have no idea what any of it means or why I should care. Apple just tells me how long I can work without a power source, which is what I actually care about.

The PC-makers just don’t get it.”

Ian thinks this is absurd, and given an example where it is demonstrably false. That's all well and good, but it doesn't really refute the original post. Indeed, it is demonstrably true for another model by the same company.

4-cell 2.0AHr Battery
6-cell 2.2AHr Battery
9-cell 2.2AHr Battery

Seriously, WTF does that mean to any normal person ?

So far from being a dumb post, it highlights perfectly the kind of thing that most PC makers don't get most of the time. If they did, they would quote a time for each battery. No doubt the batteries are common to many models, but it wouldn't take too much effort to calculate the typical battery life (by dragging amp hours for the battery from a database table and power draw of the laptop from another table). This kind of attention to detail is exactly what Apple get most of the time.

Thursday 2 April 2009

Type-Safe Python

Introspection, baby !

if frameType.__class__.__name__ == 'FrameType':
    ...
else:
    raise 'frameType must be an instance of FrameType'

Wednesday 25 March 2009

Positive tinkering (an example)

I've been tinkering today. I'm working in Python/Jython on an automated test harness. Typically, I'm standing on the shoulders of giants : the developers who have given me an API with which to test their Java app using a bit of Jemmy magic. I hope to have (relatively) large shoulders for my testing colleagues to stand on, and that means hiding / abstracting the API that I've been given even further. It's going well, but it's not quite there yet. Today I needed to write a very specific test, and there were two approaches that I could take. One was to extend an existing class which takes scripts as Python lists, to be able to do a drag and drop action. The other was to create a new class to allow custom/bespoke tests to be written without resorting to too much reproduction of boilerplate code.

Eventually I got something working. Ironed out some niggles, and was quite pleased. It would have been easy to leave it at that. It was certainly good enough. It seemed a bit clumsy though. There was still a lot of work in subclassing and calling my bespoke test (It's called 'custom', but I already know it'll be called 'bespoke in about 4 hours if I ever get some sleep). I needed to figure out a way of getting boilerplate out of a function that created an instance of a subclass and into the parent class, where it could be forgotten about for all eternity by people writing the tests.

A solution (which may itself be refactored), was to pass a parameter (called 'parameters', containing a Python dictionary, which can be accessed by key, which makes it human readable) into the parent class' constructor, the constructor calls some functions which can be overridden by the subclass. The parent class has a function that calls the test body and records results, and the test body is overridden in the subclass to do the stuff that the test writer wants to do.

It means that the test writer subclassing the bespoke test class now doesn't need give a monkey's chuff about the boilerplate code. He (Sadly we are all 'He' in the lab at the moment) just writes some simple steps and can assume that the environment for executing those steps is initiated and torn down automatically.

Refator, refactor, refactor.

I didn't come across the term 'refactoring' until relatively recently, but it's something I've always done without realising it. Or at least without labelling it. I don't know of an official definition of refactoring, but it would probably go something like this : "Refactoring is the process of improving code quality without changing its function".

Refactoring is just tinkering until it feels right.

Renaming is the simplest form of refactoring.

Renaming is also the most significant key fundamental form of refactoring. Change the name of a variable, method or class, and it can have massive implications on the design. Get a name right, instead of merely almost right, and clarity ensues; pieces of the puzzle fall into place. Glaring mistakes, omissions, duplications and complications become suddenly apparent.

MacHeist

There's some argument about the MacHeist bundle. Whether it's good business and whether it's ethical for us consumers to avail ourselves of a bargain.

I think that validity of the business aspect is for the developers to decide. If participating gets the developer a big pile of cash they wouldn't normally get, it gets them a whole lot of exposure that would otherwise be difficult to get (other than with expensive advertising), and it's not going to cause a support nightmare, then where's the problem ?

Marco Arment may think that it’s not a good idea, as conscientious consumers, to accept such steep discounts on the products that we use and love, but while I don't disagree in principle, I think the argument is a red herring. Without MacHeist, an awful lot of people would not pay for or use this software. With MacHeist, an awful lot of people will pay for this software, may install some or all of it, and may even use it occasionally.

I'm a MacHeist customer. The ethical validity hadn't crossed my mind until today. Having thought about it a little, I think I actually paid over the odds for the bundle considering the actual use I'm going to get from it. There's an outside chance that I'll use one of the apps more than twice. An app may become part of my arsenal. If it does, then it's a dead cert that I'll pay the full upgrade price for the next major release. I get some cheap useful software now, and the developer gets a customer for life.

Having this stuff needlessly installed contravenes a number of al3xs rules for computing happiness. I don't care. There are 133 items in my Applications folder. That's way too many. I don't care. I think Apple make great stuff. I think developers on OS-X make great stuff. I don't want Comic Life Magiq on my Mac because I'm into writing comics. I want it there so that when someone says, "Wouldn't it be cool if we could make a comic of that", I can show them how easy it is with great software. I become a cheap and willing salesman for Plasq (and for Apple).


Don't think of MacHeist as exploitatively cheap software, think of it as a quite expensive demo suite.

Saturday 14 March 2009

Scratch from MIT

My son, who is in year 6, has expressed some interest in programming (like lots of kids, he wants to be a games designer). I tried getting him interested by introducing him to Python. I thought he could get used to the language and OOP, without getting heavy with strong typing, verbose, unclear languages. Python gives fairly quick results (faster, probably if you don't use is like an Ada jockey who knows a bit of Java)

I'd looked very briefly at PyGame, and figured that it would be relatively easy to pick up.

Last week though, I followed a link to scratch, and it was very obvious that this was the place to start. I think I was right. I showed it to my son this morning, and with a little guidance, he finished writing a version of Pong today.

There are some aspects of scratch that I think could apply to a real IDE. Drag and drop constructs, statements, objects etc may b e a simplification too far, but the graphical representation of them seems a lot better than simple code colouring …
Scratch 1.3.1 (release of 21-Nov-08)
Uploaded with plasq's Skitch!

OK, it's little fisher price, and would need toning down in a real IDE, but it's also clear about what belongs where. It shows scope very well. It's not unlike Python's indentation based scope, but also more explicitly shows the end of the scope of a block with no additional code . There's no reason that this graphical representation couldn't be live generated while typing in a 'real' language. Something like this…
length.py
Uploaded with plasq's Skitch!

might look like this…
Untitled
Uploaded with plasq's Skitch!

There'd be a problem with the code becoming illegible in deep blocks. (exaggerating)…
Untitled
Uploaded with plasq's Skitch!

I think there's an advantage though. If the code is 15 or 20 levels deep in a single file/class/method/function, then there's some bad design going on there, and it should be refactored. The opacity would become a useful visual representation of the readability of the code.

Why the iPod Shuffle is broken

Having pondered the new (3rd gen) iPod Shuffle for a little longer, I think it's broken. I want it to fail. I want everyone who fancies one to reject it. There are two reasons. One I'd mentioned before, as a nitpicking detail: no control on the device itself. the second reason is that there's bloody DRM in the headphones. What it means is that only authorised manufacturers can make replacement headphones or extension cables that include the utterly necessary controls. The little inline remote has an authentication chip in it.

I don't object to the inline remote. I don't object to Apple selling a chip to other vendors that allows them to send the requisite signals to the device to control it. Plenty of devices have proprietary controls like this. Think TV remotes, for example. What I object to is doing this while having no controls on the device itself. Why ? It just feels broken. Headphones go missing, get trodden on, go missing down the back of the sofa. Having the player break at the same time is an appalling design decision. It's either stupid or greedy.

In programming terms, the shuffle ad its controls are highly coupled. They're so highly coupled that they should be one unit.

I've experienced the problem that Apple have introduced to an extent with a couple of televisions. Al functions are accessible from the TV remote, but not all functions are accessible from the buttons on the TV. This is a broken interface. A device, whether it is a tiny MP3 player or a big TV should still work fullywithout the remote, even if the interface by which its functions can be accessed without the remote are less convenient / more fiddly.

Edit: some doubt has been cast on whether the EFF and ilounge reports on the chip in the headphones has anything to do with DRM / DMCA. Maybe they're just trying to grab headlines.

Wednesday 11 March 2009

Thoughts on the new iPod Shuffle.

The voices on the new iPod Shuffle are different for Tiger, Leopard and Windows.

I suspect that the voice isn't produced by the shuffle from the tag text in the sound files. I think it's added by iTunes as audio. This audio could be embedded as a new tag or it could be added as a separate resource file. I assume it'll take a while to process a whole library to add this data.

Edit: the Shuffle needs a new version of iTunes. I think this supports my hypothesis about the metadata.

Overall impression is good, but I'd like to pick some nits nits...

The control is on the headphones. What if you want to use other headphones ? (I never had a problem with the headphones that came with my old iPod, but the ones that came with my new one simply don't stay in my ears).

The control is on the cable for the right ear. What about the sinister left handed people. It would make more sense to have this on the main cable before the split.

The obvious fix is for some third parties to make a cable with an inline control and a headphone socket. The problem that introduces is that the combined cable will be too long, and the position of the control in that length of cable might not be ideal. Of note, the last pair of Sony headphones I bought came with a very short cable (about 18"), and an extension cable which adds another 2 feet.

Tuesday 10 March 2009

Touch based tablet from Apple.

Maybe.

Think iPod Touch, but with an 8" display. All the better to surf with. Won't be much thicker

Will be a Touch device. Will use the app store. Apps will be full screen. Will not have a desktop.

Macintosh tablet

Ain't gonna happen.

Apple NetBook

Ain't gonna happen.

Monday 9 March 2009

Am I writing Java in Python ?

That's what's bugging me today. Or rather Am I writing is like an Ada programmer would write Java ? It's going through too many filters.

It doesn't really matter, but I've been writing stuff as methods of classes, and maybe they could just be functions. I suspect my code is 4 times the size of a 'proper' Python programmer's code.

I've never used a tuple. I'm using dictionaries, but I fear not in a good way.

I want to overload _init_ all the time.

On the other hand, I'm starting to slip into Test Driven Design. I'm mostly writing unit tests for some code I'd already written, which is to support some functional tests that I'm automating. I had three levels of classes, and at the highest level, it was more of a sketch than an attempt to get it right. Once I started writing and running tests, it all got fixed up and fleshed out. Maybe I'll start with some unit tests tomorrow and then write the code.

Monday 23 February 2009

The Oscars.

John Gruber has an interesting take on the Oscars. I agree with almost everything he says. The Kermodian certainty is to be admired, but there's one big problem: WALL-E just wasn't that great a picture. It was that great a picture for the first half, but not for the second half. My gut tells me that half a picture shouldn't win an Oscar nomination.

Sunday 22 February 2009

What I think about comments.

Some people tell you that you don't need comments. It may be true for them, but it's not true for everyone. So unless you keep your code to yourself, you need to use comments. You shouldn't state the obvious. This is a bad comment:

   # increment the loop variable
   i++;


Comments are more useful to remind yourself why you did something in a certain way. Comments shouldn't really explain what the code does, they should justify or clarify something about the code. It's better to have comments on blocks rather than lines. It's OK to add comments to help when learning a language or technique that you maybe will strip out later.

Example of a good/useful comment :

       // create and populate the first few
       // rows. Shouldn't really have to,
       // but if we don't, autosize will
       // throw a wobbler later on
       //
    HSSFRow row = null;
    HSSFCell cell = null;
    for (int rowNum = 0; rowNum < dataRow; rowNum++)
    {
       row = worksheet.createRow(rowNum);

       for (int col=0; col<headersText.length ; col++)
       {
          cell = row.createCell((col + 1), cellType);
          cell.setCellValue("");
       }
    }

It's a good comment because it's going to explain why some odd code is in there, and it'll stop someone taking it out in the future and having to go through the pain of finding a workaround for a problem that they'd inadvertently reintroduced.

It's also formatted in an unusual way. It spans multiple lines, and it's over-indented. This is very deliberate. It stems from the days before syntax-colouring. It achieves two things. The comments get out of the way when you're reading the code, and the comments stand out when you want to read the comments. I've been doing this for years. An old boss used to do it and it infuriated me. He explained why he did it though, and persuaded me to try it for a while, and it works. It's a great way to format comments.

Why readability and scope matter

I was reasonably lucky to have a decent lecturer in Polytechnic, who taught me some good programming practices. This was structured programming (Modula-2), rather than OOP, but they also apply to OOP. Essentially, it boiled down to two complementary goals: Low Coupling and High Cohesion. The goals are fairly simple to achieve by following a couple of simple rules:

1. Limit scope as much as possible.

2. A subroutine should do one thing only, and all the data it needs should be defined in its interface (its formal parameter list).

There are occasions to break the rules, such as when optimising. Breaking the rules for mere convenience, especially early in development is a definite no-no. I've done it, and it usually comes back to haunt me, and it usually needs refactoring to limit the scope.

It's arguably more difficult with OOP, because instance variables have global scope for an object, but not all methods should be allowed to alter them. It's probable that if you get into this situation, your object is too complex and should be split into smaller and simpler objects.

So that's scope.

Readability matters because code gets read far more often than it gets modified. Badly formatted code is difficult to read. Badly formatted code is confusing the reader.

I once spent several days trying to find a problem in a very long module. The module was too long, but the tools we were using made it difficult to split a lot of the code out. There was a pre-processor to flesh out system / messaging calls, but only against certain modules. The module at fault had grown to something like 10,000 lines of code. I knew he problem was in there, but I didn't have a reliable way to make it fail in unit testing - where I could debug. We didn't have great unit tests, and it wasn't possible to debug during system testing (when it failed)

The module was a bit of an unreadable mess. The indentation was all over the place and there were dozens of variables scoped to the highest level of the module.

I told my boss about this, and asked for permissions to take a few days to tidy up the indentation and fix the scoping issues. He told me we didn't have time. We were close to releasing, and we couldn't make those sort of changes.

I went with my gut. I lied about what I was doing in progress meetings and went ahead and fixed the indentation and refactored to limit the scope of everything as much as possible. I think I actually got rid of all the variables global to the module (There were the equivalent to instance variables, which remained, but these were defined elsewhere). It took about 3 days.

When I came to test again, with something more readable, as loosely coupled and highly cohesive as i could make it, I tried to find the bug again. I had gone.

I've actually no idea where the bug was, or what the change was that fixed it. The likely problem is that a global variable was being set when a local one should have been set, and this was now impossible with the new scoping restrictions. But I never found out exactly where.

I told my boss I'd found and fixed the bug, and gave some bullshit response to explain it.

{ … }

I don't really like curly braces, but I appreciate this is a personal thing. I don't dislike them nearly as much as I used to. I do prefer a good solid beginend, but at least the braces are language independent ... that is if someone is programming in Italian, they work just as well.

What I really, really hate is this …

   if (x==y) {
      …
   }


simply because the block delimiters don't line up. A far better style is this…

   if (x==y)
   {
      …
   }


I've seen coding standards that do it the right way, but I don't recall ever seeing it written the right way in a coding book. People may argue the right way this wastes a line. Bollocks! For the sake of readbility, a bit of white space delineates blocks quite nicely. Where you don't need it is when the block is very short. For example, both

   if (fileIsOpen) {closeFile();}

and

   if (fileIsOpen)
      {closeFile();}


are fine.

Python doesn't have this problem. It's one of the main reasons I like it.

++

This is something I used to dislike about C-like languages. I used to think that such statements should always be explicit assignments…
x := x + 1 ;
…but I don't mind it these days. I'd prefer a function…
inc(x);
…but I don't have a problem with
x++;
any more.

Saturday 21 February 2009

'==' = '='; '=' = ':='.

Or: One of the things I hate about C

If you started out with a language that uses this syntax, you probably think I'm nuts. Well, you're wrong. Just because you're used to the convention doesn't mean the convention makes any fucking sense.

Q. What is "=" ?

It's a equals sign, right ? Remember it from mathematics ? It's a sort of point of. Everything on the left amounts to the same as everything on the right. So in a condition, we're testing whether two expressions equal, whether they balance. So for reasons I simply cannot fathom, C-like languages use "==".

I think it's like this simply because whoever first defined the syntax didn't want to refactor the work he'd already done. Or it didn't occur to them, because they had Aspergers Syndrome or something. One of the first things you want to do when defining a language, after you've declared a variable, is assign something to it. This probably comes before testing for equality. There's not much point testing for equality until you've got things to test. So the language developer thinks to himself : "I've allocated a variable to be used. How shall I assign something to my variable ?", and he comes up with this…
x = 10
…and there's nothing wrong with this. Yet.

A bit later, he thinks to himself : "I need to check the content of my variables", and he comes up with this…
if x = 10
…and there's a problem because '=' has already been used. The next question he asks himself is "What can I use instead ?", but this is a mistake. the question should be "Should I use '=' for assignment or equality ?", and the right answer is "Equality".

BASIC uses '=' for both. Assignment should be preceded by the 'Let' keyword, but because assignment and equality can be contextually detected by the interpreter, 'Let' is optional these days.

Algol-like languages use '=' correctly and have ":=" for assignment. This is what I prefer, but anything except '=' would be fine. Just a ':' would probably do (but that might be better used elsewhere!).

Java (how and why I got started)

I'm a tester now, but I'm the only tester on the team with any programming knowledge. I've written some nice VBA to make our testing easier, but we were looking to migrate from using Excel to write and record manual test scripts to a proper dedicated testing tool.

The proper tool didn't report stuff in the way we wanted. It also didn't have an easy way to migrate our Excel scripts. Fortunately it did have an API that would allow us to access the metrics in the way that we needed and be able to take a lot of the drudgery out of migrating the scripts.

So I got stuck in. My first choice was Python. There were some examples on the vendor's website. I gave up fairly quickly though. The API was provided as a WSDL XML file, but the Python based WSDL gubbins just didn't work. I briefly looked at hand coding each message, but briefly was nought to know it would be too difficult / take too long.

Second choice was Java. I didn't have a budget for Visual Studio, and all the developers where I work use Eclipse anyway, so I figure I could get some help. In the end I didn't need their help, though I did get some pointers via email from a friend. By far the best help was from some online video tutorials. That got me up to speed pretty quickly.

Java (what I used to think)

There are things I hate about Java. Most of the things I hate aren't really Java problems at all. They're C. Some of them are in Python too. The languages I'd used - Pascal, Modula-2, Jovial, Ada and Occam - predisposed me to hating the differences.

I'd periodically look at C and periodically walk away. C sucks. It sucks for two reasons. One is syntax that I dislike. The other is that it's way to easy to compile a piece of type-unsafe crap. All those security issues with buffer overflows are because of this sort of shit in C.

The thing that I hated about Java whenever I looked at it were the enumerated types: there weren't any.

Before Eclipse

OK, the tools I used when I was a programmer were these :

The OS (pretty much always VMS)
A scripting language (on VMS this is DCL)
A text editor (I used EVE almost exclusively)
A compiler
A linker
A debugger

Note that these things do not an IDE make. This was all command line based. This is the sequence I'd use to fix an error in a pascal program might be this ...

$ eve program.pas
make a change
save and exit

$ pasccal program.pas
get a compilation error

$ eve program.pas
make a change
save and exit

$ pasccal program.pas
get a compilation error

$ eve program.pas
make a change
save and exit

$ pasccal program.pas
get a compilation error

$ eve program.pas
make a change
save and exit

$ link program.pas

$ run program.exe
check results

$ run program.exe /debug
issue commands to display code viewer
find a line number
set breakpoint at line number
continue program execution

etc. etc. etc. Everything manual, a lot of time to complete each step. The editor and the code viewer in debug, for instance, were completely different tools. There was no pointing, so no tooltips, no clicking to set breakpoints, no selecting to evaluate expressions, no code completion.

So when I finally got around to using an IDE, Eclipse, last year, it was something of a revelation. I think Eclipse is superb. I'd briefly used Visual Studio on a C++ course somewhere around 2004, but then never got to use it again. And I hated C++, so I had no incentive to use it again. The benefit of the course was an intro to OOP, but at the time I still interpreted OOP in terms of Ada 83, which I'd used on OOD based projects.

I used Eclipse with Java.

First impressions of Python

I've used Python a little over the past year. I think it's superb. The loose typing and everything-as-an-object idea really works for a scripting language. The simplicity of using indentation to delineate blocks was a major appeal. It reminded me of Occam, which I used way back in 1992.

Coming from a real-time critical system background, loose-typing is a bit of an anathema, but I'm largely converted. Not for critical systems, where languages such as Ada should be used, but for general use, and scripting in particular, it rocks.

Introduction

I'll use this for stuff that will not fit into 140 characters. It's going to be general, probably a bit Apple-centric, but with things like simple programming tips here and there as I attempt to find my coding mojo again.

I'm also 'daycoder' on Twitter.

Why 'dayCoder' ?…

Well, as I've suggested, I lost my coding mojo. The short version is that eight years of VMS Pascal does that to a guy.