Learning by Testing

A while ago, Mike Clark wrote two blog postings on how to learn Ruby by writing tests (#1, #2). He explains that he wrote a test for each bit he learned about the language, over the years collecting a set of more than 200 tests which act as his personal knowledge base on the Ruby language:

Through trial and error they taught me how Ruby and its rich set of libraries really work. Not surprisingly, typing in code and running it makes you remember. Indeed, writing learning tests is a fun way to poke and prod any new language or API. And with every test you write you’re investing in an executable knowledge base.

Unfortunately I never tried this myself, but I like the idea. According to him, the benefit is twofold: The tests assist in acquiring and checking knowledge (by what he calls “asking Ruby”) and act as a knowledge base that manifests itself in code (and some documentation, where needed, I’d like to add).

Yet I am a little bit skeptical about “asking Ruby”. In his second posting, he suggests to “make a guess” in a particular case where he doesn’t know the result of a method invocation (“Rick”.index(’t')). Maybe I’m a bit hypersensitive here, but I have some reservations when it gets to using tests to find out how things (could or should) work. I’d think it would it be better to just look it up in a reference and write the test afterwards. The main reason is that using one test case (or a few) will give you one (or few) results, from which you will have to draw conclusions and generalize—the semantics of the index method in this case. What if your conclusions are wrong for some exceptional cases? Is it possible/feasible/desirable to write tests for each and every combination of parameters for a method? Why not trying a “read first” approach?

Nevertheless, the basic idea of using test cases for playing around with a language and collecting them as a reference is a nice idea. I’ll almost certainly try this the next time want to learn something about Ruby or a different language.

How to not solve a Sudoku

I found this at Ravi Mohan’s One Man Hacking:

Ron Jeffries attempts to create a sudoku solver - here, here, here, here and here. (You really ought to read these articles. They are ummm…{cough} …err…. enlightening.)

Peter Norvig creates a Sudoku Solver.

Compare. Learn.

To increase the impact, I suggest you read Norvig’s essay first. It’s a great read and the elegance and concision of his solution gave me this tingly warm feeling of sheer developer entrancement. In contrast, Jeffries’ writings on implementing a Sudoku solver by following a test-driven development approach, are just disconcerting. In the end, he abandons his half-finished work after five postings. If he achieves anything, he impressively demonstrates that he’s not exactly an algorithms expert (which Peter Norvig, of course, is).

But, as Ravi says, there’s an important lesson to learn here: agile approaches are about software development, not about algorithm design. To be more precise: they are mainly about achieving software quality, not correctness. It’s the purpose of tests to help the developer maintain functional correctness - not to guide her towards a correct solution of an algorithmically non-trivial problem, such as Sudoku solving.

I think, this is a good example for the old saying “If your only tool is a hammer, every problem looks like a nail.” And it supports my impression that in these days too many people in the development world focus on the methodological aspects of software development and underestimate the importance of fundamentals such as algorithm design.

UPDATE: Vlad Levin goes into more detail on this issue.