Week 5, Tuesday

April 21, 2009 at 9:26 pm (Java, Week 5) (, , , , , , , , )

Eric and I spent the morning making some styling tweaks to the Rails application, and I moved back to Tic-Tac-Toe in the afternoon. I got the board score caching to work almost immediately, or so I thought. Micah sat down with me to help me with my Ant build, which had been broken since I split the project up into packages. The fix there turned out to be easy (with the right knowledge): I needed to add JUnit to the compile classpath. For some reason I had it in the classpath for the <junit> element for running the actual tests, but not in the compile.

So then we took a look at my caching mechanism, which was taking up the whole heap and throwing errors at 6 levels deep in the game tree. Micah helped me to increase the heap size to 512MB, which got us to 9 or 10 levels deep, but we still eventually took up the whole heap again. We spent some time with a profiler tracking down the objects being created, and of course it was the hashed objects (~ 6 million of them) taking up all the memory. We worked for awhile to decrease the memory we were using, but we didn’t end up making it any more levels deep. At this point, the 4×4 computer player still makes some weird moves near the start of the game, but he gets smarter towards the end and avoids losses.

Micah noticed that my caching didn’t have tests (cringe), so that was my next assignment. Because my minimax method was so big and complicated, I kind of went to town with the Extract Method refactoring and eventually figured out a way to get some tests written on the caching part. Along the way, I discovered that JUnit doesn’t allow you to test private methods, and got some “Extract Class” knowledge dropped on me by Doug, who said that if I had a private method that wasn’t already covered by tests on my public methods, maybe those private methods really belonged somewhere else, as public methods on another class! For now, I’m just changing the method I wanted to test into a public method.

I like the looks of this class a lot better now that it has smaller methods – it’s a lot more readable. I think I picked some decent names, like writeScoreToCache(), getCachedScore(), getValueToOtherPlayer(), finalScore(), calculateBestScore(), etc. There is still a lot to be done for this program to look like something out of one of these books I’ve been reading, but it’s getting closer. And I’m getting a lot better at seeing what the differences are, which I think is really positive.


Permalink 1 Comment

Week 2, Thursday

April 2, 2009 at 6:49 pm (Java, Week 2) (, , , , , , , )

Software design was my main focus today – I spent some time creating an updated UML class diagram of my Tic-Tac-Toe game. By creating a Swing-based GUI for the game, I had been forced to make some abstractions in the View/Controller area, and a lot of SOLID principle violations got fixed in that process. However, once I had drawn the UML up on the whiteboard, I saw several things that I knew Micah would point out, so I spent some time cleaning up before I had him look at it.

For instance, my ConsoleView and SwingView classes had dependencies on my PlayerFactory implementation, which was a violation of the Dependency Inversion Principle (DIP). Now, just to be clear, especially for those who haven’t already read Uncle Bob’s (Robert C. Martin’s) books and articles, programmers don’t follow these principles just because they exist – there are clear reasons to adhere in specific situations (and I think by extension, in general wherever possible). My problem here was that if I want to write a new PlayerFactory, which creates Players that have faster algorithms or which pick moves randomly, then I’ll be stuck in the situation of having to go down into all the views and change code there.

I’ll be a bit more specific to make this clearer. My PlayerFactory implementation had an enum full of things like Computer_V_Human, Human_V_Human, etc., to which the views had to have access in order to parse the names and display the game type choices to the console or GUI. So then I couldn’t change a field in PlayerFactory without needing to verify that it’s OK with the view. But PlayerFactory shouldn’t have to worry about that! I refactored PlayerFactory and the Views, adding a method gameTypeToString() on PlayerFactory, so that now the Views are telling the PlayerFactory to do something, rather than pulling out and parsing enum members, which felt kind of magical (in a bad way). At any rate, the final step was to extract an interface out of my implementation of the PlayerFactory, so that now the Views could just refer to the interface and not the implementation. The Dependency Inversion Principle says you depend on abstractions, not implementations or details. Especially when you have an idea that those details are going to change…

Which brings me to my next big assignment: I still have a significant number of DIP violations with dependencies on my Board class, which means that it will be hard to change it (it’s rigid) and I’ll break a lot of stuff when I do change it (it’s fragile). So what part of the application would you guess that Micah wants me to change? Indeed, now I need to create the option and implementation to play 3-dimensional Tic-Tac-Toe. There are 2 things I foresee happening: (1) lots of pain when changing the Board, and (2) lots of changes in other places. I know the minimax algorithm in particular is going to take a lot longer to run – I’m going to be traversing a tree with a LOT more levels: 27 vs. 9. That might not sound like a lot, but the number of nodes grows exponentially. There are 2^9 (512) nodes right now at the start of the game, but now there will be 2^27 (134,217,728) – OUCH! I may be off by one on those exponents, but you can see the problem… And I can see that I’m going to need to use some of the speed strategies that I read about when I was researching the minimax algorithm.

Permalink Leave a Comment