Naming functions for better readability
It’s a cliche but remains as true as ever… in software, naming things is hard!
For me the hard part is also what makes this so valuable and so worth our effort. The names we give things in our system can either help someone understand our code. At best they help the reader infer our intent. At worst they add a layer of indirection that masks what the code does or should do.
As a frequent reader of code (aren’t we all?), I know which one I prefer.
A recent exchange in our team proved to be a great example of this. Let’s take a look.
We have a saga that takes an action representing a record update, which triggers a multi-location update in Firebase. We store the record in its full form in a root node /articles
and also we have another location representing this entry in a timeline, eg. /timelines/articles
.
Our saga depends on many small functions that do one job. The one I want to focus on is the one that assembles the references for the multi-location update.
We have this calling code…
return database.ref().update({
[`articles/${key}`]: article,
...buildLocaleReferences({
allLocales: locales,
articleLocales,
key
})
})
Without going into the details of how the buildLocaleReferences function is implemented, it is enough to know that it returns an object representing the article in each of the locales’ timelines provided by articleLocales.
The intention of this function isn’t revealed by the localeReferences part of the name. It is generic enough to require the reader to dive into the function to figure out what references it returns.
Let’s have a go at renaming this to help the reader out.
return database.ref().update({
[`articles/${key}`]: article,
...timelineReferencesForLocales({
allLocales: locales,
articleLocales,
key
})
})
Ok, this is starting to look a little better. We can still improve on this though.
The call to the update function has logic that we could make more readable by naming. A const is a good place to start.
const articleRootReference = { [`articles/${key}`]: article }
const timelineReferences = timelineReferencesForLocales({
allLocales: locales,
articleLocales,
key
})return database.ref().update({
...articleRootReference,
...timelineReferences
})
It is not as terse now but hopefully you will agree that the extra lines contribute to being able to see at a glance which references we are passing to the update function without needing knowledge of what those references actually are.
Next time you name something in your code, consider how a future reader might interpret it and will it communicate enough to them for the current context.