Good afternoon, so, apparently, they don't have any clip on Mike, so I'm left with the
problem of, yeah, okay, so I speak with Mike.
So, and both hands are taken, okay, this is going to be very strange, and apparently
there is a new device that they've got that tracks the camera, tracks you based
on a remote control.
We will be load testing this in the next 90 minutes.
Okay, so, procedural programming, this is one of those things, it kind of half came out of
a joke, the idea of doing a talk on procedural programming, because a few years ago I found myself
giving talks on, this is what we really meant by objects and, you know, this is
functional stuff and this is how to think about it and stuff like that, and then I ended
up with a very broad paradigms talk a couple of years ago, I started thinking, the one
thing that's not getting any love here is procedural programming, and a lot of people
go, oh, procedural, that's just another word for bad, yeah, and indeed for many people
that's how they think about it, so I want to try and reconstitute that, because we have
a very, yes, we do work with software and yes, it is all ones and zeros, but we do have
a very ones and zeros approach to looking at things, we say, oh, this is new paradigm,
it equals good, so when I use this word it is equivalent to good, and, you know, you pick
a decade, you substitute the appropriate thing, you expand whether it is objects, whether
it is agile, whether it is microservices, whatever, this is now equal to good and therefore
other thing is now equal to bad, yeah, okay, it's a nice simple way of trying to deal
with the universe, but the universe tends out to be a little more sophisticated, so let's
have a look at this, some people go, oh, it's back, no, you never went away, it's always
been there, so I want to reconstitute it and also take a little bit of a journey, now
we're going to start a journey here in Bristol, here we go, a photograph, why don't I take
this, that's a few months ago, just a quick question, who actually lives in Bristol,
oh, not bad, right, good, so obviously as denizens of Bristol, you'll know that the original
Saxon name was Bridgesto, and you think English spelling is bad now, okay, the CG is
sure, obviously, and obviously there was no standard orthography, so it's variously spelled
Bridgesto, Bridgesto, and all the rest of it, and so this means place of the bridge, so Bristol
Bridge is the bridge, the place of the bridge, over the river Avon, Avon is Welsh for
River, over the River River, you know, used a lot of just software people who had a hard
time with naming, so yeah, so this got variously shortened, and by around the 1200s, people
were pretty much calling it Bridgesto, or were they, they were if they weren't from round
here, they were calling it Bridgesto, but the Bristol dialect and accent has a habit of putting
an L on the end of everything, okay, so you know, if you're proper Bristolian, you don't
have good ideas, you have good ideals, so Bristol, Bristol got the same treatment, and
why am I telling you all of this, because when I was talking about this talk to Hubert
Matthews yesterday, he made the same observation, procedure, procedural, there you go, everyone
else, procedure programming, but here in Bristol we claimed it, okay, procedural, that's
how it, that's how we're calling it, okay, okay, so really the question is, why am I talking
about procedural, so when people want me to think of procedural, they think, oh, legacy,
they think monolithic coat, okay, this is what they're thinking, monolithic, one big stone,
one big sodding stone, and so, yeah, I took this picture just over a year ago on Valentine's
Day, that's how romantic my wife and I are, let's go see some really big old stones,
that's pretty cool, so we took the kids and they were impressed by the size of them, just
as you would be when you join a new company, you go in there and it's a case of like this
code base, this monolithic coat, what does it mean, how did they move these pieces of
code, what do they do, what is the significance we don't know, but every twice a year it
lines up and gives the right results, just, so, you know, so we're going to talk about stones,
this is what you want, this is my younger son, he did about seven years ago, he was five,
I love, it just arranged some stones, and this is what you want, you're thinking like
elegantly arranged, with intention, and a mild Japanese aesthetic of seaweed on the top,
and you know, this is how we want to think about it, but obviously this is not a new
idea, Doug McElroy pointed out in the 70s that this is the Unix philosophy, right programs
that do one thing well and do it well, right programs to work together, this is a kind
of an articulation, there's been mangled into various different forms, we talk about cohesion,
we talk about single responsibility principle, and we talk about these rather elegant little
stones, these days whenever I put that slide up, lots of people go, oh, you're talking
good aren't you, current word, for good microservices, so you're talking about microservices
and I always say, if that helps you, yes, I am, absolutely that's what I'm talking
about, no, I'm talking about something much bigger here, about sort of a sort of a principle
about how we structure things that is surprisingly old, and it dates back to procedural
programming, all this cohesion stuff, this is not an object oriented thing at all, it's
procedural programming, that's where the terminology comes from, as John Cook points out,
he says in McElroy's summary, the hard part is his second sentence, right programs
to work together, it's not really the do one thing well, although that does tend to
floor as a little bit, finding out what that one thing is is nontrivial, but this
is the hard bit, and unfortunately our languages are still not much better than they used
to be, they focus on the entity to be used for the composition, but the composition is
a little bit vague, it sort of sits in the background, and so what you end up with is this
kind of arrangement of stones, rather than that elegant arrangement, and this kind of allows
us to refer to Alan Perlis, one of his one of my favourite quotes on software architecture,
and the long run every program becomes Rococo, if you're not sure what Rococo is, it makes
Baroque look minimal, then rubble, now Alan Perlis was the recipient of the, he was the first
recipient of the Turing Award, which is kind of relevant, because that was the 1960s, and
that's where I want to take you back, we're going to go back to the 1960s, intentional
use, 1960s is a font that was used extensively, gives us a sense of the 1960s, gill
souls, although technically it's 1928, the font was created, but when people think
the 60s, there's this kind of tension, there's these two views of the 60s, there's this
one, there's this one, okay, and if we go back to the 1960s, there are a few things that
are still with us, okay, there's a clearly procedural program, there's the Rolling Stones,
there's the imminent threat of nuclear holocaust, which I think is nice, because growing
up during the Cold War, that's an experience that's very difficult to describe, I can now
pass that onto my children, so thanks, you know that kind of sense, and there's me, okay,
yeah, so I was around in the 60s, in fact I predated the following slide, 1968, soft
engineering, this actually, the original uses gill songs, by the way, but it was rendered
in Futura, so there's a slight typeface mistake when they transcribe it to PDF, if you
don't know, I do care about typefaces, this is important, because this, there's an awful
awful lot of stuff that happened in the 60s, which we are not very aware of, and there
are a number of things still with us, this term software engineering, a number of people
sort of blame this conference for propagating this term, actually the person we have to
thank, is this woman here, Margaret Hamilton, she went to work for NASA, she was at MIT and
she went to work for NASA early mid 60s, and was kind of responsible for the whole moon landing
thing at one level, because she wrote a nice little piece of fault tolerance software,
without which the moon landing would not have happened, and she said, I began to use the term
software engineering to distinguish it from hardware and other kinds of engineering, yet to treat
each type of engineering as part of the overall systems engineering process, now we have
a number of kind of spaceflight, that's her in a mock-up of the command module, the Apollo,
today is the 12th of April, which means it is the anniversary of Yuri Gagarin, his little
space hop in 1961, and also the launch of the first space shuttle in 1981, and this is 1968,
which was also the year of release of 2001, a space obviously, which also uses the Gil
Songs font by an amazing coincidence, and predates the lunar landing by one year, yet shows
a beautiful example of how one would land on the moon. However, you're here for the
software, aren't you? Disappointing. Okay, let's find out. Let's find out what they thought about
things like microservices back in 1968. This is from EE, David. Define a subset of the system,
which is small enough to bring to an operational state, then build on that subsystem. Now,
notice he's not just saying, build a small bit of the system, he's saying, bring to an operational state,
that was the thing that when I read the whole of the proceedings, and I've done this so you don't have to,
but it's a real eye opener. They weren't thinking what we think they were thinking. There was a
diversity of thought that it reflects, well, pretty much what we do now. We don't have one mindset
as to how we should develop software, and we see that that was also true 50 years ago.
But there's a very specific thing here, and of course the nature of the systems they were
talking about are quite different, and yet the conclusions and principles they were drawing.
The strategy requires the system be designed in modules, which can be realized tested and
modified independently apart from the conventions for inter-module communication. John Lakeos was
in here doing a talk about modules. I mean, I was in the room, but whatever he said,
I'm going to go back to the 1960s. That's where the term originates. I had originally thought that
the term was about 1970 onwards, but it was in current use in 1968. As indeed, we're phrases
like unit testing, middleware, and a number of other surprising phrases that you can find in
the document. Other wisdom, the design process is an iterative one from Andy Kinzler.
Yeah, a lot of people blame the software engineering conference for
ratifying the waterfall process, because it's filled with observations like this.
Kinzler was pretty sharp, actually. There's some other brilliant observations. There are two
classes, assistant designers. The first, if given five problems, will solve them one at a time.
The second, we'll come back and announce that these are the real problems. I'm going to eventually
propose a solution to the single problem which underlies the original five.
This is the system type. Who's great during the initial stages of a design project? However,
you'd better get rid of him after the first six months if you want to get a working system.
So it turns out, they had C++ programs in the 1960s as well. Who knew? So slightly more seriously,
back to Alan Pearlis. A software system can best be designed if the testing is interlaced
with the designing instead of being used after the design. Oh, man, this waterfall is too much for
me. Here, he's actually describing and we'll come back to an approach described by Brian Randall
of University of Newcastle. So what I'm going to do is I'm going to put together a little piece
of code. One of my favourite little coding artists determined when a year is a leap year,
and given that we're talking 1968, I'm going to do this in our 1968. And this is my copy of
the revised report, which was 1974. And again, glorious use of fontage. Everybody was
Helvetica back then. 1970s was the Helvetica era when it came to writing programming
language manuals. And a lot of people say, how got 68? Yeah, that's a language I've either
never heard of or certainly never used. It's the most influential language you've never heard of
or never used. If you ever wonder where certain keywords came from, this is where those
keywords came from. They didn't come from anywhere else. Everybody else was at that time happy
to go integer. But no, Algos 68 is just like, we don't have time for that.
Yeah. Everybody else is calling these things records, structs. This is a whole load of stuff
here, which is really rather surprising, long, short, all the rest of it. So, yeah, let's go
back to this. And so procedure is leap year. Yes, you could put spaces in your identifiers.
Those didn't count, so I could actually take those out. They were not significant.
There's an argument. There's bull. This is defined as procedure. The whole thing evaluates to false.
So this is kind of interesting. What I'm going to do here is I'm going to create a testing framework.
So we can explore the language a little bit and get a feeling for what procedural programming,
because Algos 68 was the quintessential procedural programming language. It was the epitome of
procedural programming. It took all of the experience up until that point to try and distill.
This is what procedural programming is. So it's worth finding out what it is before we dis it.
So what we've got here is an array of propositions. That's a type we'll define. We'll look at that.
Allepeus back. Yes, I am using BDD terminology. Years not divisible by four are not leap years.
No, I'm not using BDD terminology. Well, that should nonsense is nonsense. You shouldn't use it,
but if you feel that you should come and talk to me. Years not divisible by four are not leap years.
So I've got a statement there of a simple aspect that must pass.
Void assert, if you have one where assert comes from Algos 68, not is leap year 1967.
What is this thing here? It is an anonymous procedure.
If you like to call it a Lambda, let's go for it. So 1968, people got very excited when C++ got them
in 2011. Java programs got excited in 2014. JavaScript programs had no idea what they were doing
in the mid-90s, so they didn't even know to be excited. Let's go and have a look at the
types. No. Well, yeah, it turns out that Allepeus 68 reinvented a whole load of terminology. That
makes the report almost unreadable. It is just like, yeah, you see all of that computer science
terminology that people have been establishing. This is the 1960s. We're going to reinvent everything.
IO, no. We call it transport. Yeah, input output. Transport. It's kind of logical.
So we're not going to talk about types. We're going to talk about modes.
Proposition equals a struct. Oh, yeah, it had strings. So when people sort of lament
all procedural languages don't do string handling unless they're proper procedural languages.
Yeah, there you go. Strings, you can do plus to concatenate as well. We'll see that.
Take a pointer to a procedure. Oh, void. There we go. That returns void. It returns nothing
and takes nothing. And so we can see that back here. Now I'm going to run it. Nothing surprising
about that. Okay, now we're going to explore. This is how we would iterate through the proposition
array. I've got a for loop. There's nothing particularly exciting there.
And so we're now what we're going to do is we're going to test drive it. Yes, it uses single
equals for equality. And as you can see, single equals for definition. Just just avoid confusion.
Yeah. And so we're going to put this one here used by four, but not by 100 R leap years.
And so now this one's going to pass this. So we got that. So 1968. We're going to build that up
used by 100, but not by 400 and not leap years. So we build this up progressively.
And we've got a nice little definition there. Now the thing here is that you will notice that this
there's a lot of parentheses. Okay. It's just like, yeah, the influence of LISP was strong.
But also keyboards have not been standardized to the level that they are now.
Curly brackets, you know, where do you find those? If you want to recreate the 1960s experience,
go to Scandinavia. They still have no idea where the curly brackets are. You have to kind of
of like, you have to kind of spatically e-max mode to try and find them. So it's that kind of
notion like we're going to use parentheses for everything. So let's do something slightly different
here. I'm going to create a mini DSL. What I'm going to do is I'm going to data drive this
with multiple items of data. And I'm going to write an expectation in there.
A year is not a visit by four and not leap years. So it's like 2018, 2001, 1967, one,
expect false with 2016, 1984, 1968 and four expect true and so on. And there's a little more
here. I've got to create these types. We can see these helpful constructor type things.
And this is the test driver. It's a little more complex. But there are a few things I'd like to
walk you through. Just so we can kind of sense the history and a few changes that have happened
since then. Nothing too exciting here. Dot notation was not universally accepted at that point.
So of was used. And there's a sort of, it's quite nice. The name of spec entry rather than spec
entry dot name. Then we have here, we can see that initialization at declaration. Yep, no problem
with that. Very, very subtle though. Colon equals means assign, it means this is declared as a
variable. This one means this is const. So a very subtle distinction. Like I said, these are
our 68 programmers. We don't have time to spell integer. We don't have time to spell const.
Let alone const it. We will symbolize it by the absence of a colon at initialization.
Very subtle distinction. Not one I'm sad that we got rid of. Oh, yes, if you've ever wondered
where bash and ultimately born shell comes from. Steven born, who wrote the original born shell,
was very taken with our goal 68. So he wrote the whole of the born shell using our goal 68
like notation. He used macros to make his sea look like our goal 68. And it is that code base
inspired the international obfuscated sea coding contest. Because if you opened up a sea file,
you expected to see sea. You did not expect to see some perverse reinterpretation of our
goal 68. And he was very taken with it. So he was on the inside of the shell and on the outside.
So this is where all of this stuff came from. Then we've got this. What you see within this if
statement is that there is a declaration. And then there is a call. Recently C++ programs
got terribly excited by this feature. Oh, look, we're being really modern. Go programmers are going
around. Yeah, we've had that for a few years. I've got 68s in the corner going. Yeah.
Plus equals. If you ever wondered where that came from. Yeah. So if you really want to
understand C and C++ and all of those languages, it's worth looking at our goal 68. People ripped
off fairly shamelessly. Now, here's an interesting thing. This is procedural. It turns out that
our goal 68 viewed a viewed things in terms of expressions. It did not view them in terms of
statements. It was an expression oriented language. It basically said that all of these constructs,
you can use them anywhere. It's the language that inspired people to use terms like
or fog andality in language design. There's a sort of deep irony that people originally said,
our goal 68 is too big to be implemented. It's unimplemented. It's too large a language.
It's actually smaller than C. Yeah. Well, our expectations of what defines big of change. Quite
a lot. It's a tiny language by comparison to modern standards. But the point here is that there's no
separate construct for how do I do an if else on a for values. Every language that doesn't get this
right has to introduce an alternative notation or syntax. Whether it's the Elvis operator,
whether it is Python doesn't get this right either, it says, well, we recycle the key words,
but we'll have if and else and they will actually serve a different purpose in expression.
Our goal 68 said, yeah, one idea. The body of a procedure results in a value. That's why there's
no return statement. And this results in a value. However, those are our 68 programmers.
That's a lot to type, isn't it? They all provided alternative notation forms. Love it. Don't do
this. Okay. Of course, I am using a test-driven style to explore this. And that definitely wasn't
1960s. You had to wait for the 1970s for that. Alfred A. Ho talking about Ook, which is A. Ho,
Weinberger, Kernegan, one of my favorite little languages. We issued a rigorous regression test
for all the features of Ook, any of the three of us who put in a new feature into the language
first had to write a test for the new feature. So test-driven development, that's 1970s. So yeah,
I've really old. Much, much later than the 1960s. They had to do something. I mean,
haven't said, people were wearing flares and dancing to disco. So this was a good diversion.
Okay, now back to Alan Pearlis. Let's talk a little bit about the testing thing. There is no
such question as testing things after the fact with simulation models. But that in effect,
the testing and the replacement simulations with modules that are deeper and more detail goes
on with the simulation. What on earth are you talking about now? A design work progresses,
as design work progresses, this simulation will gradually evolve into the real system to have
Pinkerton. What they're doing is they are describing without realizing it mock objects.
Another great idea from the world of procedural programming.
Simulation is the design. Okay, it took a while to be rediscovered. So what is the organizing
discipline for the set of thoughts, the set of ideas, this unruly school of how do we build
systems? People came up with a name for it. It's called structured programming. And structured
programming. This book is a collection of essays from Ullie O'Handale. Let's get dice to
an attorney hall. It was published in 74, but actually the papers date from the late 60s onwards.
Now, when most people these days hear about structured programming,
their immediate response. In fact, not just these days, to be honest,
when I started programming professionally in the 1980s, people were going like,
oh, structured programming. You mean programming without go to? If it was utterly obsessed.
You know the way we oversimplify things, ones and zeroes. What structured programming about
is programming without go to? Yeah, not really. That's not what it's about. But nonetheless,
we are kind of charged with this excitement that we have this go-to statement considered harmful
1968. Wow, that was a hell of a year, wasn't it? 50 years ago, this year.
Etzka Dijkstra, go to statement considered harmful, published in communications to the
SCM. Now, this is interesting because this phrase, this is the first outing of this phrase,
something considered harmful. And basically, we've been copying it ever since. People have
used this. There's actually a term for this. I have a Facebook page, a word Friday,
where I explore an interesting word every Friday. And one of the ones I explored a few
years ago was SnowClone. Feel free to drop this into a conversation casually.
Clieshade wording used as a template, typically originating in a single quote. And, for example,
X considered harmful. These aren't the Xs you're looking for, Xs and UI. It's X, but not
as we know it. Now it's left behind. It's Xs all the way down. All your Xs are belong to us. So,
these are examples of SnowClones that people substitute. And that is the first outing of go-to
statement considered harmful, except for one small problem. It was not Dijkstra. Dijkstra gets
the credit to all the blame for the title. He didn't do it. This is his original pay. This is
original writing. The slightly more moderate, a case against the go-to statement. Go-to statement
considered harmful was put in by the editor. At the time was Nicholas Birth, who invented Pascal,
a modular two. We'll be coming back to them later. This is clickbait 1960 style. X considered harmful.
Go-to statement considered harmful. I'm making a moderate case, but it's been escalated. You'll
never believe what happened to the codebase when he used this go-to. It's just click-through,
click-through. I need to see the penguins, the cats, and the go-to's. What was my first,
okay, this is confession time, okay. So, I'm amongst friends and whoever's out in the internet.
I did program Fortran. That was one of my first job out of Unity. It did involve programming
Fortran. I got to see some code like this. I think it's really good that people should have
to look at this stuff until their eyes start melting because you don't really understand
why people got terribly upset and I've typed about the go-to until you see quality code written
as a go-to. So, here we go. This is how we do is leap year in Fortran 66 or Fortran 4. No,
they're equivalent. First of all, six characters, that's your law, okay. Six characters. Why would
anybody want any more letters for their names? Good grief, you know. Apparently, it's logical.
They don't have Booleans. They have Logicals. You have to declare everything. Otherwise, the
compile will come along and just make stuff up for you because by default, is leap will be an
integer because it begins with I. Yeah. The letters, anything beginning with letters I through N
was automatic in the integer. Everything else would be a real number. So, year would not be an
integer would be a real number. Hence, giving rise to the Fortran joke, God is real unless declared
otherwise. Whether you've spent time in a Fortran code base, you might become
atheist, okay. You know, you're definitely in a Nietzsche moment, they go, God is dead. Look at this
code, okay. So, this is how we do the leap year thing in Fortran. If Mod Year, Fortran equals zero, go
to 20. Oh, good grief, there we are, okay. Easily, we assign to the name of the function. Go to 10,
is leap false. Now, we return. Go to 20, okay. Right. Yeah. Easy. Now, the thing is that
Fortran program is love rituals. Pointless, utterly pointless rituals. So, often they say, oh, no,
no, no, we need to make this more symmetric. So, we'll put a return in there as well.
Even though you actually fall off. And this also gave rise to all kinds of wonderful myths. Certainly
present where I first worked. Oh, if you don't put a return on, some compilers don't do it. No,
they all do. Really, from 1957 onwards, they all did. This is a story you tell your children,
okay? Okay. You just scare them with that. No, really, they would be somewhat remiss if they
didn't actually realize, I've reached the end. What shall I do now? You laugh, yeah. Now, this is real.
It's because, I don't know, we're going to have a regular, because you've got to go there,
because otherwise you don't know that you've gone, you know, you can't guarantee the compilers
get it right twice. Good God. There you go. Go to. You can trust to go to. And sometimes, yes,
Jason. No, I haven't, but I think they're all cut from the same DNA ultimately.
But no, I haven't finished this yet. Oh, good God, no.
So I haven't finished. Continue is a no op. You think I'm kidding with this stuff. It's like,
look, look at all of this ritual. It's just like we've got this color. You must jump to a
no op statement and then you can return and then you end. Are we done yet? I mean, this is,
it's just, wow. It's kind of like watching the end of the Lord of the Rings, because you
know, you keep thinking that the return, the return, okay, it's going to finish now. I was going
to finish again. Oh, no, they're at the harbor. They're going to finish once more. Oh, no, there's still
more. Okay. So, yeah, this is what we had to put up with. Then 47 came along and
actually relievers from quite a lot of this. But I actually programmed in 47, extended
47, but we had to deal with code that was written like this. I will keep the names, even though
47 loosened up a bit. I will keep the names for, oh, my goodness. And if else, construct, wow,
this is revolutionary. Now, I just want to clarify why I'm doing this for you. What I want to
scare you with, this is why people hate the go-to. But also, this is for a lot of people what
they thought procedural programming was. It turns out that with any paradigm, any paradigms,
very broad landscape. You can't see one side of it from the other. If you're a fortune programmer,
you don't even know what our goal is. You might have heard of Agal 60. You certainly would have heard
of Agal 68. And so, therefore, for a lot of people, this came to be what procedural programming was.
We get the same problem now with object orientation. A lot of people think to create an object
or into program, you need to use singletons and manager objects, okay? No, that's the equivalent
of this stuff. That's the failure mode. That's not the sort of the exemplar. So,
we end up with this. Now, it's a really interesting thing going on here. And I'm going to put
indentation in. Most of us, the first company I worked out, were pretty good on indentation,
except for my boss. He didn't believe in it. I don't believe in Father Christmas,
but that does not have code-level consequences. He didn't believe in it. And I remember
indenting his code and discovering so many bugs. It was astonishing. We do this. We do this
because we are creatures. We are visual creatures. Ultimately, at one level, we can treat this as
a linear sequence of characters. But we are visual creatures. This is why we do things. We do
things to highlight the structure of code, the logical structure, okay? We see that there is branching
here. So, why do people get upset about all those violations of this stuff? It's actually a very
simple thing. A go-to completely invalidates the high level structure of the code, okay? It's
a challenging guy to designing programs. 1995, you can find a version of it online. It's a
little harsh in places, but on the whole, it's pretty good with this one. And it's a very accurate
observation. That's the problem. It just doesn't look like it. You can pair that. It's just like,
no, I don't see what's going on. Whereas in the previous example, you can see, you can kind of
of squinted it and get a sense of the shape of it. You can sense it's form. You also have a choice
of the level of interest that you wish to direct yourself to. Now, a lot of people go, oh, well,
you know, we don't use go-to in our code. Maybe you don't have it in your language. And then
sometimes people say, well, there are other things that are like go-to, but they're not spot go-to.
And when we talk about go-to, we talk about structure programming, people often talk about the
single entry single exit discipline. And people often spend their time focusing over multiple
exits, but they never focus on multiple entry points. And you might think, how do you know, how
do I do a multiple entry point? Like this. Duff's device, which is, well, I'm going to pick on what
Tom Duff said about this one. I feel a combination of pride and revulsion that it's discovery.
I mean, it's, it's loop unrolling. Don't do this. Your compiler does it way better than you.
But this is way, way, way back. You know, this is K&RC. And what we've got here is we are trying to do
basically copying a whole load of bytes. And it turns out that copying eight bytes at a time is
really rather convenient unless, unless the thing that you're passing in is not divisible by
eight. What do you do with that little rounded bit? Well, what you do is you jump in. A case is nothing
more than a glorified label. That's it. That's all it is. So it turns out that what we've got here
is effectively, if you've ever wondered watching, watching something like Star Trek, what happens
when you teleport into the middle of something? But this is what happens. What we've done is we've
taken a switch state and we've taken a do-while state and we've teleported them to the same location.
Okay, they are interlaced and interposed and weirdly bonded to one another. This is not the
kind of relationship you want your code to have. But nonetheless, this is how you do multiple entry
points. It's trivial and see. And as Duff notes, many people have said that the worst feature
of C is that switches don't break automatically before each case label. This code forms some sort
of argument in that debate, but I'm not sure whether it's for or against. Now, obviously, he's
focusing on break. And it's the uncommon use of break. Break is more often associated. Most of the
languages that people use in this room. Break is more often associated with breaking out of a loop.
Obviously, it doesn't have to be spelled break. Now, something interesting about this talk is I
have finished this talk so many times this week. Now, normally, I'm known for finishing at the
last minute, and I did, I was indeed editing slides at the end of the end of John Laker's talk.
But I finished it this morning as well. I finished it three times yesterday, twice the day before
and once the day before that. I have not finished a talk this many times for quite a while.
What I was doing in John's talk, apart from listening to John, 100% attention, undivided,
absolutely. We'll talk about concurrency later, was I polled yesterday. Somebody give me some
suggestions for other languages. I counted up the languages I've used in this talk. It was nine
yesterday. I came up with tenth, and I thought nobody was going to come up with anything. People
coming up with all kinds of ideas that didn't fit the procedural aspect of this talk.
Now, Price tweeted at me around lunchtime, and he made a suggestion. Plan Calcool, which is
a language that was never really implemented at the time. It's a procedural language, 1948,
developed by Conrad Sussa, who invented the first electromechanical computer.
The good fortune to me, when a Conrad Sussa's son's horse a few years ago. This was a notation
that he developed, only single letter variable names. For those of you who use home computers
in the 1980s, you should feel comfortable with this. But notice he had a two-dimensional approach.
It has been implemented. Some came up with a one-dimensional approach here. But notice the nesting,
my goodness, the nesting. This is what it's all about. This is structured programming.
This is a wild loop, W. It doesn't stand for a while, via the whole loop. Again, repeat.
This is a sort routine, odd, odd, and obviously sticking with German.
Oh, okay. That's the French. Fun. That's break. That's how you break out of a wild loop.
This is a conditional expression. That's the arrow. The other arrow is that's assignment.
That's a declaration up there. What's a Randell's talk? It's a declaration up there,
which basically says this takes a raise of M items and returns a raise of M items.
I've looked at the complexity of this. It looks like an ON squared, but hey, it's 1948.
I'm prepared to take bubble saw exchange saw whatever you're offering me, because this is really
cool, because he visualized programming. Literally, we talk about nesting. He's doing nesting.
This is a proper representation. It's a procedural programming language. It doesn't support
recursion, has no go-to. Everything is passed by value, including a raise. It's kind of cool.
I didn't think I was going to put it in, but I only had an hour to figure out what it meant.
It finds some good examples. Anyway, it seems to be with us. I don't have a
break, it's a bit of a pain. Continue. If you're using continue in your code, except for
Fortran where it means something completely different. If you're using continue in your code,
I have a very simple suggestion. If, try it, it's awesome. It's a great construct.
Then we get return. This is the issue. People refer to multiple return points. This is often
misunderstood. It's partly because we've ended up with return statements in most of the languages
that we use. Most of the perceived or imperative languages that we use that have two jobs. People
often have got so used to this that they don't even think about it. Fortran is one of the only
languages I know that actually separates the two jobs. There is return as control flow. I wish
to return from this procedure or function or subroutine. There is the value that is being returned.
These are two separate concepts. Most languages fail the single responsibility principle in their
design. Return does two things in those languages. Why is that important? It's important because
it helps you understand that the way to work out the number of return points is not to
grab the instances of return. This is a deep misunderstanding. Let's have a look at what's going on
here. This is groovy. I chose groovy because it has a return keyword. Here is how to calculate
elite, whether or not a year is elite, according to Gregorian calendar, or strictly speaking the
groovy calendar. I can get rid of return keyword. Now it's the last value. It yields the value
of the last expression. I can play as it were both sides of this and see what that looks like.
Here is another way of writing it. I run a number of workshops. Some people are happy with this
and some people are happy with this. I'm going to explore this because it's got things like if
and return of it and that's kind of the point of what I want to talk about. Here is one way of doing it
and here is another way of doing it. This one is surprisingly common. Only one of these is
qualifies as structured programming. Anybody want to guess? It's the one on the left. How can I
demonstrate this? First of all, let's just take away the returns. It's directly equivalent. There
is no difference. In other words, a tail return, you can eliminate the return. What I've done is I've got
rid of its return aspect and I've separated return from value yield. If I try and do the same thing
on the right, I can do it with the last one. There, we're relying very much on disrupt the control
flow. There's no disruption here. Although you might count here, there are four returns. We're
looking at the structured programming perspective. There's only one. On the other hand, over there,
we've got a whole bunch. Let's put that back in for consistency. There is this idea of emphasizing
and these days with folding editors and it makes it easier to emphasize this idea.
If you're looking at the form of the code, why do we indent this stuff? Why does it make it
visually easier? Because what I'm trying to do is tell you what's important and what's not. These
things are at the same level. Here we see the backbone, the spine, the shape of this thing. Over
here, we see a completely different story. If I fold this stuff away, I actually have no idea
what's going on here. Because if this does or does not return, obviously it's a single statement
and I can see what's going on. But with larger blocks and particularly folded away,
you have to, the only way you can understand all of this is to understand all of it.
In other words, the reason that structured programming makes cognitive sense is because you don't
have to know everything in order to understand the top level. What is going on here? I don't have to
know whether or not this has a return in it or not because it doesn't matter. On the right hand side,
I have to because it makes a difference. And the way that this is structured makes this look like a
series of guard clauses. People say, oh, I like the guard clause, idiom, I remember people telling you
that. It's like, yeah, but that's not a guard clause. Guard clause is, oh no, it's terrible, bad things
have happened. Get me out of here. Oh my goodness, the years divisible by 400, that's shocking.
Get me out of here. No, that's part of your job. It's a fundamental part of the definition.
There's nothing weird about it. So let's get rid of that nonsense. If you want to do
structured programming, this is how you do. Let's go back to our level 68. You have no choice.
There was no return. So the idea of single return point didn't make sense. It did have a go to,
though, just for those moments when you felt like going completely wild, you know, it kind of
constrained you and then said, yeah, go, let it go. And here's one of the other things. Sometimes
people say, oh, well, you know, it's a structured programming thing. We don't need that anymore, do we?
Could you go do some functional programming and then come back and tell me how you feel?
Because functional programming actually follows a very similar principle. So here's the Haskell.
And then here, indeed, is the Pascal, a game reminding us of the fact that here's a language
that did not have a return statement, but did have a way of binding a result. This is the thing
that people often miss. They forget the translation thing. The guideline multiple exit points
was related to languages like this, like Fortran, that had this concept. And then what they do is
they end up wrapping returns and counting. You've got more than one return there. Look at where
the returns are. It's a little bit like don't translate poetry literally from one language to
another. I mean, actually, no, do. It's very funny. Okay. But the point here is that the guideline
is clearly more sensitive to language than people have appreciated. So let's go back to structured
programming. What's the fundamental idea here? One of the most powerful mechanisms for program
structuring is the block and procedure concept. It is this idea of these are the things that we group.
We encapsulate things in chunks. And then we organize them with a very simple model of arrangement.
Organize them. We organize these blocks in sequence. We organize by selection. If
we're organized by iteration, while. And we can elaborate. We can have different kinds of selection,
pattern matching and all the rest of iteration for loops and so on. But these are the fundamental
constructs. And selection is the fundamental in the sense that this is the original use of the
semi-colon operator. Because it was and why old languages used to have as a separator. But we
invented up for consistency, having an as a terminator in most languages. Because what you're doing
is you're saying a semi-colon, b, do the statement a, compose in sequence with statement b.
And so you have this nice idea of sequence there. And the idea is you can build anything out of
this stuff. And there was even a way of describing this architecturally. Although for some reason,
the software architecture movement from Carnegie Mellon decided not to call it procedural
programming. They decided to call it main program and subroutine. Hence, names like Bristol and
the River Haven. Okay. What do you see before you? Well, that looks like a bridge. That looks like
a river. That's a main program. And it's got subroutines. What should we call this paradigm? Main
program and subroutine. Okay. And what is the goal of this paradigm? The goal is to decompose a
program into smaller pieces to help achieve modifiability. This is one of those. It's not content-free,
but it is, I'm not really aware of any paradigms that are not done as enterprise jokes or a
enterprise programming effect. I'm not really aware of any paradigms that do not have this as their
objective. You know? Hey, guess what? I'm going to teach you new paradigms. Oh, what can we do
with these new paradigms? Well, our goal is to not decompose a program. We're going to try and
keep it all in one big piece and really mess up your modifiability. No, all of them. They just
have different views. They take a different worldview. And the procedural worldview very much is
organized around as its name suggests, procedures. A program is decomposed hierarchy. Ah,
now we're getting something useful. This is constructive information. Okay. If I use a relational model,
that decomposes things. If I put it into third normal form, that is a discipline of decomposition
that is aimed at achieving modifiability. And that's really good, but it's not hierarchical. So here,
we're actually getting some useful information. And we end up with stuff that looks like this.
Okay. So here's our hierarchical view. And it turns out that there was actually a
a set of terminology that turns out quite useful. Afferent, transform and efferent branches.
This is the kind of terminology you use to alienate your colleagues or just sound smarter than them.
Afferent branched out with input, transformed out with process, efferent branched out without put.
You can see that this actually does solve a particular class of problems particularly well.
It doesn't necessarily solve event driven problems, but it does solve certain classes of problem
very well. We obviously have different terminology and different areas of interest. One of the
things we find is it's characterized in terms of a single thread of control. Each component in the
hierarchy gets this control, optioning with some data from its parent and passes it along to its
children. So it's a synchronous model. It's a stack oriented model. And here is how we think about it.
So therefore, the procedural worldview is very much that we organize the universe in terms of
a single goal and activity that can be decomposed progressively. Okay. And there is value in this.
But where do we get problems? Well, first of all, let's just start messing about with the names.
There you go. This procedure is the same thing. Functions. Interesting enough,
this is also the shape of many functional programs. It turns out that you can slide from one
paradigm into another by just tweaking the dials a little bit. It turns out that what distinguishes
at this level, functional programming from procedural programming is side effects. It is not
structure. It is not large-scale structure. Functional programming is often based on this idea of
decomposition. This top-down pull-out functions. And so there is also a bottom-up
composition approach, which I'm not covering here, which is different. But I'm not going to cover
that here. However, the world is not organized into trees. This is far too convenient. You find it
in books, but the real world looks messy. It has recursion and mixing of levels and so on,
which is by attorney hall to make the observation. You cannot teach beginners top-down programming
because they don't know which end is up. Back to Alan Pearlis. Everything should be built top-down
except the first time. Which I thought was a lovely way of looking at it, because what he's doing,
is he's saying top-down is a really good way of organizing your thoughts and presenting something.
That doesn't mean it's the same as the way that you built it. But when you come to describe it
to somebody else, you don't have to give them the same war stories. You can actually say,
rationally speaking in post hoc rationality, which programs are really good at.
Let's imagine that it's like this. But there's this idea of top-down is a great way of describing
not necessarily a great way of constructing. So that does leave us with a question of how do we
construct. Was this the only thing that was going on in the procedural space? Well, no,
come in 1972, we have a whole load of discussion on the criteria to be used in decomposing a
system into modules. David Parnas really with one of those classic computer science papers
and computer science titles. These days, nobody publishes papers with these kinds of titles.
It's much more modules distilled, modules in five minutes, whatever it is.
You won't believe what happened to these modules when we decompose them using these criteria.
That kind of thing. What we're looking at here, we've posed the one
begins with a list of difficult design decisions or decisions which are likely to change
immediately embracing this idea of you cannot know everything in advance.
Let us try and embrace the volatility and try and contain it a bit. You know, hug it a little
bit closer to you. Each module is then designed to hide such a decision from the others.
And one of the most common ones, we're going to characterize Barbara Liskoff.
She was awarded the chairing award in 2009, maybe 2008. A lot of people know Barbara Liskoff
for the Liskoff substitution principle. That's her. But actually, the reason that came about
was because of her work with abstract data types. It was nothing to do with object orientation.
She also did some really good work on distributed systems. But she notes here,
earlier 70s, abstract data types defines a class of abstract objects which is completely
characterized by the operations available in those objects. A program is concerned only with
the behavior which that object exhibits but not with any details of how that behavior is achieved
by any means of implementation. So, everybody likes to use stacks. So, I'll use a stack of books
here. Stacker books about objects as it happens. And I was molly over, yeah. Let's try another
language. What language? It's really modular. Oh, I know. Modular. Modular too, in fact.
Which is actually a really, it's kind of the forgotten cousin of Pascal, better designed in many
senses. Very strong on modularity as one would hope from a language that's called modular.
Has a proper idea of modules? Separate, has the idea of modules separated into two parts.
Or there are three kinds of modules. There's the main module. There's a definition module,
which is an interface. And there is an implementation module which fulfills that. I think it's kind of
nice that languages like C++ have decided a few decades later that this is a really new and
interesting idea. And also, he had a very simple, occasionally people wonder about, should I put
things in up a case? And Nicholas Burt decided, you know what? Up a case for keywords. If you're
going to shout something, you might as well shout something that is the core language. Everything else
you whisper. So, here's a definition module. Here is an example of an abstract data type.
I have simply forward declared stack. There's nothing in the definition that tells you what it
looks like on the inside. On the implementation, this is going to be a pointer to something. But
out here, there's no indication. So, I can define, compile, use, and all the rest of it, and link
the whole system without any kind of interruption. I'm going to create, I'm going to be able to
create these, delete these, push, pop, find the depth, get the top. I've used, I've used self
here. That's more of a modular three convention. Just to make you feel comfortable and see
a ray of char. Yes, it's null terminated. That's a string. So, you have this very simple idea.
And it's a ruthlessly procedural language to the point of tedium in some places. I must confess,
but it's some really nice ideas. So, let's switch that to something that some people will be
more familiar with. Let's, we can do this in C. C has no proper module concept. In other words,
it doesn't have a name that, you know, if you have in, if you look at Python,
Python's modules are very similar in vision to modular twos in the sense of the,
you import everything using import, and you have to namespace qualify, stacks.new, stacks.delete,
or you can import from, or rather from, stacks import specific names. But here we are in C,
and I've got a way of kind of structuring this and, because I'm writing clean C, it should be
accessible to C++ programs. And I've got a choice about how I implement this. So, here's one
implementation. Hopefully, that's a font that you can read and examine, and yeah, good, yes, good,
excellent. And here's another implementation. Now, what's the difference between these? Well,
this one is C, this one is C++. They are linked on compatible, and that's a sort of good example
how we have the separation. This is what we mean. We don't mean a private section that you then
touch and everything rebuilds. That was a misunderstanding. The abstract data types really were very
much, and modules were very much link time substitution. This is what it's all about. So, I can
switch implementations easily. Now, of course, because we're talking about C and C++,
this does give us the question of memory management. And I did a lightning tool last year about
how Shakespeare was a programmer, and as it happens, my oldest son went to see a film production of
Best Last Night for his GCSE. I'm not going to focus on with Best. It's kind of like, yeah, it's
all deadly and stuff like that. Now, we're going to go for different kind of deaths. We're going to go
for Hamlet. So, what was Hamlet all about? Hamlet was all about memory management. The whole play.
Four hundred years ago, so Shakespeare did not have available the facilities we have for
exploring programs. So, the best he could do was use an actor-based model.
And here, he's exploring creation and not. And this is a question. And again,
people's influences in terms of their background. If you come through a C background,
again, people often go, they go on C and then they've ended up in Ruby. They've got C++,
and they ended up in Ruby. Then they're going to walk away thinking our procedural
languages or language with the strong procedural history. That means we're signing with a
failure on this one. Because a failure, a failure was quite keen on explicit memory management.
Just in my memory, locked in you yourself should keep the key of it, which is basically,
you mallet, you free. You did, and you, you do a delete. So, a lot of people think, oh,
okay, procedural languages, they're all like this. There's Hamlets, you know, garbage collection,
man, from the table of my memory, I'll wipe away all trivial phone records. Okay, that's what
the whole play is about. I'm sure I've convinced you in three quotes. However, history doesn't look
like that. Well, I'm not talking about my retcon of Shakespeare into the canon. Let's understand a
little bit more about what's going on here. Because I want to talk about a couple of other languages,
we'll bring in the garbage collection. Oh, actually, I can bring in the garbage collection already.
We've already seen Algos 68, hand garbage collection. So that would be 68. So in other words,
people say, oh, well, this pad garbage collection, yeah, but that's a different paradigm. Algos
had garbage collection, Algos 68. So let's look at it from a different point of view.
Earlier, Handal, Antonio Hall, earlier Handal, he was the guy, he wanted the guys, him and Kristen
Neegard, who basically came up with Simula, Simula 67. Again, the clues and the clue to the years
in the name. First object oriented language, and it was very influential. It was an extension
of Algos 60. And it too had garbage collection. So Simula 67, that's for object oriented stuff, isn't it?
Oh, that's completely different paradigm. Wait a minute, it's in the book. This is where I got
that quote from, hierarchical program structures. It turns out that the view, the view from back then
was that all of this stuff, this organizing around data types, this object orientation,
was part of structured programming. Because it's not unstructured. They called it structured for
a reason. It poses structure on your ones and zeros, your disorder, your fortune or whatever.
It's a discipline. The problem is that people only remember the control flow, because that's
what they were battling with on a day-to-day level. But also, because that was the easiest thing
to translate those languages. If you're working in Kobo, or you're working in Fortran,
or you're working in Basic, or any of these languages, this is the hardest part of the book to apply.
Not that people use this as a book, but certainly it was the last section. A lot of people
are, yeah, I don't know what, I don't understand that. All the stuff on control flow, that's much
more important. That's how we get obsessed with it. If we look here and we organize our books
accordingly as a block, here's a reference. An array of books, it's a reference. It's going to hold
references of books up to some given capacity. Count is how many we're going to track. We're going to
initialize that to zero. We can also nest our procedures inside our blocks. It's a proper block
structured language. We've got these features. That's pretty cool. But why am I showing you this?
We've already seen blocks and stuff. The only thing interesting here is the word procedure.
This is the bit that's interesting. A procedure which is capable of giving rise to block instances
which survive its call will be known as a class, and the instances will be known as objects
of that class. We take that, we add that, boom, that's how classes are invented. That's where
they come from. They are just blocks that happen to live a little bit longer. They don't follow a
stack discipline, although it is a stack. They don't follow a stack discipline. It's just like
here's a block, it's got data inside it, your variables, it's got procedures, and then you can return
the whole block. It will live longer than just your call stack. That's the whole concept. In other
words, objects are apart, they are an extension of the procedure model. They are part of the
procedure model. That's why they were included in this book. We can actually take this idea much
more literally because I'm sensitive to the varied age of people in the room. Here's some
JavaScript. I like the fact that most people who were programming JavaScript wouldn't
actually born after it was invented. Do I like that? No, it intrigues me. I've got a stack here. This
idea of let's do this without classes. Let's understand the raw materials, a block of stuff with
names that are bound to procedural or functional elements. I've got a function here called new stack.
It takes no arguments and it returns a bunch of operations in a table effectively against some
data that is truly private. It doesn't need the private keyword. It's so private you can't even
see it from outside. It's hidden inside a block. That's how private it is. We've got that. We can,
that's an implementation. We can change our implementation and nobody outside is any of the wiser,
so fully encapsulated. Then let's explore something else that was part of this paradigm.
Catination is an operation defined between two classes, A and B, or a class A and a block B,
or a block C, and results in the formation of a new class or block. These days we call that
inheritance. Notice this was so generalized you can actually have a block inherit from a class,
just a block of code. concatenation consists of merging of the attributes of both components
and the composition of their actions. Let's try that with this, but I'm going to do an object
level rather than a class level. What I'm going to do is rather than thinking in terms of stacks,
I'm going to say stackability is a property. Then you can pass in a base and then what you'll
do is you can then take whatever the base had and then add in these extra features, which will
also have the effect of overriding things. Now a new stack is a stackable of something
simply that is empty. It has nothing else. It's just purely stackable. That's quite nice.
Then we can reinvent what's known as a mix-in model. We can have something that is
clearable. Take the base, add in other things. Now I can have a new stack that is clearable
and stackable. It's a very simple composition model and I can actually linearize that,
make that a little simpler and do all this kind of nonsense. How would we use such a thing?
Well, here's the advice. You create a hierarchy of concepts. Do not be distracted by
concepts in C++. C++ committee has spent a decade and a half being distracted by them.
Fine work. I wasn't originally convinced by the idea of putting Haskell into the compile time,
but there's some interesting ideas there. Finally, I think it's time has come.
Yeah, I know. Shoot me afterwards. The construction principle involved is best called abstraction.
Wow, that's a radical idea. We concentrate on features common to many phenomena. We abstract
away features too far a move from the conceptual level at which we are working. Interesting.
I wonder if that'll catch on. So I'll risk off. What does she have to say? Well, here I'm going
to project you way forward into the 1980s. Let's talk about the list of substitution principle.
A type hierarchy is composed of subtypes, supertypes. The intuitive idea of a subtype is one
whose objects provide all the behavior of objects of another type, the supertype plus something extra.
Okay. And then she gives us a more formal definition. If for each object,
oh, one of type S1 there is there, etc., etc., such that for all programs P, they are like,
okay, great. How can we demonstrate this? Well, let's let's throw in an additional feature,
an additional mix in. I have a non-duplicate top. The idea is that if you try and push something,
if you try and push something onto a stack and it's already on the top, then we're going to ignore it.
Okay. Right. So now what I'm going to do here is I'm going to create a set of tests
and just I'm going to use an object or basically a dictionary. A name and then a lambda, a block,
an anonymous procedure. We can call it what we like. We're going to create a new stack and we're
going to push. ACCU push 2018, push 2018. The depth should be three. If you're not familiar with
JavaScript, you really, really have to want equality. Okay. It's hard enough in the real world
but Dan, you've got a political fight on your hands and code. How do you know two things are really
equal? Just keep your finger down on the equals key. It'll eventually be right.
So the depth should be three and the top one should be 2018. Okay. Right. So when we run this
against our composition of a clearable stackable, then it passes. It's green. But when we
combine it with non-duplicate and non-duplicate top, then it fails. The depth is no longer three,
because we are ignoring non-duplicate tops. In other words, risk or substitution principle is
something you can demonstrate through tests. It's a trivial thing. It's not a type theory thing. You
can actually walk tests through. You can actually say this test failed because of a violation of
risk or substitution principle. It's not something fluffy like single responsibility principle.
Although you can use code analytics to try and get a handle on that. It's not completely
incorrect like the open close principle. So this is actually something that is much more tangible
and identifiable and gets us focused on the important aspect here. Now here's an interesting thought.
One of the challenges that we have is these procedural bits. We've seen that they're all about
single-threaded code. Little bits of single-threaded code that have these nice little hierarchies.
And we know that hierarchies, well, hierarchical-like things, they work up to a point. And these
hierarchies are control flow. But how am I going to build a big system out of this? And this is
where we hadn't already had the go-to problems. This is where procedural fails to scale.
In other words, this is where it starts struggling, big code basis. Now, I would like to point out
that most code bases that are big don't need to be as big as they are. Okay? They are too big.
If you say, our code base is this big. This will never work. Your code base is probably too large
already. But that's a separate talk. The key point is that even if we do pair certain systems down,
there are ideas that are not comfortably described by these, that modules get kind of close
and they come out of the procedural paradigm. But we're still missing. That's a code organization
discipline. But that's not going to allow us to run things fast, faster, take advantage of
course. It's not necessarily going to allow us to do meaningful things at a link time and runtime.
There's something missing and procedural does not directly offer it. But the answer has been there
for a while. There's a different way of looking at this stuff. David Glande in the early 90s
was exploring a distributed and concurrent model called Linda, which has kind of got shoved slightly
to one side. And if any of those, he was in late 80s because I learned about the beginning of 90s.
So, but it kind of got shoved to the side a little bit. But there's some really interesting
stuff there. People tended to focus on the Linda model rather than there's a deeper message here.
Coordination languages and their significance. We can build a complete programming model out of
two separate pieces, the computation model and the coordination model.
So, Nicholas wrote this book Algorithms Plus Data Structures Equals Programs, which gave you kind
of like a ruthlessly hardcore top-down view of the world. Perhaps what we need is something
slightly different. Perhaps bigger programs would be better. But coordination plus computation.
Let's try and look at the world like that. Do we have examples of this? Well, yes, it turns out
one of the oldest examples. In fact, we'd actually say any shell is an example. I'll come to that
in a moment. But make is a really good example of this because what you have is make is a
coordination language. It is quite different to the language that it has. Make is structured in
terms of goals. It's declarative. And then it has procedural bits inside it. In other words, it
organizes bits of procedure with respect to high level goals. In other words, it's not the top level
of organization. The answer to how do you scale procedural code was always there, but perhaps
neglected. It's the idea of you use a coordination language. It turns out procedural is really good
for kind of small things, but really bad for really large things. And oh, don't get me started
on threading. In fact, do because we're going to do that. The problem with threading is stopping.
Okay. So this is, I did a talk last year thinking outside the synchronization quadrant. So I want
to revisit that just to clarify a few things. And actually Williams had some really good stuff on
this yesterday. And in his talk in terms of talking about how do you scale stuff? But it's
kind of convenient to divide the universe into four. That is the purpose of any quadrant diagram.
And we're going to do so along simple axes. Mutable versus immutable. That's our state, pieces of
data. And they whether or not they are shared or unshared between threads at a given point in time.
It was perfectly okay to say, here, I have a piece of code and now I'm going to pass it to
another thread of execution. If we are not sharing it, then then we're fine. Okay. So it turns
out that if you're not sharing stuff, life is easy. It turns out if you're not changing stuff,
life is also easy. In fact, let's encode this. So we're absolutely sure which is the bad quadrant
because every, every diagram has one. Red nature's color for danger. The color of the blood on the
floor from the people who program in this quadrant. Oh, yes, I know. We're going to have mutable shared
states. Brilliant. Shared between threads. Excellent. Red is also in the far east color of celebration.
And that is the, that is how we associate it with consultants who then have to deal with such code.
So, so what we're looking at here, so this is the synchronization quadrant. There is one quadrant
out of four in which you will experience pain. Yes, go there. Why is everybody in there? Oh,
God, it's so many people say, oh, well, okay, we need to worry about this, that and the other.
It's like, no, really. Look, look at over there. No, I can't see that.
Let's just be very clear. Now that we've gone through what's involved in, see, where is
procedural code comfortable? Where is it defined? What is it's history? Whether it is the ugly go-to
history or the slightly more elegant block structured history. It's over here. Yes, it does say
mutable data is okay. Okay, so we might say that that's slightly at odds with a functional worldview,
but let us understand why it was able to get away with that because first of all, it was relatively
close to the machine. Machines that did not have enough memory for you to fritter around in terms of
memory and copying and garbage collection as people often characterize it. We've got this idea of
side effects, but they are contained because we're not really sharing anything. We're not going
too big either, and you should be using a coordination language to glue these things together.
In other words, keep on not sharing. The idea of a shared nothing model. The idea is,
this works. Keep on not sharing. And so unfortunately, because you see historically, there was
never an issue with threading because all code used to be in the top left-hand quadrant.
Yeah. I mean, you know, you can talk about this program, and indeed people did. They never
actually met any because they weren't very many around. Okay, that's the point is that all programming
traditional programming was done in the top left-hand quadrant. And there was no question of
sharing between threads because there were no threads. It's a very simple kind of reduction.
Now, when people started getting threads and threads proceeded course,
we moved over here. One problem, procedural discomfort zone. This is outside the comfort zone of
that paradigm. It doesn't want to be there. That's not where you want to be with this paradigm.
It's actually very well defined over here on the top left-hand corner. So people go over there,
and then they build other language models on them and then start wondering why they get pain.
C++, hello. That C++ wants to fill out all four quadrants. You know, if it's like Bingo,
it's like Bingo. Yes. House. Yeah. Unfortunately, too many languages want to do that. We see
that with Java. We see that. We'll see that. And it's just like, yeah, we're going to get a
multi-paradigm. We do all the quadrants. We do pain. We do comfort. You know, what is your pleasure, sir?
So it's a wonderful talk. People kind of convincing me to watch it.
You know, Kevin, you're interested in programming paradigms and different ways of doing
threading and stuff like that in concurrency. Yeah. Have you seen Brett Victor's talk,
the future programming? No. And then finally, I got around to watching it.
Absolute genius. Cheer, bloody genius. It was recorded in 2013. And Brett Victor basically
presents himself as if it's 1973. So he's kind of doing the 1968 thing, but five years later,
half a decade. Wow. A lot of things happened then. Crazy ideas like the actor model and stuff like that.
And so he explores a much broader palette. In fact, I think one of the best bits is he walks
on wearing kind of like white shirt with pens on the top hand. You know, this is a much more
casually addressed conference in 2013. You can tell from pictures of the audience. And it's just
like, why is he dressed like that? It's very, oh, he's being an engineer from 1973. I get it. Very
funny. Not as funny as the talk there. There's some really good insights. I love that he puts
his threads and locks. They're kind of a dead end, right? So I think we're still using threads
and locks in 40 years time, which just like pack up and go home because we clearly failed as an
engineering field. Yeah, you know what? He's right. And that was in 2013. He is more right now in
2018. He's not that wrong. So let's go back. That comfort zone. Let's explore that.
Proceed. The idea is that the danger with any paradigm and where it starts getting a bad name
is when people apply it outside of its comfort zone. And our temptation is because we like
our ones and zeros because we like simple answers because we want to say, I have the one true hammer.
Show me the one true thumb. You know, I have the one true hammer. Therefore, I'm going to
apply it everywhere. Even when I shouldn't be, okay, there's this idea that we under we fail to
understand the applicability and then say, and now we stop. This is no longer where this approach is
comfortable. This language, this framework, this whatever. And we already had the answer. It was
back in the coordination model. Computational model allows programs to build a single computation
activity, a single threaded step at a time computation. Okay, nice and comfortable. Sit there,
you can do your module, you can do your C, you can do whatever. The coordination model is the glue
that binds the separate activities into an ensemble. Okay, so an architect, always like an architecture
definition language, but the idea is that you have something that glue stuff together.
So your ultimate architecture ends up looking a bit like this. Everything looks single threaded,
wherever you are, it feels single threaded. Okay, you're not aware of threads of activity or any
concurrency. You have a very simple worldview and everything is lovely and local. Okay, there's no
real problems. And that's what everything looks like. There's no shared anything. And then we
impose a coordination model on it. And there are lots of different coordination models. I gave you a
very simple example of make file, but one of the classic ones, let's go back to the 60s,
1964. I like using this one, a lot, Doug McElroy. To put my strongest in service and nutshell,
we should have some ways of coupling programs like garden hoses. Screw in another segment
when it becomes necessary to massage the data in another way. This is the way of I also.
This is the invention of pipes. It took another six years before they were able to find a
a character on the keyboard that would do the job. That's only half joking. It was actually Ken Thompson
who sort of said, oh, let's use this symbol. And that was it. It was in. But this is the whole
point is that that pipes and filters model is a coordination model. Again, pipes and filters does not
solve every single problem in the universe, but it is a coordination model. And so this is the idea
you glue together. These little bits of procedural C using something else. And that composition
model becomes very powerful. I did mention I might say something about composition and
and functional, but there it is. So you end up with the world looking a little bit like this.
The very simple kind of view. Everything ends up with pipes and you can chain this.
You can have it's finite size, so therefore it's bounded. The question is whether you can control
is it the operating system? Is it you? But this channel, this kind of like pipeline architecture,
this message queue architecture, these are all the ideas. It's got buffering, so therefore it's
implicit the asynchronous. So you've got that. And then you can start playing around with things,
just see how things go. People often mend up with n equals infinity, which I would suggest is
great for prototypes, but not a good idea for production. It turns out that infinite memory is not
actually available yet. It turns out that you can have a system fail because of starvation,
priority inversion, all kinds of exciting things that mean that something runs away with that.
You want to have failure at well specified points. So generally, don't leave them there.
But we have names for other categories. N equals one bounded buffaday synchronous.
One place queue. What good is that? Well, we like to call it a future from the other side. It looks
like a promise. You can build everything out of these things. Those are redundant ideas once
you have the concept of queue. What about a zero placed one? What uses that? That's a classic
channel. Now some people might be sitting there going like, ooh, you're talking about go. No,
I'm not. The go people are kind of late again. 1970s, communicating with sequential processes,
which gave rise to the Occam language 1980s. Occam is one of the most brutally uncompromising
procedural languages I have ever encountered. And it was a joy to programming. It was systematic.
It believed that indentation was significant. It didn't want you to type too much. It showed
its Algos 68 influences as well. It didn't believe in this kind of like stroking of the
programmer. It said your program did not compile. It's as simple as that with one error.
Oh, only one error. Yeah. Because it didn't have a list of errors. It would just stop at the first
one. That's it. I'm stopping. I'm not going any further. You never got a cascade of errors
because it would just stop at the first one. Yeah, I'm done. Until you fix it, I'm not playing.
But if you think that, you know, everyone uses this language, it's got such a strict
type system until you use Docum. You have no idea of the level of bondage and discipline you
can program in outstanding. Anyway, so where does this leave us? It leaves us with a question of time
because what we find on the way she, Nobel Prize winner said this, everything has been said
before. But since nobody listens, we must always start again. Most of this stuff is not new.
But we get terribly excited about it. I do love language design and languages. I think they're
great fun. But that doesn't stop me being hypercritical of them or our failure to learn.
Reading the software engineering document was profoundly fail depressing because it turns out that
we haven't really done very much in the last 50 years or other the hardware people have been
really busy. Let's put it that way. All of the benefits. Yes, yes. But as a modern developer,
I have a big screen. Yeah, that's a hardware thing. I have so much memory now. Yeah, that's also
hardware it turns out. It turns out that most of the benefits were anticipated but were
bottled up. They were waiting at the starting line waiting for somebody to say,
look, here you have the hardware to be able to try this. But there's a lot of these ideas
that are surprisingly not new. And we also have a habit of just putting things in a box saying,
oh, that's the pass it's dead. It's dead to me. As a case of what procedural programming,
we do have this habit of saying, oh, that class was really procedural. We use it, but I've used that
term. But then to actually go back and look at it, are we using it fairly? And did we properly
understand what we meant by procedural? Anyway, it turns out, by and large, no, we didn't.
It turns out that the truth was always out there. It just takes a little bit of
sort of looking around and digging out. And then you reveal these deeper insights as to how
things are connected and how programming models are connected. The things that we actually have
learnt, as opposed to the things that we have accidentally reinvented and re-led. There's matters of
form, matters of structure, and ultimately matters of reasoning. So I'm not going to say, oh, go forth
and do procedural programming. It's a case of, like, understand what it is before you working
out and work out how excited you should be by the next language feature.
Outstandingly, I finished five minutes early. So I'll do a thank you and then I'll ask for
questions. So thank you for listening.
Introduction to Procedural Programming
Reassessing Procedural Programming
Understanding Programming Paradigms
Exploring the History of Bristol
Software Engineering in the 1960s
Understanding Input and Output in Programming
Modes Over Types in Procedural Languages
Revisiting Proposition Structures
Procedural Languages and String Handling
Iterating Through Arrays in Procedural Code
Understanding Control Flow in Programming
Analyzing Duff's Device
Exploring Historical Programming Languages
Understanding Code Structuring
Decoding Procedural Paradigms
Transition Between Programming Paradigms
Understanding Abstract Data Types
The Concept of Modules in Programming
Exploring Garbage Collection History
Introduction to Inheritance in Programming
Scaling Procedural Programming
Coordination vs Computation Models
Challenges with Multi-threading
Pipes and Filters in Programming
Reflections on Programming Paradigms
What makes procedural programming relevant today?
Are modern programming paradigms better than procedural?
How can historical software engineering inform current practices?
What unique contributions did 1960s software architecture have?
What logical connections do I/O have in programming today?
How does procedural programming handle modes instead of types?
What role do parentheses play in older languages?
How did structuring programming evolve past using GOTO statements?
What is Duff's device and why should we avoid it?
How did early programming languages visualize nesting?
In what ways do modern and older languages handle returns?
How does structured programming emphasize cognitive clarity?
How do functional and procedural programming differ in side effects?
What impact did Barbara Liskoff have on programming structures?
How do abstract data types define programming behavior?
What proves the risk or substitution principle in programming?
How does the coordination model help in scaling procedural code?
What lessons can we learn from past programming models?
In this talk, Kevlin Henney questions whether procedural programming is still relevant in today's software development landscape. He notes that while the term 'procedural programming' has a negative connotation, the idea of thinking about programming in a procedural way is not necessarily a bad thing. Henney explains how new devices and technologies are changing the way we think about programming and whether procedural programming is still relevant. He highlights the importance of considering both functional and procedural approaches to programming and how they can complement each other. Henney also discusses the potential drawbacks of focusing solely on one approach and the need to consider a broader range of paradigms in software development.