Readability Advantages of C over C++

C++ is a language that was created to improve some of the features and use cases of the C language, in order to make it easier to use for application development (instead of system programming, the main area dominated by C). One of the perceived problems in C is the lack of support for object oriented features that are so common on the development of desktop applications. For example, C lacks the concept of a type that encapsulates code and data. While it is possible to program in an object oriented style in C, it is somewhat cumbersome to use such a style.

In order to make C easier to use, C++ designers added a number of features that would be more appealing to programmers. Inheritance was one of them, used to support object oriented features. Overridden methods were also added to improve object oriented programs.

C++ also added some features that can be considered syntactic sugar for already supported operations. For example, operators can be overloaded, so that many math operations, and even punctuation such as “,” can be overloaded by programmers. Normal functions can also be overloaded, by providing versions that differ on the number and type of arguments.

Later on, C++ added templates to fix a problem with the language’s type system. With templates, it is possible to instantiate a class based on one or more types. This allows for the creation of containers, such as the ones found in the STL. Vectors, maps, and multimaps can all be created by adding a type as a parameter for template instantiation.

Consequences

Although C++ designers succeeded in creating a language with support for most object oriented features, there are a lot of unintended consequences of the way many of these features were introduced.

Unlike C, in C++ it is difficult to understand, by just looking at the code being written, what will be really executed at run time. This has always been a problem with object oriented languages due to polymorphism. However, the problems have been compounded by the liberal use of overloading features in C++ programs.

Clearly, in C it is possible to write convoluted programs (especially if one wants to use the preprocessor). However, in general one just has variable declarations, function declarations, function calls, and simple expressions (such as mathematical and logical expressions). Maybe the results of a function call may not be completely understood by the programmer, but from the syntactical point of view it is easy to figure out what is going on in the program.

And, to put it clearly, the problem is not that the function or class is doing something we don’t know. The problem is mostly in trying to figure out what is happening in a given line of code. In C is very easy to figure out what is being called (up to macros): just read the manual for the functions being used and you will have a good idea of what is being executed.

In C++, on the other hand, a large number of things can be happening in a single line: an overloaded operator, a type conversion, a template instantiation, an overridden function in one of a dozen of classes, a constructor called in some part of the hierarchy, in some namespace… Who knows? You have to be smart enough to figure out what is going on in each of these cases. As your code base grows, this makes it increasingly hard to understand what is going on.

And this is not even considering issues such as exceptions, which are a huge liability, since you have to check that they will leave your program in a reasonable state at each part of your code.

Conclusion

While C++ provides a lot of helpful features for application programming, these features have a cost. It becomes increasingly difficult to understand what is going on in each line of code, unless the developers are very disciplined.

This also shows a little of the myth surrounding the idea that C++ is better than C for large code bases. While C++ has some features that might be helpful, in general the bigger the C++ code base the harder it is to understand due to these issues.

This is true even for automated tools. It is very difficult to create automatic tools to parse and change C++ (for example, to perform refactoring). In comparison, C is much easier to understand, and one can do a lot with tools such as ctags. It is not a surprise that large scale projects such as the Linux kernel use C without any problem.

Is C++ Just a Better C?

A lot of money and energy was spent in converting or writing new software in C++ during the 80s and 90s. Even nowadays, when the leading commercial language is Java, there is a lot of effort spent in learning and using C++ in several areas where performance is considered to be an important asset.

However, despite all these efforts after 20 years, C++ is not used to its full extent. Some features such as the STL have become really successful and widely accepted by the industry. On the other hand, other features such as checked exceptions and RTTI have been met with little enthusiasm.

It is necessary to understand what these features have in common and why they were not considered to be so useful as their creators supposed them to be. Especially when such features have been introduced more than a decade ago and are still nowhere near full acceptance.

Duplicate Features

One of the problems of the C++ language is that it has, more than once, introduced features that are difficult to use and/or implement. As a general rule, this is a disadvantage of languages designed by a committee. Some features end up becoming part of the standard document, but they have little support in the real world.

For example, a decade ago the designers of C++ though about the possibility of having templates defined in separate translation units from the ones where the templates are used. The intention is good, since templates take a long time to parse and compile.

However, the big problem with separate compilation of templates, provided by the external template keyword, is that it was never implemented by major compilers. The main justification is that it is a complicated feature to implement. Also, it would require modifications to the current way programmers declare and templates.

The result is that external templates are now viewed as a dead feature, something that might be useful but is not available in any of the major compilers.

Coding Standards

A related problem for C++ is that nobody uses all its features. Due to the fact that there are competing implementation for the same concept (for example, two IO libraries — the old C-base library and a stream object-based library), C++ users have to decide which option to use. This may be done in a case-by-case basis, or even by the use of a coding style.

Big companies such as Google have decide to rule out most of the advanced features found in newer versions of C++. These features include exceptions, multiple inheritance, for example. What this means in practice is that C++ is being used just as a better C, without many of the features that its creators though would be useful.

On close inspection, it seams that C++ is mostly a language designed at two levels: the first level, incorporating the ideas of the day, which change every few years with the desires of researchers. Examples include checked exceptions and run time type information. In the process, lots of incompatible ways of writing the same code are introduced. For example, are you going to use return values or exceptions? Streams or standard buffered I/O? Both have its advantages and disadvantages, so you better know what they are.

In the other hand, there is also a second level dictated by developers, as they decide which subset of the language to use. Since it is not possible to use all the provided features at the same time, one has to selectively use C++ to create new software projects. One of the ways this is done is by adopting a styling convention. In this process, developers rule out a set of features that believe are not productive.

Still, another result of this evolutionary process is that there are some features that people don’t like, but that are not easy to substitute. For example, templates are a pain to create and even to use. However most developers use them because it is the only way to do some things in C++. Somebody else could create better container classes, but that would become a huge problem for compatibility with existing libraries.

Conclusion

C++ is an evolving language. As a consequence many of its features are not well developed. Other features have been rejected by the community as too complex or unsafe to use.

A large part of being a good C++ developer is understanding what are the good and bad parts of the language, and how to take advantage of them when necessary.

Further Reading

The Design and Evolution of C++, by Bjarne Stroustrup is a great book that explain the reasoning for most of the features in C++. It is a must read if you want to understand the initial phase of evolution of the language.

Finding Ideas for Software Products

One of the main questions asked by new entrepreneurs is how to find ideas for new software products. It seems as if ideas are the main reason separating success from failure for those starting a new business. While this might seem an interesting explanation for success in life, experience has shown time after time that it is not the right way to approach business development.

First, it is well known that even great ideas may turn into bad businesses. It always takes effort to make something succeed. Even when the idea is a great one, if there is no matching effort to make it succeed, it won’t.

On the other hand, we have all seen companies coming with a well executed version of a simple idea that ends up succeeding in the marketplace. There are countless examples, even from companies as big as McDonalds and Walmart. Many of them became giants by their pure capacity of taking a simple business model and implement it to its limits.

If you are just starting, there is a number of ideas that you can explore:
– try to complement products that are already successful in the market;
– look for up sales and down sales on existing products;
– try to develop software that can deliver real results for people.

What to Avoid

The software world is littered with companies that tried to create technology for its own sake. While some of these companies may ultimately find a use for their technology, most of them will simply die. Frequently the reason of failure is that they didn’t start from a real need. They instead started with an idea for a technology, and tried to adapt it into something.

A recent example are startups created around the idea of mashups. A few years ago, people went crazy with the possibilities provided by web services, release by companies including Google, to Amazon, Yahoo!, and others. Since these web services could be combined into mashups, a lot of projects were launched to create new mashups that just didn’t make much sense.

The main reason of failure is that a lot of these people were not trying to solve a perceived need of the market. Instead, they were just smart developers trying to explore a new technology for its own sake.

It is true that some innovative companies are created this way. Usually, however, the reality is that the founders were smart enough (or lucky) to find up a niche for their technology.

Sadly, relying just in a new cool technology is a path that leads to failure most of the time. As a lot of people found out, it is much easier to start from something that people already want, and use technology to satisfy that need in a better way.

Summary

Ultimately, creating new products is not a difficult proposition, if you start paying attention to what people want to buy. Make sure you understand your users, and offer something that will satisfy their needs.