George McIntosh

I do something...with software...

Taming Grails Frontend Code With Grunt Pt. 2

This post follows on from my previous post.

First of all, an apology. In my last post on the subject, I left you with a bug. Did you spot it?

The event hook put into _Events.groovy works just fine if you’re running the app; everything works as planned, and, more pertinently, exits when the app does. Not so if you run tests.

1
$ grails test-app

Leaves orphaned Grunt processes hanging around, clogging things up and - as we found - hammering your CI server. Let’s fix it:

Currently, our _Events.groovy looks something like this

eventCompileStart = { msg ->
    def process = "grunt".execute()
    process.comsumeProcessOutput(System.out, System.err)
}

Yeh, that leaks processes. Sorry. Easily solved, though, with a shutdown hook. Try this instead:

eventCompileStart = { msg ->
    final def process = "grunt".execute()
    process.comsumeProcessOutput(System.out, System.err)
    Thread shutdown = new Thread(
        new Runnable() {

           @Override
           void run() {
              process.destroy()
           }

        }
    )

    Runtime.runtime.addShutdownHook(shutdown)
}

There. Fixed it. Actually, I’m in two minds about using Grails event hooks for this sort of thing at all, but that’s for another time.

This post is now about Bower.

As I hinted at not being a massive fan of Grails plugins for everything. Don’t get me wrong, they’re often really wonderful things, that get you integrating something sexy into your Grails app with little fuss. The ElasticSearch plugin, for example, does a lot of heavy lifting for you. But sometimes, as with the sass compiler, they’re more hassle than they’re worth. It really makes no sense for the back-end of your app to dictate what front-end libraries you can use. So today I’m going to stop using the JQuery plugin, and start providing JQuery myself. And in the spirit of using front-end tools for front-end work, I’m going to manage that dependency with Bower. If you don’t know, Bower is a dependency management tool for webapps. It uses a manifest file to describe dependencies, and fetches them from repositories on demand. You know the drill.

Create a file called bower.json, that looks like this

{
  "name": "shiny-shiny",
  "version": "0.0.0",
  "homepage": "https://github.com/georgecodes/shiny-shiny",
  "authors": [
    "George McIntosh <george@georgecodes.com>"
  ],
  "license": "MIT",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ]
}

If you have Bower installed, you can now run

1
$ bower install jquery#1.9.1 --save

and JQuery will be fetched from ‘t’internet, bunged into a folder called bower_components and an entry will be created in bower.json to boot. Handy, eh? No, not really. Not yet, anyway. That’s ok, we’re going to use some Grunt magic to make this dependency available to our app at runtime.

Grunt is a bit like Maven. Except you don’t want to kill yourself within five minutes of using it. But it’s like Maven in that it all revolves around plugins. We’re going to use one to grab the goodies from our JQuery package, and provide it to our app, in a layout we like. We could just tell Bower to change the directory it downloads dependencies to, but Bower dependencies are not just the distribution, they come with a bunch of other stuff. Mostly because currently, Bower just grabs git repos. So we’re going to use a bit of config to achieve that. But first, we need the right package. Here’s where people sometimes get a bit confused. We’re actually dealing with two dependency management packages at once here: NPM and Bower. NPM is what we’re using to manage dependencies for our build system, and Bower is what we’re using to manage dependencies for the front-end of our app. Of course, we’re also using BuildConfig to manage dependencies for the back-end of the app, which makes for three different dependency management thingies. Maybe Maven isn’t so bad after all no no no, I never said that.

Anyways, we’re giving our grunt build system something to do, so we’re using NPM to declare these particular dependencies. Update your package.json so it looks like this

{
    "name": "shiny-shiny",
    "version": "0.0.1",
    "devDependencies": {
        "node-sass": "~0.7.0",
        "grunt": "~0.4.1",
        "grunt-sass": "~0.8.0",
        "grunt-contrib-watch": "~0.5.3",
          "grunt-bower-task": "git://github.com/georgecodes/grunt-bower-task.git#master"
    }   
}

Note that the most recent grunt-bower-task brings in an outdated, buggy version of grunt that’s annoying, so I’ve forked it and fixed it. I’ve issued a pull request, but at time of writing it hasn’t been accepted. Haha disregard that, it’s fixed. Or maybe NPM allows fine-grained control of transitive dependencies, like Maven does. I didn’t find anything about it, feel free to correct me.

Remember I said that Bower packages are just the entire Git repo? Well, we don’t want that, we just want the JQuery distribution. Bower packages can specify exports. They don’t have to. JQuery doesn’t. But we can configure them ourselves. Here’s what our bower.json looks like now:

{
  "name": "shiny-shiny",
  "version": "0.0.0",
  "homepage": "https://github.com/georgecodes/shiny-shiny",
  "authors": [
    "George McIntosh <george@georgecodes.com>"
  ],
  "license": "MIT",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
  "dependencies": {
    "jquery": "1.9.1"
  },
    "exportsOverride": {
      "jquery": {
          "js": "jquery.js"
      }
    }
}

We’ve said “just give us the distro, thanks”.

So now we can introduce our grunt config.

module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        sass: {
            dist: {
                options: {
                    outputStyle: 'compressed'
                },
                files: {
                    'web-app/css/main.css': 'grails-app/assets/stylesheets/scss/main.scss'
                }
            }
        },

        watch: {
            grunt: { files: ['Gruntfile.js'] },

            sass: {
                files: 'grails-app/assets/stylesheets/scss/**/*.scss',
                tasks: ['sass']
            }
        },
        bower: {
            install: {
                options: {
                    cleanTargetDir: true,
                    cleanBowerDir: true,
                    targetDir: 'web-app/js/lib',
                    layout: function(type, component) {
                        return '';
                    }
                }
            }
        }
    });

    grunt.loadNpmTasks('grunt-sass');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-bower-task');

    grunt.registerTask('build', ['sass']);
    grunt.registerTask('bootstrap', ['bower:install']);
    grunt.registerTask('default', ['build','watch']);
}

We’ve added a bower task, and we’ve configured it to export the distribution to our grails app. That ‘layout’ function we provide is just a hack to flatten the file structure out a bit. By default we’d have a bunch of extra folders that we don’t really want. We just want the library.

Now, if we run

1
$ grunt bootstrap

we see that grunt uses Bower to grap JQuery, and then stick the resultant library in our grails app’s web-app dir. It also does a bit of cleaning up after itself, removing the bower_components directory.

Ok, so now we can just declare JQuery like any other resource. Let’s do that. First, free yourself from the chains of the JQuery plugin; delete it from BuildConfig.groovy. Now declare a jquery lib in ApplicationResources.groovy

modules = {

    jquery {
        resource url: 'js/lib/jquery.js'
    }

}

and put

<r:require module="jquery"/>

somewhere in your GSPs. You know the drill. Now, fire up the app, and you’re serving up your own, dependency-managed JQuery. Hooray! A bit of refactoring of the gruntfile. and we can delete grails-app/assets altogether.

module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        sass: {
            dist: {
                options: {
                    outputStyle: 'compressed'
                },
                files: {
                    'web-app/css/main.css': 'web-app/scss/main.scss'
                }
            }
        },

        watch: {
            grunt: { files: ['Gruntfile.js'] },

            sass: {
                files: 'web-app/scss/**/*.scss',
                tasks: ['sass']
            }
        },
        bower: {
            install: {
                options: {
                    cleanTargetDir: true,
                    cleanBowerDir: true,
                    targetDir: 'web-app/js/lib',
                    layout: function(type, component) {
                        return '';
                    }
                }
            }
        }
    });

    grunt.loadNpmTasks('grunt-sass');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-bower-task');

    grunt.registerTask('build', ['sass']);
    grunt.registerTask('bootstrap', ['bower:install']);
    grunt.registerTask('default', ['build','watch']);
}

So our current workflow is to use

1
$ grunt bootstrap

To fetch and avail JQuery to our app, and to just grails run-app to compile and serve Sassy scss. There are, of course, a number of ways of simplifying this, but that’s for another time. All that remains is to add a few things to our .gitignore, and we’re away. We don’t really want to check in any generated or otherwise managed code, y’see:

target
shiny-shiny.iml
node_modules
web-app/js/lib
web-app/css/**

Code for this post is, as always, on GitHub.

Taming Your Grails Front-end Code With Grunt Pt. 1

So I’m once again working on a Grails project, and as usual, we’re using yet another new method for pre-processing and packaging CSS etc. First Grails gig I was on, we used the JAWR plugin. Next time round, everything had moved on and we were all using the Resources plugin. Now everybody’s decided that’s not good enough, and it’s now all about the asset pipeline plugin. Additionally, I work with SASS, and the asset pipeline plugin for Grails that compiles SASS is an absolute abomination. Booting up JRuby and installing/running gems to compile the Sass? Please! How much more complexity do we need to turn a text file from one format to another, and make it squishy? To say nothing of the fact that it randomly just stops working now and again, with lovely JRuby-flavoured stacktraces.

Enough is enough. There are some awesome front-end tools around, and I’m going to use them. Specifcally, I’m going to use Grunt to compile my SASS.

Let’s start with a shiny new Grails app:

1
2
3
$ grails create-app shiny-shiny
$ cd shiny-shiny
$ grails run-app

Nice. The usual default Grails stuff. First thing’s first, I’ll clean all that cruft out, and put a nice simple front page, with no styling in. Then we’ll add some Sass. I’ll just bung a simple background colour change in for now:

1
$ mkdir -p grails-app/assets/stylesheets/scss && echo "html { background-color: #fff; }" >> grails-app/assets/stylesheets/scss/main.scss

Now delete any CSS files you have in the web-app. Ok, now we have to compile this Sass to CSS, so it gets served up. We’re going to us Grunt. If you haven’t used Grunt, it’s worth a look at some point. In order for this stuff to work you ideally need the grunt-cli installed.

1
$ npm install -g grunt-cli

Now put this in a file called package.json at the root of your project:

{
  "name": "shiny-shiny",
  "version": "0.0.1",
  "devDependencies": {
    "node-sass": "~0.7.0",
    "grunt": "~0.4.1",
    "grunt-sass": "~0.8.0"
  } 
}

and run

1
$ npm install

You now have a localised grunt installation. Now create a Gruntfile.js in the root of your project:

module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        sass: {
            dist: {
                options: {
                    outputStyle: 'compressed'
                },
                files: {
                    'web-app/css/main.css': 'grails-app/assets/stylesheets/scss/main.scss'
                }
            }
        }
    });

    grunt.loadNpmTasks('grunt-sass');

     grunt.registerTask('build', ['sass']);
     grunt.registerTask('default', ['build']);
}

If you now run

1
$ grunt sass

from the command line, you’ll find a generated css file at web-app/css/main.css

Run the app now, and you should see your new styles being applied. All well and good, but that’s a static file. What we really want, is to have the Sass recompiled on the fly. Luckily, grunt can do that for you. Add grunt-contrib-watch as a new dependency to the package.json:

{
  "name": "shiny-shiny",
  "version": "0.0.1",
  "devDependencies": {
    "node-sass": "~0.7.0",
    "grunt": "~0.4.1",
    "grunt-contrib-watch": "~0.5.3",
    "grunt-sass": "~0.8.0"
  }    
}

run

1
$ grunt install

and configure it in your Gruntfile

module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        sass: {
            dist: {
                options: {
                    outputStyle: 'compressed'
                },
                files: {
                    'web-app/css/main.css': 'grails-app/assets/stylesheets/scss/main.scss'
                }
            }
        },

        watch: {
            grunt: { files: ['Gruntfile.js'] },

            sass: {
                files: 'grails-app/assets/stylesheets/scss/**/*.scss',
                tasks: ['sass']
            }
        }
    });

    grunt.loadNpmTasks('grunt-sass');
    grunt.loadNpmTasks('grunt-contrib-watch');

    grunt.registerTask('build', ['sass']);
    grunt.registerTask('default', ['build','watch']);
}

Now, run your Grails app from one window, and run grunt from another

1
$ grunt

You’ll find that making changes to your source scss files get re-compiled and reflected in your running app quite nicely. With the out-of-the-box resources plugin.

Lovely. Shame I have to have two windows open, really. Luckily, Grails events to the rescue. If you don’t already have one, create an _Events script in your local scripts directory, and add this

eventCompileStart = { msg ->
    def process = "grunt".execute()
    process.consumeProcessOutput(System.out, System.err)
}

This will run your grunt watch task in-process with your grails run-app, keeping everything nice and neat in one window. No more messy plugins to keep track of, just use the standard resources plugin. No random JRuby exceptions, no being tied to whatever version of the Sass gems the plugin authors are up to, and if you have a front-end dev on the team, he’ll be happy you’re using tools familiar to him.

At this point, if you use git, it’s worth adding node_modules to .gitignore, and strictly speaking, the compiled CSS shouldn’t be checked in either. We haven’t touched on distributing the compiled CSS either, or dealing with Javascript in any way. Keep an eye out for future posts.

All the code for this post can be found on my GitHub.

JoAnn

Writing some tests recently, as is often the case, I found myself reaching for Joda Time. This library, as most Java devs know, is less painful to deal with than the date utilities that the JDK ships with. The other neat thing about it is, you can set the system time - well, Joda’s view of it - to whatever you want. Very handy for testing code that might at some point create dates.

Anyways, a typical way of using Joda time in a test looks something like this

class TestSomething {

    @Test
    void testthings() {

        DateTimeUtils.setCurrentMillisFixed(1385554748577L)

        // do some things

    }

    @After
    void reset() {

        DateTimeutils.setCurrentMillisSystem()

    }

}

A few things wrong here. First, it’s tedious having to work in milliseconds. Second it’s not especially legible, and thirdly you have to remember to reset the time to the real time in a teardown method in case your test fails.

So I came up with JoAnn, which makes things a bit simpler. JoAnn is so called because it’s a Joda Annotation. It looks a bit like this

@Test
@Joda(1385554748577L)
void testthings() {
    // do some things
}

That’s (almost) it. No time fiddling bleeding into your tests, no need to remember to tear it down. Just the annotation. Oh, and a way of getting it invoked. You can use either a JUnit runner, or a JUnit rule, it makes no difference. I’ve provided both

With a rule

class MyTests {

  @Rule public JodaRule rule = new JodaRule()

}

With a runner

@RunWith(JodaAwareJUnit4Runner)
class MyTests {

}

It gets even less tedious.

You don’t have to use milliseconds to set the time. Set a timestamp instead, and JoAnn will assume you meant an ISO8601 format

@Test
@Joda(timestamp = "2013-11-29T10:13:22.192Z")
void testTheThings() {}

Or there are a few more out of the box:

@Test
@Joda(timestamp = '2013-12-25', format = Format.YYYYMMDD)
void testMoreStuff() {}

@Test
@Joda(timestamp = '2012-11-19 13:03:22', format = Format.YYYYMMDD_HHMMSS)
void keepOnTesting() {}

Want to see the code? It’s on GitHub

Want to use it in a Maven project? I’m hosting it myself for now:

<dependencies>
  <dependency>
        <groupId>com.elevenware</groupId>
        <artifactId>joann</artifactId>
        <version>1.0</version>
        <scope>test</scope>
    </dependency>
</dependencies>

<repositories>
    <repository>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
        <id>elevenware-releases</id>
        <url>http://maven.elevenware.com/repo/releases</url>
    </repository>
</repositories>

Enjoy.

VCR and Aruba

I’m working on a few little command-line utilities at the moment, written in Ruby. They all use a web service somewhere along the way. This raised an interesting question: How do I test these things?

Obviously, when testing individual components, I can use something like the excellent VCR library. And for testing the CLI, I’m using Cucumber and Aruba. As a bit of background, Aruba extends Cucumber by letting you invoke console commands, and capture the stdout for matching in your feature files. This presented a small problem. VCR works by hooking itself into your HTTP library at a really low level, but Aruba launches my gem in a whole new process, which won’t be under the control of my test code.

tl;dr VCR can’t magically hook into classes of a separate Ruby process.

Luckily, Aruba has a trick up its sleeve. If the thing you’re testing is written in Ruby, it can be launched in-process, which means my VCR config would work! It’s actually pretty straight-forward. Let’s write a simple Thor app that fetches random advice, tested by Aruba and VCR.

The full source for this exercise is on Github.

The setup is simple enough. Use Bundler to create your new gem:

1
$ bundle gem advice

Then add Thor, VCR, WebMock, Cucumber and Aruba to your dependencies by adding this to your gemspec file:

1
2
3
4
5
  spec.add_development_dependency "vcr"
  spec.add_development_dependency "webmock"
  spec.add_development_dependency "cucumber"
  spec.add_development_dependency "aruba"
  spec.add_dependency "thor"

And create the basic Cucumber/VCR layout:

1
$ mkdir -p features/support

Now we write our feature:

1
2
3
4
5
6
7
8
9
10
11
Feature: The advice CLI
  In order to get some random advice
  As a CLI user
  I want to request advice

  Scenario: get some advice
    When I run `advice please`
    Then the output should contain:
     """
      some advice
     """  

Run Cucumber (using Bundler)

1
$ bundle exec cucumber

Missing steps, of course! So now we do our environment setup. Create a file called ‘features/support/env.rb’ that looks like this:

1
require 'aruba/cucumber'

And run bundle exec cucumber again. Now we’re getting somewhere. Your test can’t actually find anything to run. So let’s create it. Create ‘bin/advice’ with the following content.

1
2
3
#!/usr/bin/env ruby
require 'advice'
Advice::CLI.start(ARGV)

Now create the actual CLI class in ‘lib/advice/cli.rb’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
require 'thor'
require 'open-uri'
require 'json'

module Advice
  class CLI < Thor

    desc "please", "fetches random advice from the Internet"
    def please
     the_advice = JSON.parse( open('http://api.adviceslip.com/advice').string)
     puts the_advice['slip']['advice']
    end

  end
end

Now we have a failing test. Problem is, it will always fail, because we get a random different result every time. So let’s introduce VCR. Edit your env.rb file to look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
require 'aruba/cucumber'
require 'vcr'
require 'webmock'

VCR.cucumber_tags do |t|
  t.tag  '@vcr', :use_scenario_name => true
end

VCR.configure do |c|
  c.hook_into :webmock
  c.cassette_library_dir     = 'features/cassettes'
  c.default_cassette_options = { :record => :new_episodes }
end

And add some support for VCR in our feature, by adding the @vcr tag:

1
2
3
4
5
6
7
8
9
10
11
12
Feature: The advice CLI
  In order to get some random advice
  As a CLI user
  I want to request advice

  @vcr
  Scenario: get some advice
    When I run `advice please`
    Then the output should contain:
     """
      some advice
     """

What we’re doing in the env.rb file, is configuring VCR to detect when the feature has the @vcr tag, and use the feature name as a cassette name. If you’re unfamiliar with VCR, it records HTTP responses in YAML files called ‘cassettes’ (it can use other formats, but this isn’t a VCR tutorial so I’ll not go into that).

If we were to run Cucumber now, it’s fairly reasonable to expect the fetched web response to be recorded. But of course, it won’t, because VCR is hooking into the HTTP library in the Ruby process that’s running our tests, but the web calls are being made in a process spawned by Aruba. Go ahead and run it, nothing gets captured.

This is where our magic comes in. Add the following to the top of your env.rb:

1
require 'advice'

then add

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class VcrFriendlyMain
  def initialize(argv, stdin, stdout, stderr, kernel)
    @argv, @stdin, @stdout, @stderr, @kernel = argv, stdin, stdout, stderr, kernel
  end

  def execute!
    $stdin = @stdin
    $stdout = @stdout
    Advice::CLI.start(@argv)
  end
end

Before('@vcr') do
  Aruba::InProcess.main_class = VcrFriendlyMain
  Aruba.process = Aruba::InProcess
end

After('@vcr') do
  Aruba.process = Aruba::SpawnProcess
  VCR.eject_cassette
  $stdin = STDIN
  $stdout = STDOUT
end

to the bottom.

What we’re doing here is, telling Aruba to spawn our custom class above, which we use to bootstrap our Advice CLI. The contents of our binary launcher have been duplicated here, which is a mild annoyance, but that should be doing virtually nothing anyway. We hook up the Aruba-provided stdin and stdout, and we’re good to go. Our test will fail for the very last time. Obviously, we need to know what it is we’ve captured. So in your feature, replace “some advice” with whatever was actually returned last time. In my case, “Don’t be afraid to ask questions.”

There. Every time you run Cucumber, the client will behave exactly as in production, except the web call is intercepted, and the same response is given, keeping your tests reliable.

Have fun!

What’s My Job, Again?

For years now, it’s been an in-joke amongst my friends – few of whom work in IT in any way at all – that my job is to “fix computers”. It all started back when I was a software engineer for an EFT vendor, and was on a 24 hour support rota. One of my friends assumed that, when the pager – remember them? – went off, it was so that I could slide away and fix someone’s computer. Why? Because she had very little idea what I actually did, even though she knew my job title.

Similarly, my parents never really grokked what I do, either. At one point my father asked “so you make up your own programs?” having mildly grasped that there was even such a thing as a ‘program’ not long before. “Well, not exactly my own, but yes” was the best I could do. According to my girlfriend, I “work with that complete gobbledegook that makes no sense”; inf fact, I’m reliably informed, when anyone else asks her what I do for a living, the reply is along the lines of “he puts a load of gobbledegook on a screen”.

The point of this post is not, however, to ridicule civilians for not understanding the software lifecycle, or anything else. It’s not to ridicule them at all.

It’s because I, too, struggle to actually define what I do these days.

This is a brand new blog, to replace my most recent attempt at blogging, which was – and this is pertinent – called George Codes. There are two reasons I’m moving away from that. The first is quite pragmatic: up until very recently, the domain name georgemcintosh.com has been selfishly hogged by some American heating company or something, and I’ve been unable to get my paws on it. By chance, I checked recently, and it was available, finally, so vanity won out, and I grabbed it.

The other reason is, I’m not sure “George codes” really adequately captures what I do any more. I mean, I do still write code, but I noticed a while back that, whenever anyone asked me the inevitable “so what do you do for a living?”, my answer stopped starting with the words “I am a” and began starting with a vague description of what I do. “I build software”, or “Oh, I build web apps”, or something else. Which is true. I do that. But I do a lot of other things, too. I just don’t think “coder”, or “developer”, or “programmer” or any other word that means “writes source code”, cut the mustard any more.

I am not my stack, dammit

I’ve never been a fan of being described as a “ developer”. Whether that something is a language – I hate being described by recruiters as a “Java developer”, especially since I haven’t written a line of Java in over 2 years – or a framework – some might currently say I’m a “Grails developer” – or even an entire field, such as “web developer”, the term always seems to do me a dis-service. I am not my stack. I am not pigeon-holed that way. I’ll give anything a go. This is a WordPress blog, using a theme I’m evolving myself. My [company website[(http://elevenware.com) is build on Sinatra, and I have a spattering of Grails and Rails apps kicking around the Internet. It’s irrelevant. I’ve also written a bunch of messaging apps, and rich client apps, and all sorts of things, in ‘C’, Java, C#, whatever. None of them define me.

So I have long disliked being called a “ developer” because “something” can mean so many different things. Now, I don’t like the developer bit, either. It’s not what I do any more. Here are some examples of things I do in my day job, which do not make me a developer, are not necessarily required in order to be called a developer, and which are also done by people who definitely are not developers:

  • Provision servers
  • Build continuous integration environments
  • Script single-click deploys
  • Coach developers on how to code
  • Advise clients on their software architecture
  • Advise clients on better approaches to requirements capture
  • Help clients choose technology stacks for the right reasons
  • Define development processes
  • Challenge designs that seem inadequate or wrong
  • Ask clients questions that lead them to figure out that they meant something other than they first thought they did

Many will argue that some or all of the above is actually still within the remit of the developer. That doesn’t change the fact that when civilians hear the word “developer”, none of the above leap to mind. All that leaps to mind is “he writes gobbledegook on a screen, and makes a computer do something”.

So what do I do? I have no idea. I do something…with software…

I can write software. I can help others write it. I can take it from being an idea, to the inkling of a plan, to being source code, to being a tested, deployed artefact. I can decide what sort of platform to build it on. I can often build those platforms, in nice efficient, repeatable ways. I can script. I can automate stuff. I can motivate people. I can test stuff, I can even write automated tests. I can spot when a practice is worth doing, and when it might not be, after all.

I can’t define what I do in simple terms, but that’s ok. I’m betting that most people can’t, if they try hard enough not to.