|
In this episode, we talk with Kevlin Henney about the C++ programming language. We look at the history and the culture of the language, and how it went through several phases in its evolution. We also take a look at some of the special language features of C++ and their overall influence. TranscriptThis is Arno speaking, and I am interviewing Kevlin Henney on C++. We are sitting at EuroPLoP 2007 in Bavaria, having a good time. Kevlin, would you like to start by saying a few words about yourself? Oh yes. I am Kevlin Henney, I am an independent consultant and trainer. I am based in the UK. More generally, the thing of interest I guess is my background in C++. I stumbled into C++ sort of by accident, sometime around 1990, and growing interest in Object Orientation at that time. I pursued that to the point that it was professionally useful, and followed through on a number of things; writing articles from the early 90s onwards, getting involved in the Standardization Process through the British Standards Institute, that was around the mid-90s. Pretty much that has characterized my work. I guess probably the 1990s would be the right way of looking at it. I still have a great deal of involvement with C++ projects, but in terms of my writing, I guess that is not as C++ focused as it used to be. In terms of Standardization, I still stand back from the Standardization Process a little bit, but I am still partly involved with it. Yeah, we will get into the Standardization stuff later on I guess. The reason we are doing this episode on C++ is basically that some of our listeners felt that we were too Java-centric and sort of treated C++ as being dead. Well, C++ is sort of alive and kicking, it is just not as much represented in media. So what would you say if someone told you C++ is obsolete, is it? Well, there's two answers to that really, aren't there; there is the yes answer and there is the no answer. Let's start with the yes answer. Yes, C++ is obsolete, but so is Java, so is C#, so is Ruby, and you can pick any language, this is a standard language, it doesn't generally help people, and tends to add more darkness than light. So where is it not obsolete? Let's understand that although we try sometimes to simplify the idea of programming language movements and say everybody is doing language A and no longer doing language B, it's never that simple. The landscape is at very least two dimensional, very complex, people in one corner don't necessarily have anything to do with people elsewhere. Their needs are often very different. Get two arbitrary software developers together, and you will find that their problem spaces are typically quite different, their basic vocabulary set, their development processes and so on. So in that sense, C++ does not have the role that it used to, so it can be said to be obsolete for some roles. Some of these have been displaced by in places Java, and in other places by C#, and in other places by languages like Ruby and Python, and so on. There are also roles that C++ has never really had any weight in, and that have grown in the last ten years, so it is very unlikely you will find a lot of Web programmers dealing with that. But again, that concept of Web Programming really did not exist in the form we recognize it now, say ten years ago. But where is C++ actually picking up, that's the interesting question, because as I said, I still do quite a lot of C++ work. My work divides between C++, Java, little bit of C#, and various other languages, development process and design and so on, but the C++ stuff has shifted, it is noticeable. I am not seeing many people creating general application UIs in C++, which I might actually personally say is a slight relief. But what I am seeing them doing is there is a focus, more and more people are concerned with applications that are reaching very large scales, high performance needs, and so on; it's kind of the software that you don't see, the software that is routing the traffic around the planet type software. There is a great deal of emphasis on that, where people care about performance, they care about the byte-level control, they care about talking to the metal, if you like. But at the same time, talking to the metal is no longer as simple case of lashing together some assembler code, or even C code, you need a way of building something that is sustainable with a large team of developers, and has quite rich concepts, and that appears to be where C++ is gaining ground. You have the area of algorithm expression in research, which is not something that other languages are necessarily well suited to in the mainstream. There is a sort of growth in this area, where people are actually saying well, if I am looking at some number crunching, I care about performance, I care about the structure of the algorithm, these things combine, and languages like Java have shown they are not really quite up to this in their style; their style actually lies elsewhere, their strengths are elsewhere. But you are not going to find C++ developers sitting there doing Spring-like applications, or rather if they are, then they are going to spend a lot longer doing it than their colleagues. But what we are seeing is there is growth elsewhere. It's even actually being re-used, reinstituted - sorry, in a number of cases as a teaching language. The landscape on teaching languages is no longer as clear as it used to be, the field is muddied a bit; some people are exploring the use of dynamic languages, other universities are sticking very much with their Java curriculum, some have favoured C# and so on, but some have actually retaken the decision to go with C++, partly because they are finding that although it's complex, it offers them more of what they want to teach computer science graduates. You can point to pretty much anything, and that's a figurative statement as well as a literal one. You have mentioned this a couple of times now, that C++ is viable for things you cannot do with some other languages. What is so special about the language, what about its range of features, what makes it applicable to a wider range of features, of problems, be it for implementation, be it at the teaching level? Partly it is its history, every language has a history and a soft spot therefore. Where C++ comes from is one thing to say that C++ evolved from C, that statement is certainly true, but it fails to tell you why, and it fails to tell you what the focus was. The focus there, Bjarne Stroustrup was originally looking at this, it's a systems language, that is what he wanted to express, this is what he wanted to provide. A systems language that had facilities that were more sophisticated than those available in C, which was the systems language of emerging choice at the time, late 70s, early 80s. So from that point of view, he wanted to be able to talk about programs from a slightly different perspective, although C gives us a structured programming language with the basic sort of notions of structured data, indirection, allows us to abstract the specifics of the machine to the point that we are talking about pointers and not addresses. There is a whole load of pain that you no longer have to go through. Having been a Systems Programmer in Fortran, the move to C was a welcome relief, so a better alignment. So we had that with C. Now, what is it that C++ gives us? Well, it continues that progression. Why merely have structured data when we can have a rich vocabulary and say our program is composed of stuff, stuff has behavior and recognize that we want constructs that allow us to freely change our lines about data structure. If we are talking about a systems language, it's actually quite important to have that at byte level control, but it's also important to be able to change your mind given that data structure volatility, okay, that was a good idea, but that's changed the data structure, but I still want the same operations. But how do I do that and not incur an abstraction penalty? So that notion has always been there. So to go back to the question, what we see is that the tradition of C++ is as a systems language. A systems language is a language in which you can build pretty much anything, and you can control the parameters that you care about. Now, that obviously means that you have a great deal of power. It doesn't necessarily mean that it is the right tool for every job. It doesn't necessarily mean that every job is easy, but it ultimately means that every job is possible at that level. It does also bring with it a certain culture, which is why you don't see C++ developers necessarily pursuing the same interest and framework styles as you find in other spaces, such as Java and C#, as a very rich world of open source software, where we see both activity but also differences. We see some very big differences in focus. So I am not actually interested in seeing C++ developers trying to create a Spring-like frameworks or anything like that, I am much more interested in working with its sweet spot, which is that area of systems programming. I don't really want to teach people to script in C++, we have already got perfectly good languages for that, but if you start thinking about wanting to create the plumbing for an Image Processing System, I would probably want to be expressing my algorithms in C++. Okay. You have been talking about this evolution, C++ as a systems language that does what used to be done in C. What was the evolution actually? I mean, C++ started as a preprocessor, front end for C, if I recall correctly, but then sort of evolved away from that with the Standardization Process. What were those steps and where is it today? I think we can characterize the history of C++ in -- I used to characterize it in three ages, but we are now reaching the point where it's worth starting to think about characterizing that in four ages. If we start off with the earliest stage, the stage that goes from really the creation of the language through to the late 80s, and around circa 1990. This early stage was characterized by the original name of the language, "C with Classes". The idea, although one can look at it in terms of a preprocessor, it has always pretty much been a compiled language. It just chose to spit out its C code at the back end originally, and this is what came to be the AT&T Cfront compiler. Now, in that point of view, the primary approach there that was favored was a style of Object Orientation, sort of borrowed from Simula, that was characterized by say single inheritance, sort of simple public, private model, presence of classes and virtual functions, and features such as that, a few other little ideas borrowed in from ALGOL 68, some Operator Overloading, things like that. All served up as it were on a sort of a C infrastructure, sort of classic source file model that existed and continues to exist. That really characterizes the early age of C++. Now, it starts coming into its own right. People start tackling certain problems. They understand the style of a language; every language has a style and a way of designing that is encouraged. What emerged was the -- there were other aspects, there were other regularity aspects in the language; there were ideas that took us into where the second age of C++ was, which is actually when it grew most. Although, Templates and Exceptions were sort of there, they were sort of not as widely supported. What we can actually say is that in this period of the second age of C++, there was the greatest diversity in the portability of -- well, another point, having lived through it, lack of portability. That was the biggest problem, the divergence between various compilers, but part of that was learning what the language felt like to be on its own. Little things like the introduction of new fundamental types, because overloading makes it a different language to C. You can no longer merely say that Booleans can be like Integers and vice versa. You actually have to distinguish between them in a meaningful compile time fashion, because that is the character of the language. Other aspects, Multiple Inheritance were introduced. Let me think, we had Pure Virtual Functions allowing Abstract Classes. So a lot more things started creeping in from people's design thinking and realization of what a C++ system might look like as it grew larger. So it was a working with the language, a feedback of that, but there was also this rate of change. Now, the consolidations happened in the third age of C++, what you might characterize as modern C++, which really is sort of 1997-1998 onwards. What characterizes this period is the Standard, and the Standard Library, the International Standard of the language. This presence has actually made quite a big difference to the way that people perceive it. Many people have been surprised by how successful this has been in helping to converge over time the divergent platforms that we have. There was a lot of C++ compatibility issue as I mentioned before. This has made a big difference. It also helped influence people to recognizing the language in its own right. Historically, people used to teach C++ kind of the way they learned it. They learned C, then they learned Objects, then they learned C with Objects, so to speak, and as the language evolved, they would teach you the features in the order that they had learned them. Very good example of this is the introduction of Templates. Although they were introduced early, they came into their own, and really found their style and space through the Standardization of the language. That and things like Standard Template Library really characterize that. Now, what we find is that historically, in the early 90s, people would put -- authors would write books on C++ and the last chapter would probably be on Templates, and training courses would follow a similar idea, and Templates would be on the advanced course, you would never do it on the introductory course. You would have styles like that. Then there might be a chapter on the Standard Libraries, that started emerging, and that would probably be one of the appendices, or maybe one of the last chapters, so people taught this in that order, which is actually quite peculiar, because many of these things, and I had to -- what we actually saw in that period was a shift from C programmers moving to C++, to non C programmers, with a very different background, people that looked at pointers, not as a natural mode of expression and syntax, but with some suspicion and fright. So you suddenly realized, okay, this is a different constituency and in the library we have simple String type. Okay, so to not be taught the String type until last thing was a very curious thing, but again, it was historical. Sort of makes it harder to write "Hello World!". Oh, there were lots of challenges to Hello World, and Good Bye C++ was the immediate response of many people. It was a very -- it was quite a strange time where people were realigning themselves and saying, well, actually the way to teach C++ is to teach C++, not to follow this historical progression. There is no denying that there is complexity in some of the Template stuff, but at the same time, there is no denying that there is complexity in any feature. The simple Template stuff is simple. The hard Template stuff is hard. So instead of shoving it at the back of the course, you bring it to the front. And I was involved in a training company in the late 90s, where we sort of dealt with this issue. We turned it around in one of the first courses to actually do this, to actually teach from day 1, here is a string object, and don't worry about the underlying String types, we will get to char pointers later. Here is a vector, don't worry about what those angle brackets are, just read it as 'of', so that's a vector of int. What can you do with it? Oh, you can resize it. Can you, okay, that's good. Can you assign it? Yes, you can, it does everything you expect. Can you subscript it? Does it know how big it is? The answers to all of the above are yes. So we start with that idea, and you don't need to teach Templates now, there is this notion of usage versus plumbing, and you don't need to be a plumber in order to use a tap. So the point that has emerged since is that there are many, many people who have approached C++ from historically a very different perspective from the one where many people went off and explored other languages. That third age has also coincided with a growth of networking software, and a growth of embedded software and so on, which is one of the things that has helped keep C++ sort of fairly alive and popular, but not in a way that is, how should I put it, sexy and fashionable. Yeah, it's not necessarily sexy and fashionable, but as with fashion, if we look at the world of fashion for inspiration, because it is somewhat like software development, when we find that there is somebody walking on a catwalk, and we see what they are wearing, it is very unlikely that the regular person in the street would be wearing that. Although it's where the news is, it's not what people are actually wearing. People are wearing jeans and t-shirts, and they are getting on with things to solve that particular problem space, and sometimes that is C++, sometimes it is an obscure homegrown languages, sometimes it is Java, sometimes it is one of a 1,000 different scripting languages, it may even be COBOL, but it's the jeans and t-shirts, that's where it is. Which brings us to the fourth age, which is the next standard, the next standard is in the process of being finalized, we are looking at 2009, and introduces based on experience, not only a larger range of libraries, but also some language, core language enhancements. Well, from anybody else's point of view, it will mostly be in the area of Templates, and the type system that Templates deal with. Again, that will give rise to a different style and a different approach, and we can characterize that as it were as a forth age that's coming. We are planning a separate episode on that, quite interesting topic, but it sort of goes beyond the scope of what we are talking about now. That saves me a bit of hassle, and Bjarne can get to talk about it. We can also set him up quite nicely here, because what is interesting in the way I used to characterize the first three ages of C++ is they roughly correspond to an edition of Bjarne's book; first, second and third edition. So I am now eagerly awaiting the fourth edition. I know Bjarne is working on another book at the moment, but he has got a couple of years to catch up on the standard. Okay, but you mentioned a couple of the features now, and I know you long enough to be pretty sure that C++ is one of the languages that you love. So looking at these different types of things you can do with C++; I mean it's a multi-paradigm language. Why don't we take a look at some of the features and you tell us what's great about them, what's special about them, how it differentiates C++ from what you can do in more boring, more down-to-earth languages, that maybe look sexier but don't get the job done as well. So let's start with Templates. What's great about Templates? The length of the error messages. Okay, that's a cynical response, let's get that one out of the way. Templates can be potentially challenging. What is great about templates? Well, we can state a number of facts, here are a couple of facts. The Template system is actually sort of Turing complete. You can actually -- it's a programmable system. It's an interesting side effect, it was never really intended, but you can perform calculations in it. This allows you to do things in compile time that give you no runtime overhead. It allows you to express and use the same kinds of abstraction sophistication at compile time that you don't really want to sit in the runtime or would traditionally be done in another language or external configuration tool. Obviously the downside to this is the subtlety of some of the expressions, and also some of the sophistication you need to have to understand what's going on, and the ability to read angle brackets. But given the prevalence of XML these days, I am less concerned about that than I used to be. So it boils down to, Templates are great because they allow you compile time optimizations of performance, of memory footprint, that you wouldn't be able to have otherwise because you would have to have the generalization in the code and incur the runtime overhead. That's part of it, but there is also something more than that. It's not just the speed factor, it's the ability to express certain ideas, relationships between types in a compile time way. We can actually see -- perhaps one of the ways of looking at the Templates -- normally when people say Templates, the usual expectation is that somebody is going to talk about containers. Yes, this is all certainly true, you have the container library and many aspects like smart pointers. We rely on those for Templating, but that is basic generics; that's sort of your introductory level generics. This is the kind of thing that people normally think of as being generics. Let's put it this way, that is the beginning of the idea of a generic system, not the end, whereas many languages, in spite of the experience that is around, about using a generic type systems, many languages introduce generic type system that stops pretty much with the collections and things, and it doesn't go much further. What you have in C++ is that, that is just the beginning. So the notion I have just described, all this other stuff, is metaprogramming at the Template level. I wouldn't necessarily encourage everybody to do it, in fact I spend a great deal of time discouraging people from doing it. It can be frighteningly obscure at times and also surprisingly unnecessary. But as a tool when it's needed, it does offer you the way of describing at compile time relationships between types, values that you need. Something that other languages have a capability for through runtime reflection, but what we are talking about here is, as it were a compile time view, and perhaps that's the best way of looking at the C++ Template system. It is a static version of what many people see in dynamically typed languages. It is historically based on duck typing, for want of a better term; the notion that if it looks like a duck and sounds like a duck and it waddles like a duck, then it's a duck. You no longer have to say that to perform the capability of Foo, you have to inherit from class Foo. You just say, if it looks like it does Foo, then it does Foo. So that is the notion that we have, but it's what somebody once described as frozen Smalltalk; what it's done is it's frozen at compile time. Of course, that doesn't give you the general flexibility, but it does give you some of the things that people want, and they want them at compile time, given that there is a notion of compile time, and they want them in a way that allows them to control the bits, the bytes, the performance and so on, and these are the people that care, then having this mechanism is incredibly powerful. The challenge is that the language was not originally designed for this -- sorry, the template mechanism was not originally designed for this, so it strains a little to express some of the concepts, and it requires certain amount of ingenuity. You can see some of that ingenuity in a variety of publications, and also as certain amount of publish code, such as the BOOST Libraries, in order to make these things work. What we are seeing in the next generation of C++ is an acknowledgment of the power of these, but also a type system, as it were. One of the things that most duck type systems suffer from, and this I refer to dynamic languages as well as the statically compiled ones, is there is no duck. I am unable to point to the duck and name the duck, it's an idea, I cannot name it within the programming system. So it's really a type system for Templates that we are looking at in the future. But that notion of Templates allows the expression of things, like the Standard Template Library, and it's a radically different style of programming, it's not a sort of classic OO style at all. I guess to be honest, if the STL hadn't come along, it's unlikely I would still be doing C++. There is really weird stuff you can do with C++ Templates that go way beyond, for example, the Java generics which are something entirely different, but in C++, you can, for example, inherit -- a class can inherit from a Template parameter. Do you know of any example where that is useful? Yeah, there is a number of frameworks where what you are effectively trying to do is take a class and inject behavior into its base class. This has been used in a few places. Examples can be found in Microsoft's ATL, where what you are doing is you provide a base - you provide some kind of class, and it's parameterized with respect to something else that it inherits from, it gets these features. As we are at a patterns conference, it's probably appropriate to point out that this technique is very similar to an idea of Template method, whereas traditionally the Template method pattern can be expressed using a base class where you provide some hooks for behavior, and you provide a well-defined method, which has got some kind of algorithm. In C++, what you can do is freeze this at compile time. So it's not the runtime performance that I am after, I don't want a runtime hook method in that sense. My member functions are actually well-known, the situation is well defined, with respect to this framework. I don't want any runtime lookup. I want a distinct and definite type that I want to manipulate. Now, what you do is you allow yourself to put the behavior into the base class and notionally override it upside down by using this technique. So yes, there are applications of this technique, and this is -- it's a surprising one when you first see it, it's not a technique I would expect to see in every application, but at the same time, it's not something that is obscure or academic, there is genuinely practical applications of it. Another controversial feature in C++ is Operator Overloading, what's your take on that, is it useful or does it do more harm than it does good? Well, there is a number of different ways of looking at this one. First of all, let's understand what it is that you get for your money. With Operator Overloading, you are talking about taking the existing set of operators in the language and being able to overload them for types that you have defined or someone has defined, and provide appropriate behavior for them. Things you cannot do is extend the range of operators in the language. There are some languages that allow you to do this, and it is not proven to be useful, it allows people to go off and create their own private dialects better known as idealects, where one person thinks it's an absolutely brilliant idea to add an operator to a language and everybody else thinks it's one of the craziest things out and it reduces the comprehensibility of code. So no, C++ doesn't allow you to do that. Of course, it does allow you to get kind of a bit clever, and the point is there is no constraint on the semantics you provide for your Operator Overloads. But C++ is actually in the majority of languages as it were that have popularity these days. There are a very few languages that don't support some form of Operator Overloading. Even scripting languages are actually more able to do this than many mainstream languages a few years ago. The desire to not support Operator Overloading was motivated and carried through in Java partly because you can indeed write obscure code. You can end up with some crazy stuff, where somebody goes, a+b-c, and you look at that and you think okay, what am I looking at? Ah! Right, what you are looking at is a database transaction, and then the final commit, is like nope, no, I don't see that. Of course, this does not stop -- this is not really a very sound objection for a number of reasons. First of all, I have seen a lot of code. I do code reviews, and I have seen code in various languages, and I am impressed with what people are able to do with just ordinary named functions that completely mislead and hide their meaning. So what is it that Operator Overloading is supposed to give me, what's the value proposition? If I were to add two things together that are intrinsically addable, they are value types of some kind; whether they represent monetary quantities, whether they represent physical quantities, measurements and so on, and I want to add them. Then I want to see a+b, I do not want to see a."add"(b), so I want to see a+b+c, I do not want to see a."add"(b."add"(c)). I don't want to see this kind of stuff, it's clumsy and unwieldy. Advocates of this position have very little to stand on, for a very simple point of view. I have a five year old son and he can read a plus symbol, and he knows what it means. He can't spell plus, he can't spell addition, he can't spell subtraction, but he knows what a minus sign is, and he has got a rough idea of what it might mean. So he is five years old and he is able to understand these operators. Apparently, there are bunch of people at Sun who don't think that developers understand this stuff. This is a little patronizing in my point of view. Much as I love the Java language, it is a bit patronizing. If I want to add two concepts together, I want to be given the operator, there is already a name for the idea; it's not 'a d d', there is a plus symbol for it. If I want to subscript into something that represents a collection of things that is based on a key or an index, I want to use my square brackets, because that's what the language says. I talked earlier on of the language having a particular style, and when I am working with that language, then subscript is the way of doing that; plus is the way of doing certain things, assignment is the way of doing others, the arrow operator is the way of accessing a level of indirection, ++ is the way I move to the next thing, whatever it is the next thing is in a sequence. There is a set of conventions that govern this, and of course people can try to go against conventions. There are cases where this works, but most cases don't. This is more about development process and development maturity than it is about the language. I think people incorrectly blame the language for these features. Now, I will just close that discussion on Operator Overloading with some of the wilder uses, and actually say that in some cases these aren't justified. There is a minority of cases where almost creating a private language does make sense. The current growth in the idea of domain specific languages, and also in particular embedded or internal domain specific languages, where we create a sort of mini language within a language, actually goes back decades, certainly to the Lisp community, but it has been represented in some of the more powerful languages over time. The current language of choice for many people is Ruby. But this history also exists within C++, and the idea is that the Template facilities combined with many of the Operator Overloading facilities allow you to create effectively a private domain specific language in the context of C++, and there is a great deal of exploration of this. 'The Generative Programming' book a few years ago, that sort of demonstrated some of the techniques. At this point there are a number of libraries that express certain ideas that are -- well, let me pick on a very simple one, the BOOST Spirit library, is a language in which you can define the grammar of the language and parse it. Now, traditionally, this should be done by separating out your tools, your LEX and YACC, your ANTLRs or whatever, and having different build steps. Now I can actually represent the syntax of the language in something that actually looks like BNF in C++, and actually treat that as an object. Compose my syntax, treat it as an object, hook events to it, and basically run a parser off this. Now, that's pretty cool. There are this use of -- I understand that Martin Fowler coined the term a couple of years ago, about fluent interfaces, where you have this ability to chain things. When you have chained method codes, when you have a language that supports Operator Overloading and Templates, you can do this quite extensively. There is a great deal of experience in certain parts of the C++ world, in creating libraries in this particular style. But of course there is always the question of taste and judgment, and that can sometimes put Operator Overloading just a little bit too far. Okay. Another of the controversial features in C++ is Multiple Implementation Inheritance, what's your take on that? I don't particularly have a great problem with it, but it used to be one of these issues that would polarize people in a very strong way, sort of, do you use vi or Emacs kind of question. Without any rationale, people would get very, very hot under the collar. Multiple inheritance makes things certainly more complex in the language, from the point of view of the compiler writer, and it can make things more complex from the point of view of the developer. If the developer does not have a reasoned way of thinking about multiple inheritance and applying it, then they are looking at it just as a language mechanism, they are not really thinking about it as a design tool. In truth I find, I don't really use multiple inheritance for Implementation very much at all, and I would struggle to think of many case where I do. The style that is popular in language design say from early mid-90s onwards, and we see it manifested in Java and C# is that you have a dominant class, and then you have interfaces that are mixed in. I find that I used that style quite a lot and occasionally my Mixins will have a little bit behavior, but not often. That's partly to do with the style of design and an approach and having a clear design style and vision. What people have struggled with, with multiple inheritance is that they were originally presented with multiple inheritance as an implementation idea. They were given it as a mechanism. Here is a language feature. If you take that's kind of designing the wrong way around, it doesn't solve a problem. It's a case if I am wondering around with a solution that has a lot of mechanics and plumbing and I am looking for ways to apply and that I have certainly seen that in code bases. I'm probably guilty having used that many, many very years ago, but I would always advocate the ability to be able to multiply inherit even though I would no advocate its common use. It's the idea that in some cases when you are trying to bring together two pieces of code that this is one of the more discrete ways of doing it and the ability to do non-public inheritance is what makes this a practical approach. A lot of what you have been saying sounds to me like C++ gives you a wide range of powerful tools just don't use them all the time. So it sounds to me like C++ idioms, the knowledge of how to actually use the language features is particularly important maybe even more important than other languages. Yes. I would definitely agree. In recent talks over the last year or so I've started using the quote from Spiderman, "With great power, comes great responsibility". I am quite -- I guess black and white on this. Though I would say that for many people I wouldn't recommend C++ and I wouldn't recommend it for all problems at all. I counter-recommend it in many in many cases because it is a complex language. Criticality of knowledge is that much higher for C++ than it is in many other mainstream languages. It doesn't mean that you can't make it mess in other mainstream languages. Like I said I am an independent consultant and I do work in languages other than C++. You can make a mess. It's just a criticality the value of a particular level of knowledge has in C++, that distinguishes between successful design and unsuccessful design is that much more important and the bar is that much higher. You are given a wide variety of features and many of them, as it where, are the sharp tools of the language, get it wrong, you cut yourself badly. This notion is that as you say the mastery of the idioms, the familiarity with the approaches and techniques does require some study and some recognition. It's not a language you can walk into and be productive from day zero. It doesn't have necessarily that characteristic, but once you have reached a particular level, you are likely to find yourself thinking quite fluidly in it and once you have reached that level then it's again that kind of -- if you pass through the gate the language is irrelevant. In principle you can master any language and from that point. So yes the idioms and this is one of the interesting things in C++ is this reliance on things that are beyond the language and beyond the library - this world of knowledge that here at the Patterns Conference we try and capture in pattern form but has been captured in different narratives and article styles and book context and pretty much from the outset. Certainly characterize the second age of C++. One of the idioms that when I -- time back when I did C++ that was one of the important idioms was the canonical form. It was sort of lot of things to remember to do consistently and easy to forget. So are there now ways to sort of do that in one place and have it reused or have it that checked or something or does it still require this knowledge all over the place. There is still the case of having to know what you are expecting, but things have actually got simpler. The kind of orthodox canonical class form is not necessarily a solution to a problem. It is a regular set of things that are probably there. It's almost like a checklist. What we have discovered over time is there are actually easier ways of expressing some of the ideas, the relationships between the operators and certain operations. Maybe you could just shortly explain what this canonical form is about? Yes. This form was recently identified by Jim Coplien and his book 'Advanced C++ Programming Styles and Idioms' and this is the book I had mind when I said that the second era of C++ was characterized by focus on idioms of that nature. This orthodox canonical class form focuses on what am I expecting in my class interface, and it is primarily about the operators, destructors and constructors and the relationships between them. It has become more apparent that there are the idioms that we would really want to apply, for example it's fairly unlikely the most classes should have an assignment operator or copy constructor and they are not things that classes that represent entities or service style objects do not really have value semantics that are useful or meaningful and therefore we would normally find such objects on the heap. We might allocate them on the heap ourselves; we might get a factory to do it. We might do it in a number of different ways, but these objects may also be expressed polymorphically and again there are number of challenges for people trying to do assignment with polymorphic types in class hierarchies and the simple summary is don't do it. So the nature of idiomatic practice in C++ has in many ways got simpler because originally people were looking at how do I fashion the tools and now people have looked at it the other way around, it's like what is the problem I am solving and organizing the language features around that. The columns that I used to write for briefly for 'C++ Report'and then for 'CUJ' online, we are entitled from mechanism to method, and that was kind of a reaction to the fact that people focused on mechanism for using the language features. What I am interested in is, okay what is the thing that we are building, I am expressing an object that has the following characteristics, not C++ characteristics, but domain characteristics. From that I can say this object is not assignable, we have idioms for expressing non assignability indeed if we look a little further afield we also have libraries that express that it is possible to inherit a non copiable capability, I am not copiable at all and express that at the class level. So there are number of different ideas that allow us to think about our classes in a different way. This applies to assignment, most classes probably not meaningfully assignable, but also when we start working with libraries, that are based of value semantics, such as the STL what we also find is for all of those classes where we do want meaningful copy semantics, it's already been taken care of for us. So there is less attention paid to how do I construct this class in this particular way when I am allocating loads of things on the heap and I need to manage my resources, more of these are encapsulated, so you just write the class. The copy behavior comes for free end is correct; the destruction behavior comes free and is correct. So that kind of distinguishes again, this is one of those things about the criticality of knowledge and also the way we teach the language. If we look at somebody working with 1990s C++ style and idioms, the chances are they are struggling more than they need to. It's a wasted challenge in that sense, they do more manual memory management than they need to. They are worrying more about how their pointers are flying than they need to. They are worrying more about which old idioms to apply where new idioms simply express things in terms of libraries or better encapsulated types, so understanding how to encapsulate types and value based programming has improved as well. So the idiom landscape is definitely shifted. There is nothing that will necessarily automatically check things, there are various tools that will check for the usual, bits and pieces likely memory corruptions and so on, but what we are really looking at is capturing a style in the midst of all the possibilities that actually make sense and it can be considered to be relatively simple. These styles do exist, you see some surprisingly short and elegant pieces of code that years ago people would have expressed ten times the size. Let's take a look at C++ culture, one other things I always found weird about the C++ culture is that there were obfuscated C++ contests. Do they still exist or has a language sort of outgrown -- them? Well technically we can actually argue that the contest never really existed, because historically there was the International Obfuscated C Coding Contest, but it was never deemed appropriate to do a C++ one because it would be -- there is no challenge. It is very easy to create obscure code in C++ and there is no denying that and we can go back to the earlier conversation we were having about operator overloading. It's not a hard thing to do. Hopefully, though, people aren't thinking of the code as sort of executable line noise, we don't really want to re-create Perl in the land of C++. What we are looking at is the focus sometimes though is on cleverness and technique, I would say that's a very strong aspect of the core C++ culture. I don't think that is necessarily particularly healthy and something I find myself often critical of and I spoke favorably of template metaprogramming earlier on. I actually spend a lot of time, discouraging people from this, not because it's a bad idea, it's just that not a generally applicable idea. It's an idea that has a very good soft spot beyond which you really don't want to be doing the stuff. You will create solutions that are so clever that your colleagues will just be stunned into silence and you have therefore created a job for life, nobody else can maintain this code. There are certainly plenty of cleverness around there is sometimes an obsession with performance, often obsession with micro-optimization at the expense of architectural thinking. I find in the C++ culture that, it is a case that the people and many people understand the cost of particular operations, but they do not know the value of their particular designs and when we look a little further there are aspects of the C++ culture that have moved forward and embraced things like generic programing, which is not simply generic programming templates. It is a misapplication of the word generic for which Alex Stepanov How would you characterize the role of Microsoft Visual C++ and the MFC in the overall C++ landscape? Is that sort of two different cultures, how are they related, how are they different? It has been very influential on a number of levels. Microsoft's involvement in C++ has been very on and off over the years, and unfortunately in recent years it's been very on. I think that'd be the best way of putting that. Historically, Microsoft introduced a very modest compiler and they weren't first into the C++ Compiler space. It was a very modest set of capabilities, not a bad first effort. That was Microsoft C/C++ 7, the precursor of Visual C++ 1, and it wasn't bad for the time, but then they failed to do the basic thing which is actually upgrade it and update it. So people were left with a very first-aged view of C++ for a large part of the early 90s and there were some leaps forward in the compiler and the environment at around that time and that looked pretty good. Then it sort of plateaued again at around Visual C++ 6, which has become a sort of compatibility non-standard if you like, it's become a chain around the necks of many developers because it is -- actually it has quite poor compatibility with the standard and has been used for a lot of code. Fortunately the story gets better. Microsoft has a much more engaged C++ team. Now the conformance of their compiler is pretty good. It used to be a case that you wouldn't trust a Microsoft Compiler, I tend to use it all the time now. So there has been a real shift; the language has been adopted more positively as the compiler compiles the language as opposed to somebody else's idea of the language. And so we have that aspect. So the compiler is very influential. When they sort of offered an edition of the compiler for download for free that was called influential as well. A lot of people now have access to the basic set of tools. So this is all the good stuff with sort of some footnotes. For me the bad side has always been the MFC. When I first encountered it back in 1992, I was underwhelmed by the design expertise that had gone into it. It looked kind of like a thin wrapper written by a C programmer with VB background on top of the Windows API which is kind of what it was really, and it's kind of grown from there. It's grown into sort of whole industry of itself, and now it's not to say the library is not without use or -- and it's not without intricacy and detail and there are a number of techniques in there. It can be adopted elsewhere, but it has created as sort of a much larger training industry and a much larger book industry and a much larger support industry than it should have done. It also introduces a number of things that are more complex and putting together a UI in MFC is not necessarily a particularly painless experience to get the most out of UI design in MFC actually requires you to know quite a lot about the underlying API. So in that sense we can see that it's not a successful encapsulation, it's facade of that level. You find yourselves sometimes struggling with defaults and the approach to try and create a DSL within the language through the use of macros and the support of wizards has only been partially successful and indeed a colleague of mine once describes the wizards as sorcerer's apprentices because really they introduce things that cause you problems. They seem to compensate for things that should be in the library. So yes, I am being highly critical of MFC here, and unashamedly so, and I know that some at Microsoft regarded as a blot on the history. When they started doing things like the ATL that highlighted a better level of sophistication and understanding of what you can do with C++. Okay, one last question. I have the impression that you love C++, any final words; you'd like to say about what you love about C++? Why you think it's a great language or anything else you'd like to add before we wrap up? I think the anything else I'd like to add up before I wrap up is I do like using multiple languages, but I do have a particular soft spot as you've noticed for C++, but not an irrationally driven one. I deal with, as I say, a lot of languages. Things I like about C++, well, obviously there is a certain comfort in familiarity, it is other than -- I would say, the any other language that I might compile or code in that I've been using as long as is probably C. But I don't use C on its own very much. So it's probably the language I have used longest continuously, and the only way that any other language will be able to compete with that, is if I actually don't use C++ for five or six years, then Java become the next one. But, yes, I do enjoy using it. There is a high degree of familiarity. The familiarity also comes from the work that I used to do, where really knowing the inside out detail of the stand in the language, made a lot of sense. Again, it's the sense that I can apply the language to a number of problems, and again, the kind of problems that some of my customers deal with. They deal with things where you are actually -- you care a great deal about the performance -- the bits, the bytes and that level of control, and so I enjoy working in that space. The frustration for me comes from the other aspects of C++ culture and the accidental complexity that the language brings with it to find that good design takes probably more effort than it does elsewhere. I find the pleasurable experience of just being able to easily involve tests and simple design in other languages. Sometimes lacking from the experience of my clients in C++, although, I would say, I have a relatively similar experience in C++ because I write my code in a way that can -- it does that. That's not the experience shared by many people. So in the sense that I love C++; yes, I'd like to share that experience more widely and encourage people to sort of pursue a slightly more economic and a more modern style in that sense. Thank you very much. Thank you Arno. |