A bit about my background: The first machine I programmed was ca. 1970 in high school--a Monroe programmable calculator with four registers and a maximum of 40 program steps. The most complicated thing I got it to do was to iteratively calculate factorials (of course it got arithmetic overflow pretty quickly). As an undergrad Biology major I learned BASIC on DTSS and later Fortran IV and PL/I for an S/360 model 25 (32K max memory). I decided to go into computer technology rather than Biology and attended CS grad school. I completed all the coursework but never finished my thesis. After interning at IBM's Cambridge Scientific Center for a few years, I joined DEC's software development tools group in early 1980, later joining the GEM compiler team to design and implement the non-compiler parts of the compiler back end (heap memory management, generating listing files, command line parsing, object file generation, etc.). Compaq acquired DEC and about a year later sold the Alpha chip technology--including the GEM optimizing compiler back end--to Intel. Many of the engineers--including me--went with it. I retired from Intel in 2016.
One important thing I learned early on in my career at DEC is that there is a big difference between Computer Science and Software Engineering. I was very lucky that many of the top engineers in DEC's compiler group had studied at CMU--one of the few schools that taught SW Engineering skills as well as CS. I learned good SW engineering practices from the get-go. Unlike CS programming, SW engineering has to worry about things such as:
o design and implementation for testability and maintainability
o test system development
o commenting and documentation so that others can pick up and maintain your code
o algorithm scalability
This thread has spent a lot of time discussing how programming has changed over the years. I bring the SW Engineering skill set up because IMO it's just as relevant today as it was in the past. Perhaps even more so.
My observation is that programming style has changed in response to hardware getting faster and memory capacity getting larger. If your program has to fit into 8K or 32K you have to make every byte count--often at the expense of maintainability and algorithmic efficiency. As machines got larger and faster, programming for small size became less and less important.
The first revolution along these lines was the switch from writing in machine code (assembler) to higher-level languages. Machines had become fast enough that in general it didn't matter if the compiler didn't generate the most efficient code possible. In most cases the increase in productivity (HLLs are less error-prone than assembler) and maintainability more than made up for less efficient code.
The second revolution was structured programming. Machines fast enough and large enough that one didn't have to resort to rat's nest coding to make the program small and fast enough to be useful. Structured programming made code more easily understood--both by humans and by optimizing compilers.
These days we have machines with several levels of data caching and multiple processor cores running asynchronously. If (as in the HPTC world) you want to get the maximum performance out of the hardware, you have to worry about framing your program in a way that can be multitasked (to take advantage of all those cores) and you have to worry about efficient cache management and interprocessor communication. The ways to do this are not always intuitively obvious. Modern optimizing compilers know all the (often completely non-intuitive) efficiency rules and can best apply them when you write your code in an algorithmically clean manner and leave the grunt work of running it efficiently on the hardware to the compiler. It's a very different world than when you had to figure out how to fit your code and data into 8K!
-Paul W.