We're planting a tree for every job application! Click here to learn more

Thoughts about naming variables and methods

Isaak Uchakaev

7 Jul 2021

•

4 min read

Thoughts about naming variables and methods
  • Python 3

The proper naming of variables, functions, methods, and classes is one of the most important attributes of elegant and clean code, that clearly reflects the intentions of the programmer, without assumptions about what was meant.

In this article, we will talk about code that is the exact opposite of the one described above - about code that was written carelessly or thoughtlessly. This article is a small confession, because I, like any other programmer, have also written such code in the past (in fact, I still write the bad code sometimes, though refactoring makes it much better). This is nothing terrible as long as we understand that we need to work on it.

This article is a translated version of my article from harb.com so, if you know Russian then you can read the original version.

Let's start.

Variables

One of the most annoying kinds of variables is variables that give a false impression of the nature of the data they store.

The requests library is extremely popular among Python developers, and if you have ever been looking for something related to requests, you must have come across something like this:

import requests

req = requests.get('https://api.example.org/endpoint')
req.json()

Whenever I see this, I feel annoyed and even not because of the shortened name, but because the name of the variable does not match what is stored in this variable.

When you make a request (requests.Request), you get a response (requests.Response), so reflect this in your code:

response = requests.get('https://api.example.org/endpoint')
response.json()

Not r, not res, not resp and certainly not req, exactly response. res, r, resp – these are all variables whose contents can be understood only by looking at their definitions, and why jump to the definitions when you can initially give a suitable name?

Let's look at another example, but now from Django:

users_list = User.objects.filter(age__gte=22)

When you see users_list somewhere in the code, you quite rightly expect that you can do this:

users_list.append(User.objects.get(pk=3))

but no, you can't do this, since .filter() returns a QuerySet:

Traceback (most recent call last):
# ...
# ...
AttributeError: 'QuerySet' object has no attribute 'append'

If it is very important for you to specify a suffix, then specify at least one that reflects the real situation:

users_queryset = User.objects.all()
users_queryset.order_by('-age')

also okay, because such abbreviations (_qs) are usual for Django:

users_qs = User.objects.all()

If you really want to write exactly _list, then take care that the list really gets into the variable:

users_list = list(User.objects.all())

Indicating a type of data that a variable contains is often a bad idea, especially when you deal with dynamic languages, such as Python. In cases when it is very necessary to note that the object is a container data type, it is enough to simply indicate the name of the variable in the plural:

users = User.objects.all()

Consider another example:

info_dict = {'name': 'Isaak', 'age': 25}
# ...
# ... 
info_dict = list(info_dict)
# ...
# ...

You see a dict and you might want to do this:

for key, value in info_dict.items():
    print(key, value)

Instead, you'll get an exception, because you were misled, and you will understand this only if you go to the definition of the variable and read the entire code from top to bottom, right down to the section from which you started the jump — this is the price of such variables.

Thus, when you indicate in the variable name the type of data stored in it, you are essentially a guarantee that this variable must contain the specified data type at any time during the execution of the program. Why should you take this responsibility if it is the direct responsibility of the interpreter or compiler? You shouldn't! Better to spend time thinking of a good variable name than trying to figure out why the variables do not behave as you expect.

In the example above, the choice of the name of a variable is rather bad, and you could give a name that more accurately expresses the context (no need to be afraid to use names related to the subject area), but even in this case, you could make this code better:

info_dict = {'name': 'Isaak', 'age': 25}
# ...
# ... 
info_keys = list(info_dict)
# ...
# ...

or even like this, which is more idiomatic:

info_dict = {'name': 'Isaak', 'age': 25}
# ...
# ... 
info_keys = info_dict.keys()
# ...
# ...

Another type of annoying variable is ones with a shortened name.

Let's go back to requests and consider this code:

s = requests.Session()
# ...
# ... 
s.close()

This is an example of an unnecessary shortening for a variable name. This is a terrible practice, and its horror becomes even more apparent when such code takes up more than 10-15 lines of code.

It is much better to write as is, namely:

session = requests.Session()
# ...
# ...
session.get('https://api.example.org/endpoint')
# ...
# ...
session.close()

or

with requests.Session() as session:
    session.get('https://api.example.org/endpoint')

You may argue that this is a more verbose option, but I will answer you that it pays off when you read the code and immediately understand that session is a Session.

Will you understand it by variable s without looking at its definition?

Methods

Smart naming of functions and methods is something that comes only with experience in designing an API, and therefore you can often find cases where methods do not behave as you expect.

Consider an example:

>>> person = Person()
>>> person.has_publications()
['Post 1', 'Post 2', 'Post 3']

We expressed a very clear-cut question in our code: “Does this person have publications?”, but what kind of answer did we get? Did we ask for a list of publications of a person?

The name of this method implies that the return value must be of Boolean type, namely True or False:

>>> person = Person()
>>> person.has_publications()
True

We can use a more appropriate method name for getting publications:

>>> person.get_publications()
['Post 1', 'Post 2', 'Post 3']

or

>>> person.publications()
['Post 1', 'Post 2', 'Post 3']

We often like to call programming a creative activity, and it really is. However, if you write not readable code, and then justify it with “creativity”, then I have bad news for you.

Further reading

I'm leaving this list of outstanding relevant literature written by well-known professionals in the field for further study of the issue:

  1. Robert Martin — Clean Code
  2. Robert Martin — Clean Architecture
  3. Robert Martin — The Clean Coder: A Code of Conduct for Professional Programmers
  4. Martin Fowler — Refactoring: Improving the Design of Existing Code
Did you like this article?

Isaak Uchakaev

Backend Engineer

See other articles by Isaak

Related jobs

See all

Title

The company

  • Remote

Title

The company

  • Remote

Title

The company

  • Remote

Title

The company

  • Remote

Related articles

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

•

12 Sep 2021

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

•

12 Sep 2021

WorksHub

CareersCompaniesSitemapFunctional WorksBlockchain WorksJavaScript WorksAI WorksGolang WorksJava WorksPython WorksRemote Works
hello@works-hub.com

Ground Floor, Verse Building, 18 Brunswick Place, London, N1 6DZ

108 E 16th Street, New York, NY 10003

Subscribe to our newsletter

Join over 111,000 others and get access to exclusive content, job opportunities and more!

© 2024 WorksHub

Privacy PolicyDeveloped by WorksHub