About do one thing
Do one thing at a time - As stated in our earlier posts like DRY Principle (Computer Science), KISS Principle (Computer Science), or even Comments – What you should keep in mind, readability should be crucial to anyone's code.
Something that lastingly improves the readability of your code is a technique called "do one thing". It is often confused with the single responsibility principle (SRP), and the names are indeed confusing, in my opinion.
The main concept behind this is to reduce the code's complexity by diminishing the things statements and functions do, to exactly one simple thing.
To show you an example of how it works and how significant the improvements can be, look at the following (garbage) code:
class Sieve:start = 2def __init__(self, n):self.n = ndef run(self):l = [True] * self.nprims = list()for i in range(self.start, self.n):if l[i] is True:prims.append(i)for j in range(i + 1, self.n):if l[j] is True:if j % i == 0:l[j] = Falseelse:continuereturn primss = Sieve(120)print(s.run())
Sieve of Erastothenes
What does this code do? Rarely anybody can tell that after just reading it. If you read it thoroughly or inspect the output
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113]
You might find out that this is actually the sieve of Eratosthenes or at least any algorithm dealing with prime numbers. But if you never heard of the sieve of Eratosthenes, you will most likely search a while until you figure out what this code does and why.
And even if you wrote this and are fully aware of what it does, you might forget all of it in just a few days.
Why is that code garbage?
Some people might argue that the code works perfectly fine, and some might even argue, "but it is optimized!". Besides someone telling you that most likely never heard of broadcasting in Python, he or she also didn't respect the first rule of optimization:
And the reason for that is that you never really know what your compiler or interpreter actually does. Things that look complex to calculate might be faster than some "optimized" branch of code. To effectively optimize code, you need profound insights into the language at hand and the compiler or interpreter.
This is a job for experts that are specialized in this kind of work. As a developer, you should always rate readability over optimization. However, refactorings regarding optimization also should only be done if the time required for computation largely exceeds the expectations.
With the concept of the sieve at hand and the idea of a simple job, let's rephrase our code in a more meaningful way.
class SieveOfEratosthenes:start = 2prime_numbers = list()def __init__(self, maximum):self.maximum = maximumself.boolean_array = [True] * self.maximumdef run(self):self.sieve()return self.prime_numbersdef add_prime_number(self, number):self.prime_numbers.append(number)def is_prime(self, index):return self.boolean_array[index]def sieve(self):for number in range(self.start, self.maximum):if self.is_prime(number):self.add_prime_number(number)self.remove_multiples_from_sieve(number)else:continuedef remove_multiples_from_sieve(self, prime):for number in range(prime, self.maximum):if number % prime == 0:self.boolean_array[number] = Falsesieve = SieveOfEratosthenes(maximum=120)print(sieve.run())
Isn't this, in contrast, way easier to read and get? Even if your code is still garbage, using the name of the concept as the class name, you can reduce someone else's research effort from hours to minutes as they can easily find what this should be about. The functions themselves are easy to read as the function name represents exactly the one thing the function does.
Thank you for reading this article! I hope I was able to make the point. I am aware that the improved sieve code isn't perfect. If you come up with an even better to read solution, please e-mail us or post a comment. The smartest solution you can come up with will be permanently displayed here.