This post is part of The Software Architecture Chronicles, a series of posts about Software Architecture. In them, I write about what I’ve learned on Software Architecture, how I think of it, and how I use that knowledge. The contents of this post might make more sense if you read the previous posts in this series.
Programming languages themselves are not an artefact of architecture, but I would feel that The Chronicles of Software Architecture would be missing something if I wouldn’t write about it.
So, let’s make a quick review of programming languages history, its evolution and check what we can learn from it. I’ve added some dates to the post just as a curiosity, they should be seen as rough estimates, the important is the evolution sequence and the problems they were trying to solve.
1950s – Non-structured Programming
Software Development was a very obscure activity, performed in only a few places in the world. Assembly was the hot language back then, it used very low-level operations like “add”, “sub”, “goto” and manipulated memory addresses directly. It was slow and difficult to build a simple application. To create a simple IF statement we needed few lines of code and for a loop, it would take more than a few lines… The possibility of grouping and reusing pieces of code came later on, so the coding style was very linear and code reuse was limited to copy-pasting code within a file or between files.
1960s – Structured Programming
Algol ~1958, Fortran
Structured programming came up, introducing code blocks, constructs for control structures (if/then/else, case, for, while, do, …) and sub-routines. We could, then, create more interesting code flows and, more important, we could group code instructions and reuse it, although with some limitations, like the sub-routines always acting on the same global variables. It was at this time that the first ideas of reusability came to practice.
1970s – Procedural & Functional Programming
Pascal ~1970, C ~1972
Procedural and functional code came to life during the 1970s. At this point we finally had:
- Procedures: Set of instructions that don’t return data;
- Functions: Set of instructions that do return data;
- Data structures: Records, similar to an associative array;
- Modules: Code files that could be imported into other code files.
During the 1970s was also when the term “Spaghetti code” got coined, following Edsger W. Dijkstra letter to the Communications of the Association for Computing Machinery (CACM) in 1968, titled “Go To Statement Considered Harmful“.
It was during the late 1970s that the first ideas of Event Oriented Programming surfaces and Trygve Reenskaug writes his paper about MVC (which used events).
Thus, with these improvements, we had better reusability, as subroutines (procedures and functions) could perform the same logic with different data. We could also model domain concepts by grouping related data into complex data structures. And, finally, we gave the first steps in decoupling and modularity where we could create code reusable in other code files and events to decouple the client code from the logic being executed.
1980s – Object Oriented Programming
Simula ~1965, Smalltalk-71 ~1971, C++ ~1980, Erlang ~1986, Perl ~1987,
Nevertheless, it was during the 1980s that the usage of the current programming paradigm became generalized: Object Oriented Programming, with visibility levels, methods (messages), objects, classes, and later on packages. This is the same as saying increased encapsulation and modularity:
- Visibility levels allow us to control what code can access a specific set of data;
- Classes allow us to define/model domain concepts;
- Objects allow us to have different instances of the same domain concepts;
- Packages allow us to group classes that together represent a domain or functional concept and work together to perform some task;
- Methods, which functionally represent procedures and functions, but conceptually should be seen as messages (or better yet, commands) that can be issued to a specific type of objects.
1990s – Subject & Aspect Oriented Programming
During the 1990s Subject Oriented Programming and Aspect Oriented Programming came to light.
Subject Oriented Programming calls for the different representations of objects, according to who is “looking” at it. For example, while a human might see wood when he looks at a tree, a bird might see an amount of food and shelter. Translating this to a programming, it means that object properties and behaviour can be different, depending on who sends a message to the object (who triggers a method on an object).
Aspect Oriented Programming tries to completely separate cross-cutting concerns from the actual business logic by injecting the extra code at “compile” time. An aspect is, for example, a method name. A cross-cutting concern is, for example, logging. Using AOP, we can simply configure the system to inject code that performs logging into all methods that comply to a specific pattern, for example, “log all calls to methods whose name starts with ‘find’“. (TYPO3 is an example of a CMS using AOP)
After the establishment of OOP, the big focus has been in adjusting ourselves to programming for the web, evolving existing languages, creating new languages specialised for web development, developing frameworks, adjusting the tools and architectures for the massive amount of requests and data of today.
There were some attempts to evolve the Programming Languages, like Subject-Oriented Programming (objects behavior is different, depending on the subject firing the behavior), or Aspect-Oriented Programming (code injection at compile time), but in essence the programming language paradigm didn’t change much as we still use OOP for most cases, although functional languages seem to have been gaining some adoption as of late (maybe a hype?).
The point I am trying to make is that in the first decades of software development history, programming languages evolved in order to provide for reusability, but also to prepare software for change (be it changing the functionality, refactoring or swapping a section of code completely), they evolved in the direction of Modularity (low coupling) and Encapsulation (high cohesion).
As we will see in my next posts, Architecture continues this evolution, although at a higher level of abstraction.
1979 – Trygve Reenskaug – MVC
1993 – Alan C. Kay – The Early History of Smalltalk
1993 – William Harrison, Harold Ossher – Subject-Oriented Programming: A Critique of Pure Objects
1997 – Gregor Kiczales, John Lamping, Anurag Mendhekar, Chris Maeda, Cristina Videira Lopes, Jean-Marc Loingtier, John Irwin – Aspect Oriented Programming
2005 – David R. Tribble – Go To Statement Considered Harmful: A Retrospective
2017* – Wikipedia – Programming Paradigm
2018* – Wikipedia – Simula