Can you write expressive code? – Christmas break challenge
Before you go away on holidays and feast on Christmas and New Year’s eve parties, I want to propose you a challenge about writing expressive code to keep your skills up during the holidays period.
I’m going to show you the code for a simple task performed by an application. I’m even going to explain that code to you. And as you’ll see, this code is not exactly the clearest you can get, but it’s typically the sort of thing you could find in real life applications.
Your challenge is to show us how you would have written this code expressively. Post a comment down below this article with your solution!
In the next post on Fluent C++ (coming out January 3rd), I’ll show a technique to transform obscure code into expressive one, and we’ll apply it to the piece of code of this challenge, to see how to transform it into something really elegant.
So you’ve got until that date to show us what you call expressive C++. Merry Coding!
The objective
The user of your application is planning a trip across several cities in the country.
He would drive straight through from one city to the next if they are close enough (say under 100 kilometers), otherwise he would take a break on the road between two cities. The user doesn’t take more than one break between two cities.
Let’s say that we have the planned route in the form of a collection of cities.
Your objective is to determine how many breaks the driver has to take, which can be useful for budgeting time for them for example.
The surrounding code
This application has existing components that you can use in your code, but these components are not to be changed.
The class City represents a given city on the route. City can provide its geographical attributes, amongst which its location which is represented by a class Location. And a object of type Location can itself compute the driving distance to any other Location on the map:
class Location { public: double distanceTo(const Location& other) const; ... }; class GeographicalAttributes { public: Location getLocation() const; ... }; class City { public: GeographicalAttributes const& getGeographicalAttributes() const; ... };
The offending code
Here is the current implementation for working out the number of breaks the user has to take:
#include <vector> static const double MaxDistance = 100; int computeNumberOfBreaks(const std::vector<City>& route) { int nbBreaks = 0; for (std::vector<City>::const_iterator it1 = route.begin(), it2 = route.end(); it1 != route.end(); it2 = it1, ++it1) { if (it2 != route.end()) { if(it1->getGeographicalAttributes().getLocation().distanceTo( it2->getGeographicalAttributes().getLocation()) > MaxDistance) { ++nbBreaks; } } } return nbBreaks; }
You’ll probably admit that this code is fairly obscure, but this is the kind of thing you can find in real-life applications.
Your challenge is to rewrite this piece of code so that it still outputs the number of breaks of the given route, but in an expressive way.
To avoid your wasting time trying to figure out how this code works, I’m going to explain it to you. This way you can spend more time writing clean code than deciphering obscure code.
The part that needs most to be explained is the iteration logic:
for (std::vector<City>::const_iterator it1 = route.begin(), it2 = route.end(); it1 != route.end(); it2 = it1, ++it1) { if (it2 != route.end()) { ...
Maybe you have seen this technique applied before. This is a trick to manipulate adjacent elements in a collection. it1 starts at the beginning, and it2 point to the element right before it1 all along the traversal. To initialise it2 with something we start by setting it at the end of the collection, and check that it2 is no longer at the end within the body of the loop to actually start the work. So the point here is to iterate over the cities in the route, by treating each city with the one after to it.
Inside the loop, if the distance between two cities is greater than 100 kilometers then another break is added to the total number of breaks of the route:
if(it1->getGeographicalAttributes().getLocation().distanceTo( it2->getGeographicalAttributes().getLocation()) > MaxDistance) { ++nbBreaks; }
This is where you start coding
Any ideas how to transform this obscure piece of code into an elegant and maintainable one? Keep your coding skills up during the Christmas break and drop a comment to show how you would choose to write it!
For fun, compare your code with what your friends wrote by sharing this post with them or tweet about it with one of the buttons below. In the meantime, Merry Christmas, Happy New Year, and Happy Clean Coding!
– Jonathan Boccara
Don't want to miss out ? Follow:   Share this post!