C++ Stylistics

C++ Stylistics

>>Our speaker today is Kevlin Henney. Kevlin
is a consultant and an author. If–I won’t even try to list all of the different places
that he’s been published. If you’ve been following C++, then you’re–you’ve undoubtedly read
the several of his articles already. He always has interesting things to say. And today,
he’s going to be talking about different styles for using C++.
>>HENNEY: Okay. Thank you, Matt. Okay. It’s quite a lot to get through so I may well skip
some slides, and we’ll see how we go. I’ll play this one by here. I want to explore some
of these questions of programming styles to C++ that tend to pop up. There’s some–sort
of a growing interest in programming styles and the multiplicities of styles available
to developers, and this seems to be reaching out across languages. There’s also a strong
recognition that many languages have tried because they have pushed themselves to supporting
many styles in the past. It turns out that some of this interest is not new and there–but
there’s also a certain amount of confusion in this space. Not least of which–thanks
to our friend, the word paradigm which has really messed things up properly. I’ll have
a quick look at that and describe why I favor the word style. But also describe the notion
why I–why most languages can claim to support multiple styles. But the focus here is on
C++. In the absence of a perfect language, we have a language that is used in production
in a number of places and has a very strong track record. There are many, many styles
that we could be looking at. I have constrained this to just three broad groups; two of which
are properly styles in terms of a way of thinking. The third, which was just a bucket placeholder
for two quite different styles, which are put under the language mechanism. That’s the
only one defined by language mechanism, and so were template-based styles. There are many
more styles we could be approaching. There are things that I’m not going to cover, and
particularly areas where the support is not core in the language or the support is not
there in the language at all. You can sort of fake up a functional programming style;
sort of, kind of, but it’s never going to be the same as using Scheme or Haskell. That’s
not a style that is supported. If we talk about concurrency, there are so many overwhelmingly
different styles of concurrent programming, and strictly speaking, none of them is supported
in standard C++. Although we have ways of wrapping things and doing things, the most
pervasive style here is a substandard, free threading style, which kind of fits out as
an offshoot of procedural. Again, and I’m not going to talk about that one because certainly
it itself is a talk. And I presume that you’ve got some kind of idea of programming for style.
I want to get a sense of how many of you use C++ either sort of–yes, 20% or more of your
time is taken up. Okay. So, there’s–it’s something–okay. That’s reasonable. Okay.
That’s good. So, that will allow me to shoot pass a lot of slides and just go, “Yes, you
know this.” I want to, first of all, look at this question of styles. Convenient enough,
there’s a word that covers what I’m interested in. Stylistics, the study of the literary
styles of particular genres or writers. This captures probably a little more closely the
way that we look at work with different approaches to programming. Then, the common use of the
word paradigm. Trouble with Paradigm. Paradigm is a term from linguistics. So surely, it
should apply to programming. Well, not really. That’s not how it’s used. The sense in which
people have kind of tried to use it. It was popularized by Thomas Kuhn in his 1962 book,
I think, [INDISTINCT] “The Structure of Scientific Revolutions,” a book that–I wouldn’t say
it’s [INDISTINCT] reading but I will actually claim to have read it. It’s–and yes, I got
something from that many years ago. The–and that was what it defines the modern use of
the term. Now, what is interesting is that even there, you think, we’ll that–that’s
it. There’s a concrete solid definition. But even then, that doesn’t work. Many people,
when they look at it from the kind of Kuhnian sense, are trying to say that there’s one
way of doing things, that there’s one kind of dominant and overarching way of doing things.
Now, in programming, this has never really been the case. The world of programming is
diverse. And one area where people are programming may–can be completely disjoint to another
area. You got a COBOL programmer talking to an APL programmer, going back a few decades?
No, unlikely. They do not have a common language or even a common way of speaking. That has
not changed. There has never been a single overarching model. That may be something that
we teach a lot, that may be something that is in the press and is in vogue, and is sexy;
but there’s never been one single way of doing things. The other way in which people use
it, is they try and use it based on the first point. They try and use it to make a marketing
point. And it’s related to the term paradigm shift. And that notion of shift happens. The
idea is, well, we’re all doing this; but now, it’s all going to be different. We’re all
going to be doing that. That’s mostly for dramatic effect or to make yourself just sound
a little bit clever. You know, there’s another way of doing something. Probably more usefully,
the–sometimes, people try and relate it to language features. And again, that’s a very
mechanistic way of looking and I don’t enjoy looking at languages just purely from the
point of view of mechanism. It’s how the mechanisms are into play. So for example, overload–being
able to overload functions is not a paradigm. Although I know that I’ve seen that played
in the book. Perhaps, the most useful one and the one where it was originally used with
great effects, is a 1978 Turing Award Winner–his name just escaped my mind just at the moment.
And he wrote the paper–Robert Floyd, here it is. He wrote a paper to–where he effectively
used paradigm to mean pattern or architecture style if we use a more modern vocabulary.
And what is interesting is that, he related this to what many people try and use the branding
multi-paradigm form. Now, a paradigm makes you try and sound smart. But multi-paradigm
is designed to make you sound really smart. Okay. So, we already have confusion over the
term paradigm. Multi-paradigm just multiplies the confusion. Sometimes, it’s a set of language
features there. The challenge here is that, if you’re saying that a paradigm is related
to a style or a pattern, then clearly, a single paradigm approach is a failure mode. If you
only have one way of doing something then that is a problem. So by definition, anything
that is multi-paradigm is normal. Single paradigm is a lack of imagination and ability. A programming
language, that its general purpose is by definition multi-paradigm. I know a very few general
purpose program–well, I don’t know general purpose program in languages that could ever
able be said to fulfill only one paradigm. A part of the problem with this is, the term
paradigm is not a normalized term. It’s not disjoint. You don’t have this mutually exclusive
with that. You look at things, you see them at different levels overlapping with the rest
of it. Not useful term, too much confusion. Let’s use something else. Focusing on Style.
From the dictionary, we can see that it talks about the notion of style, a manner in which
something is done, distinctive appearance and design. If we start looking at building
architecture and talk about building styles or the sort of the schools of design that
exist, that gets us a little bit closer to what we’re talking about. And there is no
notion, we only have one way of doing something. These are all complimentary. They can co-exist,
and indeed, that’s the normal state of being. There is nothing mortem about it. There is
certainly nothing post-mortem about it, although that is a term that seems to be gaining some
popularity in certain courteous. So, what we can say is that individuals have styles.
Well, lovely little word that’s not commonly used, idiolect. The problem is that idiolectic
style is problematic. I’m sure you’ve already encountered code that falls into this category.
Oh, yeah, yeah, that’s the way he codes for a particular way of doing it. The school of
thought establishes an idiom, so a group kind of approach. But even when we say procedural
style, that doesn’t tell you that there is one way to do something. You get a C++ program
using a procedural style. I ask you, what that has in common with the Fortran programmer
using a procedural style? Having been a Fortran programmer, I can–I can tell you, these are
worlds apart. Having gone from Fortran to C, I recognized that all of my C code initially
looks like C-tran. C in respect with a very heavy Fortran accent. It was unrecognizable
as proper C, although syntactically correct. When I did Fortran again, a year later, my
Fortran was unrecognizable to a Fortran programmer, and that was one of the first things my colleague
changed. So, to even say procedural style doesn’t nail it down. Each language pretty
much comes with its own–its own notion. Now, of course, any real problem is going to demand
a little bit more imagination. The idea that if you only–there’s nothing more dangerous
than an idea if you have only one idea. So, you are expecting, in a series pieces of software,
to mix styles at different levels in some way. Some of it may be individual preference;
but in other cases, we’d like to think that it’s anchored in the problem. The challenge
here is that, when people mix styles, it does take skill and taste. These are two things
that are not necessarily easy to teach but can be acquired over time. And obviously,
there’s a certain sense of subjectivity to taste, but there is some into subjective agreement.
And when people often use this notion of mixing styles, and sometimes I–I’ve heard people
say, “Yeah, we’re doing multi-paradigm development.” What that actually means is we haven’t got
a clue what we’re doing. We’re doing all kinds of different things and it’ll kind of fits
together. The other branding for this is post-mortem. Again, I’m not interested in that. What I
think a lot of these approaches are missing is the focus on the problem domain. What crazy
idea, that–your solution styles. There’s somehow hopefully a relationship between the
style that you choose for your solution and the nature of the problem that you are solving.
If you are solving a process control problem and you are bickering over whether procedural
versus object-oriented is the right way to look at it, you’re looking in the wrong place.
Neither of these styles is the dominant architecture of a process control system, okay? And there
are–that it has aspects of both. Both of these styles can be incorporated in the more
tactical level. In other words, it’s the wrong discussion. In other words, what is the problem?
And get a crazy idea. The notion that we would like to relate the problem to the solution
is something that has a very strong resonance with patterns which is something that I’m
very interested and have a–recently long track record with. But also, other idea is
problem frames that are–relate to the work of Michael Jackson. And you are invited to
guess which Michael Jackson it is. You have a number of choices, you can pick from a menu
of four. There is Michael Jackson “The Beer Hunter” who sadly died last year, but go to
bearhunter.com, author of some very good books on beer and whisky for around the world. Good
Christmas present, these books as well. There is Sir Michael Jackson who’s head of the British
Army and head of the UN Force in Kosovo, it’s not him. And there’s Michael Jackson the methodologist.
That sounds promising. And then there’s the other one. We’re going to skip that one. Now,
Michael Jackson the methodologist is a–and requirements guy, focuses extensively on this
idea that there are different kinds of problem that require different kinds of description,
okay? And there are characteristic things that tell you about the kind of problem it
is, and that will lend itself to suggesting a way of solving the problem in an appropriate
style. And Robert Floyd, in his paper, on “Paradigms of Programming,” which I want to
point out again, goes back 30 years, he made the point that one of the challenges that
we have in programming is that we don’t have enough paradigms, using his term. We do not
have a sufficient stock to address the actual problems. We have–we have a narrow limited
vocabulary. That was his perspective. So, if we go and look at something like C++, there
are a number of things that it’s quite good at and aligns very well with. And we are going
to do this kind of idea of aligning problem solution domains, then–when you have to do–when
you have to talk to the machine and you care about things that are machine-level abstractions,
then you’re on that level of control. There’s a kind of an essence of control freakery to
the language. You know, this is not a language for people who like to drive in automatic.
You need a manual gearshift, okay? But once you’ve got that, boy, you can use it. So,
if you like that, then it will fit. So, there’s a personal fit as well. But in many other
respects, we’re talking about where it fits in the world of the things we want to build.
Embedded systems is a good fit there. Real time systems, you have that kind of level
of accuracy. If you–if you look at languages that have been general purpose but not designed
for these and you’ve–for example, if you look at something like real-time uses of Java,
you practically have to–got the language and all of the big selling points in order
to get it to work in that–in that environment; where C++ requires relatively little adaptation
for that point of view, almost none. It depends on the kind of systems we’re talking about.
High-performance computing, systems programming in general, algorithmically focused code.
I find that if I have to write an algorithmically focused code, certain frameworks are pleasing
and easy to use in Java. If I write algorithmically code in Java, I don’t know if I get–it’s
difficult to describe but the experience is boring, the experience is one of tedium. I
enjoy certain other activities in Java but algorithmically focused code is just tedious
to write. It doesn’t support the right level of mechanisms; although extensively, it has
a common heritage. Games programming, not exciting one there; and obviously, many other
domains where C has been favored in the past. These are the core areas. Although C++ has
a certain reputations being a general purpose application language, we are kind of seeing
that one drop off. And I’m not actually too sad about that, to be honest. Having been
involved in training and consultancy for a number of years, I’m quite happy that there
a bunch of people out there not touching–using C++ for that purpose, so it’s making my life
a little bit easier. So, there are other areas where C++–and it doesn’t really fit. And
some of that is from its own design. Some of it comes from its history. Some of it comes
from problems with library design and cultures of library design. C++ has suffered a diversity
and enjoyed a diversity of different library approaches. But some areas just never really
took off the way that it could’ve done, or indeed, there are other ways in solving these
things. And I’m thinking particularly here, it’s nothing you can’t do any of these things.
It’s just that when you actually realize when you work backwards from what you’d like, it
doesn’t look like the C++ code. It’s doable. Of course, it’s doable. Ultimately, anything
is doable given a computer. With smart people, it just might take a bit longer to do it in
dissembler, okay? But it’s all achievable. That’s what we’re after, its effectiveness.
So, I’m going to have a quick look at procedural styles. So, it seems appropriate to pick a
nice little algorithm to start off with. This is one of my favorite algorithms. It’s no
encapsulates in the STL. And it’s actually a–it’s quite a good process for sort of software
development in the small though difficult to replicate. And normally, unless, you’re
a Nobel Laureate or, you know, Turing Award Winner, maybe you want to put a step forward,
check it, you know. So, what do we mean by procedural programming? It’s notion of a hierarchical
decomposition of tasks, okay? It’s about the things that we do. The things that we do it
with tend to be more slightly more subordinated, they’re more passive entities. We look at
things flowing through this. In this sense where the notion of the data structure is
considered more passive, there are some degree of commonality with functional programming
because the idea there is your primary construct is a thing that does something or transforms
something. The data flows through the system. And this is reflected in the styles of analysis
thinking that grew out of this school of thinking, data flow based approaches. This is all very
much about level. It’s–the dominant element is the thing that we are doing. That is decompose
the thing that we are doing. Now, we have a number of choices. The classic view of procedural
programming is very much the top-down view, the structured programming view. I’m a little
reserved about using the term structured programming. Has anybody actually looked at the book called
“The Structured Programming” that was written in 1974 by Dijkstra, Hoare and Dahl. Because
in that, you’ll actually find the–what we call object orientation. It’s quite chiefly
listed as the third section, so–because it is programming with structure. So, structure
programming, as a term of differentiation, I’m not entirely sure it’s the right one.
But nonetheless, people often use it in this way. There are differences even within this
basic space. A notion that is often overlooked is there is a fundamentally different style
between more algorithmic in process based code. The–for example, there is actually
a technical difference between a procedure and an algorithm. An algorithm, you wait for
it to terminate because it’s supposed to terminate. That is what characterizes it. A procedure
is not necessarily going to terminate, and then it leads us into the world of processes.
And indeed, there’s a whole different style out there which we’re not going to touch today.
But nonetheless, if you wait for an interactive system that is written in a procedural style
or indeed any style, if you wait for an interactive system that characterizes process and processing,
if you wait for that to terminate, you will be disappointed. You cannot say, “The post-condition
of this action is,” because there is no post-condition. Post-condition is system shutdown. So, there’s
a very different style of expressing these. As the algorithmic’s view which offers your
one frame of thinking and there’s a process view that offers you a different fit. So,
even within procedural style, there’s a reason that this section is called procedural styles
plural, because there is more than one. Again, when we look at things like event-driven systems,
I’m trying to characterize it by the nature of the problem in the architecture. We can
use procedural styles. What we end up with is an inversion of control flow? Function
pointers and in C++ [INDISTINCT] as well. Member function pointers support it up to
a point, a little better off when we start using some of the newer library features.
It’s not something that you get out of the box in C++ in terms of the core language.
But the notion of being able to bind a context of execution together with the target of execution
of the action, then that’s quite nice, that’s very pleasant. There’s a–there’s a number
of features in the TL1 library originating from boost and making their way into the C++0X
standard, which may or may not be hexadecimal. We’re not sure of that value of x. It’s kind
of touch and go as I understand it. But although we have used this–I mean, if you think about
all the windowing code, it’s clearly event-driven. The use of callbacks and these approaches.
It fits here. I would say event-driven systems also fit with OO, but I’ve got other things
to say on OO so I won’t be revisiting that topic. But in truth, there is a–there’s good
support here but there is a very large hole, from my point view, having worked with a number
of other sort of languages and context. The lack of metadata and reflection means you
can’t support where style of architecture known as implicit invocation. Has anybody
here ever used Orc? Okay, a few hands go up. There’s a big–and of those–has anybody of
those people used Perl? Yeah, okay. But, you know, Perl–I never really kind of got along
with Perl. I thought all kind of certain elegance to its designed, I think–it has this kind
of implicit invocation approach. Perl is kind of executable line noise, very, very strongly
kind of top-down procedural in its approach. What was nice about Perl–about Orc is that
you would–you would say, right, this is a language. It is structured for the execution
of matching regular expressions on input, on a sequence of inputs. It’s a sequence of
transformation. It’s–it fits within a particular architectural model and it does so very well.
And when does this piece of code get executed? Well, when it matches these, you have the
notion of a rule or a trigger that it implicitly matches. There is no, “If it matches this,
than do this.” It just is. The structure of the program is characteristically defined
like this. Now, this is a style that if you–if you have a language that supports metadata
reflection and indeed an element of meta-programming, you can get quite a lot out of. And a lot
of–there’s a lot of Ruby frameworks out there that demonstrate the power of this approach.
And a lot of the model driver architectures that are perceived as being lightweight in
approach rely on the use of annotations, that they just allow you to mark up a class. You
can actually do this. It’s a good exercise when you’re thinking of something interesting
to do. Create an Orc like framework that allows you take a class and annotate all the regular
expressions you would like a particular method to execute on. And it’s just–and it just
is. It’s very, very simple. There’s no registration processes, no if, else, if. It’s a very different
start. This is a hole in C++. Now, what I’d like to do is take that event-driven style
or event-driven problem and do something with it. And I want to demonstrate some different
styles. Timer on-off. So, you have heating. Well, no, you don’t, you’re in California.
But I’m from the U.K. We have heating, it gets cold. You need to turn the heating on,
you need to turn the heating off. And rather than doing it manually, you’d like to have
this on a timer. That makes a certain sense. So, we have our heating class and we can turn
it on and turn it off. If you favor a flag-driven approach to programming, it’s–you would have
enable [INDISTINCT] true or false. But let’s actually use this kind of sensible kind of
style of program. An intentional one where we say, “Turn it on. Turn it off.” And we
got a timer and we choose our time of day and we initialize that and we have the notion
of being able to run it and cancel it. The one I’m interested in though is this. There
is something I would like to do. I would like to turn that on at one time of day, and turn
it off at another time of day. What goes in the gap? Okay. So, here is a C-style approach.
The C-style way is it has a certain elegance to it in terms of its brevity. It is short,
it is very sweet. You have two functions that are based on the task. I would like to turn
this on; I would like to turn this off. It’s a very simple view of that level. And then,
we have–yeah, then it kind of goes a little bit messy. Void pointers. Okay. So, C++ is
a statically typed language, and this works for an awful lot of cases. But when you really
need to sort of start getting general with certain things, to start messing about with
the bytes, then you need void pointers. The other reason that void pointers are often
used is generosity. I don’t want to confuse that with generosity of templates; but it
is that general purposeness. It’s that how you get generics and see as it were. You tell
the compiler in known and certain terms. Thanks for your help, okay, but I’ll take it from
here. Trust me on this, okay. That’s what you’re doing. Now, obviously, it’s a trust
based game, trust the programmer. It is one of the notions, the spirit of C that we–that
we have in C++. But there is another aspect to this. I mean, it is–it’s difficult to
call that code there and this code here pretty. It’s quite ugly, okay? And this is–this is
messy. You’ve got a lot of issues going on here. You’ve got a correlation as well. And
this is one of the challenges, is that there is a–as it were an unnormalized correlation.
What I mean by that is that the top–the thing you pass in here–the thing you pass in here
are correlated with one another, but you’ve just told the type system, “Don’t worry about
it.” The type of that depends on what you’re–what you’re passing in here. You better agree.
Now, what is missing here is this correlation. Now, when we look at this from an object-oriented
point of view, we have a name for a thing. It’s called an object. You know, the way these
things are always kind of together and we’d like them to be together in a meaningful way,
that’s a thing. So, Classic OO Solution is used in command pattern. Now, this tends to
be–so this will–this will work as indeed with the previous one. But this has required
a certain expansion in the amount of code. We’ve introduced a command. We’ve got a pure
virtual function. It effectively represents an interface. Timer is at least simple. So,
if it’s–so the–we shifted the complexity over to this stuff. And you see the top line
represents a contract that’s quite straightforward. It’s this stuff where we’re getting the accidental
complexity, the complexity we introduced to the problem in solving it. Okay. That’s that–that’s
just the kind of the noise. That’s the overhead you have to pay to get this working. And we’ve
got the thing like the heating point or all the kinds of other things, and then it’ll
do the right thing. So, type safe, it is–it is correct. It–it’s not as direct as it could
be though. So, if we return to proceduralism but we look at it from a modern C++ point
of view using either boost functional, TL1 functional, C++0X function, there is a nice
little function wrapper. It is the idea of saying, “Well, a function, we can use an object
in a tactical sense and it wraps it up. It wraps it up. It contains the polymorphism,
in which we’ll about in the next session. And now, I’ve actually got everything wrapped
up. There–it’s quite nice because this is the only bit of code. I’m actually showing
where it’s–it actually shows you how it execute–or and set up. So, we got a timer. I’m going
to turn it on. Here’s when it goes on. We’re going to bind the operation to turn it on
against system. We’re going to turn it off. When it goes off, then we’re going to bind
the off operation with the system, and then we’re going to say run, and that’s it. So,
there’s a certain directness. This is still procedural code, okay, that we have not institute–we
are using objects in a relatively tactical sense, but the overwriting style is that of
proceduralism. But it’s done in a style that fits what we’re working with. Now, Object-Oriented
Styles. And then, again, this is where the plural really matters. There’s quite a few
procedural styles but the plural really matters when it comes to object-orientation. When
people talk about the object-oriented style versus the procedural style, or the object-oriented
paradigm versus the procedural paradigm, that [INDISTINCT] us over a remarkable number of
differences of perception. With object-oriented programming, there are also models that are
common to lots of different object models. You are partitioning the development and indeed
the runtime into units. And the development is partitioned into classes characteristically,
that’s the typical one, that’s the paradigm of object-oriented programming. Another use
of the word paradigm, example. Yes? Yes, not a good word to use. This is the common example.
There are other object models that don’t use classes and its runtime into objects. So,
you have this notion of characterizing objects in terms of identity, state and behavior.
For different objects, these way up in different ways. So, some objects are stateless. Some
objects, the identity is irrelevant. And other objects, the behavior is trivial but the state
matters. There’s this kind of shift and interplay between these three aspects. So, you have
this kind of structure. And the–a kind of formal way of characterizing is something
that–seeing is the rule of–or that–kind of the three things–the three columns of
object-orientation; encapsulation, polymorphism and inheritance. But if you want to be a little
more precise, it’s runtime polymorphism and it’s formed polymorphism that is called inclusion
polymorphism. There are three other types of polymorphism; parametric, coercion and
overload based polymorphism. C++ does have the benefit supporting all four of these.
And it’s one of the few languages to do so. So, if we’re looking at paradigm, meaning
programming features or mechanisms, then actually, it’s quite rich in this respect. But as I
say, this is only scratching the surface. Here are some sort of space of diversity.
You’ve got a statically typed school and you’ve got the dynamically typed school. When we
try and get these people talking to each other, they have very little to say, except abuse,
okay? There is–there are–the experience of programming in small talk. The experience
of programming in Ruby is fundamentally different to the experience of programming in C++. These
are very different. So, people would struggle to recognize these as being the same kind
of object-oriented thinking. A lot of people push this a lot 15 years ago. “Oh, yes, small
talk and C++ and objective–and objective C.” And there were a number of other languages
that were puffing around. The notion is that they are actually very well different. They
share some common elements. But it’s like, you know, COBOL and Fortran. They’re both
procedural and they’re from the 1960s. Well, they must share a lot in common. Well, yeah.
IBM, you know. So, that’s about it. They are very different in their outlook. So, in statically
typed models, inheritance is normally used in–the main reason–one of the main reasons
you use inheritance is to introduce polymorphism. In dynamically typed languages, you need it
for that. The only reason you use inheritance is for sub-classing as opposed to sub-typing.
It’s a very strong distinction. In statistically typed languages, they may or may not be support
for reflection. This is something that C++ misses. It eliminates a whole class of things
that you can do; but of course, we have support for other things that we can do. But it does–it
does characterize the fact that this object-orientation is kind of different to that object-orientation
in very fundamental ways. There’s object based programming. Object based is often referred
to in terms of just being kind of encapsulation or classic ADT. The only kind of polymorphism
you’re really thinking about is link-time or compile-time polymorphism. It’s–there’s
no–there’s no real sense that you’re dealing with runtime substitution of anything. That’s
not really the game. Inheritance is not a player in the space. C++ has recent support
for that. And then, we have things like prototype based approaches, which I guess these days
characterize and it–what can be seen in things like JavaScript. There is no real concept
of class. Again, that’s an object model but not one that has supported out the box in
C++. And if you do try and support it, it looks a bit strange, people look at you funny
for doing it. So, we have a number of things. You have the data privacy concept in C++.
We have a private keyword; but it’s not as private as you’d like it to be. We have to
recognize that there are techniques for decoupling C++ code further. But coupling is one of the
dominant forces that we’ll shape or hinder along system and the style. But that does
have an influence. We are missing a number of dynamic facilities in a language, which
is a pain in the backside, to be honest. The fact that there’s no reflection and there’s
going to be no reflection in a standard way does limit certain options. But again, the
presence of virtual functions and standardized function adaptors is very useful for a number
of other things. And object-based program, very well supported indeed. The no inheritance
view, why would this be useful. Classically, value-based programming is the area where
this takes off. This is a sort of a–this is again in the object-oriented family where
it blends nicely into the generic programming family we’ll look at in a moment. Now, Object
Lifecycle Management tends to be the challenge that people have. And sometimes, people look
at the world again in black and white and this side versus that side. And it’s all about
GC versus Explicit Memory Management. That’s not necessarily the right way to look at it.
There are four fundamental ways of organizing lifetimes. Explicit management, you choose
when you get rid of an object and you do so explicitly. I would like it at this point
in the code here, and that is decoupled from the point of which it is created, okay? It
just has to come after it. Before, it doesn’t work and twice definitely doesn’t work. And
that was a bad idea as well, okay? These are–these are classic failure modes. Scope bound, this
is the simplest of all the models. It is automatic, so non-manual, it is deterministic, likely
explicit but it is deterministic. You scope the life of an object within the life of another
thing. That thing maybe a bounded scope, a functional scope or it may be the scope as
it with a lifetime of another object. My gut instinct is, if you can organize as much of
your code as possible using number two, that eliminates a large class of hassle the people
encounter. But if you are used to creating your object dynamically and then–and that
is your favorite style, then you will find yourself dealing with the problems of number
one. It’s not that you can’t do it, it’s just sometimes a bit challenging if you make everything
a pointer that needs to be managed with a delete. Then, we have Reference counted. Now,
one and two are kind of supported out of the box of C++. The third one is a library addition.
This is something that you have to do yourself or you get from the box shared pointer. So,
it’s not supported out of the box. There are limitations to it, and more becoming apparent
overtime. I think it is a very effective technique for the problems that it solves. But I find
people sometimes trying to solve too much with it. There are performance costs to this,
there are architectural cost to it. It’s a basically intrusive approach and the–there
is a certain fear sometimes of smart point to madness. And they’re not always smart,
there’s–there is a kind of like, “Yeah, just use it,” because you’re not sure about something,
use a smart pointer to do this. However, that is something that we can support within a
language and it does have applicability. It can be effective. And then, we have Garbage
collected. Now, this one’s outside the realm of standard C++, and there’s a lot of discussion
and debates about how best to support it. Garbage collection these days is not the same
as garbage collection was 20 years ago or 40 years ago. As we move to increasingly concurrent
models of programming, incremental as opposed to stop the world garbage collectors have
a big win in–for certain kinds of architecture. And this is a–it will be a shame when all
of that are able support this in a standard way. Now, let’s have a look at some of the
styles within this broad family of styles. Inheritance-based approach is inheritance-based
thinking. This is where many people are first introduced to object-orientation, where they
first get to grips with having gone beyond the basic class. They’re object-based approach
in C++. They are then introduced to inheritance. Now, there’s a certain syntactic overhead
doing this. The default that you expect is not the default that you get. But the–once
you’ve got–you’ve got ahead around call on public and here’s the thing I’m inheriting
from, the normal emphasis is on being able to compose with respect to code. The idea
of organizing classification as being a way of organizing the commonality of your code
to avoid duplication, to avoid the joy of copy and paste, and maybe reduce your macro
account a little bit, you know. That’s–these are all the ideas that this supports. So,
there is a case here for inheritance-based program, and you end up with kind of style
and approach, kind of like this. You end up with a–at least with disciplined guice, you
can end up with a kind of class hierarchy where you support infrastructure basic facilities,
you build on its services, then you have your problem domain, your application space. And
you kind of compose it at this level. So, it’s a composition technique for dealing with
code primarily. But I would actually say that this whole approach, even though it’s the
one that people are often taught, it is the one that was counted or reused and all the
rest of it. There’s–there really is no such thing as reuse the way that people describe
it. Reuse is an accident property of anything. It’s difficult to plan for it. What most people
mean when they talk about reuse is use, you know. It’s a–it’s a far less attractive and
exciting term. When you–when you use a line break, you are using it for what it was intended
for normally. And you are not reusing it unless you’re doing something really crazy with it.
So, in that sense, reuse in the real world is about repurposing things. I can reuse these
seats here and rearrange them to form a bed. Not a very comfortable bed, but I can do that.
That’s not their primary use. I am reusing them outside their original domain of replicability.
And what we have here is the notion of what people are trying to do when they talk about
reuse as create commodity, which is a very different thing. So, tomorrow I will fly back
to the U.K., I will not reuse the plane. I will just use it for the purpose it was intended.
There’s nothing fancy or exciting about that. So, this is the kind of the attraction that
people have often ended up with, and it is a very intrusive approach. It is sometimes
based on coincidental opportunities, but it does introduce a very strong form of coupling.
And in C++, that coupling is amplified through the fact that it’s–involves the source code
structure. So, we need to be keenly aware of that. But regardless of that, there is
this kind of inheritance-based approach or inheritance first approach has fallen strongly
out of favor in terms of interface-based programming. Interface-based programming, which we could
look at from the other side as being part and parcel of component-based programming
is where we focus and we make a straight separation of the way you use something, the usage type,
the interface to it from the way that it is built and implemented. The underlying concrete
class of creation type that we make a strict separation. Not just a kind of a, well, we
put some of the implementation details down in the hierarchy. No. A really strict separation.
The–we can do this relatively easily in C++. This is not a problem. There has been a growing
trend towards using flatter class hierarchies that are wholly abstract at the top, moving
away from the style where we are trying to accumulate implementation. It turns out that
the challenge is not to write code, the challenge is to organize code. And this offers us a
more meaningful way of working with things. You end up with the equivalent code. And actually,
these two–these two diagrams are taken from a couple of real projects, the before and
after. We took inheritance-based code that was tightly coupled, that was difficult to
test and we teased it apart, retaining little broad layering structure but making a strict
separation between the concept of the thing that we were dealing with and the realization
possibilities, and the amount of executable code remains the same. It’s conserved. The
amount of declarative code does go up a little bit. You have more construct. But the amount
of stuff–actually doing stuff remains consistent. This is far more extensible. It also emphasizes
something different. If you go back to this one, there’s an intentional–there’s an–there’s
two intentional points to the titles. This is Infrastructure + Services + Domain. This
is Domain x Services x Infrastructure. This is domain-centered from the point of view
of people who are working with the application. This is what they see, they are not–they
don’t have the weight of the infrastructure pushing down on them. And having seen developers
struggling with the fact they’re getting all these arbitrary dependencies through struggling
to deal with those from a testing point of view, this makes the difference. They want
to see application concepts and have their code integrate into a more plug-in style.
That’s one of the things that interface-based approach support very nicely. The other notion
is the freedom of combination, the flexibility, the degrees of freedom. This is a plug-in-based
approach. They’re not hardwiring assumptions. Inheritance is a very strong relationship.
This is about composition. It’s not that nobody thought the composition would be a good idea,
it’s just that this style of program naturally–programming naturally encourages it. But you can actually
see there’s a spectrum. They want to turn out–they want to suggest that these are two
mutually exclusive approaches. There is a spectrum from the inheritance or sub classing-based
approach to a more sub-typing and an interface-based approach. General thinking moves this way,
but we do have some challenges. This are the–there are the benefits and parallel development
testing, component deployment, plug-in styles. So–but it shouldn’t make a difference, but
it does. The lack of it in specific construct in C++ for doing this means a lot of people
miss it. A lot of people miss it as an opportunity. It requires more ritual and ceremony as well
as adherence to a–an idiomatic style. If I’m working in a C# or Java, I just go interface
whatever, open curly, things that I care about, with semi-colons, I don’t have to worry about
putting abstract or anything like that, and curly, and we are done. In C++, there is a
certain ritual and ceremonies that I’ll have to go through. It’s still called class then
I have to argue with my colleagues at whether or not I’m going to put an I in front of it.
I must admit I’ve never been particularly fond of this approach because it makes everything
bunched up in the wrong place of the alphabet. And, you know, I came, I sore, I conquered.
No, this is not interesting to us. Okay. And that, I don’t find a particularly effective
style. Even worse is where you see companies where they’ve got I such and such and then
you look at it and say, “Yeah, but it’s got implementation code in it.” “Yes, it started
out an interface, but we couldn’t change the name.” Yes, this is the piece of code that
is lying to you. It’s a convention–it’s not as useful as people think it is. However,
once I’ve got past that argument, then I’ll go open curly, public, virtual, I come like
with the virtual, equals zero, semi-colon. What are we going to do with the destructor?
And how–do we make that–and that’s going to be pure virtual or not, but I still have
to provide a definition. I can make it protected if I don’t want people to–there’s lots of
little fascinating decisions we can go through. That means there’s a little bit of accidental
complexity there. I’ve not found it to be a problem personally, but I do recognize that
it is a problem for many people. A lot of people just don’t get it. They don’t hit the
convention. They don’t understand what the implications are in the long term of actually
keeping to the style; because you’re actually telling people to not write code. People are
paid to write code so they feel a little bit uncomfortable. Maybe I could put a little
bit of helpful default stuff in there, you know. I’ll be just helpful. Programs are terribly
helpful to people, but this is actually a disadvantage. If you got helpful stuff, put
it the next layer down, keep the top clean. There are very good reasons for doing this
and there are a number of techniques that buffer and allow you to change the elements
of the hierarchy and maintain that crisp idea of, that is just the way you program to it.
What is interesting is that, in spite of the fact that people do struggle with this in
C++. When they do it, it tends out to be very effective. A team that I’ve consulted for
over many years told me that this was one of the most useful–or, no, this was the most
useful thing I ever told them. The possible indication of that is that nothing else I
told them was of any use at all. That’s fine. You know, getting one hit is good at least.
So–but the notion here is that there is a style that we are potentially overlooking.
We also have this notion of a lack of proper modules, like the other side of the interface.
The–actually having a formal unit of composition for the implementation code, and making a
very clear notion about that. Naming it, having a concept of dynamic loading this portable.
It doesn’t mean we can’t do it. It does mean that we have to be careful when we support
different platforms, shared objects on Linux, DLLs, and–or Microsoft Windows, very different
semantics between these. But nonetheless, there are possibilities here, but they are
largely ever looked because it doesn’t look like you’re doing much. That makes people
feel uncomfortable. Value-based programming, I indicated before is one of these areas that
C++ does have very good support for. The idea of–now again, this is not a single all encompassing
idea, this is just a category of dealing with objects, and they are well represented in
C++. The idea of values is that they are fine grained objects that are strongly informational,
they’re identities of very little interest, and they typically reflect on objects in the
real world that have these properties; money, dates and so on. Depending on your domain,
these have–these are other values or entities of interest. But there are particular styles
here. You don’t really worry about dynamic memory. These are things that you can copy
around quite freely, and therefore, copying transparency can be useful passing by const
reference, all of these things. This is relatively well understood even if people don’t describe
it in these terms. And the next standard will provide better opportunities for optimizing
this kind of code, being able to move values, relevant when we’re dealing with all value
objects that do internally manage their own memory allocation. It just gets rid of a little
bit of potential waste when you end up with all of these spare copies floating around.
However, some of the details of page be quite subtle and I am dreading–I’m dreading the
prospect of actually having to teach some of these stuff that’s going to come up in
the next seminar. This is kind of a little bit expert-friendly. It is powerful. If you
know what you want from it, you can do an awful lot with it. But I am a little bit concerned
at this point, we–that–what the accidental complexity is. I don’t have enough experience
with it to really comment. But it does seem interesting that most people are focusing
on–or people are regardless C++ experts. So, general Object-Oriented Issues. Not everything
fits this worldview, okay? And that’s acceptable. Some of that comes about because C++ does
not necessarily have a unified type system. But in some languages, there is a unification
of the idea of an object and a function, and there is no contradictions in between these
two. We can do this through adaptation in C++ but it requires adaptation as opposed
to being out of the box. But once you’ve got it up and running and once it becomes a culture
of a particular project, then it can be very effective. But the other aspect is to be keenly
aware that C++ is one of many possible worlds. This is the kind of the many worlds theory
of objects if you like. Now, final family of styles. Well, they’re not really families.
Two different styles we’re not going to look at, that are actually unified just because
of the mechanism that you–we use to express them in C++. And it’s more coincidence than
anything else. There is no such thing as a template paradigm. There is no such thing.
It is a language mechanism that can be used for good, for evil, for obfuscation, for clarity,
whatever. So, let’s have a look. Generic Programming is the one–the name is unfortunate and this
has been recognized by Alex Stepanov and others that generic programming is not really the
right term because it makes it sound like it’s generics. This is a style that is focused
on algorithms. It is a style that is general in its outlook. That is the emphasis. In C++,
we tend to build on compile-time polymorphism and value-based programming. In other words,
templates, overloading, conversions, copying and encapsulated memory management. These
are all the key features here. As a style, well, I’m going to–I’m going to just skip
this slide because we’re getting close to the end. It’s got a lot going for it, but
I would say that it seems to be one I’ve not seen any applications that have this as their
dominant structuring principle. And I’m talking about significant large scale applications.
So, I’m happy to see some. But most of the time, I see this. It tends to be a tactical
approach. The–we have some interesting stuff coming up in C++0X concepts, and I believe
Doug Gregor has already given a talk here at some point in the past on that. So again,
I’m going to skip that. But let’s just have a little look at a nice simple fragment and
then the wrap up. The–this is a little example based on some code from TL1. And a random
number generators. There are certain elements of style if you’re using lots of templates.
Remember type [INDISTINCT] is your friend, often overlooked. This notion of loop-free
programming is the idea of being able to compose in one place something, as I said, reminiscent
of functional programming here, being able to compose in one place. Something that is
centered around an algorithm of some kind and uses objects that best in a tactical fashion.
The dominant idea here is the thing you want to do. Okay. Now, mixing styles. I want to
kind of skip that. I want to kind of briefly talk about template metaprogramming. Anybody
come across that? Lots of angle brackets, kind of scary. Wow, look at that. That’s fantastic.
Okay. The challenge here is that C++ doesn’t really support metaprogramming in the general
sense. It only supports a particular compile-time approach. They could be used for some very,
very useful things. Some really keen observations–sorry, optimizations. But what I would like to emphasize
here is that it–it’s a–domain of applicability is not for every programmer. It is not the
kind of thing that you’d use like an if. It’s not the kind of tool that you so say, “Yeah,
I use that everybody.” If you do, you have to be either really knowing what you’re–really
know what you’re doing or not in this case. You can spot the template metaprogramming
code, can’t you? It’s the stuff over here. I do urge you to look at your code by doing
this technique of zooming right out and reducing the point size to something little. We–people
do it with helicopters, and they find the lines of ancient fields still in the ground
from thousands of years ago. You can do this with code and see the characteristics from
the air. That’s the template metaprogramming. This is a piece of code that turned into this
piece of code. There’s no template metaprogramming here. It’s just all overloading a couple of
objects, that’s it. And the notion here is that this was unnecessarily complex for the
problems. It’s easy to get blinded by the light. So, I’m done from that point of view.
I think we may have time for a couple of quick questions. There are no questions. It was
all entirely clear. You understood everything I said, nothing was contentious. I believed
that for a second. Okay. Let’s get back to this. Mixing Generic and OO Styles. Come on.
Surely, there must be something here. This shouldn’t be difficult because we’re dealing
with two orthogonal forms of polymorphism. That’s the theory. The practice unfortunately
is, they really don’t get all. In practice, we have to write layers of adaptation. This
is annoying, you cannot have virtual template functions. This is very annoying. So in theory,
although in the principle they are actually independent, they do not mix either. They
stay independent. That is quite a struggle. People often write articles and bits of libraries.
Indeed the–one of–one of my contributions to the Books Library is a type that messes
around with your idea of a polymorphism. It’s kind of, well, you know, it’s a value of any
kind but I don’t–yes, well, let’s move that around. There are a number of techniques there.
That function wrapper I showed you early on is another one. I invite you to look at the
implementation and see how you feel afterwards. It’s pretty smart. But again, if that’s what
it takes to mix, you have to be very careful. So, it can be challenging. In practice, I
found you can actually do this. But you end up with a layering and you reduce the amount
of adaptation. But you end up with the layering. I found that objects in the large and generics
in the small, that works very, very nicely for me. If I use standard dependency management
techniques, just kind of–like of some Robert Martin type stuff, they I find that I have–I
create myself a useful space where the generic programming, it just flows very nicely. But
there’s a strict separation and there is this kind of layering. Okay. Is that contentious
or do you agree with that as well? Come on. Give me–give me a question. Matt?
>>Can you give us an example of where you think that template metaprogramming is a good
idea?>>HENNEY: There–yeah. Yeah, okay. Not here.
Can I–can I give an example of where I think template metaprogramming is a good idea? It’s
difficult to know whether I’m addressing solution problems or not. One of the areas where we
do find this to be useful is in selecting types and organizing types for what–well,
for small pointers for example. In other words, if I want to get a smart pointer and I would
like it to have–re-export some capabilities based on its type, the parameterized type
that I give it, then there’s no way to do that without having a compile-time if. And
that compile-time if is going to come in the form of template metaprogramming. I found
that when I have used–there’s–actually, I lied a little bit, actually. There is a
little bit of a template metaprogramming here. I can’t remember exactly where it is. But
that’s the point, it’s very discreet. I’ve used it to select between two types, basic
trait style selection. So, it’s very modest to use. It’s just a light sprinkling. The
other area, but I don’t have personal experience in this one–in a practical project other
than personal toy projects, is where you are using this to–as you were to select an option
that you don’t want to take at runtime, but you’d rather take a compile-time. I know it
was generator constant of some kind. And you’d rather not have to either pull out Windows
Calculator and calculate it manually and hard-code it or have the cost of running it at a compile-time.
Again, some of these features are actually being–some of the issues I’ve just described
are actually being addressed in the next C++ standards. So, you won’t necessarily need
template metaprogramming. It’s called–more, it’s like a bridging solution in that sense.
>>[INDISTINCT]>>HENNEY: Okay. Right. Thank you very much
for your time.

14 thoughts to “C++ Stylistics”

  1. o yea i forgot lol. but ive seen other vids that are longer than ten minutes that have nothing to do with google or youtube. one was this super mario world thing it was 11 minutes.

  2. Uh, I'm pretty sure the reason some videos go past ten minutes, is the user essentially has a.. "deal?" with youtube.. or whatever the hell you call it.

    I could be wrong.

  3. yea i think you're right. u can become a partner and get paid and i think u can have vids as long as you want…. i saw one that was over an hour…. the guy was trying to count to infinity lol and made it to 2000

  4. does anyone think its neccesary to learn any other language before c++. can you just jump into it as a newbie and how long will it take you to grasp the concept. any books for someone new would greatly help thanks guys

  5. @numbahwhun Learn by programming! Your will learn programming and a programming language at once. Look after the answers to your questions. Search for exercises. One example "Project Euler"

    Books: New algorithms; The pragmatic programmer; Design patterns; Refactoring; Books about specific subjects: graphic, audio processing, database handling, user interface building, modeling, networking, …; Books about specific programming languages.

  6. I'm no longer a fan of Kevin Henney. He's got a great voice but I think he likes the sound of his voice a bit too much. More substance please.

  7. I know this is a very old video and so this wasn't the case back then, but "reflection will not be supported" is not true anymore.  There is a study group on the committee devoted to a static-time reflection mechanism.  I'm not aware of any adaptations in the coming standards updates, but I'm sure reflective features will be soon to come for C++ (if only in a limited way at first).

Leave a Reply

Your email address will not be published. Required fields are marked *