Wednesday, September 22, 2010

On comments

On stackoverflow there is a very interesting thread on controversial opinions on programming. From the that thread codes the following quote.


"Most comments in code are in fact a pernicious form of code duplication. We spend most of our time maintaining code written by others (or ourselves) and poor, incorrect, outdated, misleading comments must be near the top of the list of most annoying artifacts in code."


I wholeheartedly agree with the above. It might be tempting to think that adding comments only improves your code. However, that is not the case. I think it is clear that bad comments are worse than no comments. Recently I saw the following in an iterative improvement algorithm:



size_t const iterations = 10000; // just use 5 for now



The comment raises more questions than it answers. Is the code wrong? Is the comment wrong? What does "for now" mean? How the does value change once "for now" is in the past? A better comment would explain how to choose an appropriate value for iterations either based on solution quality or runtime performance.


Further, it can be tempting to add comments to explain bad code rather than write better code. For example, it is easy to write something like the following:



// caller must delete return value
some_type_t* some_function();


Eventually someone will forget to delete the return value. Instead of a comment
this policy can be enforced by code. So the above could easily be changed to:



std::auto_ptr<some_type_t> some_function();


Using std::auto_ptr means that the return value will be deleted unless the caller goes out of the way to avoid deleting it. So it is no longer necessary to document the policy in comments because it is documented in the code.


In many cases it is possible to reduce the need for comments by improving the structure of the code. This lets the compiler check for inconsistencies and problems which it can never do with comments.

Monday, September 20, 2010

On Functional Programming and C++

It probably seems a bit odd to talk up Functional Programming (FP) and then give examples in C++. As the syntax for FP is so much more concise in other languages. After all the following C++ can be rewritten in Python quite easily:


class save_as_cb_t {
 document_t& document_;
public:
 save_as_cb_t(document_t& document) : document_ (document) { }
 void operator()() const
 {
  document_.save_as(get_save_filename_using_dialog());
 }
};

The equivalent Python (assuming some definitions) would be:


def save_as_cb():
 document.save_as(get_save_filename_using_dialog())

While the Python code is far more concise I still find C++ to be an effective language for FP. Functions are able to be used as values that may be passed to or returned from other functions. When doing this typedef is your best friend.


void acc(double& a, double const x)
{
 a += x;
}

typedef void (*fn_t)(double&, double);

fn_t g(fn_t f);

The above shows a simple function for accumulating floating point values. By using typedef we have an easy way to refer to the type of the acc function.

Treating functions as values is the beginning of FP. Using FP we frequently want to be able bind arguments to functions to compose new functions. Since there is no direct support (yet) for this we can use the C++ type system to create closures. The following C++ binds the first argument of acc function to an existing double variable.


class acc_fn {
 double& a_;
public:
 acc_fn(double& a) : a_ (a) { }
 void operator()(double const x) const
 {
  a_ += x;
 }
};

In the above case a_ is passed by reference. Since we control the type of the bound argument, in this case double&, we can bind arguments using whatever type is most appropriate. Allowing us to pass by value or by const reference for immutable values.

Thursday, September 9, 2010

On paradigms

At university I had the opportunity to study a number of different languages and paradigms. I'm glad I did because after entering the workforce it seems like there is a strong emphasis on programming in Object Orient languages using Object Oriented techniques. I think though that function programming offers an excellent way of structuring code in many cases.

Consider implementing a graphical user interface. GUI toolkits are frequently written using an OO structure. This works well because widgets share a common interface for many things and have common behaviour. Perfect for OO. However, when it is time to connect the classes for the application to the interface function programming techniques provide an excellent way of structuring the callbacks (or whatever they are called in the toolkit).

To give a concrete example say you have a user interface structured around a document (like a word processor). You might have a class than in part looks like:


class document_t {
// ..
public:
void open(std::string const& path);
void save() const;
void save_as(std::string const& path);
};

std::string get_save_filename_using_dialog();



In the UI you will probably have toolbar buttons or menu items for open, save, save as and so on. We need to connect these widgets with a callback. In the case of save as we would like a function that looks like:



void save_as_cb()
{
document.save_as(get_save_filename_using_dialog());
}


Where document is the document for the current window. We can compose such a thing using FP techniques. Using boost/bind.hpp we could compose a function object to represent the above using:


boost::bind(
boost::mem_fn(&document_t::save_as),
boost::ref(document),
boost::bind(get_save_filename_using_dialog));


Again, document is the document for the current window. If the above is a bit much a simpler form would be as follows.


void save_as_cb(document_t& document)
{
document.save_as(get_save_filename_using_dialog());
}

boost::bind(save_as_cb, boost::ref(document));


I find the conciseness of the FP approach an advantage. It makes the behaviour of the code stand out because there is less additional structure to comprehend. Below is how you might write a class to implement the same callback.



class save_as_cb_t {
document_t& document_;
public:
save_as_cb_t(document_t& document) : document_ (document) { }
void operator()() const
{
document_.save_as(get_save_filename_using_dialog());
}
};

Saturday, September 4, 2010

I'm between jobs now

Hi,

About a month ago I started a year long leave (without pay) from my job of 11 years. I now have a bit more time on my hands for indulgent activities like writing a blog. I studied computer programming at University and have been programming ever since. So I plan to put in writing some of my thoughts on programming and programming languages. Surely I have picked up some insights in those 14 years. However, I am on holiday so the real content can wait until tomorrow.

Bowie