I went on a reading binge over Thanksgiving break. Read on for reviews.
Test-Driven Development By Example
First I read Test-Driven Development By Example. This is a very short book, especially given the hefty price tag. I would probably not have bought this if I'd seen it on a shelf at the store rather than online.
That said, it's a good book if you want to understand the mindset behind the whole test-driven development fad. The book is heavy on mindset and light on mechanics; it doesn't tell you how to set up an environment, how to compile and run tests, or any such thing. It just goes through some examples and explains what the programmer was thinking, and how to tackle the problem from a TDD point of view. The intended audience therefore is someone who has plenty of experience programming and wants to learn a new way to look at problem solving.
The book goes through writing some terrible code (admittedly terrible by the author) to solve a simple problem, then refactoring the code to be less and less terrible by means of tests. The writing style is engaging and casual and he describes mistakes as well as successes, which is a nice way to write a tutorial book. The alternate writing style, belting out the correct answer the first time every time, is not as enlightening, and I appreciate it in this book.
The book places a heavy emphasis on writing tests FIRST, making small incremental changes, and refactoring as you go. It also explains how TDD can be related to various OOP design patterns, which I didn't find all that helpful. And it describes some "test patterns", which I found even less helpful. But it's mostly an aesthetic objection; something about "design patterns" sits less and less well with me the more I get away from Java-like languages. The information is still good, straightforward and to the point, take it or leave it.
I have been unable to drink the TDD Kool-Aid, but I can see where it'd probably result in an improvement in some of my code for certain specific kinds of problems. I'll probably try it out again next time I have to write a little library at work.
This book is expensive and short, but the alternative for learning about TDD are half-baked blog posts, which is why I bought a book. I don't know of a better book because this is the only one I have, and I'm unsure at this point whether I really want to buy another book on this topic. But this book is highly recommended by many TDD
fanatics enthusiasts, so I don't know.
The Little Schemer
Next I read The Little Schemer. The style of this book can best be described as "cute". Examples all use food, and it instructs you at various points to go make yourself a sammich (even leaving room in the book for "jelly stains"). This somehow makes the topics, which can be rather intimidating, somehow less scary. The book is very short, and not very dense (not many words on a page), but they somehow cram a lot of information into the book anyways, via the many examples. It's a very focused and methodical book.
This book goes through developing a simplified dialect of Scheme, with a focus on recursion and building up parts of the language from very simple primitives. There are some neat little things along the way, like using s-expressions to represent numbers, and building up a full set of arithmetic functions using nothing but "add 1", "subtract 1", and recursion. It'd be insane to do in real life because of performance, but it's really neat from a "hey look what you can do, isn't this cool!" point of view.
The first half of the book is pretty simplistic (at least for me, with some basic knowledge of Lisp and Scheme), but the second half really starts delving into some crazy things, passing lambdas around to lambdas and writing evaluators and stuff. But you almost don't even notice because of how solidly the foundations are built up to that point, and how well the examples are explained. (You probably will notice once you hit the y-combinator, on account of your brains detonating.)
This not a good book for "learning Lisp" in terms of learning the gritty details of to use a real-life implementation of Lisp. But it's a good book for learning some of the concepts that make Lisp and functional languages powerful. This is a very interesting and unique book, also highly recommended by many in the Lisp world. I'm already planning to try The Seasoned Schemer next.
Real World Haskell
Finally I started plowing through the recently-released Real World Haskell. This book is freely available online, which is great. It also allows readers to make comments on every paragraph in the book, which is a highly collaborative and probably very intelligent way to write a book, and also can provide insight for readers who don't understand the text at any given point. I may buy a hard copy, I haven't decided. (The online version has some FIXME notes and typos that I can only hope are fixed in the real thing.)
I'm only up to chapter 11, but it's good so far. It gives a ton of examples and goes slow enough for people completely new to Haskell to pick the language up. And it includes some of the mechanics of compiling and/or running programs in GHC, which is extremely helpful. I did start getting lost around the time monads were introduced, but that's to be expected. It usually takes me two or three good reads of this kind of book before I grok it all, which is no fault of the book.
Haskell. Last time I used it, I wrote Pong in Haskell in one of my college classes. It was an immensely painful experience. I'm going back to re-learn Haskell now because I find myself edging more and more toward functional languages and away from the C/Java world.
Haskell is far too much to swallow if you have no experience with functional programming, which is probably why I hated it in college. (That said, a smarter person than I may have fewer problems.) After graduating school, I got my first whiff of this world again via Perl's
grep and friends. Then Ruby pushed it home for me with its widespread use of block parameters (lambdas in disguise). And after learning Lisp (and especially later, Clojure) I can't live without higher-order functions. If I had to write a classic for-loop and manually keep track of a counter variable I'd probably vomit at this point. Haskell takes function manipulation to an even greater extreme, which I still haven't fully wrapped my head around, but I like what I've learned so far.
Laziness is awesome, function currying is awesome, and this is the first time I've read about folding, apart from brief struggles with Ruby's (poorly named)
Enumerable#inject. Pattern matching strikes me as vaguely similar to Common Lisp's / Clojure's destructuring-binding, which is one of the nicest features I've seen in any language when it comes to making a programmer's life easier.
Maybe it's all just interesting because it's still new to me. But I like the whole idea of functional programming. I like the idea of functions that always produce the same output from a given input. How and when to handle side-effects and object mutation is a problem that's always nagged at the back of my mind even when writing Ruby code.
That said, Haskell still (at this point in the book) does not strike me as a practical or real-world language in the slightest. You've got to jump through some crazy hoops to get a lot of things to work, especially when it comes to I/O. The book describes how to write a pretty-printer, and how to parse a binary file, both of which require some acrobatics to write concisely in Haskell. In particular the parser library lost me entirely; functions were being chained to functions in all directions and I couldn't follow it.
I think one reason Java is so popular is that you don't have to be a genius to write it. To write Haskell (or even Lisp) well, to take advantage of the language and use it smoothly, you really do need to do some deeper thinking. The abstractions are more powerful and more "abstract". It's not too hard to understand a world made of objects with a bunch of knobs you turn via method calls. Lambdas and recursive functions and monads and typeclasses are a more ephemeral thing.
That said I plan to stick with the book. Practice makes perfect.