Wednesday, January 26, 2005

Accessing Private Fields

I had read an article about unit testing private methods. As the article states, there are several approaches to this and also several reasons why you should consider NOT doing it (such as considering your design more carefully and testing public methods will indirectly test private ones). And while I'm still thinking about the merits of when you really need to test private methods, one thing did stand out to me and has proven very useful for my Monopoly Simulator.

I found that my Player objects should not expose their amount of cash as a publicly accessible field or method. Players in the real game of Monopoly, need not reveal how much money they have on hand. However, this presented a problem from two standpoints:
  1. The Bank (or some other aspect of the game) might need to know how much money they have left in order to properly control the flow of the game - I have yet to actually run into this scenario yet, so I'm going to employ the principle of YouArentGonnaNeedIt - and not worry about it until I need to.
  2. During unit testing, the cash level of a player indicates a successful test or not. This I have ran into and have used reflection to solve the problem.

Here is a method that accesses a private int field of any object:

private int getObjectPrivateIntValue(Class clazz, String fieldName, Object object) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
   Field field = clazz.getDeclaredField(fieldName);
   field.setAccessible(true);
   return field.getInt(object);
}

This is my first time bypassing the security of a class like this, so I'm not sure of all the ramifications yet. One thing I've noticed though, is that I'm tempted to put this kind of method into my actual application. This seems like a really bad idea. But, for unit testing code, it seems ok.

My next challenge, which is along these lines, is going to figure out how to make it so certain methods on Players (such as sendToJail() and pay(int amount) ) are only accessible to authorized classes (such as the Bank or Board objects). I can't make these methods package protected because other Player objects should not be allowed to call these methods. I need either some sort of SecurityManager. Maybe this is another place that aspects could help?


Wednesday, January 19, 2005

Monopoly Simulator

I have been working on a Monopoly Simulator for the past week or two. It's turning out to be an interesting project. At first I thought it would be interesting to simulate games to see if I could glean any strategic points, but a quick Google search turned up all kinds of Monopoly statistics. But, the more I thought about it, the more I thought it would be interesting to have a "pluggable" architecture so that different "players" could have different rule sets. Of course, because of my competitive nature, this quickly leaped to having people develop their own players with their own set of behavior rules (e.g. when they buy property, which properties they go after, trading, etc...) that could play against each other. On the other hand, I have a hard enough time finding people to play the regular Monopoly board game with me, much less code their own player rules in Java.

So, now I think I'm resigned to develop it just for learning's sake - which is sort of freeing.

I started out ok last week and identified which objects I would need and came up with what I thought would be a working model. Things were going ok, but then in typical form, I got a little excited about the whole thing and threw TDD out the window. Several lunch hours later, I had a Monopoly simulator that was "working" in that it actually simulated games and had a winner at the end, but I had no idea if it was working properly because I had no unit tests. The design also ended up in a rather unsatisfying mess with little room for expansion or flexibility. I need to refactor, but looking at it again I think I need to start over and just pull bits and pieces out as I need them.

I'm really interested in trying to integrate AOP in here somehow. I think in the area of generating statistics this will be great because that is certainly a cross-cutting concern. Each action in the game should be able to register some statistic of what just happened. Also, I'm thinking of using a rule engine for the player rules. That way, it's much easier to modify the player behavior using pseudo-english and, who knows, may even help get someone else to develop their own player.

More on this later.