Sunday, October 16, 2011

Don't expose class internals

I'm going to disagree a bit with Robert Martin, the author of Clean Code. In his G14 "Feature Envy" smell he uses the example of an method on an HourlyPayCalculator class that takes an HourlyEmployee argument and then uses its properties to do its job. That makes the method "envy" the HourlyEmployee class - the method "wishes it was inside the HourlyEmployee class".

So far, so good. Unfortunately, Robert continues with a counter-example to the feature envy smell; he uses the following example (Java code):

  public class HourlyEmployeeReport {
    private HourlyEmployee employee;

    public HourlyEmployeeReport(HourlyEmployee e) {
      this.employee = e;
   }

    String reportHours() {
      return String.format("Name: %s\tHours: %d.%1d\n",
      employee.getName(),
      employee.getTenthsWorked()/10,
      employee.getTenthsWorked()%10);
    }
  }

Robert says: "Clearly, the reportHours method envies the HourlyEmployee class. On the other hand, we don't want HourlyEmployee to have to know about the format of the report. Moving that format string into the HourlyEmployee class would violate several principles of object oriented design."

I believe there's a way to solve both problems. The HourlyEmployee class has to know about the concept of reporting; that's why we're exposing the getName() method. The only decision is whether we hide this concept or make it explicit. Here's a way we could make it explicit (I'll use C# because, while I can read Java, I'm not confident enough to write it):

  public interface HourlyEmployeeReporting {
    void Report(string name, double tenthsWorked);
  }

  public class HourlyEmployee {
    private string name;
    private double tenthsWorked;
    //... other stuff, but keep the internals hidden

    public void Report(HourlyEmployeeReporting reporter) {
      reporter.Report(name, tenthsWorked);
    }
  }

  public class HourlyEmployeeReporter: HourlyEmployeeReporting {
    void Report(string name, double tenthsWorked) {
      var report = string.format("Name: {0}\tHours: {1}.{2}\n",
        name, tenthsWorked / 10, tenthsWorked % 10);
      // do something with the report value, like writing it to a Logger
    }
  }

This way we haven't sacrificed any of the object oriented principles: everything is encapsulated, we can still have reporting and, quite importantly, reporting is exposed as a concept instead of being hidden just because we can use the internals of the HourlyEmployee class to do it.

[Note: I am not saying that exposing getName() doesn't work. I am saying that the way I'm showing is more object oriented.]

Thursday, October 06, 2011

The Awakening

The source of their Powers was never discovered; what nobody had doubted, however, was that there was a will behind it. Both the fact that there were exactly nine of them – one for each billion people – and the fact that each of them gained their powers on January 1st, 2050, at exactly midnight local time, made coincidence a too unlikely explanation.

Once it found out about their existence, the world called them superheroes; but amongst themselves they would use the name Champions.


The people would not discover the existence of the Champions for more than a year, though, because at the same time they had gained their powers, the Universe had started responding to spells. Some would call them wishes, or prayers; whatever the name, people's intentions were starting to directly affect the real world. Like many religions had insisted, it would only happen if the person making the wish genuinely believed in it; unlike what those religions had taught, the effect of the wish appeared to be completely unrelated to its content. Someone would pray for a million dollars, truly believing in the power of prayer; a week-long drought would be the result.

Very soon, in a matter of days, people realized what happened and started experimenting. Whatever the reason for this change, it appeared to be almost mechanical in the way it interpreted the spells. They had to be voiced - mere thinking did not seem to have an effect - but the language would appear to have little relevance. Wishing for a million dollars in English, French or Chinese would all cause a week-long drought, with maybe minutes in difference; on the other hand, wishing for a million Euros or Yuan would change the length of the drought significantly and work was in progress to determine the exact relationship. Intonation, number of people making the same wish, number of repetitions - everything had an effect.

It didn't take long before the experiments were formalized; by next Fall, Universities throughout the world began adding to their curricula courses in the new science of Magic. The governments were even faster in regulating the new Spellcaster profession. The American DHS was the first to have a Magic Crimes Division, but other agencies and governments followed suit very quickly. Even the Vatican announced that they were going to convene a special council to analyze the new situation.


Ideas for further development:

  • The DHS asks for the power to record everything, including private residencies, to discover people who make unlicensed wishes. It is granted, as long as the search is never done manually, only through an AI that can check warrants. The recordings are also supposed to be erased after an year but, with cryptographically-secure storage being practically free, this is not something you can count on.
  • A black market in spells develops very quickly.
  • The copyright lawsuits in spells dwarf anything previously seen with movies, music or patents; the next richest guy on the planet is a spell writer.
  • Religious fanaticism leads to armed confrontation against the government; even regular people are uneasy with the idea of the government regulating religious prayers.

Sunday, October 02, 2011

TDD by example - first book

This is an alpha version of a TDD booklet I wrote. As I said earlier, I plan on writing several of these.

TDD by example - Evaluating an expression [pdf]

It's a hands-on book; if you don't plan to follow it by writing code, it might not be of any help. The intended target are people who have done no TDD at all, or who tried it and couldn't make it work. If you have experience doing TDD, this book will probably look childish.

Feedback will be strongly appreciated. Positive if at all possible, but even "it sucks" is better than nothing :)

The book is also available from Amazon for $4.99 for Kindle (if you're in the US or Canada; I know Amazon changes the price in other countries) or $14.99 in paperback.