Cat confusions #1: A cat named Albert and a cat named Rupert

Rupert. As if he gives a damn, he writes his own code ©Doug Powell

The problem statement: Design a cat park, to which two cats can go to play. One is named Albert and the other named Rupert. The park has a smart system, which tracks the toy catch and retrieve game that cats play. If a cat retrieves a toy to a post, if it decides to, then its retrieval count goes up. If a cat decides to leave the toy mid-way or just does the thing that cats do with toys, the lost count goes up. The smart system determines the outcome of each event.

Your job is, shall you choose to accept it, is to print the retrieval and lost count, if greater than 0, for each of the cats, when they exit the park.

Now, few souls rose to the challange, and below is one solution that I was presented with:

It starts with, creating a class CatPark to track the events that happen in the park, determined by AI, such as

  • Toy retrieved
  • Toy lost
  • exit the park
class CatPark {
static final String ALBERT = "Albert";
static final String RUPERT = "Rupert";
private CatGame albertsGame = new CatGame(CATS.ALBERT);
private CatGame rupertsGame = new CatGame(CATS.RUPERT);
    void onToyRetrieved(String catName) {
if (catName.equals(ALBERT)) { albertsGame.onRetrieveComplete();}
else if (catName.equals(RUPERT)) { rupertsGame.onRetrieveComplete();}
    void onToyLost(String catName) {
if (catName.equals(ALBERT)) { albertsGame.onLost();
} else if (catName.equals(RUPERT)) { rupertsGame.onLost();}
    void exitPark() {
if (albertsGame.getAlbertRetrieveCount() > 0) { System.out.println("Albert retrieved " + albertsGame.getAlbertRetrieveCount()); }
        if (albertsGame.getAlbertLostCount() > 0) { System.out.println("Albert Lost "+ albertsGame.getAlbertLostCount()); }
        if(rupertsGame.getRupertRetrieveCount() > 0) { System.out.println("Rupert retrieved " + rupertsGame.getRupertRetrieveCount()); }
        if(rupertsGame.getRupertLostCount() > 0) { System.out.println("Rupert lost " + rupertsGame.getRupertLostCount()); }

If you are looking at the solution, and have done a little bit of Java programming, and the bells don’t start to ring for you, keep reading further.
The CatsPark oversees CatsGame, which is as follows

public class CatsGame {
private GameTracker gameTracker = new GameTracker();
private int catId;
    CatsGame(int catId) { this.catId = catId; }
    void onRetrieveComplete() { gameTracker.incrementRetrieveCount(catId);}
    void onLost() { gameTracker.incrementLostCount(catId);}
    int getRupertRetrieveCount() { return gameTracker.getRupertRetrieveCount();}
    int getAlbertRetrieveCount() { return gameTracker.getAlbertRetrieveCount(); }
    int getRupertLostCount() { return gameTracker.getRupertLostCount(); }
    int getAlbertLostCount() { return gameTracker.getAlbertLostCount(); }

If you have encountered any form of OOPS in your life, you might start seeing various violations of inheritance, reuse, encapsulation, abstraction etc. Well for me, I started to sob.

If we see further, the code for GameTracker:

class GameTracker {
private int albertRetrieveCount = 0;
private int albertLostCount = 0;
private int rupertRetrieveCount = 0;
private int rupertLostCount = 0;
    void incrementRetrieveCount(int catId) {
if (catId == CATS.ALBERT) { albertRetrieveCount++; }
else if (catId == CATS.RUPERT) { rupertRetrieveCount++; }
else { System.out.println("Wrong cat id"); }
    void incrementLostCount(int catId) {
if (catId == CATS.ALBERT) { albertLostCount++; }
else if (catId == CATS.RUPERT) { rupertLostCount++; }
else { System.out.println("Wrong cat id");}
    int getRupertRetrieveCount() { return rupertRetrieveCount;}
    int getAlbertRetrieveCount() { return albertRetrieveCount;}
    int getRupertLostCount() { return rupertLostCount;}
    int getAlbertLostCount() { return albertLostCount;}

and not to forget the Cat constants:

class CATS {
static final int ALBERT = 1;
static final int RUPERT = 2;

The main program runs it as follows:

public class Main {
public static void main(String[] args) {
CatPark park = new CatPark();
Random random = new Random();
for (int i = 0; i < 20; i++) {
int outcome = random.nextInt(4);
switch (outcome) {
case 0:
case 1:
case 2:
case 3:

If you still think this is good solution, imagine what you need to do, if one more cat, named Gilbert, decided to join. How many classes would need to change.
Well there are currently 5 classes in use

  • CatsPark
  • CATS
  • CatsGame
  • GameTracker
  • Main

In the above code, all the 5 classes will need to change, to handle cases for each cat: to keep track of retrieval and lost counts of all the individual cats by name.

If the park becomes famous and Hubert and Lambert decide to join, well can you imagine what changes you need to do in the code?

Imagine adding 100s of cats, or thousands.

As if it was not enough, consider that when among 1000s of cats listed for the park, you need to remove the cats who stopped coming, or the case when Albert changed name to Delbert.
Can you guess how many classes need to be modified: well you might have guessed it right, all of the 5.

One will need to search, add, replace, modify, remove and possibly use all the tools of code editing and refactoring to do that, and imaging the bugs and maintenance nightmare.

Now to me, I could not take it any more, I fainted (not for real).

A good, if not well written code, should be immune to small changes in requirements like that, and not overly dependant on the details of the problem. The solution should be generic enough to scale for small demands, without putting a lot of edit stress on the system.

If you know what’s wrong with the above solution is, you know the basics of OOP, and you may not need to read further.

If you don’t know how bad that is, I suggest reading up on OOP or Java for beginners, or, you could wait for next post, in which I will introduce basic OOP to simplify the Cat confusions.

P.S. Feel free to dissect the (simple) problem, and the (not good) solution. Please treat it as a basic programming interview question.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.