A friend approached me the other day, asking the same question I’ve been asked so many times that if I had a dollar for each time I’ve been asked, I would have exactly $17.50.
‘That Swift that Apple did last year’, he said. ‘Is it worth anything?’
‘Yes’, I nodded, trying not to start another rant.
‘That was… um… very informative.’
‘You asked a simple question. I gave you a simple answer. What did you expect?’
I was still trying not to get into the details. I haven’t got all day.
‘You know what I meant’, he started. ‘the information on the Internet is full of the pros and cons of that language. Some say it’s useless, some love it. I’ve seen posts about its bugs, but also long lists of features that might speed up my work. But I still have no idea why they’ve done it. Making a new language, you know. There’s so many of them already. What is that for?’
Well. I did my best not to overreact…
I failed.
‘Listen, pal,’ rant is on its way. ’Let’s just say that it’s very strange that it took them that long to get there. Especially considering that they are inventing the wheel all over again.’
He was surprised. If by surprise you mean a blank expression and dropping jaw. He hadn’t seen that coming. But there was something in his eyes that made me think he really wanted to understand what the hell is going on. So I thought I would give him a chance.
‘I would invite you for a coffee, but this is going to take a lot longer than that’, I said.
‘I’ll bring scotch.’
I have no idea why I wanted to get things straight just then. The night was long and the booze – it would appear – helped rather than just blurring our thought processes. And so, as a result, I thought I would share my thoughts with a wider audience. So if you really want to know why the hell there’s a new language called Swift and why you will – eventually – create apps in it (considering that you are an iOS developer) – sit down, relax, bring a pint. Or two. And listen to a story.
Computer got personal
You have probably seen ‘The Imitation Game’ already, which leads me to believe that you know how this whole shebang got started. Let’s just say that computers were born and a person named Alan Turing can be regarded as a father to all of this. He gave us much more – but getting into more mathematical details of the whole theory doesn’t really get us any further at this point. More important is that Thomas Watson (president of IBM in 1943) was very, very wrong when he announced that there was a world market for a total of five computers. The mere fact that you are reading this using a device connected to the world wide web means that you are proving him wrong.
It happened. We have more computers than anyone could have imagined. But in order to get there, we had to make the original concept smaller, faster and more accessible. The invention of microcomputers that hit the market in 1977 was a giant step forwards. However, one of the obvious problems was something called “User Interface”. This problem was solved by guys you probably already heard of. In order to do this right, people called programmers had to have a good way of communicating with the machine in order to tell it what to do.
So – as long as a computer is not something you expect to be able to keep on your desk at home – machines can be big and the instructions given to them don’t need to be all that complex. The computer was being used by the squints anyway. They were squinting, producing formulas that then were translated to the computers, and – after a lot of huffs and puffs – computers were giving answers that squints then could squint about some more.
Easy. Maybe that’s why they called that formula translator a… erm… Formula Translator. Fortran in short. This probably rings a bell.
But then – computers got more… tiny. More accessible. There had to be a way of giving a boost when it came to communicating with the thing.
Telling it what to do
The computer by its nature is more simple than you probably imagine. We can even say it’s very dumb. Meaning that instructions you are giving it are limited and actually quite simple. Move something into a special memory, perform a simple operation on one or more elements in that memory, get the result, move around to a different set of instructions – and so on. That simplicity made computers possible and usable. There’s only one problem with this. People such as you and I need something more… readable. A simple equation, for example, adding two values to get a result cannot result in gibberish no one will be able to understand (unless you are a computer fetishist).
That’s why squints came up with an idea of formula translation, and since then we call these things “translation methods”. But you probably know them rather as “compilers”. The idea was to create more readable languages that an average person (in this particular case, an average still means squint) can understand. Everything was based on entities called “functions”. You had a main function that started automagically and from that point, you could run different functions, collect results and react to them using logical statements. This was a fantastic tool for the guys that just needed to solve equations. I don’t want to give you a stupid lecture about what happened then, and how those languages were bouncing around. But a few things are worth mentioning. First of all, those languages ended up grouped in three “classes”:- Imperative languages – pretty much all the languages you ever worked with, probably; Functional languages – where everything is a function. And no – I’m not talking about JavaScript. We will get to that. – SML is a good example; and Logical languages – for example Prolog.
Because of the obvious reasons of general usability and speed, imperative languages with ANSI C at the front completely took over the market. It was easy to learn, quick to compile (it was a one-pass compiler, and no, I’m not even trying to explain it now) and fast. Everything you would ever need, right?
The problem was code maintenance. More people working on a single project started to come up, hard, against someone else’s code. We’ve got design patterns, coding conventions and stuff like this but even allowing for these, the bigger the project, the more complex and profound the problems started to be. But there were two things programmers hated most.
Ownership
Ever had that problem that something is lying around your house and you have no idea if it’s yours or whether someone left it and will collect it at some point? I had. Now imagine the same situation in code. You are calling a function, and getting some resulting data in allocated memory. Somewhere. The question is – is that yours now, in which case you can maintain it and release it when you’re done, or should you leave it alone and wait for someone else to collect it?
That was bothering people for years. There were design patterns created just to solve that particular issue. How to differentiate whether the memory you’ve got is yours or not yours? And it was never only that simple. The worst case scenario was always when the same memory was used by multiple parts of the code. What then? When should that be released? How can you know if everyone has used it and doesn’t need it anymore? Oh, I know you’ve got answers to that now. But at that point in time, the solutions that you have in your mind simply didn’t exist.
Let’s just say that more time was spent by coders on fixing bugs caused by this particular problem than anything else. Well… almost anything…
Two things in the same time
In the beginning, we didn’t have too many problems with doing two things at the same time. At all. All programs had only one thread and everything had to be done in that single one. The first attempt at making something multithreaded wasn’t even multithreaded! It was just a round robin structure of functions that were called on one by one. And each and every one of them could move itself around the structure to change its priority. But let’s be honest. That’s not a real multithread.
But when something else came along… That was a disaster. Immediately, applications start to have problems. How to manipulate the memory when more than one thread is accessing the same data. And changing it. It’s not merely that one thread can change it and then the other will get weird results. What if threads get switched WHILE changing the values? As I said before – even assigning a value to an attribute is more than just one operation on the processor. We’ve got some mechanisms to prevent such a thing, but programmers have to be aware of the issue.
As an addition to the overall confusion, yet another issue appeared. How to visually get your head around the fact that some of your code is done asynchronously somewhere else? How to wait or obtain the data between threads and not get a spaghetti code full of pass-through function pointers called and defined somewhere else?
These two issues and the growing size of a typical application led to a very simple conclusion. We need something better than just a simple list of functions grouped in modules. And more complex language to maintain the code.
Or we are doomed.
Small talk, big programming
In 1970 there was a company founded that had just one purpose – to find new better ways of using electronics. You could say it was squint wonderland. It was called Palo Alto Research Center Inc. It was division of an already well-known Californian company – Xerox- and is quite often referenced just as Xerox PARC. You probably came across that name reading about the genesis of User Interface. How Jobs copied the idea of the graphical interface and the mouse. But that’s not their only big creation.
The one I want to tell you about is something called Object-Oriented Programming. The idea was extremely simple. Instead of making application modules with lots of functions that can be called anywhere (and have to have unique names), you can organize your code in something they called objects. An object is an instance of the class. Class is a newly defined type of instance in the code. So not only basic data types such as integer, character, an array or a simple struct would be available. Now you can have classes.
What is a class? Why is it better than simply having a struct? A class also has a group of information embedded in it called attributes. A struct could do that. But there was quite a lot about it that a struct couldn’t handle. First of all, not only attributes were coming with it. Objects could respond to something called messages. A message passed to the object was literally a call to a function embedded inside the object alone. The obvious question is why? Well. It was quite hard to modularise a big product and keep a unique naming convention. Now you could have functions that had any meaning only within the scope of a single instance – an object. However, there was much more to it than that.
The concept of polymorphism was introduced. This was the idea that one type (class) can inherit from another type (class) and add more functionality to it (attributes, more messages). In the code and execution, one could refer to instances of both classes as one (the parent one) and use it as much as required. And if you knew that this particular object was actually something more specific, you could use the functionality of that specified class. That also meant that you could typecast objects into anything and then simply try to pass a message that might or might not be understood by the instance. This almost literally blew people’s minds. The idea was extremely simple in its nature but quite a lot of people struggled to get their heads around the concept. So PARC simply created a language that goes with that principle. It was called Smalltalk.
Smalltalk was predicated on the idea that everything in it is an object. Even a constant “1” typed into the source code was an object of a specific type (integer) of a constant value 1. It showed how to implement complex projects following an object-oriented approach. But it did so much more than just that. Smalltalk solved quite a lot of other issues. It showed how to create an object-oriented language – yes. But they also added a lot of other stuff – for example, anonymous functions. It was 1972 when Smalltalk implemented them although they were previously introduced in another language called LISP. You could create a function within a message call, so a message – whenever it was needed – could call that asynchronously. You could keep your asynchronous code in one place. You could easily see the logic of your program without the necessity to implement too many external functions somewhere and divide your code into a single flow between files or modules.
How cool was that?
The language was created quite early (1972) but it took some time before it was actually shown to the world. At first, it was given to a small subset of companies such as HP and Apple. And only after the second version was released was it presented to a wider audience. It had its disadvantages. First of all, it needed a virtual machine to work. That wasn’t something that the industry liked. That meant that the language had a middleman that slowed the execution down. It was also presenting a mixfix notation. You probably never heard of it. That just a hint on how prefix notation was deeply embedded in the industry. In most of the common languages, whenever you’re defining or using a function, you are giving it a name and then the attributes. For example:
somethingToDo(a, b)
In a mixfix world, to make method names more informative and to ease overloading, the name of the function was mixed with attributes instead of prefixing the whole name before the attributes. So you would have something like:
somethingToDoWith: a and: b
Quite confusing, isn’t it?
But people had seen the object. PARC also released ANSI for the language and its virtual machine. A lot of squints started to look into it and tried to use it in the real world.
And they failed.
Subjectivity
The most annoying thing about Smalltalk was that no one could see a real-world implementation using it. It was too far from the machine. It was far from the programming everyone was used to. So people started to implement their own languages that would follow object-oriented principles in their own way. That is how two big object-oriented languages were created. Objective-C and C++. Both of them had different ideas as to how to implement the objects principle.
Objective-C started from already known ANSI C. Brian Cox took the idea from Smalltalk and tried to incorporate as much as he could into ANSI C using an additional preprocessor that would be put on top of the already existing ANSI C compiler.
He used the same notation (mixfix) because it was quite a good way of solving the issue with message overloading in the classes, and added his own keywords that could handle the object definition, creation, inheritance, etc. It worked! He used his own naming convention, so classes were called “interfaces”, and messages were kept as they were in Smalltalk. There was a “nil” and “self” as in Smalltalk. What we now commonly know as “interfaces” were called “protocols”. Preprocessor was pretty good at all of this.
But more importantly, it was still compiling to ANSI C and then being translated to binary code. He simply used the technology that already existed. That inevitably caused some limitations. He had to ditch the idea of anonymous functions. Objective-C also had a division between implementation and header files because ANSI C needed it. The problem was that it was a totally different approach to the languages from that which had gone before. Mixfix notation, a lot of keywords starting with “@”… A lot to learn.
Bjarne Stroustrup had a different idea. He thought writing the whole thing from scratch was a way better approach. He created C++ and added as much as he could to it. From C++, we have names such as classes and interfaces. He used the well-known prefix notation. He also introduced the idea of inheriting from more than just one class. That, however, was something of a misfire. The idea was noble but the implementation caused more problems than it was worth. Type casting in this language was, and still is, a nightmare. And the way that language evolved from it was adding more and more confusion. C++ also dropped the idea of messages as such. You had something called methods. If not defined otherwise, methods were simply functions defined somewhere. Just like you had it in ANSI C. But you could “virtualize” those methods. In this particular case, methods started to behave more like messages in Smalltalk. Pointers to them were kept with the object alone. And only with this polymorphism was possible in C++.
By contrast with ANSI C with pre-processor, C++ was not a one-pass compiler. It had to have more. Binaries had a totally different footprint and mixing C++ with ANSI C was more problematic than Objective-C alone. But it was C++ that won that battle. People loved it and started to use it and extend its foundation libraries (stdlib etc), giving birth to a totally new way of programming.
The middleman
Object Oriented Programming speeded up the development significantly. The code was more readable and extensions to it were significantly easier to implement. But one more thing bothered programmers: the idea of having a virtual machine in the same way as Smalltalk.
All compilers were compiling – at some point – their code into simpler sets of commands that were easier to optimize, before assembling then into a native binary understood by the machine. Keeping it that way, and interpreting on the fly, had some advantages. It was slower – obviously – but Moore’s Law applied. Computers became faster and faster. And having an application that can be run on every machine possible (as long as it had an interpreter – virtual machine – on it) was very promising.
Java implemented that idea in the real world. They took the Object-Oriented approach, added a virtual machine and sold it as an easy-to-use language that could produce applications that could be run anywhere. Even in your fridge – we will get to that.
That was a moment when everyone knew that computerization would get everywhere. And there was one more thing; the virtual machine could solve one more problem – memory. It could scan the application runtime during its execution and release any memory that was no longer being used anywhere.
That was supercool. Developers could simply forget about the problem with memory. This was more difficult for the machine itself, and in fact, was slowing it down. But what the hell. Machines were already fast enough. Why would we care, right?
The flop
I remember watching my friend staring at his drink and saying nothing for a few worrying minutes. He was still digesting what I had told him.
‘What you say is all very cool, he started. ’But I still have a funny feeling that everything that happened was a very bad thing.’
‘Because it was’, I responded.
‘Hold on for a minute’, he raised his voice.
‘These principles were noble. Implementation had issues, but everything was going in the right direction. Obviously.’
‘Obviously’, I nodded.
‘But it was going too quickly and all of those guys were deviating quite a lot from those principles in order to deliver something that was diverting from what it should have been in the first place.’
‘I’m not sure that I follow’, he said.
‘Well’, I wriggled in the chair a bit. ‘Nor did they. Because they had totally forgotten that the personal computers they were working on were not the only computers out there…And that is when everything went bonkers.’
to be continued…