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.

 

Comments

Popular posts from this blog

Simple code: Immutability

Immutability is a special thing that in my mind deserves a short explanation and praise. If you're familiar with functional programming you surely recognice the concept of immutability because it's a key ingredient of the paradigm. In the world of object oriented programming it's not as used and as easy to use approach but there are ways to incorporate immutability to parts of the code and I strongly suggest you to do so. Quick intro to immutablity The basic idea of immutability is unchangeable data.  Lets take a example. We have a need to modify a object's property but because the object is immutable we can't just change value but instead we make a copy of the object and while making the copy we provide the new value for the copy. In code it looks something like this. val pencil = Product(name = "Pencil", category = "Office supply") val blackMarker = pencil.copy(name = "Black marker") The same idea can be applied in functions and metho

Simple code: Readability

Readability, understandability, two key incredients of great code. Easier said than done, right? What one person finds easy to read and understand another one finds incomprehensible. This is especially true when programmers have different levels of understanding on various subjects e.g. object oriented vs. functional or Node.js vs. Java. Even though there are obvious differences between paradigms and programming ecosystems there are some common conventions and ways to lower the barrier. Different approaches It's natural that in programming things happen sequentally e.g. you can have a list of objects and you need to do various things to the list like filter some values out and count a sum of the remaining objects based on some property. With the given list const stories = [   {name: "authentication", points: 43},   {name: "profile page", points: 11},   {name: "shopping cart", points: 24},   {name: "shopping history", points: 15},   {name: &qu

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", &q