Posts Tagged ‘clean code’

Tests are dangerous
Do you write tests because you are expected or told to do so, or do you write them to help all those (including yourself) who will sooner or later work with your code? Tests are code as well, so they should be written an maintained with the same amount of care as the production code. Here I share reproductions of some badly written tests I happened to come across here and there. I’m not going to show the original ones since the aim of this post is not to blame the authors of them but to show how easy it is for tests to become harmful when insufficient amount of thought are put into them.
TDD vs. PHP gotcha’s: TDD wins!
How many problems do you see in the following test?
<?php
class ThreeLetterWordCollectorTest extends PHPUnit_Framework_TestCase
{
public function testThreeLetterWordCollector()
{
$cut = new ThreeLetterWordCollector();
$actual = $cut->collectThreeLetterWords("bar hello foo world");
$expected = array("foo", "bar");
$this->assertSame(sort($expected), sort($actual));
}
}
It’s just a minor issue that the name testThreeLetterWordCollector does not provide any new information about what behavior it is testing. It’s just the words of the tester class in different order. There are probably better names for a variable than $cut as well. (Don’t make me think! It’s an abbreviation of the term “Class Under Test”.) But the real problem here is the dangerous one: this test does NOTHING! The intent here is likely to be to compare the arrays ignoring the order, but PHP’s sort() function does not work the way one would assume knowing most other languages. Actually, it is one of PHP’s worst library functions. Have you read PHP: a fractal of bad design? It’s a must-read. sort() does the work in-place and returns a boolean depending on the success of sorting. (And to make things worse, it compares elements in a crazy undeterministic type-juggling way by default. I’ve written about it a couple of months ago.) So in the end, given that ThreeLetterWordCollector::collectThreeLetterWords() returns an array, the assertion will always pass, regardless of the contents of the array.
If that test and the production code it validates had been written with TDD, then they would have been attempted to be seen failing and once the test passed when it should have failed, then the problem would have been noticed immediately. Don’t trust tests you have never seen fail!
Comparing strings the Unix-y way
Another test written in PHP, but this one actually could have been written equally badly in any popular language:
public function test1()
{
$expected = __DIR__ . "/fixtures/expected.conf";
$template = __DIR__ . "/fixtures/template.tpl";
$actual = __DIR__ . "/fixtures/actual.conf";
$generator = new ConfigFileGenerator();
$generator->generateFromTemplate($template, $actual);
$result = 1;
system("cmp $expected $actual 2>/dev/null", $result);
$this->assertTrue($result == 0);
}
Let’s ignore the fact that the naming of this test is even worse than in the first example. But the way it compares the expected and the actual output is gotta be a joke. A surprisingly bad one. I didn’t even know that this cmp command existed! Oh how I miss you, good old Assembly! Now seriously, what does this test print when it fails?
There was 1 failure:
1) ConfigFileGeneratorTest::test1
Failed asserting that false is true.
Thank you, dear test, now I know what requirement is broken and what is the exact problem with it. If this test was written with keeping not just the happy case in mind but the possibility of failing as well, then it would at least read those two files and compare their contents as strings using the assertions provided by the test framework, producing usable output when going red. Maybe all that would be done by a method named assertFileContents(). Or bringing it to the next level: taking SRP into consideration, the config file generator logic could be decoupled from reading and writing files on the disk, so the latter could be easily mocked in the test harness. (It would run faster as well.) And no fixtures in various files would be required, the test could be fully self-contained!
Obfuscating tests using mutable test data
You can’t say I’m picking on tests written in PHP, here’s a Python one:
class FooFinderTest(object):
def test_foo_finder(self):
expected_foo_ids = [ 1, 2, 3, 4 ]
foo_finder = FooFinder()
self.assert_foo_ids(expected_foo_ids, foo_finder.find(bar=True))
self.assert_foo_ids(expected_foo_ids, foo_finder.find(bar=False))
def assert_foo_ids(self, expected_foo_ids, actual_foo_ids):
if len(expected_foo_ids) != len(actual_foo_ids):
print "Unexpected number of foo ids: %s" % str(actual_foo_ids)
sys.exit(1)
while len(expected_foo_ids) > 0:
if expected_foo_ids[0] not in actual_foo_ids:
print "Expected foo id %d to be found" % expected_foo_ids[0]
sys.exit(1)
del expected_foo_ids[0]
The question is: what do we expect in the bar=False case? Those knowing Python well can tell the correct answer: this test expects an empty list when bar is False. Those knowing Python well can also tell that whoever writes a test like this, does not know Python, since it has a built-in test framework so no in-house invented wheels are necessary. E.g. the unittest module and its assertEqual() method could have been used instead of this make-shift assertion that removes all the elements from the list which is passed by reference so it becomes empty before assert_foo_ids() is called for the second time.
Tests are first class citizens too!
In theory, tests encourage and help you to refactor. But a test like the next one does the opposite of that. (You know the Game of Life kata, don’t you?)
class GameOfLifeTest(unittest.TestCase):
def test_any_live_cell_with_less_than_two_neighbors_dies(self):
world = World()
world.put_cell(0, 0)
world.put_cell(1, 0)
game = GameOfLife(world)
game.evolve()
self.assertFalse(game.get_world().is_alive(0, 0))
self.assertFalse(game.get_world().is_alive(1, 0))
def test_any_live_cell_with_two_or_three_neighbors_survives(self):
world = World()
world.put_cell(1, 1)
world.put_cell(2, 1)
world.put_cell(0, 2)
world.put_cell(1, 2)
game = GameOfLife(world)
game.evolve()
self.assertTrue(game.get_world().is_alive(0, 2))
self.assertTrue(game.get_world().is_alive(1, 2))
def test_any_live_cell_with_more_than_three_neighbors_dies(self):
world = World()
world.put_cell(0, 1)
world.put_cell(1, 1)
world.put_cell(2, 1)
world.put_cell(0, 2)
world.put_cell(1, 2)
world.put_cell(2, 2)
game = GameOfLife(world)
game.evolve()
self.assertFalse(game.get_world().is_alive(1, 1))
self.assertFalse(game.get_world().is_alive(1, 2))
def test_any_dead_cell_with_three_neighbors_becomes_alive(self):
world = World()
world.put_cell(1, 1)
world.put_cell(2, 1)
world.put_cell(0, 2)
game = GameOfLife(world)
game.evolve()
self.assertTrue(game.get_world().is_alive(1, 2))
What would happen if we needed a Cell object instead of pairs of coordinates? How can a new coordinate system be introduced in this code? How many places do we need to touch the test code just to change the signature of GameOfLife‘s constructor? Imagine any feature request for the game along with the necessary refactorings needed to add the feature cleanly and you will see that the test above makes most of them harder to implement since it needs a lot of changes in several places for basically any change that might occur in the interface of the production code. This test is too coupled to the interface of the production code and its collaborators, in other words, it defines classes and methods multiple times but the behavior it aims to validate is lost inside the noise.
Conclusion
Be careful when writing your tests. Having tests is certainly better than not having them, but to make them effective and helpful, one should never forget the goals the tests are written to reach. Tests are code, so standards, metrics, design principles and readability should be applied on them as well.

Game of life – never getting boring
Do you think it’s funny to implement Conway’s Game of Life for the 20th time? According to my experiences, the answer is hell yeah!
Since the Global Day of CodeRetreat event (organized by Marton Meszaros in Hungary), I’m a big fan of the CodeRetreat format of coding dojos. I’ve been attending all the events of the CodeRetreat Budapest Community, and at the last one, I even helped coaching during some of the sessions. Nucc and me decided to introduce this event to our fellow developers at BalaBit as well and fortunately the management was kind enough to support us by dedicating some working hours to learn about TDD and other modern software development methodologies.
At a CodeRetreat event, you always implement the four rules of Game of Life (without UI and such fancy stuff). Doing the same task again and again makes the problem well-known and understood so you can focus on the style and design of your tests and code, which is the goal of a CodeRetreat. You don’t have to finish the implementation, though, it’s not about Getting Things Done or competing which pair is the first to finish. More like Not Getting Things Done. Often it’s impossible as well to finish for you have only 45 minutes to work. After that, well, code is deleted, a short retrospective meeting is held then a new session begins. Pair programming is mandatory, and by changing the pairs after every session you’re guaranteed to learn a lot from others. To make sure that you won’t be able to train yourself during the day to finish new constraints are introduced in every session, like infinite grid, immutability of states, 3 line methods with at most 2 parameters, no-mouse (did you notice you go faster when you use only keyboard shortcuts in your IDE?), etc..
During the first few sessions, there are no constraints. The goal is getting the problem understood. In the implementation, you just do whatever you want. That seems to be the hardest constraint though, since people tend to not finish during the first sessions. Instead they do Big Design Up Front and forget to care about the software to be implemented. These are the sessions where nice UML diagrams about Cells and Neighborhood relations and Worlds and Games and Rules and such nicely designed stuff are drawn, then people realize after 45 minutes that they spent almost an hour working on getters and setters but not a single rule of the game got implemented. Yep, there’s a reason for the Four Rules of Simple Design having been invented. ![]()
Turns out if you’d started the very first testcase with the first rule (“Any live cell with fewer than two live neighbours dies, as if caused by under-population”), you might have had a working implementation of all four of them after 15-20 minutes or so. And nothing more than that since you wouldn’t have written code that is never used except for making those UMLs feel more complete. YAGNI!
Of course there’s a chance that such a quick and dirty implementation will be, well, dirty. It may contain at least one thing you consider ugly. But you have more than half of the session left and the safety net of a bunch of tests to refactor the hell out of it!
You spoiled the public interface of your Game with methods that should belong to a class named Board or World or Map instead? Are you feeling the need to test a method that is declared private? After extracting such methods into a separate class, you might end up with a Game class that has no state at all and contains only one public method that just creates new generations of cells based on a previous one.
On the other hand, after realizing how over-engineering slows them down, many people try to continue with sloppy design, skipping the refactorings for example to get rid of language primitives in the most abstract levels of the business logic or to conform to the SOLID principles, etc. They can be forced to do so by introducing requirement change surprises. For example, to handle hexagon maps along with square grids, a Topology or similar interface has to be extracted from the class representing the board, which can encapsulate the details of coordinate systems and neighborhood relations between coordinates. (Did you notice that the rules of the game do not depend on the placement and shape of the neighbors nor the neighbors themselves, but only their count is what matters?) To handle colored cells which know how old they are, cells have to be represented by a separate class instead of bare coordinate-tuples or boolean flags.
Such refactorings can be a pain in the ass when tests contain copy&paste, duplication, redundancy and duplication, so they must be cleaned up as well: by extracting common fixtures, creating abstract assertions based on the repeating patterns of similar assertions, etc. (Abstract assertions even help you to conform to such rigorous principles like “1 assertion per test.”)
Imagine your day to day software development work boiling down to such simple business requirements implemented by a couple of short but well named methods in a few simple and minimalistic classes, all of them thoroughly unit tested (by unit testing I mean unit testing), all of those tests proven to be useful (since you’ve seen them fail and turning into green a couple of seconds later) and providing 100% coverage of assertions. Wouldn’t it be easier than digging yourself through stack traces in mindblowingly complex codes full of nested infinite-but-conditionally-breaking-somewhere-in-the-middle-do-while loops depending on side effects of getter functions and badly named global variables coming from a dozen layers away? If you know this feeling I’m talking about, I’d recommend you to visit the next CodeRetreat near your location (look around in Twitter or Facebook) – to try something new!

GitHub breach: Rails mass assignments vs. Architecture
You may have heard about what happened to GitHub the other day. (BalaBit source codes like Zorp-GPL or syslog-ng codes mirrored at GitHub were not affected.)
In short: any user could upload her public key to the account of any other user by exploiting that GitHub uses unprotected mass assignments to instantiate objects responsible for storing public key data.
But how the hell can something like that happen in a well-structured, clean architecture? Here’s a code snippet using mass assignment:
class User < ActiveRecord::Base
belongs_to :group
# ...
end
user = User.new(params[:user])
A User object is created and its properties are set immediately to hold arbitrary values, possibly controlled by an attacker.
Now let me show you some dirty PHP code (hey kids, this is dangerous, don’t try this at home and never use such a code in production):
// $_POST = array("name" => "John", "group_id" => 5);
$columns = implode("`, `", array_keys($_POST));
$values = implode("', '", array_values($_POST));
mysql_query(
"INSERT INTO `users` (`$columns`)"
. " VALUES ('$values');"
);
You’d never do that, right? Not just because of its vulnerability to SQLi, but because this code mixes several responsibilities, several layers of a web application: input processing and data persistency for instance. It’s not just the code that’s crappy in the example above, it’s the behavior of the code! Blindly writing anything into the database coming from the user is surely a bad idea. No matter what a beautifully chaotic dance of how many classes and objects and layers and Routers and Controllers and Models and Whistles and Bells do the same thing as the PHP code above, it still remains a mess. From a behavioral point of view, there’s not much difference between the above two code snippets.
No, blacklisting/whitelisting model attributes is not the OO way of solving this issue, especially if you think of different possible use cases. A truly object oriented, clean architecture would instead separate business logic itself (ie. implementation of use cases), collecting information required for the business logic (and nothing more) from the input, passing that information to the business logic and sending the output of the business logic into some data persistency layer, etc.
Web is just a UI, a delivery mechanism, an ugly detail! says Uncle Bob Martin in this talk. When business logic is truly separated from HTTP request processing and other web (thus, UI) related tasks the application does (all the layers with their own unit tests), such accidents like setting a field of a business logic data structure that should not contain user supplied value, would not happen.
Separate your business logic from both the UI (ie. web) and from data persistency, so you can write unit tests to verify its operation with security in mind, independently from the framework and third parties your application relies on.

A few words on Clean code
Today I gave a talk at BalaBit Meetup regarding clean code principles and related techniques. I had to squeeze the stuff into 25-30 minutes, so a lot of principles and tricks had to be left out (LoD, KISS, vertical formatting, to mention just a few of them). In the hope that it may be useful, I uploaded my slides to slideshare.net.



Twitter
LinkedIn