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