The term Software Engineering was coined in NATO conference back in 1968. This title was considered provocative at the time. It was used to encourage the software industry to improve predictability and quality of development process. Today the job title Software Engineer is widely adopted, however engineering-programming connection is still being questioned. Software-engineering mindset has yet to give us some silver-bullet method that considerably improves quality of programming products. Maybe it’s time to take a fresh look at the complicated programming-engineering relationship and what it means for the future of software development.
Computer programming has always been intertwined with traditional engineering fields. First computers were clunky machinery that broke down often. Teams of electrical engineers had to maintain these devices on a daily basis. First programs were produced not by writing code, but by connecting physical wires on switchboards. At the beginning there were no programming courses in universities so naturally first programmers were engineers and scientists that needed expensive computations for their everyday work. Such circumstances made it seem that programming itself was a form of engineering.
In order to discern the difference between programming and engineering we need to take a closer look at the essence of each discipline. Engineering at its core involves the transfer of abstracted design to physical reality. For example, a car designer can conjure any crazy futuristic design for a new car model, but then an engineer has to actually implement it. The engineer transforms original design to physical implementation model. To perform this operation he has to have intricate knowledge about constraints of physical materials and their interactions. He has to do rigorous calculations and implement systems with acceptable tolerances that can withstand changing physical environments. He has to make engineering-design compromises during this process and the initial design has to be adjusted to match the physical realities of engineering.
Computer programming, on the other hand, is a different kind of process. It is our way of making sense of the world by describing reality with symbols and making abstracted models of it. The ultimate goal is not to have our models embedded in the physical world but to detach them from practical constraints completely. One can clearly see such trend in digitization of trade in our society. A banking system today is mostly an abstract construct. Most trade operations are done by flipping bytes in computer memory and not moving physical assets around. As long as our mental model of such banking system works good enough the model fulfills its task. That is the reason why our monetary system evolved from physical tokens exchange to digital operations.
Engineering and programming are related in a circular way: engineered reality comes from abstractions and abstractions come from observations of reality. A lot of times there is some overlap too. For example, programming is partly engineering when we are adjusting and optimizing our programs to match the physical constraints. Most of the programmers deal with such familiar limitations as computer memory and CPU speed. We are also engineering when we try to scale and distribute large systems on server nodes. Dealing with embedded systems will always be more about engineering than programming too.
I would argue that software quality and development speed has increased in the last 50 years. And the main reason for that is not some specific programming methodology, but decrease of engineering problems that a programmer has to face. Assembler was the first programming language and it was tightly coupled to specific machine architecture. Such circumstances made expressing programming abstractions extremely hard. Higher level languages such as FORTRAN and C separated programmer further away from the engineering aspect of programming. Java and JavaScript removed the concepts of pointers, that were tightly coupled to computer architecture and made programming even easier.
Current programming languages are much more advanced than assembler but we still have some way to go. The most popular languages today are still based on old C-style syntax. In order to increase quality of our products we will need to find some new kind of semantics that will allow us to quickly produce robust and error-free programs. The future belongs to programming languages that do not make programmer think about CPU or memory limitations, object reference comparison and the reasons for imprecision of float division. The main challenge of programming today is not dealing with limitations of physical reality, but systemizing our mental models into robust and effective interactive abstractions that can be unanimously understood by people and machines.
What is important is that programming can stand as a field on its own. We don’t have to look up to engineering as a big brother. We have to invent our own methodologies that help us to abstract our reality in a more efficient way. Programming and engineering are not interchangeable terms. We need both of these concepts to communicate the difference between the processes of abstraction and physical implementation. By separating the fields of programming and engineering we can better understand what it takes to write robust programs. This separation will also help us to establish programming as a mature discipline that can stand on its own in the post software engineering age.