Search This Blog

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.