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.


Permalink Leave a Comment

Jemmy in Scala and readying for deployment

June 11, 2009 at 10:08 pm (Scala, Week 12) (, , , )

I spent most of the morning working on integration tests to make sure I’ve got control of the Swing side of things. Jemmy is the library I’m using to drive these high-level tests. It’s great that I can now find some text on a button and click that element – it gives me a high level of confidence that I’m not going to break things when I go in and refactor things a bit later on. There were a few gotchas I ran across, so I thought I’d share those for anyone else trying to integrate Jemmy into a Scala project.

First of all, getting up and running was a bit of a trial. I knew I wanted to drive the tests with the same framework I’m using for the rest of my testing on this project: Scalatest (which is awesome, by the way – lots of choices for test syntax, though no mocking capabilities that I know of). There was some talk in the Jemmy docs online about writing a main function in your test class, which I wanted to avoid, and the only way I found to fire up the application was something like this:

new ClassReference("SwingTicTacToe").startApplication()
mainWindow = new JFrameOperator("Tic-Tac-Toe")

And, to end it:


The sleep was a workaround for what I believe to be a threading problem – I spent about an hour trying to figure out why my tests were not failing as they should have been if mainWindow was closed after they ran, only to find that there was apparently a timing issue going on when I added a println right before closing the window. The println took just long enough to give me the right behavior a little more than 50% of the time. All of this weirdness leads me to believe that there’s an easier way to do this. Eric Smith worked around it in a Java application he’s working on by using Mockito to mock out the application itself (sounds like he’s restricting Jemmy testing to his view), but I’m not sure how I’d do that in Scala.

Another problem I encountered was getting the tests running in an Ant task. I ended up with this:

<target name="test-integration" depends="clean, init, build.compile, test-integration.compile">
   <exec executable="scala">
     <arg line="-cp ${statemap.jar}:${scalatest.jar}:${jemmy.jar}:${build.dir}" />
     <arg line="org.scalatest.tools.Runner" />
     <arg line="-p ${build.dir}" />
     <arg line="-o" />

Of course, this is relying on some other definitions elsewhere in my build.xml file, but the problem I had was that I didn’t have a task like I would have with Java. Also, it’s important to note that all the arg tags have attributes name “line”. When I was following examples I saw in the Ant documentation, I saw lots of tags that looked like <arg value="..." />. This didn’t work in my case, apparently because “value” mangles strings with spaces somehow. Changing “value” to “line” did the trick immediately.

I also spent some time breaking my previously single-directory, default-package code into parallel test and source directories, with four packages: basegame, gui, console, and players. I still have some final code quality checks I want to do, but it’s very close. If I have time left over after passing through again for SOLID violations, I may work on some styling and learn about graphics objects and drawing in Swing (gradients, specifically).

Permalink Leave a Comment

Refactoring to separate presentation from logic

June 10, 2009 at 5:41 pm (Ruby, Scala, Week 12) (, , , )

My plan today was to dig into my Swing code, get some tests wrapped around it, and eliminate the duplication that built up last night as I played around with styling. Company business intervened, so I spent most of the day on a project with Eric M. and Caleb working on translating a large set of data into YAML format (with occasional HTML where necessary). As we got started, I realized that my work was going to be extremely error-prone, tedious, and slow if I just copied and pasted things over, formatting as I went. So I hacked up a Ruby script to do the basic import to YAML, which I think saved a lot of time (and I feel much more comfortable with handing this to the client). We did still do a bit of manual work (every export we sampled from our word processing program had limitations), but it wasn’t too bad.

Eventually, I got back over to my Swing code and eliminated a lot of duplication. I’m working on extracting all view/presentation code away from the code that I need to test. I’m not, for instance, going to bother with a test to make sure that the background color is blue. Among other benefits, this will make it clear to me when I’m finished, as I go through and add tests. I read the chapter in Programming in Scala last night on pattern matching, and I’m seeing uses for it everywhere now. I’m going to be very careful to avoid switch statements where polymorphism is possible, but I’m starting to get more comfortable with Scala and find multiple solutions pretty quickly.

There’s been some talk recently on the JRuby mailing list about using Jemmy to write integration tests on Swing code, so I’m excited about its prospects as I delve into my GUI tests.

Permalink 1 Comment

Constant improvement does not require judgmental reflection

June 9, 2009 at 6:49 pm (Scala, Week 12) (, , , , )

I spent much of the morning wrapping tests around the state machine code I’d written last week and over the weekend. Obviously, this isn’t the ideal way to write tests. I want to be a programmer who does TDD all the time, but I wasn’t that programmer on parts of this project. In the sections of the application where I’d done similar things before (the board and the players, for instance), I had no problem incrementally describing the functionality in specs and implementing it. But as I wrote my first state machine code and experimented with a new interface to Swing, I found myself implementing more and testing less.

As I gain experience and learn from colleagues through pair programming, I imagine that my discipline and abilities with regard to TDD will continue to improve as they have in the past few months. In the time being, I’m proud of the amount of code I’ve been able to delete as I write tests and discover the functionality that is really necessary. There is plenty left to do, but my Scala code is much simpler and easier to modify than the Java version of Tic-Tac-Toe, even though the language is still pretty unfamiliar, and the documentation sparser than Java’s.

I was complaining to Doug late this afternoon about the variations in GUI frameworks that make it difficult to get started in a new one, and I realized that what I really want is to know Swing and Limelight as well as I know XHTML/CSS. Again, I think this is a case of frustration based on lack of experience: once I have years of day-to-day Swing experience under my belt, that will feel great, too. I’m slowly learning to reflect on my coding in a less judgmental way. Bruce Eckel’s recent blog post, “A Career in Computing”, advises “There is no right answer … and always a better way. Show and discuss your code, without emotional attachment. You are not your code.” This gels with my experience in music, where I find it very easy to beat myself up mentally for mistakes that I’m not yet skilled enough to avoid. My goal here is not to feel good about bad code, it’s to learn from my mistakes and engrain a healthy state of mind when coding. If I’m frustrated when coding, I’m teaching myself (unconsiously, of course) that it’s the correct way to feel when coding, and inevitably I’m going to make less progress.

Permalink Leave a Comment