Hamish Rickerby

Technology Consultant & iOS Developer based in Sydney, Australia

Function Arguments

| Comments

In Clean Code it’s advocated that the ideal number of arguments for a function is 0. Then, 1, 2, and in very rare cases 3. No functions should take more than 3 arguments.

In general, I agree with this. Fewer function arguments = fewer separate parts to understand and should aid with readability (and understanding). There are a couple of complexities though that I’d like to run through here. One is levels of abstraction, and the other is testing.

Abstraction

When a function has 0 arguments, it can only do 3 things:

  1. It can call other functions
  2. It can access data (object state) from itself and return it.
  3. Nothing - if it doesn’t call other functions, or query object state, then why bother calling it?

A useful niladic function is effectively a wrapper for other code, providing a higher level of abstraction. For example, if we wanted to get a set of data from a report, in a particular format, we could call functions as below.

1
2
3
4
5
extract_report_variables_as_json()

# vs

extract_report_variables_from(a_report, FORMAT_JSON)

The niladic (0 argument) version reads nicely, and seems simple to understand on the surface. It also provides a higher level of abstraction than the function where you have to provide the report to extract the data from, and the format to return the data in. This (in my mind) is a double-edged sword. The extractReportVariablesAsJson() function completely hides where it gets data from, and how the formatting request is passed in (and potentially what other formatting options there might be).

1
2
def extract_report_variables_as_json(self):
    return extract_report_variables_from(self.report, FORMAT_JSON)

It’s also unclear if there are side effects from this. To figure this out, you need to delve down into the functions to bottom out what they’re all doing. For example, to generate the JSON format extract, it may write the data to disk, and this may cause exceptions due to disk space, or permissions problems. You could receive a seemingly unrelated error to the task you’re trying to perform due to side effects happening inside an abstracted function.

In the OO world, the general takeaway is that this is a perfect situation. The object provides abstract functions, and they hide the complextity of what is happening under the covers. The main issue I have with niladic functions is the tying of the function to particular state in the object, eg, in our example above the report used will always be self.report. To avoid this, the developer has to repeat the abstraction to generalise the functions, all the way down. The developer also has to consider what abstract, and what more detailed (generalised) functions their object might like to expose, and set appropriate access controls on these functions. For this to happen in reality requires a diligence and dedication on the side of the developer to their craft. They must continually strive for clean code - to wrap and abstract out functions. This is a good thing, but not something that’s always done by default.

Testing

Testing functions has (I believe) an interesting effort curve, depending on the number of arguments in the function, as well some more fundamental constructs of the language you’re developing in.

Niladic Functions

With niladic functions, you may have to perform more test setup around the function to be able to test it effectively. When a function takes no arguments, you have to setup the data elsewhere for it to operate on. If your function operates on the data it’s passed, then you only need to deal with that function to test it. I consider (in general) the test creation effort for niladic functions to be greater than for functions that take arguments.

Functions with 1+ arguments

I believe the easiest function to test is one with one argument. You can pass in the data you want the function to operate on, receive the result, and check it. This is also true for functions with more than one argument, but the problem with these is that the permutations of possible arguments explode. If you’re looking to exhaustively test out a function, then you need to multiply the possible values for each argument together. Lets say you have a function that takes a single boolean. This has 2 possible values you can pass in to it, so it is relatively simple to test exhaustively. If you have a function that takes 3 boolean arguments, then you have 8 possible permutations of the arguments (2 x 2 x 2). Things get crazy when we start looking an other data types such as String or Int. How many different values can you have for a String?

Typed Arguments

One other issue for consideration is if the language you’re using supports typed arguments. If it can, a function can define (and ideally enforce) the type of data it can accept. In languages that don’t support this, your function could receive data of a different type to what it was expecting.

1
2
3
format = "My Custom Format"
report_data = True
extract_report_variables_from(report_data, format)

To generate tests to exhaustively test this is virtually impossible. You won’t practically be able to create all the different permutations of options available.

How to solve?

I think there is a way to get a level of confidence in your functions that receive arguments via testing. Unit tests can provide expected, common scenarios that you want to test for to make sure that the function is behaving under normal scenarios. This should always be done.

If your function can support it (and your language has appropriate libraries), Property Based Testing can provide a level of confidence that your function can handle all other scenarios. I’m not going to go into it in depth here, but in general, you construct test specifications that will randomly generate test data and pass it to your function. They will repeat this over and over again a number of times, and determine if your function operates as expected in a wider number of scenarios that is humanly possible to code manually. This should give confidence that your function works correctly, even in the face of misuse.

A Small Functional Refactoring of Javascript

| Comments

I’m working on a web based productivity application at the moment, and have been modifying some old code. This code deals with synchronisation of data with external services, and storage of metadata about the synchronisation of that data. The application had quite a bit of duplication in dealing with this metadata; specifically in extracting data from the stored structures. In the interests of having very DRY Javascript, it was time to refactor.

The configuration/metadata structures typically look like

1
2
3
4
{
  ...
  config: [{ key: 'attribute-name', value: { value: 'attribute-value' }}],
}

Sidenote: value is embedded in value because the top-level value item actually receives an object to store, so other fields can be added in the future

The metadata object was then optionally attached to other user-entered data entities, and queried when updates that require synchronisation to be triggered.

1
2
3
4
5
6
const containerObject = {...
  config: [
      { key: 'itemId', value: { value: 12345 }}, 
      { key: 'itemState', value: { value: 'active' }}
    ],
};

The application was already using RamdaJS to extract data from these types of structures. To query, there was a whole bunch of duplicated code that traversed the containing objects, and extracted data. Example below.

1
2
3
4
5
6
// Extract config object, maybe.
const syncData = R.propOr({}, 'config')(containerObject);
// Find a structure with a specific key value
const itemSyncData = R.find(R.propEq('key', 'itemId'), syncData) || {};
// Extract the value from the entity with that key
const itemId = R.path(['value', 'value'], itemSyncData);

To DRY all this up, I looked at the possibility of using Currying and Partial Application to help me define generic extraction functions, and reuse them.

First of all, I turned the above into a composed function, with the results of one step flowing as the inputs to the next.

1
2
3
4
5
6
7
8
9
10
// compose reads from the bottom up, like you're feeding in the object from
// the end and it's consuming it, right to left.
const composedFunction = R.compose(
  R.path(['value', 'value'],
  R.find(R.propEq('key', 'itemId')),
  R.propOr({}, 'config')
); 

// How to use?
const itemId = composedFunction(containerObject);

However, this only supports config objects in the container, and itemId’s inside that. We can make this more generic.

1
2
3
4
5
6
7
8
9
const composedGenericFunction = (data, key) => R.compose(
  R.path(['value', 'value'],
  R.find(R.propEq('key', key)),
  R.propOr({}, data)
); 

// How to use?
const itemId = composedGenericFunction('config', 'itemId')(containerObject);
const itemState = composedGenericFunction('config', 'itemState')(containerObject);

Better because we get more reuse, but we still are repeating ourselves with the definition of the attribute that houses the config. So, lets make our function even more reusable with currying and partial application.

1
2
3
4
5
6
7
8
9
10
const composedGenericCurriedFunction = R.curry((data, key) => R.compose(
  R.path(['value', 'value'],
  R.find(R.propEq('key', key)),
  R.propOr({}, data)
)); 

// How to use?
const configGetter = composedGenericCurriedFunction('config'); // Partial Application
const itemId = configGetter('itemId')(containerObject);
const itemState = configGetter('itemState')(containerObject);

We can take this a step further with something like below, and generate a getter that will retrieve the itemId from different containerObjects.

1
2
3
const idGetter = configGetter('itemId');
const idOne = idGetter(containerObject);
const idTwo = idGetter(containerObjectTwo);

We can also extract fields from other objects that conform to the same structure, but aren’t under a config key.

1
const syncDataGetter = composedGenericCurriedFunction('syncData');

So, with the use of currying and partial application with Ramda, we can create generic, reusable functions that are then used to generate other functions that we can use in our application. Super easy and effective way to DRY out your javascript.

Meteor, Heroku, and Bcrypt

| Comments

Just had a very frustrating day. Was getting a deployment error on Heroku with a Meteor app I’m making.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Starting process with command `node build/bundle/main.js`
/app/build/bundle/programs/server/boot.js:324
}).run();
   ^
Error: Module did not self-register.
    at Module.require (module.js:365:17)
    at Module._compile (module.js:460:26)
    at Module.load (module.js:355:32)
    at Object.<anonymous> (/app/build/bundle/programs/server/npm/node_modules/meteor/npm-bcrypt/node_modules/bcrypt/bcrypt.js:3:35)
    at Error (native)
    at require (module.js:384:17)
    at Function.Module._load (module.js:310:12)
    at Object.Module._extensions..js (module.js:478:10)
    at bindings (/app/build/bundle/programs/server/npm/node_modules/meteor/npm-bcrypt/node_modules/bcrypt/node_modules/bindings/bindings.js:74:15)
    at Module.load (module.js:355:32)
Process exited with status 1
State changed from starting to crashed

I was using the build pack at https://github.com/srbartlett/heroku-buildpack-meteor due to its support for Meteor 1.3.

The issue seems to be that the npm-bcrypt atmosphere package doesn’t force a recompliation of the npm bcrypt package via node-gyp (I could be wrong here, but that’s what it seems like). It seems that the atmosphere package includes the wrong (or a fixed?) architecture, where as what we actually need is to recompile for the current target. To fix this, I’ve altered the buildpack to remove the bundled bcrypt package, reinstall from source, and copy back to the bundled location. The reinstall from source seems to force node-gyp to compile for the correct architecture.

My altered buildpack is available at https://github.com/rickerbh/heroku-buildpack-meteor if anyone wants it.

Back to Basics - Editors

| Comments

My boss bought me a copy of the seminal classic The Pragmatic Programmer. It’s full of sensible advice for both beginners and experienced software professionals.

I have lots of thoughts about the contents of this book but what I’d like to cover is usage of text editors, and specifically becoming proficient with a editor that’s typically universally available. I can think of 3 of these for UNIX systems. vi, emacs, and nano.

When I was at university I used emacs for all CS course text editing. In my first job, the UNIX servers we had didn’t have emacs installed. I wanted to install emacs, but the application vendor didn’t allow us to, as they had a support contract and hadn’t tested their application with emacs on the box, so no-dice. vi was it for a few years. Then, I just a stopped using these types of editors for about 11 years. The advent of IDEs (Eclipse, Xcode) meant I didn’t have to use these “basic” editors about had a lot of point-and-click, plugins, refactoring etc functionality available.

Until now.

The Pragmatic Programmer has convinced me to relearn basic (and powerful) UNIX tools, and I’m starting with emacs. In my job (at the moment) I typically do about 50-80% dev, the rest other stuff (sales, management, architecture, analysis). So I spend a fair amount of time in development environments. I’m not a big shortcut key user, and this needs to change - it’s just wasting time moving that mouse around to get to menu items and select text.

So far, I’ve started with base emacs installations, Haskell packages, git packages, Clojure packages, some convenience packages, and I’m about to start with some JavaScript packages. Also getting used to the keystrokes again is a bit tricky, but I’m getting there. To help out, I’ve moved other IDEs I use (like WebStorm) to use emacs bindings as well.

I’m enjoying the ability to use the same environment for text + 3 languages + code control. Super powerful.

If you’re interested in my setup, I have an emacs file in my dotfiles git repo. Check it out (ho ho ho).

If you have any tips for emacs please let me know in the comments or on Twitter - @rickerbh

Reading Not Reading

| Comments

I recently finished a book called Apprenticeship Patterns (more on why later) and one of the things it suggested is keeping an online list of books you read, and books you want to read. So here is mine.

http://hamishrickerby.com/books/

I’m going to add a few more books to the read list as well - ones I think other people may be interested in.

If you’ve got any recommendations please let me know in the comments or on Twitter - @rickerbh

Brief Update

| Comments

It’s been ages.

  • Completed that 1000km run goal
  • Sold a house
  • Wife got a new job
  • Sold another house
  • Moved to Sydney
  • Getting there with Haskell (thanks to Haskell Programming from First Principles - buy it - it’s great)
  • Bought a house
  • Feeling in a really good place professionally

Why I’ve Taken a Full Time Job

| Comments

I’ve relapsed. I swore I’d never do it again, but I have. I’ve accepted a full time job.

I’m not in it for the money

I’ve been running happtic for just over 2 years now, and it’s been quite lucrative. I’ve managed to get a small, but reliable base of repeat/ongoing direct clients, and developed some applications that have done very well. I’ve only taken on 2 non-direct contracts in that period, so am happy with how that’s worked out. Overall, I’d say the business has been successful in terms of providing my family with a relatively good income. Sure, having a stable income, holidays, superannuation etc will be great, but that’s not why I’ve taken the job.

It’s a growth and opportunity thing

The main issue I’ve been struggling with in running happtic is growth. I wanted to turn happtic into a larger business, providing technical consulting and development service with a team of 10 or so. I haven’t been able to get enough volume of projects/clients to warrant taking on any extra staff (apart from that time I hired a graduate/entry level developer, and he called in sick on his first day and never got in touch with me again).

I’ve learnt that there are things I’m good at, and things I’m not good at. I’m great at systems architecture, technical strategy, software design, and development. What I’m not good at is cold business development. Once someone is at the door, the conversion rate is high, but getting them to the door is hard for me to orchestrate.

Joining a larger organisation, with a pre-existing client base and sales team helps me meet my goals of leading a technology team, in a position of influence in an organisation. One key thing that I remember from a corporate management training course many years ago is that in companies (and in real life), the path to achieving a desired outcome may not be the path you expect. If you can recognize that the outcome is what you are after, there are many paths that can take you there, so you shouldn’t be precious about how you get the outcome, as long as you get that outcome. The outcome I’m after is to lead a technology focussed team of people, providing development, consulting, and technical strategy services, and that’s what this job is.

What’s the new job?

I’ll be working as “Director of Mobile” for Simple Machines. The job will involve setting up and leading a mobile development team, as well as an office, here in Melbourne.

One particularly exciting thing about the job is the split between client and product work. Simple Machines have clients, as well as their (our!) own products and investments in startups, so there will be varied work which is great. I find working on a single product can feel a bit stale after a while, so having a mix of client and product work will definitely help with that, but also provide the satisifaction you get from growing and evolving a system over time.

If you’re looking for any mobile app development (iOS, Android, WP, any platform) or development of complex, high performance, scalable applications, get in touch [email protected]

1000km - February

| Comments

Progress has been a bit slower this month. Short month, very hot here, and new baby all contributed to slowing progress down. Oh, in other news, we now have a baby! Exciting.

190km complete at end of Feb, which leaves me with a 30km buffer. The last graph was a little incorrect too - Numbers only puts dates correctly (in relative terms) on the x-axis if the graph type is a scatterplot. Dumb. The new graph below is correct.

1000km - January

| Comments

Progress on the 1000km is good so far. 109km run in Jan, and I’m sticking to the 10km distance per run. Weight is also starting to fall, which is great because I’m about 9kg heavier than I should be.

Because I’m also a nerd (and if you’re reading my blog, you probably are too), here’s a graph marking progress. Grey line is what I need to run to get to 1000km this year. Any blue higher than the grey line is kms in the bank for a rainy day.

Meteor

| Comments

A couple of days ago I received an email from meetup.com about meetups that I might be interested in. Usually this is full of crap I don’t care about, like mothers groups or salsa dancing, but this most recent mail featured an intriguing group called “Meteor Melbourne - a better way to build apps”. So, I looked into it.

Meteor is a framework based on node.js that allows you to write responsive, reactive, real-time web applications in javascript on both the client and server side. I’ve always considered javascript as a toy language - I think this opinion comes from my first interaction with JavaScript waaaaaay back in the late 90’s (I think it was somewhere between ‘96 and ‘98), when all it was really used for was alert boxes and tic-tac-toe implementations. However, I’ve recently been doing a lot of work for clients with Parse and their “cloud code” functionality, taking some logic out of mobile apps and running it on the Parse servers - and you use JavaScript to do this. They promoted use of Promises, and I’ve been doing a lot with RAC in iPhone apps, so this functional style is something I’m familiar with and like. I also have a friend who is helping a mate out on a startup, who is looking at some serious “enterprise” functionality implemented with server-side javascript, so I thought it was maybe time to seriously look at this thing too, and I checked it out.

Amazeballs. Meteor is MAGIC. Don’t believe me? Watch this screencast.

I think the magic for me comes from the real-time (well, super fast at least -> sub second synchronization) nature of the system, and the automate shuffling of data between the server and client to synchronize/update pages with no specific actions on the developers part. The built in support for packages is also really tidy, although having to use a 3rd party packages system (Meteorite and Atmosphere) for more modern versions of some of the core packages (eg, bootstrap-3 vs bootstrap-2) seems a little undesirable.

It’s super fast to get set up (1 line install, 1 line to start), and this includes server, database, sync between client and server. Want user authentication? Two more command line hits (1 for a UI, 1 for a login provider package), and 1 line to get the UI template built in. Amazingly productive.

Where I see huge potential for Meteor is in the mobile space. Having a web app, which automatically pushes changes to a mobile device is super powerful. With the current state of mobile apps you typically need to poll for changes to data, unless you build your own data sync solution or rely on something like iCloud to push changes around for you (haha, yeah right). When I’ve done this sort of thing in the past with Parse, I’ve actually gone as far as abusing the Apple Push Notification Service to actually trigger a mobile device to re-query a web service to retrieve new data as APNS is the only push mechanism available. Having a service that reliably notifies a client when data changes server side, with sub-second speed, solves a whole bunch of problems for app developers.

This is the tech stack that I’m now looking at using for my small business productivity tool, and I’m hoping that mobile sync works just as well (and fast) as the client-server sync does. Next up is a small proof of concept to test this out.

I haven’t been this excited about web development since I saw DHH’s web app in 15 mins rails screencast in 2006.

Oh yeah, I went to the meetup too. Nice job meetup.com