Saturday, March 21, 2015

Book Review: Clojure Web Development Essentials by Ryan Baldwin

A few weeks ago, I got an email from Gavin Cardoza at Packt Publishing offering me a free e-book in exchange for writing a review of Packt's recently-published Clojure Web Development Essentials, by Ryan Baldwin. I think I'll turn down the offer of a free e-book, but I'm happy to write a review because I think Baldwin has done an excellent job on the book. (Disclaimer: I did get a review copy of the book at no charge).

Rather than trying to survey all the tools and libraries available to the Clojure web developer, the author has made the very sensible decision to zero in on Luminus, a mature and well-crafted base project that provides you with the fully-functioning core of a web application, without locking you into a rigid framework. Starting from the Luminus defaults, Baldwin then walks you step by step through the process of configuring the server, configuring the logs (including the tricky bits!), handling forms, persisting data to a SQL database, handling logins, security, and sessions, and finally deploying to production. At each step, you have a fully operational (though incomplete) web application to play with, so the feedback is immediate and satisfying.

In keeping with the Essentials theme, the author sticks to the basics, and resists the temptation to drag in all the interesting related topics that so often muddy and confuse introductory tutorials. Anywhere Luminus offers the developer a wide range of choices, Baldwin picks a good one and runs with it, without falling down the rabbit hole of trying to consider the strengths and weaknesses of each option. This makes the book much easier to follow, retain, and apply, and keeps it from getting boring. Those other choices are out there, and you can learn them later if you're interested, but when you do, you'll already have the basic essentials down, and will be much better equipped to relate new information to what you already know.

As a web developer who uses exclusively MySQL (and/or MariaDB) in my day job, I was interested to see that Baldwin chose to focus on PostgreSQL as the database for this book. That's a good choice for anyone interested in deploying to Heroku or a similar platform, where Postgres services are easier to find than MySQL services, but it might surprise you if you're coming to this book from other web development environments like me. If you haven't played with Postgres before, this book might whet your appetite for more.

If I had to criticize this book for anything, it would be regarding two points. First of all, this book is written from the point of view of a developer working either in OS X or Linux, not Windows. That's understandable, since Clojure development involves a certain amount of command-line work, and Windows brings in a bit more complexity when it comes to getting everything up and running. The omission does make it easier for the book to stay focused on the Essentials of Clojure web development, but might prove frustrating to Windows-based developers trying to get their feet wet in Clojure for the first time.

My other complaint is that the book does not spend a lot of time on the topic of web security. This, again, is probably a tactical decision in the interests of keeping to the Essentials, but being the naturally paranoid person that I am, I wish the book had devoted more discussion to the topic. It does at least walk through the process of using bcrypt to secure passwords, instead of making the mistake of storing them in a decryptable form, so that's a big point in its favor. But an appendix, or at least a link or two, would not have been amiss.

Other than those two complaints, I was very impressed by this book. The writing style is lively and interesting, yet clear and to the point. The examples are easy to follow and do a good job of conveying the technology they are trying to explain. And I love his decision to implement his database interactions using YeSQL rather than a more complicated ORM or ORM-ish system. As someone who has to wrestle with ORM syntax every day (in PHP, no less), the simplicity of straight SQL-as-a-function is something I drool over.

I've got a number of Packt books and I keep going back because they're generally high quality and their e-book format is just right for the Kindle app on my iPad, but I have to say that Clojure Web Development Essentials looks like one of their best so far. Kudos to Ryan Baldwin on a great job, and I hope he decides to do a follow-up book on securing Clojure web applications. (Hint, hint.)

Sunday, October 20, 2013

Test-Assisted Design

I'm re-thinking my opinions about unit tests and test-driven design. On the one hand, part of me immediately liked the idea of TDD as soon as I heard it: by writing out your tests first, you have a clear, unambiguous spec for what you're supposed to build. It's clear, because it has to be a test that the machine can run, and it's unambiguous because it's a test. It either passes or it doesn't.

On the other hand, I've been having second thoughts about unit tests ever since I saw Rich Hickey's talk on Simple Made Easy, the Magna Carta of functional programmers. Tests are good, but-- Tests are necessary, but--

The thing is, unit tests could be thought of as a kind of code smell, or a kind of technical debt. You're writing tests because you don't know what your code is going to do. And maybe that's unavoidable. Maybe programming is just too complicated for us to write code that always does exactly what we expect it to do. But still, a code smell, a sign of an undesirable circumstance that we should be trying to avoid or reduce.

Monday, July 29, 2013

Nil is not enough

Here's the context: I'm separating out all my data-store-related functions into their own namespace. Specifically, I'm working on my User model. I want to write a function that creates a new user in my data store, but only if there's not already a user with the same username. No problem, right? If the user already exists, I just return nil, the same as for any other error.

Now I'm using the create-user function I wrote above, and I pass in a user name, and I get back nil. Does that mean there was a database error (not enough space left on drive) or does that mean there was already a user with the same name? I want to get additional information out of nil, but nil doesn't contain any information. It's nil!

Sunday, July 21, 2013

Setting up Friend: a few preliminaries

[Revised: found out my first diagnosis and fix were incorrect, but eventually I tracked down the real answers.]

For my summer project, I'm developing a web site that local food banks can use to let people know what items they currently need. Long term, I want this to be accessible via smart phones, but for now I'm just getting started with the basics. I'm using the Luminus framework to kick things off since it's so convenient and well-documented.

I initially set up my site with support for DailyCred, which I only heard about because it was one of the template options for creating a new Luminus project. It seemed pretty easy to set up, and I got as far as redirecting users to DC and getting back the token, but at that point DC would complain that I was using an unknown client ID (even though it was a valid ID that worked correctly in their sandbox), and I'd be dead in the water. Finally I decided to fall back to a more conventional approach: today's project is to rip out all the DC stuff and replace it with Friend. Partly this was frustration with DC, and partly it was because I just got done watching this video, and wanted to take Friend for a spin.

Wednesday, January 11, 2012

Ah, a secret gateway into ClojureScript

I've been very interested in ClojureScript since it was first announced, but somehow I've never quite made it over that first hill. I think that may be about to change though:

ClojureScript One is a helpful resource for getting started with ClojureScript. It is not a library or a framework. It is an example with lots of documentation. We hope that by looking through this example and reading the documentation we can remove the barriers that are stopping you from experiencing how much fun ClojureScript development can be. Once you have this experience, we think you will be hooked.
You can find ClojureScript One on the web at http://clojurescriptone.com.
 I've downloaded the git repo and got the "Getting Started" stuff up and running in no time. Now if you'll excuse me, I have a REPL or two to play with...

Tuesday, January 10, 2012

The perfect language

I was browsing through Planet Clojure the other day and saw a post about "The Book the World Needs." Not to give away the plot, but the missing book is an introduction to functional programming for non-FP programmers.

I'm not the guy to write that book, but reading that post reminded me of some of my early programming experiences, and helped me understand what it is that I find so appealing about Clojure.


Sunday, November 27, 2011

What I've learned from Salty

I spent the weekend hacking at my Salty library for Clojure. Salty is a thin wrapper around the Selenium WebDriver framework, and it allows you to programmatically control a web browser like Firefox, as I've mentioned before. It turns out there is already a Clojure lib for WebDriver---clj-webdriver---that is full-featured, easy to use, and very mature. For that reason, I'm probably not going to invest too much more effort in Salty. But that's fine: I mostly wanted to try this as a learning exercise, and clj-webdriver makes it easier for me to check my homework. Here's a few notes on what I think I got right and what I think I got wrong.