Tidying up Tic-Tac-Toe and some serious writing

June 12, 2009 at 4:53 pm (Scala, Week 12) (, , , , )

Today was packed! I started out by wrapping some more tests that I’d been wanting to write (clearing out TODO’s that had been hanging around). None of them were actually very hard, which was a welcome relief after struggling a bit yesterday with integration tests.

Then I drew some UML to analyze my code for SOLID problems (and package principle problems). Things were actually not as nasty as I had feared, but there were four or five violations that became immediately apparent. I had my Player factory in my basegame package, so there were some circular dependency problems between the basegame and players packages. I solved that pretty easily by moving the factory into the players package where it belonged. Another problem I had was with my Game class depending on a concrete Board implementation for a clear() method, which I got around by requiring my Boards to implement that clear() method.

After cleaning up these violations, I worked on refactoring my test code, some of which was not DRY at all (I learned kind of late in the game about Scalatests’s BeforeAndAfter trait). I also wrote a kind of neat trait that allows for easy Console redirection. I also went ahead and posted the code to GitHub: http://github.com/trptcolin/tictactoe-scala/tree/master. The trait I’m talking about is at test/unit/console/ConsoleRedirection.scala. Passing a function as a parameter makes this kind of thing easy – where you need to wrap a function in some other function calls.

For the time being, you’ll need Scala in your path to actually run the game. I may at some point turn this into an executable jarfile, but not tonight.

I also did a lot of work based on helpful feedback and suggestions from Micah, Caleb, and Eric S. on a more in-depth and technical blog post that’s my other remaining apprenticeship challenge. It’s a refactoring of a simple example to a more functional style in Scala, and it took a lot more reflection and thinking than I expected it to. It’s not that I expected to breeze through it, it’s more that I hit several points where I thought things were great, and then got feedback that made me take a few steps back, because the issues they raised were things I hadn’t even considered.

Today at Lunch & Learn we watched the Clojure Peepcode. It was pretty awesome, but there was a point maybe 3/4 of the way through where I should’ve taken a break, because I got a bit lost. I was definitely glad I’d had some experience with Scheme (Clojure, like Scheme, is a Lisp dialect) – that helped a lot at the beginning. There’s one feature of Clojure in particular that seems amazing to me. My understanding was that if you construct an expression where a symbol is used in place of a function, and a map is the argument to it, the expression will result in finding the value in the map whose key is the symbol at the start of the original expression. I’ll have to look into this further, and I’m not sure if there’s a practical reason for this, but it seems to me to be along the lines of Ruby’s 5.times {puts "hello world"}. Pretty cool stuff.

Advertisements

Permalink Leave a Comment

Week 1, Thursday

March 26, 2009 at 7:05 pm (Java, Week 1) (, , , , , , , )

I FINALLY got my head wrapped around the minimax algorithm today. I went more slowly and stepped away more often, and I finally have an unbeatable computer in Java. This took me a heck of a lot longer than it did in Ruby, but I think it was reasonable considering my limited Java knowledge, a new algorithm, and new knowledge about things to avoid.

My last step was kind of an interesting one: I rewrote (not refactored) part of the algorithm in a way that was easy for me to understand, very slowly and deliberately, and it came out right! Imagine that…

// before:
bestScore = Math.max(bestScore, -minimax(child, depth - 1, otherPlayer);

// after:
otherPlayerScore = minimax(child, depth - 1, otherPlayer);
maxOtherPlayerScore = Math.max(otherPlayerScore, maxOtherPlayerScore);
bestScore = -maxOtherPlayerScore;

If you take a minute or two to look through this, you’ll see that the two versions are not equivalent. Although I could break the second version down into one line, I don’t trust myself to be able to understand it as well later on, so I’m leaving it explicitly spelled out this way.

I demoed the game for Micah and indeed, it seemed to work correctly. Micah had me draw up a UML diagram of the code in its current state, with all the methods and dependencies that I knew about, and Micah pointed out violations of the SOLID principles for object-oriented class design. I’d read about them but needed a refresher and deeper understanding, so he walked me through each of the principles, asking me what they were and where I saw problems. I didn’t catch them all of, course, but I was glad I at least had a cursory introduction already. I made sure that I understood the kinds of situations in which a principle violation would bite me.

For those unfamilar with these, you can learn more on Ward Cunningham’s wiki (he’s the inventor of the wiki, among other distinctions):

I just read about these for the first time a few months ago (they’re detailed in Agile Software Development: Principles, Practices, and Patterns by Robert C. Martin (Micah’s dad, incidentally). I had more Dependency Inversion violations than anything (though certainly not as many as my Ruby version had), but there were some Open-Closed problems as well.

My next step, which seems realistic for an Agile/XP project, is to put a GUI on top of my Java code. I haven’t done anything to speak of with Swing, so I spent a couple of hours this afternoon investigating the API and figuring out sizing, colors, and other things I’m going to need to draw the board.

I have an Open-Closed violation or two around my GameDisplay class, which means that my design is going to have to change around that point in order to substitute the GUI for my command-line output. The good news is that I HAVE a display class in the first place; my Ruby display code was coupled to the rest of the game in several places.

Permalink Leave a Comment