Archive for October, 2014

Another example of Object Theater

Thursday, October 30th, 2014

Mastermind

This year I gave my Web Applications students the task of writing a Mastermind game. You can see some of their work here, here and here. The game works like this: the computer starts a new game by inventing a random secret code, composed of 4 digits from 1 to 6. For instance: 5414.

The player must deduce what is the secret code by trying guesses. To continue the example if my first guess is 1234, the computer will answer “-+” which means that I got one number right (+) and another number is present in the secret code but in a different position (-). Of course, I don’t know which! I can then try more guesses, until I have enough clues to guess right.

You get a score for each completed game, that is equal to the number of guesses. Of course, the lower the score, the better.

A player will earn a score that is the average of all the games he or she completed.

Procedural!

Teaching Object-Oriented programming was not one of the goals of the course. Therefore, most programs I got were very procedural. (Please note that the example that follows is from a good student and his work earned a very high score in my course. It was a good web application, even though it was not object-oriented).

I’d like to show an example of procedural code. This is a controller object that handles a “guess”.

public void guess() throws IOException {
  String gameId = request.getParameter("game_id");
  String code = gamesRepository.findSecretCode(gameId);
  String guess = request.getParameter("guess");
  String answer = compareCodes(code, guess);
  String player = gamesRepository.find_game_player(gameId);
  guessesRepository.createGuess(gameId, player, guess, answer);
  gamesRepository.incrementGameScore(gameId);

  // if game is won
  if(answer.equals("++++")){
    gamesRepository.setFinished(request.getParameter("game_id"));
    int oldScore = gamesRepository.getPlayerScore(player);
    playersRepository.addFinishedGame(player, oldScore);
  }

  // return json data
  response.getWriter().write(toJson("answer", answer));
}

This is classic procedural code; the game logic is found in the controller (method compareCodes()) and the repositories (three repositories!). There are no domain objects.

The database structure is something like

       1      *      1      *
player -------- game -------- guesses

The gameRepository adds a row to the games table when a new game is added. The guessesRepository adds a row to the guesses table when a new guess is guessed. The controller must take care to call the proper repositories at the right time. The controller “knows” the database structure; if the database structure changes, the controller code will probably also change.

Object-Oriented

What I’d like to do instead is

  • Domain objects that handle all the game logic
  • No logic in the repositories or the controller
  • Just one repository is enough, thank you. The repository should take care of adding rows to the proper tables.

The domain object should probably be the MasterMind game.

game.guess(request.getParameter("guess"));

The “guess” message is what sets the domain logic in motion. The controller should not need to know anything else.

Q. What if the game is won? Who updates the player’s score?

A. The game object should do that.

Q. Where do we see that the game updates the player’s score?

A. Not in the controller. The controller does not know or care. Handling victories is something that is done in the game object.

Q. Really! How do we update the player’s score?

A. The game probably knows its player, and tells it to update its score if the game is won.

Q. How does the game get a reference to its player?

A. The controller does not know. But see next question.

Q. Where do we get the game object from?

A. From a repository, of course. We suppose that the repository will return it with all the dependencies that it needs to have. If the game needs a reference to its player, the repository must take care to set it up.

String gameId = request.getParameter("game_id");
Game game = gamesRepository.findGame(gameId);

game.guess(request.getParameter("guess"));

Q. How is the state of the game persisted?

A. By asking the repository to save the game.

// Here we are in the infrastructure world
String gameId = request.getParameter("game_id");
Game game = gamesRepository.findGame(gameId);

// Now we pass to the realm of pure domain logic
game.guess(request.getParameter("guess"));

// And now we return to the infrastructure world
gamesRepository.save(game);
response.getWriter().writer(toJson(game));

So we have seen another example of object theater. The infrastructure details are dealt with before and after the main action. The main action is sending “guess” to the game object. There is where the functional requirements is dealt with. Before that, and after that, is infrastructure code that deals with non-functional, performance requirements.

Object-Oriented Theater

Thursday, October 30th, 2014

Update 30/10/14: I first read about the “Object Theatre” in a message by Anthony Green on the GOOS mailing list; I didn’t remember it consciously when I wrote this post, but it certainly has been working in my brain ever since. The “Object Theatre” metaphor is his invention, not mine. Thanks Kevin and Anthony for pointing it out.

Yesterday evening I attended a good introduction on functional programming by Mario Fusco. One of his slides illustrated a well-known principle of functional programming. There are pure functions, and “functions” with side effects. Good FP style suggests to keep non-pure functions at the edges of the program, so that the inner core of your program only contains pure, mathematical functions.

He showed this picture

http://www.slideshare.net/mariofusco/if-you-think-you-can-stay-away-from-functional-programming-you-are-wrong/41

In fact, a very similar picture can be drawn for good object-oriented style. In good OO style, you want to separate your domain objects from infrastructure objects. The domain objects contain just domain logic, they execute in memory and have no references to file system, databases or network services. They can be mutable, of course! But they are “pure logic” in the sense that they live in a platonic world where we are only concerned with the functional behaviour of our programs.

Infrastructure objects, on the other hand, deal with everything else: user interface, databases, file systems, web services… All the things that are needed to connect our platonic world of objects to the outside world.

So what’s good OO style in this context? In my opinion, it’s good to keep the infrastructure objects in an outside shell, while the inner core of the program contains only pure domain objects. Let me give you an example.

Suppose you have a Counter object that needs (for non-functional reasons!) to be made persistent. The functional logic is about incrementing and decrementing the value of the counter. The infrastructure logic is about making sure that the counter retains its value across reboots (which is definitely a non-functional requirement.)

The wrong way to do this is

// bad style! don't do this
class Counter {
  public Counter(int id, CounterDao dao) {
    this.id = id;
    this.dao = dao;
  }

  public void increment() {
    value++;
    dao.incrementCounter(id);
  }

  private int value = 0;
  private int id;
  private CounterDao dao;
}

The usage of this counter would be

CounterDao dao = ...;
Counter counter = new Counter(123, dao);

// here we perform logic and also persist the state
counter.increment();

The above example is bad style, because it mixes persistency logic with functional logic. Bah! A better way to do it is:

class Counter {
  public void increment() {
    value++;
  }
  private int value = 0;
}

See? Only pure logic. We don’t care about persistency there. We could use the counter this way:

// we start this use case in the world of infrastructure
CounterDao dao = ...;
Counter counter = dao.findCounter(id);

// here we enter the world of pure logic
counter.increment();

// here we return to the world of infrastructure
dao.save(counter);

I like to call this structure “object theatre”. Imagine your domain objects as actors in a play. You want to setup a scene where your actors are set up in a certain way: Arlecchino talks to Colombina, Colombina has a fan in her hand, etc. When the scene starts, the actors perform each according to their character. When the scene ends, we lower the curtain.

I imagine that an object-oriented system works the same way. When a request arrives, we set up the scene by retrieving all the proper objects from various repositories and we connect them appropriately. This is setting the scene. Then we send a message to one object that sets some logic in motion. The objects send messages to each other, carrying out a computation. This is playing out the scene. When the domain objects are done, we conclude by returning the objects to their respective repositories. This is lowering the curtain.