diary @ telent

TDD, BDD, executable specification#

Thu Apr 7 14:26:57 2011

Topics: ruby

The new system at $WORK finally went live about a week ago, hurrah.

The upgrade itself took a few hours longer than I'd have liked, and (short shameful confession time), some (but probably not all) of this could have been caught by better test coverage. Which set me on a path towards SimpleCov (I'm using Ruby 1.9, rcov doesn't work), which led me to start looking at the uncovered parts, which set me to thinking. Which, as we all know, is dangerous.

TDD advocates (and pro-testing people in general) say "Don't test accessors". There are two reasons to say this that seem to my mind like good reasons: Ron says it because he wants you to write tests that do something else (something useful) that happens to involve calling those accessors. J B Rainsberger says it because "get/set methods just can't break, and if they can't break, then why test them?"

The problem comes when you adopt the mindset typified by BDD that "the test examples are actually your executable specification", because in that case how do you specify that the object has an accessor? This is not an unreasonable demand. Suppose we have objects whose purpose is to store structured data that will be used by client code - for example, User has an age property. Jbrains - which must surely be the Best Nickname Ever for a Java guy - says there's no useful test you can write for this (or not unless you don't trust your platform or something, but that way madness lies). But even if we are going to write one: a test that stores one or a few example values can easily be faked by the bloody-minded implementor ("the setter is called with the argument 42, then the getter is called and should return 42? I know! def age; 42; end") and a test that stores all possible values and tests they can be retrieved will take forever to write/read/run. Really the best notation in which to specify the behaviour of that property is the same notation which, when run by the interpreter, will implement the said behavior -

    attr_accessor :age
It's not just accessors either. Everything on the continuum between declarations of constants (SECONDS_PER_DAY=86400, are you really going to write a test for that?) and simple mathematical formulae
    class Triangle
      def area
        self.base * self.height / 2.0
      end
    end
are most readably expressed to humans as, well, the continuous functions that they are, not the three or four example data points that we might write examples to test for. For any finite number of test cases, you can write a giant case...when statement that passes all of them and still doesn't work in the general case.

Yes, we could and often should write a couple of tests just to make sure we haven't done anything boneheaded in implementing the function, but they're not spec. They're just examples.

But here's the rub: where or how do we put that code to make it obvious that it's specification that happens also to be a valid implementation - and not just implementation that may or may not meet a spec expressed in some other place/form? If we're laying out our app in conventional Ruby style, it can't go in the spec/ directory because that doesn't actually get run as part of the application, and it shouldn't go in lib/ or models/ or wherever else unless we are prepared to make our clients rootle through all that code looking for whatever "this is specification not just an implementation detail" flag we decide to adopt) when they want to use our interface.

I'm going to make a suggestion which is either radical or bone-headed: we should smush the rspec-stuff together with the app code: embed examples (which may in some cases be specification and in other cases be "smoke tests") in the same files as the implementation (which may itself sometimes be specification and other times be the result of our fallible human attempts to derive implementation from spec), and then we can have some kind of annotations to say which is which, and then we can have some kind of rdoc-on-'roids literate programming tool (To Be Implemented) go through the whole lot and produce two separate documents. One for people who want to use our code and want to know what it should do, and the other for the people who have to hack on it and need to know how it does. Or doesn't. And then maybe we can have code coverage metrics that actually mean something.

What I miss most about Lisp#

Sat Apr 30 22:23:33 2011

Topics: lisp

It's been three months since I wrote anything longer than one line in Lisp, and over a year since I wrote more than a screenful of the stuff.

What I miss most is not CLOS or the REPL or even macros (per se, anyway). It's

And maybe the REPL (although irb does most of that). And kinda sorta Defsystem, but I seem to be in the process of reimplementing that ...

But I hope soon to get Rubinius installed, just because I still have the irrational opinion that a grown-up programming language ought to be able to implement itself (and I have a thing for native code) so project 1 there is to see if I can hack the backtrace thingy at least into it.

I did it my way#

Sun May 1 10:50:35 2011

Topics: lua ruby
telent_net 63709899460321280 short unoriginal observation on ruby blogging engines: quicker to write your own than evaluate all the other poorly documented ones telent_net 63710033904549888 ... this observation only holds if you skimp on the documentation of course. which is where we came in

If you can see this, you can see my blog design all changed again. This time it's a Ruby Sinatra application (whence the name my-way running on thin-prefork which keeps the article texts in git and uses RedCloth plus some ugly regexps to turn them into HTML. The Markdown vs Textile decision is not an especially interesting one in the first place, but gets a lot easier still when you have something like 9 years worth of previous articles in Textile format.

Publishing is achieved by pushing to a git repository on the live machine (a Bytemark vm). A post-update hook in the remote repository is responsible for checking out the updated commit (git doesn't like pushing to non-bare repositories) and sending SIGHUP to the running instance of my-way which causes it to reindex files.

dan@bytemark:~$ cat /home/git/my-way.git/hooks/post-update        
#!/bin/sh
GIT_WORK_TREE=/home/dan/src/git/my-way git checkout -f
kill -1 `cat /tmp/my-way.pid`

The version of my-way on github lags the actual version slightly, because I need to separate the engine from the articles and from the config data (there are things like adsense subscriber id, flickr api keys, etc) before I push the latter to a public service. Will clean it up in the next few days.

And my apologies to RSS feed subscribers. I've finally dropped the /diary prefix on the URL for this blog, and the old RSS feed didn't use GUIDs and I'm too lazy to make the new one do so either, so the upshot is you just got the ten most recent articles in your feed again. Sorry.

Introducing Projectr#

Mon May 2 09:39:18 2011

Topics: asdf lisp ruby

Why might you want to know the names of all the files in your project? One might turn the question around and ask why would you possibly would not want to, but maybe that's not a constructive dialogue. So let's list some use cases

As far as I can see from my survey of the Ruby world, the current practices for each of these use cases are pretty ad hoc. Maybe you write a file full of require or require_relative statements (as the RBP blog author likes to do), maybe you use a glob, maybe you write a MANIFEST file, but there seems to be a significant lack of DRYness about it all. This led me to think there is a gap in the market for

  1. a language for describing the files that a project comprises
  2. some tools to interrogate a project description written in this form and find out what's in it
  3. some code to load them into a running interpreter - and for bonus points, when files have previously been loaded into said image but since changed on disk, to reload them. This could be used in irb sessions, or could form the basis of a development-oriented web server that reloads changed files without needing to be stopped and started all the time

Note that item 3 above gives us something that "file containing list of require statements" doesn't, because it allows us to reload files that we've already seen instead of just saying "meh, seen it already". If you're using a comparatively low-powered machine then reloading your entire app in irb every time you change a method definition is unnecessarily and obviously slow. If you're also using Bundler (which I rather like now i's settled down a bit, and will write more about in a future entry) then the additional bundle exec is not just slow, it's SLow with a capital S and a capital L and a pulsating ever-growing O that rules from the centre of the underworld.

Here's one I made earlier

Projectr::Project.new :test do
  # directories may be named by symbols or strings
  directory :example do
    #as may files
    file "file1"
    file :file2
    directory "subdir" do 
      file :subdir_file
    end
  end
end

h=Projectr::Project[:test] h.load! # it loads all the files

  1. and again h.load! # nothing happens this time
  2. touch example/file1.rb h.load! # loads only the changed file

At the time of writing this, the github version does about that much, but is quite clearly still version 0. Stuff I am still thinking about:

I will doubtless form my own opinions on all of these issues in time and with more experience of using this tool in practice, but feedback on them and on the general approach is warmly welcomed.

Fork, clone, spindle, mutilate