The importance of Good Code
Did you know code can smell? Do you use Python TDD (Python test-driven development), BDD (behavior-driven development) or any other strategies to test your code? If you aren’t testing or writing clean code, your code reviews may look something like this:
Bad code causes problems, which may come in the form of introducing too many bugs.
And we all know the costs of having bugs in your code…
In this article, we’ll go over the consequences of bad code and how to avoid it.
The total cost of owning a mess
Over the span of a year or two, teams that were moving very fast at the beginning of a project can find themselves moving at a snail’s pace. Every change they make breaks two or three other parts of the code. No change is trivial.
As the mess builds up, the team’s productivity continues to decrease. And, as productivity decreases, management does the only thing they can: they add more staff to the project in hopes of turning things around.
However, that new staff is not versed in the system’s design. In fact, they, and everyone else on the team, are under horrific pressure to increase productivity. As a result, they all make a bigger mess, driving the productivity ever further toward zero.
All developers with more than a few years of experience know that messy code slows them down. And yet, all developers feel the pressure to write messy code in order to meet deadlines. In short, they don’t take the time to go fast!
True professionals know that they will not make a deadline by making a mess. On the contrary, a mess will slow you down instantly and force you to miss the deadline. The only way to make it on time—the only way to go fast—is to keep the code as clean as possible at all times.
The Grand Redesign in the Sky
If you’ve been a victim of messy legacy code, you’re not alone. In fact, most developers have been through similar experiences, and it’s a cycle that can be hard to break, as Robert C Martin describes it in his book “Clean Code: A Handbook of Agile Software Craftsmanship”.
“[Management eventually authorizes] the grand redesign in the sky.
A new tiger team is selected. […] They get to start over and create something truly beautiful. […] Everyone else must continue to maintain the current system.
Now the two teams are in a race. […] Management will not replace the old system until the new system can do everything that the old system does.
This race can go on for a very long time. I’ve seen it take 10 years. And by the time it’s done, the original members of the tiger team are long gone, and the current members are demanding that the new system be redesigned because it’s such a mess.
If you have experienced even one small part of the story I just told, then you already know that spending time keeping your code clean is not just cost effective; it’s a matter of professional survival.”
Robert C. Martin Clean Code series
Python test-driven development
So, you’ve somehow ended up with bad code. What now? Don’t worry! This can be fixed. However, it may take time, so start as soon as you possibly can!
Give your development team the tools that they need to fix those bugs much faster and clean up the current project.
This can be done with a very interesting strategy called test-driven development. In TDD, unit tests are designed, developed and run before starting work on each web or mobile app functionality with the aim to make the code simpler, clearer and bug-free.
Another great tool when it comes to testing is test automation.
What are automated tests?
Automated tests mean the testing work is done for you by the system. You create a set of tests once, and then as you make changes to your app, you can check that your code still works as you originally intended, without having to perform time consuming manual testing.
What are the benefits of automated tests?
They will save you time
This is especially true when automated tests could do this for you in seconds. If something’s gone wrong, tests will also assist in identifying the code that’s causing the unexpected behavior.
They don’t just identify problems, they prevent them
They light up your code from the inside, and when something goes wrong, they focus light on the part that has failed, even if you hadn’t realized something was wrong.
They make your code more attractive
As Jacob Kaplan-Moss, one of Django’s original developers, says: “Code without tests is broken by design.”
They help teams work together
Tests guarantee that coworkers don’t inadvertently break your code (and that you don’t break theirs without realizing either). If you want to make a living as a Django programmer, you must be good at writing tests!
The tools that make our testing easier
- Python is easy to work with and easy to read
- It’s very popular
- It’s great for machine learning
- It’s the fastest-growing major backend language
- It makes our day-to-day work easier and more enjoyable
- It makes TDD much easier.
- It’s built with Python
- It has an excellent community
- It’s highly secure
- It has a great set of libraries
- It’s good for SEO
- It’s highly scalable
- It’s based on the DRY principle
- It includes the Django default admin panel
- It’s portable
According to the Python website, the unittest unit testing framework “supports test automation, sharing of setup and shutdown code for tests, aggregation of tests into collections, and independence of the tests from the reporting framework.”
In an agile environment, it’s important for developers to push changes quickly. But, with every change that requires a modification to the frontend, they need to run appropriate cross browser tests. While a small project may make due with manual testing, an increasing number of history points make a case for automation testing.
Here is an example of how these tools combined make our lives easier
Writing test for legacy code
What happens with legacy code? How should you proceed in these cases?
Boy scouts rules: Test what you touch
- Write a test that asserts current behavior before you touch the code
- Write a test that asserts new/modified behavior and see it fail
- Do coding stuff
- Check if your test pass
- Profit significantly
Unit tests should:
- Cover the smallest piece of code possible
- Run fast
- Not use a database, file, etc.
Now, let’s take a look at the different situations you may come across with legacy code and what you should when facing each one:
Assignment 1: Feature request (altering an existing functionality)
- Test existing functionality (integration testing)
- Test new functionality (integration testing)
Assignment 2: Battle a BUG in a code that touches the world
- Read the code but don’t touch it
- Get the class in a test harness
2.5. Break dependencies?
- Create a subclass
- Test out the view
- Make the world a better place
Assignment 3: Add new features to existing (and unruly) ones
|Option 1: Just write the damn code in the existing method|
|Option 2: Mock your way through it|
|Option 3: Refactor|
Final Thoughts on Python test-driven development
Python test-driven development may be time consuming and testing legacy code is definitely not an easy thing to do, but it’s important to know how to tackle these tasks, especially when your codebase starts to show symptoms of bad code.