Skip to main content

Simple code: Naming things

There are two hard things in programming and naming is one them. If you don't believe me ask Martin Fowler https://www.martinfowler.com/bliki/TwoHardThings.html.

In this post I'll be covering some general conventions for naming things to improve readability and understandabilty of the code.

There are lots of things that need a name in programming. Starting from higher abstractions to lower we need to name a project, API or library, we probably need to name the source code repository, when we get to the code we need to name our modules or packages, we give names to classes, objects, interfaces and in those we name our functions or methods and within those we name our variables. Overall a lot of things to name.

TLDR; Basic rule

There's a single basic convention to follow to achiveve better, more descriptive naming of things. Give it a meaningful name i.e. don't use shorthands like gen or single letter variables like a, x, z instead tell what it represents, what it does e.g. generateRandomDate, book, books or findBookByISBN, MongoDBBookRepository.

Variables

Let's start from the lowest abstraction, variables. There's the usual suspects a, b, i, j, x, y that are good names in the right context but generally really bad variable names. The next level contains names like entry, datum, date that are probably ok names within a closed context e.g. a anonymous function or a loop but outside of it probably not so good. Then there are the better names like shoppingCartItem, transactionDetails, creationTimestamp.

There are situations where generally bad variable names are good e.g. when operating in a coordinate system variables x, y and z make perfect sense and should be used. Or i as the array index of a loop or x and xs presenting the head and tail of a collection. These are common conventions that developers recognize and understand.

Functions and methods

Variables are inside functions so let's name a few functions. Same namings as with variables also apply here. Not so good names contain things like do, genRndD. These two could be named e.g. sendEmail and generateRandomDate.

Words are meaningful when naming functions e.g. findEntity vs. getEntity. Find implies that it tries to find something whereas get implies that something that always exists is retrieved. Find can return a entity, null, optional with value or empty etc. and get should always return the requested entity or fail miserably.

Things that functions live in

Classes, objects and interfaces also have the same rules as things inside them. Common naming strategy in the Java world has been to name a interface e.g. BookRepository and the implementing class as BookRepositoryImpl when a better name could be e.g. MongoDBBookRepository. With this type of naming the implementing class has a name that is self descriptive and it tells exactly what database it's implemented for.

Packages and modules

Packages and modules are used to separate things from each other and on the other hand as a way to group things that are related to each other. In a application one could have a package named net.polarcoder.myapp.db or net.polarcoder.myapp.persistence the two have the same meaning (at least in my head) and either is a good choise as long as only one of them is used not both and as long as the package contains only database related things.

The harder choise with packages comes with things that could be placed in any of several packages e.g. a database configuration object could be placed in the database package or it could be placed to a configuration package. Either one being a valid choise a team/project/company/community/language convention should be a guiding rule. Personally I would place it in the database package because it's database related.

Naming in tests

One common pattern I've seen over the years is that naming in tests is not considered at all. Even in situations where a codebase has a good, consistent naming in tests the naming is everything but. In my opinion naming in tests should be done with as much care as in the production code. What's more annoying than a failing test that's written with a poor naming and you have to figure out what's it doing and why it's
failing?


Pay attention to naming in tests. It's just as important because those tests are also meant to be read by another person.

Next part

In the next part I'll be tying this subject to another important aspect, readability.

 

Popular posts from this blog

DIY home automation, new generation

I've had my DIY home automation system for controlling outlets and reading sensor data running for about two years now. The system has been working fine and I haven't had any need to touch the code since I added the sensor reading to it, until a few months back. Need for new functionality Few months ago I got a new IoT toy for a lend from a friend until I'd get my own toys, a ruuvitag sensor beacon. Ever since I found the ruuvitag for the first time from kickstarter I had the idea of getting a bunch of ruuvitags and adding their weather station sensor readings as part of my home automation system. The original home automation backend included only tellstick compatible devices and was written in Python, and in my mind it was kind of a hack. The ruuvitag beacons communicate via BLE i.e. Bluetooth Low Energy and that meant that I needed to add functionality to read the beacon data via bluetooth. I found a ruuvitag Python library and initially thought that I'd just...

Simple code: Unit tests

Unit tests are the developers number one safety net. Let that sink in. This is the number one reason for writing unit tests. Unit tests are written by developers for developers to ensure that the code works as expected and handles happy and sad paths correctly. With enough unit test coverage the tests enable a safe environment for refactoring and rewriting code. Unit test scope Unit test should test a single thing, a method or function call and it should test only one use case within. In other words a unit test should test a function with a single input. This is a important guideline to understand. When a unit test tests a function with single input it makes the test isolated, repeatable and predictable. Example of good tests: @Test fun findsAddress() {   val address = findAddress("Stevens street 35", "Southport", "Australia")   assertThat(address).isNotNull() } @Test fun doesNotFindAddress() {   val address = findAddress("Stevens street 697", ...