Search This Blog

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.

Is Your Programming Language Hostile To Functions?

Last week I talked about why functions should be short and sweet. Some people commented that some programming languages make it easier to write short functions while others make it harder, and that disparity among languages could influence the natural length of functions in programs written in those languages. I absolutely agree. If you write in a language that reduces the friction involved in writing functions, you're going to write more of them. If your language is hostile to functions, you're going to write less of them.

By hostile, I don't mean active aggression towards functions. I mean making the act of writing functions difficult enough that every time an opportunity arises where adding a function could clarify the code, you find yourself debating whether or not you want to actually spend the effort to do it. Let's look at a couple examples from two languages at opposite ends of this spectrum. Ruby will take the role of the near-frictionless language, and C++ will take the role of the openly-hostile language.

Now don't take this pairing to mean that I'm taking pot shots at C++. I honestly like C++ as a high-performance, flexible language where you can really program closer to the metal than almost any other language short of assembly. It just so happens that it also exemplifies a language that makes writing functions more difficult than necessary.

Starting With A Simple Example


Let's say you want to add all of the values in an array, and you want to wrap that functionality in a method so that you can call it on the object's data at will. In Ruby the class implementation would look something like this:

class BigData
  // ... other class stuff ...

  def sum
    @data.reduce(:+)
  end
end

Assume that @data is set somehow in some other part of the class definition. The important thing here is the method definition. I'm not sure how defining methods could get any easier in Ruby. Parentheses in the method signature are not required, the return value is simply the value of the last statement in the method, and no separate declaration is needed. It's simplicity itself. On the other hand, here's a C++ implementation of the same method:

// BigData.h
class BigData {
  // ... other class stuff ...

public:
  int sum();
};

// BigData.cpp
int BigData::sum() {
  int s = 0;
  for (int i = 0; i < _data.size(); i++) {
     s += _data[i];
  }
  return s;
}

Again assume that _data is set in another part of the class that's not shown. It's also assumed that _data is a vector so that the size() method is available. Look at how much more effort is involved in creating a method here. The method needs to be declared in the class definition in the header file, and then the body of the method is defined separately in the implementation file. In the header file, the declaration needs to go under the correct public, protected, or private heading. To be fair, Ruby has protected and private access specifiers as well (with slightly different behavior than C++), but methods are public by default in Ruby, which is generally the common case for methods. In C++ methods are private by default, so the public specifier is necessary if you want to call the method from outside the class.

Then in the implementation file, the containing class of the method must be specified in the method name, so the method declaration appears a second time in almost, but not quite the same way. The body of the method is more verbose than in Ruby because Ruby has an incredible amount of support for looping over enumerable data structures, while C++ does not. Some third-party libraries, like Boost, do improve on this shortcoming somewhat, but the functionality isn't there out of the box. Then the method has to explicitly return the desired value, necessitating another minor statement.

The definition of the method could have been included in the header file, but that changes the behavior of the compiler. Putting a method definition in a C++ header file causes that method to be inlined in any code where it's called. For short methods that may be desirable, but that's certainly a premature optimization, and most of the time it's better to let the compiler make that choice for you with all of the information it has.

A More Complex Example


Okay, so Ruby makes adding short methods much easier than C++, but how do things look with something more complex? Instead of getting a simple summation of the data, what if we wanted to apply an arbitrary mathematical transformation to that data? The class doesn't know what the transformation will be ahead of time, but it takes a function, applies it to each element of its data set, and returns the transformed data set. Here's what that would look like in Ruby:

class BigData
  def transform
    @data.map { |element| yield element }
  end
end

Wow. One would think that was going to be a bit harder. Honestly, all I've done is rename the map function that comes with Ruby's Enumerable mixin and exposed it as part of the BigData class. Maybe that seems useless, but Ruby makes this kind of thing so easy that if it improves the program's readability, it can be worth doing even if it's just recycling functionality that's already available. That's partly why DSLs (Domain Specific Languages) are so common in Ruby.

The map function uses a code block to define what will be done to each element of the enumerable data that it was called on. In this case, the code block passes each element to the code block associated with the transform method, and the transformation is defined where transform is called, like so:

data = BigData.new
new_data = data.transform { |x| x*2 + 1 }

Assuming that the data is initialized in new, the data set will be scaled by two and offset by one. Nice and simple. If other transformations are necessary, you simply make more calls with the other transformations in the code block. So how would this look in C++? Here's one way to do it:

// BigData.h
#include <vector>
class BigData {
public:
  void transform(std::vector<int> *result, int (*f)(int));
};

// BigData.cpp
#include <algorithm>
void BigData::transform(std::vector<int> *result,
                        int (*f)(int)) {
  result->resize(_data.size());
  std::transform(_data.begin(), _data.end(),
                 result->begin(), f);
}

Once again, the declaration and initialization of _data is not shown, but assume it is a std::vector<int> and data is loaded into the vector by some other means. The new wrinkle in this example is the function pointer int (*f)(int). Since C++ doesn't have a yield mechanism like Ruby (and many other languages), the desired function for the data transformation has to be communicated to the transform() method some other way, and a function pointer will suffice. The syntax is not nearly as nice as the yield-to-code-block syntax, though.

The syntax for std::transform() is much uglier than map, too, with four parameters to pass instead of a single code block because it's not a method of std::vector. This design allows std::transform() to be used with any type of iterators, but then those iterators have to be passed into the function explicitly.

A vector for holding the results of the transform is also passed into the function because having the method return a vector would cause all kinds of sticky design decisions that would fill a blog article all by themselves. Let's just say that this is one way that the lack of garbage collection in C++ makes programming functions specifically, and the language in general, more difficult than garbage collected languages.

Another issue that should be apparent by now is that the C++ implementations only handle vectors of integers, while the Ruby implementations for both examples can work with collections of any type that supports the '+' operator (and any other operators used in the code block) and is enumerable. The added complexity and reduced flexibility in C++ is because of its static type system vs. Ruby's dynamic typing. The C++ code could be extended to support more types using templates, but that would add a great deal more complexity to the syntax jungle we already have so I won't get into it now.

Getting back to the example at hand, I haven't shown how to use BigData::transform(), yet. The function that will be passed to it needs to be defined, and the result vector needs to be declared.

// main.cpp
#include <vector>
#include "BigData.h"

int scale_and_offset(int x) {
  return 2*x + 1;
}

int main() {
  BigData data;
  std::vector<int> result;
  data.transform(&result, scale_and_offset);
}

The code is predictably much more verbose than the Ruby code, and you have to make sure to pass a pointer to the result vector, as is required by the BigData::transform() method declaration. Additional transforms will each need their own functions defined, and if you only need to reference them once, that's a fair amount of overhead. If the compiler you're using supports it, you could use a lambda in place of the scale_and_offset() function to simplify things a bit, but it's not the prettiest syntax you've ever seen:

data.transform(&result, []()(int x) {
  return 2*x + 1;
});

And Your Point Is...


My intention with the above examples was not to demonstrate a ground-breaking use case for functions, but to showcase the differences in how functions are declared and used in two very different languages. Ruby clearly makes writing short functions easy with things like dynamic typing, exceptionally clean syntax, and code blocks. C++ makes it more difficult at every turn, but why does it matter? All of that extra syntax, decision-making, and code-writing may seem insignificant on a small scale, but it quickly adds up to a lot of extra mental overhead when writing in languages that are hostile to functions. I'm certainly not advocating that we stop using those languages. Every language has its advantages and disadvantages, and even with all of C++ complexity, ugliness, and sometimes insanity, it is still a great language in many domains.

The key thing is to recognize when you're programming in a language that creates a lot of friction and to be aware of all the ways that it makes using functions difficult. Keep that knowledge in mind, but don't shy away from writing small functions. That path leads to madness. Be prepared to put in the extra effort to make your functions short and sweet so that you can test them better now and understand them better later. The benefits still outweigh the additional effort. And if you're writing in a language that makes functions easy, take full advantage of it, and appreciate how good life is.

Functions Should Be Short And Sweet, But Why?

In my early days of programming, I would write functions good and long. Screen after screen of complicated logic and control structures would fill my coding projects with only a scant few mega functions dropped in to break things up a bit. It was years before things improved and I learned the value of splitting up those long stretches of coding logic into more manageable pieces. As I continue to improve as a programmer, I find that the functions I write keep getting shorter, more focused, and more numerous, and I keep seeing more benefits to this style of programming.

At first, the main barrier to small functions was likely the difficulty in learning to program in general. (By 'functions' I'm referring to all manner of parametrized blocks of code: functions and routines in procedural languages, methods in object-oriented languages, and lambdas and procedures in functional languages.) Functions are a hard concept to understand when they're first introduced, and to all appearances, it looks easier to write everything out in one long stream of logic. Getting the program to do what you want at all is hard enough, so why complicate things by having the execution path jump in and out of all kinds of functions as well? And once all of those chains of if-else statements and nested for loops are working, the last thing you want to do is change anything that could break it again.

Likely the most obvious value-add for functions becomes apparent when you start repeating code. Instead of copy-pasting those blocks of code, you can parametrize them into functions and reuse one block of code many times. The long road to the understanding of DRY has begun. Yet, you may resist breaking up your code into many more smaller functions because of the friction involved in doing so. After all, the code is working, and it seems like an awful lot of effort to refactor it all into functions of ten lines or less. Screen-length functions should be good enough, right?

Wrong. There are so many more benefits to writing short and sweet functions, but before getting into those benefits, let's look at an example that we can refer to.

An Example Command Interface


I've been writing a lot of embedded code in C/C++ over the last couple years, so examples in that vein come easily for me right now. For this example imagine you're implementing a command interface between a host processor and a slave processor that are connected over a serial communication protocol, like SPI or UART. A command packet will consist of a command, any associated parameters, and an optional block of data. The slave will receive command packets, process them, and reply with a response packet, or a simple acknowledgement if no response data is needed by the host. We'll keep it really simple and not allow the slave to initiate any commands.

When I first started programming, I might have implemented the slave's command processing as one massive function, and maybe broken off some repeated code blocks into functions after it was working. But that method of coding imposes a huge amount of cognitive overhead. It would be much simpler to start out with something like this:

void IntHandler() { 
  HostCommand hostCmd = HOST_CMD_READ; 
  IntDisable(INT_SPI0);
  SPIDataGet(SPI0_BASE, (unsigned long *)&hostCmd); 
  HandleHostCommand(hostCmd);
  IntEnable(INT_SPI0);
}

This is the interrupt handler for when a SPI peripheral receives data over the serial interface and raises an interrupt in the slave processor. The function simply sets a default command, disables future interrupts, reads the command from the SPI peripheral, handles the command, and re-enables interrupts. The bulk of the work is done in the HandleHostCommand(hostCmd) function call, which looks like this:

void HandleHostCommand(HostCommand hostCmd) {
  switch (hostCmd)
  { 
  case HOST_CMD_NOP:
    HandleNop();
    break;
  case HOST_CMD_READ:
    HandleRead();
    break;
  case HOST_CMD_SET_IP_ADDR:
    HandleSetIP(); 
    break;
  case HOST_CMD_SET_CHANNEL_CONFIG: 
    HandleSetChannelConfig();
    break;
  /*
   * Many more commands and function calls.
   */
  default:
    HandleError();
    break;
  }
}

Again, this is a fairly straightforward function that focuses on one task - routing each incoming command to the function that will handle it. The implementation of each HandleXXX() function is equally simple. Here's the one for a NOP command:

void HandleNop() {
  SPIDataPut(SPI0_BASE, HOST_REPLY_POSACK);
}

This function is especially simple because it implements the no-operation command, which just echos a positive acknowledgement back to the host processor. Other command handling functions will be more complicated, but not by much. I could go on with more functions, but I think you get the idea. So other than making the functions dead simple, what are the advantages to coding this way?

Easier To Write


One of the incredible things about programming this way is that as you are writing, drilling down into each of these simple functions, you quickly realize where you can reuse one small function in another place. Even though it might seem like coding is a little slower to begin with, once you get a few levels deep in a complex task, all of a sudden you find that you're not writing as much logic. You're mostly calling functions you've already written, and the logic that you do still need to write is very straightforward.

Coding lots of smaller functions allows you to concentrate more easily on the task at hand instead of holding hundreds or thousands of lines of code in your head, and you can make good progress much more quickly and correctly. It also frees up mental resources for solving the more complicated problems in programming, which is what you really want to be spending your mental energy on.

Easier To Read


Besides making code easier to write, lots of short functions makes code much easier to read. That may be counter-intuitive because you would think having so many functions with only a handful of code in them would force you to jump around the code a lot more, searching for the implementation of this or that function. Most of the time that's not the case. More often than not, you're looking for a specific block of code to find and fix a bug or add a feature. Finding that code block is actually easier when you don't have to sift through hundreds of lines of irrelevant code in the same function, trying to decide if any of it influences the bug you're tracking down or if it it will break when you make a change. Once you find the right code, it's already isolated in a nice self-contained package that's easy to understand and change.

Reading and understanding code is also aided by the focused nature of small functions. In the command interface above, the code in each function exists firmly within one layer of abstraction. Low-level peripheral interface code is not mixed with higher level decision or control structures, which in turn is not mixed with book-keeping code. It's the Single Responsibility principle applied to functions. The purpose of each function is immediately apparent, and that helps considerably when you have to come back to it in six months (or five years) to make a change. Not to mention the fact that small functions are much more portable, making changes even easier.

Easier To Test


Long functions are notoriously hard to test. Making sure all code paths are covered and the code is functionally correct becomes a nightmare. If you add in interactions with hardware peripherals, like the example above, things get even more difficult because simulating what the embedded hardware does for offline testing is a real challenge. But testing the code above is quite easy. The functions that interface directly with the hardware can be mocked without the need to maintain complicated state for long, involved tests because the functions that use the hardware interface are short and simple.

Coming up with tests for each function is also straightforward because none of them do very much. For example, the tests for HandleHostCommand() just need to pass in each command and a few invalid commands and make sure the correct function is called each time. Nothing could be simpler.

Easier To Name Variables


One of the hardest problems in programming is naming variables, but when you drastically cut down the size of functions, naming becomes much easier because the amount of context that must be held in the variable name is smaller. If done right, variable names should get shorter as functions get shorter while their meaning becomes easier to understand and remember.

Imagine the complexity of the variable names that would be required if all of the command processing code was written in HandleHostCommand(). Command-specific variable names would quickly get out of hand, and there would be the unhealthy urge to reuse variables for multiple purposes. Both of those problems are neatly avoided by splitting the command processing into individual functions.

Easier To Self-Document


In Code Complete, Steve McConnell describes the Pseudocode Programming Process, where pseudocode is used to refine a routine until it reaches a point where it is easier to write the code than to write more pseudocode. Then the pseudocode is converted to comments and the code is written below each comment. Considering what I think of comments, McConnell didn't go far enough with his recommended process.

Each comment ends up redundantly describing the following code, making the comments essentially useless. Instead of writing code for each comment, coming up with a good function name and putting the code in the resulting functions would be a better approach. Then the code becomes more self-documenting, and the comments can either be removed to de-clutter the code or used as the function's documentation if necessary.

When code is structured with lots of small functions, the function names become a great way to describe what the code is doing directly in the code. Learning Ruby and Rails is making this advantage even more apparent to me. The omission of most parentheses in Ruby makes the code so easily readable that small functions are much more common and comments are used far less frequently. Most of that advantage can be carried over to other languages, and at least in the example above, comments wouldn't add much value to the code while increasing its verbosity drastically. That's not to say that comments should never be used, but their necessity is drastically reduced.

Make Your Life Easier


Of all of the advantages of writing small functions, the most profound is probably how easy it makes testing. Without short functions, testing can be completely overwhelming and is likely to be resisted or delayed to the detriment of the project. With short functions, tests practically write themselves, and if TDD (Test-Driven Development) is practiced, short functions tend to be the natural result of the tests that are written first.

Making testing easier should motivate you to write smaller functions all by itself. Making code easier to read, write, change, and document as well is even better. It took a long time to appreciate how beneficial it is to program this way because I couldn't get over the friction of creating all of those little functions. Try it. Write those short and sweet functions. It will free your mind.

Skiing Can Teach Us A Few Things About Programming

Alpine skier

A couple weeks ago, I described a skiing exercise as an example of how, in many sports, practice is intentionally made harder to make playing the real sport easier, and that the same principle can be applied when practicing programming. It turns out there are a few more things programmers can learn from the thrilling sport of alpine skiing.

Plan, Then Execute


When you're out skiing, there's a lot of planning that happens before and during each run. It all starts with deciding how you'll get up the mountain when you're down at the bottom, snapping into your bindings. Whether you're with a group or on your own, you'll need to decide which run you want to try out, and which lift will get you to the desired run with the least amount of skating across flat open snow. Depending on how far away it is, the best way may actually involve going down one or more different runs to get to the one you really want to do. And if you are with a group, you'll have to take everyone's wishes and abilities into consideration and make compromises as well.

Once you're on the lift, you may pull out the resort map again and try to figure out how you want to attack the run, or if you've been down it a few times already, you may be thinking about how you want to do things differently this time. The same run can feel entirely different each time you go down, depending on the path you take.

When you arrive at the top, narrowly avoid those people that congregate near the lift exit, and take a moment's pause on the crest of the run, you'll want to take a survey of the slope below. You'll be deciding on your initial path, looking for obstacles you want to avoid (or pursue if you want to challenge yourself), and waiting for any other skiers to go far enough down the run so that no one gets clobbered.

Once everything's clear, you can push off and carve your way down the mountain. However, the planning doesn't stop here. You need to be constantly looking out for new obstacles and making minor course corrections all the way down the run. You may stop and reassess your path at times if there's a blind spot created by a large ridge or if something entirely unexpected happens, like someone being loaded on a stretcher by the ski patrol up ahead.

Your path down a ski run is the combination of a general plan of attack and a series of dynamic decisions that take the current conditions into account. You may reach your destination by an indirect route, but being flexible is crucial to having a safe and enjoyable trip. This method of planning and execution applies equally well to programming, both at the project level where it should sound quite similar to agile methodologies, and at the coding level where you have to understand the code you're changing and adapt to new information as you're making changes.

Pick The Right Skis


There are all kinds of different skis out there, and they all have different strengths and weaknesses. Powder skis are much wider than other skis so that they will float on top of deep, fluffy snow instead of diving into it and burying you. Trick skis are much shorter and may have tips that curve up on both ends so you can go backwards as easily as forwards. As the name implies, these skis are built for playing in half pipes and terrain parks, and it's much easier to pull of flips, spins, and grinds with them.

Hyperbolic skis are made to carve turns easily in a wide range of conditions and are highly recommended for beginners for their easy learning curve, yet they're still fun for advanced skiers. The classic all-mountain ski is still the best choice for moguls because they are narrower than hyperbolics, making it easier to switch edges quickly and make incredibly fast turns, a requirement for attacking the bumps. Finally, super side-cut skis are a hybrid between hyperbolics and all-mountain skis. They make some compromises in either direction so they tend to be good in more situations, but not the best in any one situation.

Given that there are so many types of skis, you will want to pick the best one for the type of skiing you want to do. For example, if you want to try out the bumps and all you have is a pair of powder skis, you're not going to have a good time of it. Of course, these types of decisions come up in programming all the time, and the most obvious analogue for skis would be programing languages. If you pick the right language for the job and you know how to use it well, you're going to have a much easier time than if you only know one language and try to use it for everything. Being well-versed in multiple languages makes you a much more versatile programmer.

Be Aware Of Conditions


When you're out on the mountain cutting up the runs, the last thing you want is to be caught by surprise by unexpected conditions. At best, they could make your day rather uncomfortable. If you're more unlucky, poorly handled surprises could land you in the hospital, or worse. Conditions include the weather expected for the day, the type of snow on the slopes, and the actual obstacles and people around you while you're going down a run.

You should be aware of all of these conditions because they're important for your safety and comfort. Skiing in sunshine is much different than skiing in a (light) snowstorm, and skiing in a blizzard is ill-advised. Temperatures and wind speed will drastically change what you'll want to wear, and dressing in layers is always recommended because you'll be warmer or colder at various points of the day, depending on the immediate weather and your activity level. If you're wearing lots of layers, you can adjust so that you're not sweating or freezing.

The properties of the snow can vary tremendously as well. Fresh powder is great, but if it's deep enough, you'll need those powder skis to enjoy it at all. Wisconsin hard-pack is a combination of man-made snow and excessive grooming, and hyperbolic skis tend to work well in it. You should take extra care when skiing in soft, wet snow because you can hit patches of slush that will grab your skis and send you tumbling down the run. And then there's ice. Make sure your edges are sharp, and good luck!

Most of the time skiing is really not as hazardous as I'm making it out to be here, but it's still important to stay aware of what's happening because accidents happen when you least expect it. The same holds true in programming, with the conditions being anything from the OS environment to the current program state, and accidents taking the form of bugs. The more aware you are of all of the conditions in play for the code changes you're making, the more likely you'll be able to recognize, avoid, and fix bugs in your code. Over time, experience will teach you what conditions matter in any given situation, and you'll be better able to handle all of those nasty coding surprises.

Find The Zone


After all of the planning and adjusting for conditions becomes second nature and you really get comfortable with your skis, you'll find that your enjoyment of the sport reaches to new heights. Your skis become an extension of yourself, and you can anticipate your next turns with complete fluidity and purpose. Being in the zone can be both a serene and thrilling experience. The feeling that comes from conquering the mountain with grace and control is exhilarating. To me, that is what skiing, and programming, is all about - mastering the tools and yourself to surpass your limits and accomplish feats you never thought possible.

What I've Learned From A Year of Blogging


This will be my 52nd post to this blog, and since I've been writing a post per week, that means this post will complete one full year of blogging. Woohoo! Before I go any further, I'd like to thank you for following along on this journey. I really appreciate all of the thoughtful comments from those who have shared, and the knowledge that thousands of people have read at least something from this site. I hope that I've been engaging, and that you've learned something. I know I have.

That is, after all, part of the reason why I started this blog - to teach and to learn. I've learned a lot about software development over the past year by expanding into web development and sharing some of that experience here, hopefully in a way that will encourage you to also expand your horizons. Along the way I've learned a few things about writing as well. These are things that I would never have really understood, had I not pursued this blog.

First, I still hate writing, but I love it, too. I used to hate writing in school because I rarely got to write about things that I cared about. Writing about dead presidents or dead authors really did not interest me that much. I'm not saying those topics wouldn't be interesting to anyone, but they certainly didn't inspire me to want to write any more than I had to. Now I hate writing for a different reason. I hate it because it's a really hard thing to do well. Some nights I sit in front of my laptop staring at a half finished sentence for minutes on end, trying to figure out how exactly I want to say what I'm trying to say. Other times I'll spend half an hour or more deciding how to proceed to my next thought and exactly how to structure the next few paragraphs. It's terribly frustrating at those times.

However, it's incredibly satisfying to write about things I'm passionate about, and the act of writing motivates me to learn about the things I'm writing about at a deeper level because I want to sound reasonably competent. There are also those moments when everything starts to flow smoothly, and I look back in surprise at how well some of those thoughts were expressed. That's where writing really becomes enjoyable.

So it's a love-hate relationship, and like anything else worth doing, it takes work. But there's more, much more.

Writing helps me write better code. It makes me think more about how to structure code so that it is more easily understandable. In writing, to explain something clearly you should find the simplest way to express a thought without losing any of the original meaning or intent. That sounds easy when put like that, but it is an extremely hard thing to do in practice. It takes constant effort and years of practice. You never reach perfection, but you can spend a lifetime trying. A lot of that effort and mindset readily transfers between writing and coding, and I've seen my code improve consistently over the last year.

Of course, what I want is to reach a point where I can just write, but it is never thus. I'm always stopping to think about things, to look something up, to grab a link or a picture that I need to include. The whole process feels stilted and halting. Then I read people like Steve Yegge or Paul Krugman, and their writing seems so effortless and casual. It seems to me like their words flow from their fingertips like running water, and I wish I could write like that. For all I know, they can't actually write like the way I'm imagining, either. After all, I am reading their finished work, and that should flow. But I still want the words to come easier than they do. I suppose that is the purpose of those creative writing exercises where you purposefully write about a topic non-stop. I may have to try that soon.

Related to how hard it is to write smoothly and quickly is how hard it is to transfer the thoughts I have milling around in my head to those of you reading these posts. You see, I have all of these interconnected thoughts in my head about any particular topic, and they all exist at once up there as ephemeral ideas without concrete words or phrases attached to them. Some are stronger than others. Some fade in and out of consciousness. Some pop up from my sub-conscious mind with a fleeting glance and I have to capture them before they disappear.

The medium of the written word is entirely different. It's linear and sequential. Linking different thoughts in a written piece is hard when at any given point I have a half dozen different ways to continue, and connections to points I made earlier can be imprecise or awkward. I have to decide exactly how to line up all of these thoughts to make a coherent overall point, but that isn't even the hardest part. What I'm trying to actually do is pull an idea, with all of it's supporting material, out of my mind and present it to you full and intact. The written word is merely a means to that end. Finding the best way to represent that idea concisely so that it is understood as the same complete and compelling idea that I had is a tremendously hard problem.

That hard problem never seems to get any easier because my previous efforts never seem good enough, and I'm always trying to improve my writing and explanations. I would never have thought that after a year of writing it wouldn't get any easier, but making writing easier was never really the point of blogging for me. The point was to write better. If I hadn't gotten any better and writing had only gotten easier, I probably would have gotten bored with it fairly quickly. Easy things are boring. It's the challenging things that hold your attention.

Another thing I constantly struggle with is my writing perspective. I feel like ‘I’ is arrogant, ‘you’ is presumptuous, and ‘they’ is vague. If I always write in the first person, I run the risk of appearing pompous and selfish because everything is about me. If I write in the second person, I'm assuming that you are indeed like how I'm claiming you are or you do what I'm claiming you do. If I write in the third person, nothing has any force behind it because I'm always writing about some innocuous other person. On the other hand, first person is more personal and honest, second person is more direct and engaging, and third person can diffuse emotions about more tense subjects. So each style has its advantages and disadvantages, and I'm still trying to figure out the best times to use each one. I tend to bounce from one to the next as I see fit, but I'm still not sure what the best approach is.

To address some of these writing issues, I read a lot. I've always been an avid reader, but I've noticed that how I read has changed. I now see where other authors are struggling with the ideas they're trying to express because their writing will get awkward. I see when they are being vague because at times I struggle with being vague, and it becomes easy to notice the signs of vagueness when you have them in your own writing. See, I did it right there. It happens when you’ve mentally integrated the ideas and justifications behind the thing you’re writing about, but you’ve lost the context. Then you have to come up with an example that fits the reasoning now embedded in your memory, and that can get quite hard. There may also be an element of not wanting to single out any one person or event if what is being discussed has a negative perspective. There is a fear that readers will focus on the particular example you present, and agree or disagree with it while the larger point is missed or ignored.

Speaking of disagreeing, some readers will latch onto one minor mistake in an article and use that as justification to discount the entire article, or the author in general. My most hated criticism of anyone's writing is when someone comments, "He obviously doesn’t know what he’s talking about because of what he said about x." Maybe x isn't important to the main point of the post. Maybe it was added as a bit of filler that the author thought was interesting but should have left out. In any case, that type of criticism is maddening because the critic is not trying to engage in a debate about the merits of the author's arguments. The critic has already decided that he doesn't like the post, or even the author, for some reason, and he's finding any reason, however small, to discount the author entirely. It's lazy reasoning, and now I pretty much ignore that type of criticism instead of wasting energy responding to it.

I have found that reading any kind of criticism gives you the strong desire to cover absolutely everything about a given topic in a single post, but it simply cannot be done. Articles would quickly turn into book-length ramblings and never get finished. There is no end to the tangents and back stories that can be pursued in writing about anything. The hard part is picking what to focus on. I know that is something I need to work on. I tend to write long posts, and I'd like to tighten up my writing in the future. That will take some discipline on my part.

Finally, I've found that there is great tension between sounding confident and humble. I want to be confident about the things I write about without sounding arrogant, and there is a nagging temptation to fill posts with caveats and disclaimers. It helps to remember something my high school Research & Comp teacher told me. Your readers know it’s your opinion, so you don’t have to constantly remind them. Say what you believe and present it as strongly as you can. Say it like you have the authority to say it. Every author adds their subjective opinion to their writing by the simple fact that they are choosing what to write about - what facts to include and what not to. The reader is not going to be convinced through apologies, but through the strength of the writing, the reasoning, and the facts, so cut the crap.

Overall, this has been a successful first year of blogging, and I plan to keep it up. I've learned a lot so far, and I hope I've been entertaining and enlightening to read. I would definitely recommend starting a blog to anyone wanting to work on personal development. Pick something you love to do and write about it. You'll be amazed what you learn in the process.