Search This Blog

Be Skeptical of Standard Methods

Standards can be a real time-saver when used appropriately. Adhering to the right collection of standards for a project can save a lot of blood, sweat, and tears. But the wrong application of standards can have as bad of an effect on a project as the right way can be good, resulting in wasted effort, delayed projects, and general frustration. The difference between these situations often boils down to experience and judgement.

Of course, 'standards' is a loaded term. We could be talking about anything from communication protocols to development processes or anything in between. There are industry standards that are in widespread use and proprietary standards that don't even extend beyond a single department or team within a company.

Some standards provide great value because they establish a way of doing things that all interested parties can depend on to work with reliable results. Other standards stifle creativity by restricting possibilities too much or they create obscene amounts of useless work by trying to be everything for every possible situation.

In general, industry standard communication protocols are known quantities, and it's more or less straightforward to choose the ones you need for a given project. While it is certainly possible to make bad decisions in this arena, they're not going to be on the order of rolling your own protocol for connecting to a web server or transferring files across a network (I hope). Those are not the types of standards we're going to worry about here.

On the other hand, an industry standard development process is an oxymoron. There is no such animal. Even the various well-documented Agile methods are implemented in wildly different ways from one company to the next, and those differences matter. Companies can choose between Scrum, Extreme Programming, Lean Software Development, Kanban, or many other variants. They can mix and match different aspects of many of these methods. The possible variations are as numerous as the number of companies that use Agile methods. As a result, it's quite easy to claim to use Agile methods while doing nothing of the sort.

Regardless of what kind of development process a company uses, the main purpose of a standard process is to avoid as many mistakes as possible, whether those mistakes are software bugs, broken features, or deployment errors. It may seem that junior developers would need this kind of structure to help them avoid the innumerable pitfalls that are strewn throughout the development process, but as they gain experience, all of the processes, protocols, and reviews become extra overhead that provides less and less benefit. For senior developers all of this structure confines thinking and saps creativity.

My previous company designed ASICs, and on any given project we had a series of reviews that gated each phase of the development process. (It's much harder to practice Agile methods in ASIC design because each release includes a six to eight week wait to get real silicon back to validate, but we did work towards Agile methods in many ways.) As part of each review, the team needed to run through an extensive checklist of design issues and confirm each item as either verified correct or not applicable to the design.

Some of these checklist items were good design practices that were worth remembering, but they would have been more useful as guides throughout that phase of design than when we were trying to pass the gate into the next phase. Other items made no sense at all because there was no context for them. Some team somewhere in the company was bitten by some issue at sometime in the past, and this checklist item was meant to make sure that never happened again. The problem was that no one else had any idea what it meant or why it had earned a spot on the checklist.

Once useless items start creeping onto company-wide review checklists, they degrade the validity of the entire checklist. Developers get confused about which items apply to the design they're working on, and they start glossing over more and more items until they start rubber stamping the whole thing. Then the review becomes a tedious exercise in hand waving and rationalization that results in endless developer frustration and destructive management skepticism.

The original intent of these checklists was good, but as soon as they started trying to cover too much, they stopped being a tool that developers could use effectively and became an annoyance that developers dealt with tangentially to the project. Instead of enabling good development practices, the checklist creators tried to dictate those practices and micro-manage the development process.

A flexible and efficient development process will provide primitives, not solutions, much like a RISC processor is more flexible and efficient when compared to a CISC processor. A CISC processor tries to be all things for all programs by including many complex instructions that do specific high-level tasks like procedure calls or list sorting. The added complexity ends up wasting silicon area on instructions that are hardly ever used in most programs.

On the other hand, RISC processors attempt to provide a much smaller set of simple instructions that are widely applicable and more easily optimized by compilers. The extra silicon area freed up from not having complex instructions can be spent on things that improve the efficiency of most of the remaining instructions, like caching, pipelining, and branch prediction.

RISC processors provide primitives, not solutions. It's up to the software developer and the compiler to most effectively use those primitives to build the best solution. Passing that control up the stack where there's more contextual information results in cleaner, faster programs.

A standard development process is similar in that the context of any particular project can't be known when the process was created, and the people that create the process may not even understand which methods will make projects more successful. The development team knows the context, and they need to use the process in the context of their project. Smart developers will be able to use a flexible development process to build great software. An overbearing process filled with mindless checklists, inane procedures, and verbose coding guidelines will only slow them down and reduce the quality of their output.

As for the junior developers that are normally the justification for detailed development processes, company standard processes will not save them from making mistakes. Making mistakes is how they learn. A bunch of formal processes are not going to magically create expert developers. They need to gain real project experience and deal with setbacks and slip-ups before they will have internalized the knowledge and skills that make up a senior developer. Having a good mentor will go much further towards this goal than instituting standard development methods and expecting good practices to rub off on them.

Great developers have great judgement. They know what to do in a wide variety of situations to create amazing software with a minimum expenditure of effort. This kind of judgement cannot be captured in lists or guidelines, procedures or protocols because every situation is different; every software program is unique. Standards cannot possibly encompass the diversity of thought and experience that goes into software development, nor should we want them to. While standards certainly have their place and can be useful guides, standardization cannot create greatness. It can only achieve consistent mediocrity. It takes good judgement and creativity to elevate that mediocrity to greatness.

A Right And A Wrong Way To Design An Interface

Ever since the iPhone was unveiled, interface design for high-tech products has taken center stage. The role may go by many different names - user interface design, user experience, human-computer interaction - with subtle differences in meaning, but the basic idea is the same. How do you best design a product or feature so that its use is simple, obvious, and convenient? The better a designer can answer this question, the more useful and enjoyable the product will be.

The best way to get a handle on this question is to analyze a common interface, but instead of exploring the graphical interface of some app or web site, let's compare the keyless entry systems for the Nissan Leaf and the Toyota Prius. The basic idea of keyless entry is that you can lock and unlock your car without getting out your key or fob. It sounds like a simple task, but simplicity can be much harder than it appears. Even seemingly obvious designs are very easy to get wrong.

A Tale Of Two Keyless Entry Systems


Both the Leaf and the Prius have a keyless entry feature that purports to allow the driver to get into the car without rummaging around for a key to unlock it, but they accomplish this feat in slightly different ways. The Leaf has a physical button on the driver and front passenger door handles right where your thumb rests when you reach for the handle. If you have the key fob near the door, you can push the button once to unlock that door. Push it again to unlock all of the doors. Push it a third time to lock all of the doors again. Pushing the button after opening any door will also lock all of the doors.

In comparison, the Prius has a sensor on the inside of the driver door handle that can tell when a hand crosses it. If the key is near the door when this happens, it will quickly unlock before the driver can pull the handle to open the door. To lock all of the doors, there is a pressure-sensitive area on the top front part of the door handle that acts like a button.

The first concern for any design is to get it working. If it doesn't function at a basic level, then there's no point in looking any further. The feature is broken and no amount of beautiful design will save it. Both of these keyless entry systems work flawlessly in the common case, so there's no issue with basic functionality. You can walk up to the driver side door with the key in your pocket and unlock the door with the door handle. It just works.

If you start expanding the situation a bit, though, the Prius design starts revealing problems. Say the temperature outside drops below freezing - not an uncommon occurrence here in Wisconsin for four months out of the year. If you're wearing gloves any thicker than normal driving gloves, the sensor won't recognize your hand and the door won't unlock. You have to pull off a glove and either grab the freezing cold door handle or hunt for your key fob to unlock it, defeating the purpose of keyless entry.

The Leaf's button is nicely rounded and set out far enough from the rest of the handle that you can easily mash it with even the thickest winter gloves on. It's a nice advantage to be able to keep those gloves on while getting into the car. Once inside, the Leaf's essential buttons on the console are large enough to manipulate with thick gloves on so you can leave them on and drive, but I digress.

Things Diverge From Here


Expanding our situation even further, let's say you have a kid. Many people have these, and for quite a few years they need to or like to be carried. The contortions involved in carrying a kid and getting at a key in the wrong pocket (it always seems to be in the wrong pocket) could inspire professional gymnasts. To avoid struggling for your keys with the Prius, you have to open the driver door, twist and bend to hit the inside door unlock button, and then go open the door where the child's car seat is - probably on the other side of the car. You can't double-trigger the door handle sensor to unlock all of the car doors, and the sensor only exists on the driver door.

With the Leaf, you can slide to the left, hit the door unlock button twice with a free knuckle, slide to the right (reminds you of being at a wedding reception, doesn't it?), and open the child's door. If you're on the passenger side, reverse left and right and it works just as well because there's a button there, too.

If you're not carrying a kid, this situation still applies if you're carrying anything heavy that you want to drop in the back seat, but what if you want to put that heavy object in the trunk? If you have a Leaf, no problem. Go right up to the hatch, maneuver one of your hands so you can pull up on the hatch release, and the car will unlock the hatch and pop it open for you. Drop the heavy object in and close the hatch. You could walk off without worry at this point to get more heavy stuff because the car is still locked!

Now try the same thing with a Prius. Sorry, you have to go over to the driver door, get your hand around the handle while carrying that heavy object, open the door, find a way to contort yourself to hit the door unlock button on the inside, and go back to the hatch to open it. That's right, the hatch does not have the keyless entry feature. If you don't want to look like an idiot pacing around your car with a heavy package, you'll have to find a way to get at that key in your pocket. Don't forget to lock up when you're done because the whole car is unlocked.

How Did Nissan Get It So Right While Toyota Got It So Wrong?


There are many more situations that routinely come up where the Leaf's keyless entry proves to be so much more convenient than the Prius. Why is that? What made key fobs so nice was that you could unlock all of the car doors from anywhere near the car. The person unlocking the car wasn't necessarily going for the driver door. Nissan must have realized this and designed the keyless entry system so that the ability to unlock any door was within easy reach. That makes keyless entry work in almost every situation.

Toyota seems to have gotten distracted by new technology that involves extra sensors that probably play nicely in a dealership showroom with potential customers. And while having a door handle that senses your hand is cool at first, the novelty quickly wears off when you start running into all kinds of situations where the feature is essentially useless. Every time that happens, I get frustrated at the system's inability to meet my needs, and that adds up over time.

When designing an interface, first and foremost it has to work. Both keyless entry systems achieve that. Then the interface should be designed for as many use cases as possible. Nissan nailed this goal, and Toyota came up short. Once those requirements are met, you can design for beauty, aesthetics, and high-tech coolness. Nissan settled for a simple, functional design with utilitarian buttons, and they could improve on this design in the future if they figure out how to solve the not-so-simple sensor issues.

Toyota succeeded in making a sleeker door handle, but you'll end up pulling out your key fob a lot more with a Prius. They misunderstood what makes a good keyless entry system, so almost every case where you really need the system to work, it falls flat. If Toyota would have used their keyless entry design in a wider variety of situations, they likely would have noticed its deficiencies and come up with a better design that would be useful when it counts. Don't make the same mistake with your own designs. Use them in as many real-world situations as you can think of, and make sure they work as simply and conveniently as possible.

Two Years of Nissan Leaf Mileage Data

I've had a Nissan Leaf for two years now, and it continues to be an exceptionally fun car to drive. The acceleration is incredibly smooth, the car is ridiculously quiet, and it's been completely trouble free so far. The relatively short range of 75 miles has been no problem, as I primarily use it for my 23-mile round trip commute to work and for random errands in town. The trips are short enough that I almost always charge to 80% to extend the life of the battery.

In the summer I can easily go back and forth to work twice on one 80% charge, but in the winter I would barely make it home on the second day, so I charge everyday. This winter has been especially cold, with quite a few subzero mornings and a couple of days where the temperature went below -10℉.

Because the heater on the 2012 Leaf sucks so much power from the battery, I've taken to using the heated steering wheel and heated seats to keep me more comfortable. The amount of power they use is negligible, and they do an adequate job as long as I have a winter coat, hat, and some driving gloves. I probably could use the heater with no problem because my commute is so short, but the car wouldn't really warm up until I was almost to work anyway, so I skip it and use the much faster heated wheel and seat.

On the first especially frigid day that hit us, I was a bit worried about having the Leaf sit outside all day without plugging it in. When it gets too cold, the battery needs to heat itself to keep from freezing. I didn't want to head home after work and find that the battery had drained itself too much for me to get home. It turns out that I had nothing to worry about. Even after sitting in -11℉ temperatures for nine hours, the battery only lost about 5 miles worth of charge, so there was plenty left to get home.

That's all well and good for winter performance, but I like to dig a little deeper into the quantitative measures of how the Leaf has been doing. I have tons of data on this car, so let's see what it can tell us.

The Daily Trip Log


I've kept a log of every trip I've taken in the Leaf, and I've already written about what I found from the first year and a half of data. For my initial methodology, you can read the beginning of that incredibly long article. A few things have changed for the most recent data I've taken, so I'll talk about that briefly before going through the data.

First, my Leaf's software upgrade near the end of June, 2013 did have a significant effect on the accuracy of the GOM (Guess-O-Meter, i.e. the range estimator). The GOM used to have large variations in two different ways. The estimated miles-to-empty would change significantly while driving in response to changes in speed or inclination, and the initial guesstimate after charging would vary markedly depending on the previous day's temperature and the temperature during charging. The software upgrade dramatically reduced the first type of variation, and also somewhat reduced the second type.

Because the software upgrade changed the GOM behavior, I decided to divide the 2013 data into two halves at the date of the software upgrade. This split works out rather well because that allows for estimating battery capacity changes in roughly six month periods while still having a full range of temperatures represented in each period. Doing one year periods is less useful because the battery capacity could change more significantly within one year than within six months.

The second methodology change has to do with how I recorded the day-to-day temperatures. Initially I was recording a maximum and minimum temperature for each charging cycle, but when analyzing the data I found that this caused a problem when there were more than two trips between charges. Only two temperatures were represented in the charging cycle when there were actually more, and since the range is highly dependent on temperature, I felt this setup was not adequate.

For the last five months of data I logged the temperature for every single trip and then calculated a mile-weighted average temperature for each charging cycle. This more accurate data logging combined with the software upgrade effects resulted in range vs. temperature data with substantially less variance.

Finally, I got a P4460 Kill A Watt electricity usage monitor for Christmas, and I put it into use in January, measuring the amount of energy the car uses from the wall outlet. The intention here is to measure exactly how much electric energy I'm paying for to drive a certain number of miles, and to get a more realistic estimation of the Leaf's miles/kWh efficiency value than its own optimistic estimate.

Interestingly, the Kill A Watt meter was working wonderfully, but I had it plugged into an outlet extender so that I could use the other outlet plug that would otherwise have been covered up. Apparently, the cheap-o extender couldn't handle the 12 amps of current pulled by the trickle charger, and it fried itself and took the meter with it. Luckily, the charger was unharmed, and I got the meter replaced at no charge (thanks Menards!). The new meter's been working great now that it's plugged directly into the wall.

With this new set of data, I'd like to answer two main questions. How much capacity has my Leaf's battery lost so far, and how much am I really paying per mile in electricity costs? Let's start with the harder of the two.

Capacity Loss After Two Years


Figuring out how much battery capacity my Leaf has lost is hard to do because I'm depending primarily on the GOM, which is highly variable depending on previous and current conditions. I could get a special meter that hooks into the car's CANbus and reads raw charge information coming off the battery controller, but I would really rather not. That may be something early adopters and people that love messing with their cars like to do, but that's not the average car owner. I chose to figure out what information I could from the instruments available without making any modifications to the car.

The newer 2013 Leaf remedies the variability problem with the GOM somewhat because it also has a battery level meter that shows the state of charge as a percentage. Having that extra resolution would be exactly what I need to do more accurate calculations here, but until I trade in for a newer Leaf, this is the data I have (click for a larger image):

Post-Charge GOM Vs. Temperature

This scatter plot is separated into 2012 (blue), first half of 2013 (red), and second half of 2013 (yellow) data. If I do linear regressions on the 2012 and 2013H2 points, I get two linear equations that estimate the temperature behavior of the battery for those two time periods. If I assume the battery is at 100% capacity at 75℉ in 2012, then I can solve those equations for what the battery capacity is at 75℉ in 2013H2, and for this data I get 95.0%.

That's not too bad. If that trend continues, my battery wouldn't hit 70% capacity for another 10 years. I'm not sure what kinds of effects impact battery life in the long term, but I've read a number of articles that claim that capacity loss is more significant in the first year or so and then tapers off in the medium term. It would be great if the battery could last for 10+ years and still be usable in a car, but I really can't say how it will behave at that age because that data doesn't exist, yet (or at least isn't available to us common folk).

For the sake of argument, I went further with the calculations in the same way that I did in my last data analysis. I used the linear equations for the capacity-temperature behavior to calculate what the GOM should have estimated the range to be for each charge cycle, had it been able to predict the future average temperature for the trips taken on each charge. Then I calculated what the total range would have been for each charge given that starting point and assuming the rate of decline of the GOM per miles traveled would continue until the battery was empty.

To make this data transformation useful, I had to remove the first five months of data because it was so variable that linear regressions were useless. As I speculated before, this behavior could be due to the GOM being in a learning period for temperatures it doesn't have historical data for, yet. Given that caveat, the scatter plot looks like this:

Linear estimation of range vs. temperature scatter plot

In this plot it's hard to tell if the range decreased at all in 2013H2. Running regressions on the 2012H2 and 2013H2 points and then plotting the resulting linear equations with 3-sigma error lines gives the following plot:

Linear estimation of range vs. temperature line plot

Here you can clearly see the reduced variance in the 2013H2 data points by the significantly narrower error lines for that linear estimate. Improving the calculation of the average temperature per charging cycle probably helped tighten up the variation of the data. The software upgrade likely increased the accuracy of the GOM as well. The more realistic GOM reporting is possibly also the cause of the significantly lower range at low temperatures, although there is much more 2013H2 data at temperatures below 25℉. That extra data at low temperatures is likely pulling the 2013H2 lines down closer to their real values.

If I assume 100% capacity for the 2012H2 range at 75℉, and do the same estimate of capacity loss as before, I get a capacity degradation to 94.5% for 2013H2, or a 5.5% loss of battery capacity. This is in good agreement with the previous estimate, so it's fairly likely that that's where my battery capacity is at after two years and 12,000 miles of use. Compared to my estimate of about 4% capacity loss from five months ago, it seems possible that the loss is slowing down as well. I'm pretty happy with that, and qualitatively in real day-to-day use, I haven't experienced any noticeable loss of capacity. Seeing the numbers confirm that gives me good confidence that this Leaf's battery could last a good long time. I do try to take good care of the battery, and I would like to think that it's paying off.

The Real Cost of Driving Electric


I've written before about how I suspected that the Leaf's mileage efficiency calculations were grossly optimistic. Now that I have an energy meter at the wall outlet, I can measure exactly how much it costs per mile to drive the Leaf. After all, I don't really care if the battery-to-wheels efficiency is 4 miles/kWh or 6 miles/kWh. I'm not paying for the electricity used at the battery. I'm paying for the electricity used at the wall.

Using the energy meter, figuring this out is now pretty easy. In addition to other measurements, the Kill A Watt meter keeps track of the total kWh of electricity that have passed through the meter since it was last reset. All I do is note the kWh on the meter in the morning after each charge and record it for the end of the previous charge cycle in my trip log. Then dividing the change in miles on the odometer by the change in kWh from the energy meter gives me the total energy efficiency for that time period.

After about a month, I've driven 569 miles and charged for 217 kWh, giving me an efficiency of 2.62 miles/kWh. Over that same period, the Leaf reported an efficiency of 4.0 miles/kWh on its display. I was not surprised that the Leaf's measured efficiency was higher. I expected that. I was surprised at how much higher it was, though. If that difference was fully accounted for in charging losses, that would mean that charging with the trickle charger is only 65% efficient. I don't believe that's true, and I figure there are some other possibilities for charge loss.

January was a bitterly cold month, and when the battery has to heat itself to keep from freezing up, that energy usage is probably not factored into the Leaf's efficiency measurement. Losing a few miles of charge to the battery heater when the car is parked outside all day can make a significant difference in the efficiency value. The battery also needs to heat itself up to a certain temperature before charging and it will continue heating itself from outlet power as long as it's plugged in and the ambient temperature is cold enough. I'm quite sure that electricity use is not counted towards the Leaf's efficiency measurement.

It's possible that charging efficiency is also lower at cold temperatures. It will be interesting to see if the two efficiency measurements get closer together when the weather warms up. If the wall measurement doesn't get within 85% of the Leaf's measurement, I would be fairly skeptical of the efficiency numbers that the Leaf is reporting.

Regardless of what the Leaf is saying, now I know how much electricity I'm using to drive the car, at least in the winter. At $0.18/kWh for electricity, distribution, and wind power offsets, an efficiency of 2.62 miles/kWh results in a cost of $0.0687/mile. The average new ICE car has a fuel economy of about 25 mpg, and loses about 20% of that in these freezing temperatures. My wife just filled up her tank for $3.30/gallon, and at that price it costs $0.165/mile to drive the average new car.

That makes the Leaf 2.4 times cheaper to drive on a per mile basis than the average new car. Of course, the ratio will change if any of those number change, but it would take an awful lot to tip the scales in the ICE car's favor. I would expect the Leaf to look even better in the summer because its efficiency increases dramatically, and the price of gas normally goes up as the weather gets warmer and people are driving more.

After Two Years, I'm Quite Happy With A Leaf


The severe cold we've had in Madison this winter has certainly tested the Leaf in new ways, and I'm quite pleased with how it's performed. The heated seats and steering wheel are enough to keep me comfortable without draining the battery on super cold days to keep the cabin warm. By taking good care of the battery through garage parking, charging to 80%, and not charging when I don't need to, it looks like I've kept the battery capacity loss to about 5% so far. Finally, I'm paying a little more than I thought to charge the car, at least this winter. But that will improve in the spring, and it's still 2.4 times cheaper per mile than the typical ICE car. Consider me one very happy Leaf owner.

If you're interested in the other stuff I've written about my Leaf, it's all here:
Part 1: The Acquisition 
Part 2: The Summer Drive 
Part 3: The Winter Drive
Part 4: Frills and Maintenance
Part 5: The Data
Part 6: The Future
Part 7: The Energy Efficiency Meter

Tech Book Face Off: Agile Web Development with Rails 4 Vs. Ruby on Rails Tutorial

It's been quite a while since I've done a Tech Book Face Off, and that's because it's taken some time to get through this pair of books. Whereas most tech books can be read straight through, (even books on languages to get the gist of them, with a little experimentation thrown in) these books are meant to be worked through. They are both written in a tutorial style where they describe how to build an actual web site using Ruby on Rails. That approach makes perfect sense for a web framework like Rails.

I was really looking forward to both of these books. I'd heard lots of great things about Ruby on Rails Tutorial, and I was quite interested to see what working through a tutorial style book would be like. I figured the change of pace from conventional tech books would be refreshing (and it was). Then with Agile Web Development with Rails 4 I was anticipating another great read from Dave Thomas, a co-author of The Pragmatic Programmer - one of my all-time favorite programming books. Having David Heinemeier Hansson, the creator of Rails, as another co-author raised the bar even more.

As for Rails itself, I, of course, had very high expectations because of the vast amount of publicity and high popularity it carries in the web development community. Without knowing any other web frameworks to compare it to, I must say that I was impressed with how easy it is to make well-structured web applications quickly with Rails. Things did get a bit confusing at times because Rails does so much for you that it's not always clear how all the different parts of an application are connected together, but that may have also been due to the fact that I had no prior experience with how web applications are built. At any rate, it didn't take too long for everything to clear up after some experimentation.

Rails is an opinionated web framework that has very strict ideas about how a web application should be built. As long as you follow its lead and program in its style, development will be extremely smooth and you can focus on designing an awesome web application instead of figuring out all the minutiae of things like URL routing, HTML template processing, and database management.

So what is the Rails way? First and foremost, Rails conforms to the MVC (Model-View-Controller) architecture. The model is the encapsulation and organization of the data that your application uses and stores, i.e. the database, and Rails supports a clean ORM (object relational model) to most of the common databases in the industry, including MySQL, PostreSQL, SQL Server, SyBase, Oracle, and SQLite. The view is the representation of the data that can be consumed by humans or other computers. Rails can generate views in the form of HTML, XML, and JSON out of the box and more forms, like PDF, with plugins. The controller basically connects the model and the view with all of the logic and validation that's necessary for making decisions and computing results in the application.

There's a lot more to the Rails philosophy and architecture, but let's move on to the books.


Agile Web Development with Rails 4 front cover VS. Ruby on Rails Tutorial front cover

Agile Web Development with Rails 4


This book actually has three authors: Sam Ruby, Dave Thomas, and David Heinemeier Hansson (known in the Ruby community as DHH). Even with three cooks in the kitchen, the book has a consistent style and feel to it. There is an ongoing narrative about a client that you're working with to build a web store with a shopping cart. The story can get a bit cheeky at times but overall it's pleasant and lighthearted. DHH steps in periodically with sidebars that go into more detail on specific topics on the Rails philosophy, which was nice.

The first part of the book covers setting up the environment for Ruby and Rails. I had already set everything up by the time I read this book because I went through the Ruby on Rails Tutorial first, but I had done it with Rails 3.2 so I tried installing Rails 4.0 alongside for this book. It worked without a hitch. The second part is the tutorial section that goes through building an online book store with a product catalog, a shopping cart, order forms, confirmation emails, administrative accounts, and more. Everything was broken up into small, discrete tasks, or iterations in agile terminology. The last part goes deeper into the details of how Rails works under the hood with its major components: Active Record, Action Controller, Action Dispatch, Action View, and Migrations.

The tutorial section was great for getting your hands dirty with Rails right away. There's nothing like entering a few commands, writing a few lines of code, and seeing a web application come alive before your eyes. It quickly became apparent that most of the work in building a Rails app was spent writing the HTML and CSS templates, and most of the initial work of connecting the views to the database and getting the application operational was neatly handled by Rails. I'm sure to get a finely tuned application, more work would need to be done in the model and controller, but an impressive amount of work is already done for you.

Two things struck me about the tutorial. First, the authors assumed that if they mentioned some practice once, like checking code into Git after every iteration, the reader would then remember and use that practice from then on. I liked this approach of explaining things clearly and then focusing on new information instead of constantly reminding the reader and engaging in too much hand-holding. Second, even though this was an Agile book, not much space was devoted to TDD (test-driven development), and test-first development was hardly mentioned at all. I was surprised by this omission, but I'll talk more about that with the Ruby on Rails Tutorial.

What I liked most about this book was the Rails in depth section. I have trouble remembering how to use languages or frameworks unless I really understand how they work. This section gave me enough knowledge about Rails to really anchor my understanding of how all the pieces connected together, where to look for code, and which files to edit to accomplish different tasks. And the authors were able to lay all of this information out in about 150 pages so it was concise, focused, and extremely helpful. I would say the book is worth buying for this section alone.

Ruby on Rails Tutorial


Whereas Agile Web Development with Rails 4 was split between tutorial and explanation, this book by Michael Hartl is a full-on tutorial. It goes beyond Rails, expanding into many more areas of modern web development. In addition to Rails proper, it covers TDD with RSpec and Capybara, version control with Git, deployment to Heroku, Behavior-Driven Development with Cucumber, a number of other Gems, and a bit of SQL and JavaScript.

In this case the application you're building is a Twitter-like web site that allows users to log on, write short messages, view other users' messages, and follow other users to create an aggregate message feed. It's pretty much a no-nonsense guide to implementing all of the parts of a Rails application that makes a web application like this work, and it is superbly done.

The TDD work flow presented in the tutorial is very compelling. It was great to see how writing tests first can focus your programming efforts and improve productivity. It works best when you already have a good idea of what you're trying to do, so it won't be the right approach in all cases. But where you can write tests first, it's really slick, and a lot of tasks that you'll do in Rails will fall in that category because of the well-defined architecture of Rails applications.

The tutorial is not without its problems, though. What I found difficult about the tutorial format - and this is true of the second section of Agile Web Development with Rails 4 as well - was that it was distracting. While it was great to write code while reading the book because I could see immediately how to use Rails features and where different code should live, it also involved a lot of context switching between reading about features and writing code. If I made a mistake and tests started failing so that I'd have to stop and debug, or I went off on a tangent experimenting on something I found interesting, things could quickly get out of control, and I'd lose the thread of the book completely.

Another problem with the tutorial format was that most of the explanations were focused on how to implement the next part of the application. There was little in the way of describing the Rails features that were being used, how those features worked, and why everything was put together the way it was. The emphasis was all on getting the application features done, and I think that's a poor way to learn anything well. To really learn something so that you can use it effectively, you should understand why it works the way it does at a deeper level.

That critique may sound harsh, even damning, but that's not the case. I thought that as a tutorial Ruby on Rails Tutorial was exceptionally well written, and I enjoyed building up a fully functional Twitter-like application immensely. The issues I have with tutorials may not apply to you, so don't let that stop you from using this book. It's an excellent introduction to Rails that will get you up and running with a real web application in short order. I would recommend checking it out.

The Defining Differences


Both of these books do a great job of introducing Rails, but in slightly different ways. The Ruby on Rails Tutorial has you work through a more extensive (and I would say more interesting) application in its tutorial, while Agile Web Development with Rails 4 supplements a shorter tutorial with more in-depth explanations of the features, organization, and inner workings of Rails. Personally, I would have liked a treatment that presented a series of detailed explanations of how to use the different features of Rails and why they work, with a set of exercises following each chapter that would end up implementing a coherent application by the end of the book.

What I'm describing is essentially a textbook for Rails, but since that probably doesn't exist, I would have to pick Agile Web Development with Rails 4 as my preference. It does a better job of explaining what goes on in Rails under the hood, and I needed some of that to internalize how to use Rails and remember it more permanently. If you learn best from tutorials, and the more in-depth stuff is less important, then the Ruby on Rails Tutorial will serve you better. In either case, great books, and I really enjoyed writing my first Rails applications.