I have some predictions for 2020. They may (or may not) be correct.
Hardware: Virtual desktops and the cloud
I expect 2020 to be the "year of the cloud", in a sense. While cloud computing is popular, I see the phrase "the cloud" becoming more popular in the upcoming year, even more popular than cloud computing itself. How can this be? How can the term be used more than the actual thing?
I expect that lots of people with use the term "the cloud" to mean online (or web-based) computing, even in situations that do not use actual, honest-to-goodness cloud computing.
We will see an interest in virtual desktops, specifically for Windows. Today's PCs are real PCs with operating systems and applications. In 2020, look for a push (by Microsoft) for virtual desktops - instances of Windows hosted on servers and accessed by a browser or by Microsoft's Remote Desktop program.
Most folks will call this "Windows in the cloud" or "cloud computing". The former is a more accurate term, but the second is not too wrong. Virtual desktops will be hosted on servers, with some applications built for cloud computing and others not. Microsoft's Office products (Word, Excel, and Outlook) will all reside in the cloud as try cloud applications. Applications from other vendors will run on virtual desktops but won't be true cloud applications.
Virtual Windows desktops offer several advantages to Microsoft: they are paid as subscriptions, so Microsoft gets a steady cash flow. Second, Microsoft can move customers to the latest version Windows 10. Third, and perhaps most importantly, Apple is not prepared to offer a matching service. (Apple remains in the world of "fat desktops" which run the operating system and the applications. They cannot move that experience to virtual workstations hosted in the cloud.)
Cloud-based Windows is not for everyone. Some will be unwilling to move to virtual desktops, and some will be unable to move. Anyone who insists on running an older version of Windows will remain in "fat desktop" land. And anyone who cannot install their software (perhaps because they have mislaid the install CD-ROM) will stay with their current desktop computers.
Those who do move to virtual desktops will be able to use simpler, lightweight computers (perhaps Chromebooks, perhaps computers with "Windows in S mode") that run little more than the software necessary to access the virtual desktop. The physical desktop computer will be a "terminal" to the virtual desktop. The benefits for those users will be cheaper hardware, more reliable desktops, invisible backups, versioning of data files, and the ability to shift work from one lightweight desktop "terminal" to another.
Programming languages: More Python, less Perl
Perl was perhaps the first programming language to be designated a "scripting language". (It won the designation, although other languages such as Awk and Csh predate it.)
But Perl has fallen on hard times. Developers have left Perl for Python, and the "Perl 6" effort, delayed and poorly advertised, has now re-branded itself as "Raku" to allow Perl 5 to continue without the cloud of eventual shutdown. The change comes late, and I fear that many have abandoned Perl in favor of Python.
Ruby is in a similar situation, with Python appealing to many developers and interest in Ruby is waning.
Python is winning the "scripting race". Many schools teach it, and many experienced developers recommend it as a first language to learn. (I'm in that group.) It has good support with libraries, tools, and documentation. Microsoft supports it in "Visual Studio Code" and in "Visual Studio".
I expect Python to gain in popularity, and Perl and Ruby to decline.
Programming languages: Smaller languages
I expect to see a shift from object-oriented languages (Java, C#, and C++) to smaller scripting languages (Python and perhaps Ruby).
Object-oriented languages are effective for large, complex systems. They were just what we needed for the large, complex applications that ran on PCs and servers -- before cloud computing. With cloud computing, we build systems (large or small) out of services, and we strive to make services small. (A large application can built of many small services.)
Java, C#, and C++ can be used to build small services, but often Python and other languages can be a better fit. The "big" object-oriented languages carry a lot of baggage to make object-oriented programming work; the smaller languages carry less.
Two possible contenders for building services may be Swift and Visual Basic. Swift is relatively new, and still undergoing changes. Visual Basic has evolved through several generations and Microsoft may create a smaller, lighter version for services. (These are guesses; I have no indication from Apple or Microsoft that such projects are underway or even under consideration.)
Programming languages: Safer languages
The languages Rust and Go are getting a lot of attention. Both are compiled languages, letting one build fast and efficient applications.
Rust and Go may challenge C and C++ as the premiere languages for high-performance systems. C and C++ have had a good run, from the 1970s to today. But more and more, safety in programs is becoming important. The design of languages such as Rust and Go give them an advantage over C and C++.
C and C++ will stay with us, of course. Many large-scale and popular projects are written in them. I don't expect those projects to convert to Rust, Go, or any other language.
I do expect new projects to consider Rust and Go as candidate languages. I also expect projects to convert existing systems from their current technology (which could be COBOL, Fortran, or even C and C++) to think about Rust and Go.
Containers: Nice for deployment, little else
Containers were quite popular in the past year, and I expect that they will remain popular. They are convenient ways of deploying (or sharing with others) a complete application, all ready to go.
Containers offer no benefits beyond that, however, and they are helpful only to the people who must deploy applications. Therefore, containers, like virtual machines, will quietly move to the realm of sysadmins.
Development: better tech than ever
For the year 2020, the picture for development looks rather nice. We have capable languages (and lots of them); stable networks, servers, and operating systems; powerful tools for testing, deployment, and monitoring; and excellent tools for communication and collaboration. Problems in development will not be technical in nature -- which means that the challenges we face will be with people and interactions.
For developers (and project managers), I expect to see interest in collaboration tools. That includes the traditional tools such as version control, item tracking, and messaging tools such as Slack. We might see interest in new tools that have not been introduced as yet.
Summary
I see a bright future for development. We have good tools and good practices. The challenges will be people-oriented, not technology-oriented. Let's enjoy this year!
Wednesday, January 8, 2020
Tuesday, October 1, 2019
A World without Windows
Could Microsoft discontinue Windows? Is it possible that the future will see no Windows PCs?
Windows has been the key product for Microsoft. Or it was, in the 1990s and 2000s. Back then, Microsoft's was to provide everything, and have all Microsoft products connect. Windows was the platform. The Office suite was the set of common tools. Exchange provided directory and authentication services; Windows used it to log in users and Outlook used it to route e-mail and store organization calendars. SQL Server was the database, and also used by other tools such as Visual Studio and TFS.
That strategy worked in the days of networked computers. It doesn't work today, and Microsoft has changed its strategy. They moved away from the "Windows and everything for every user" strategy. They now offer cloud services and cloud-based applications. Microsoft is happy to sell virtual Windows servers from the cloud. They are also happy to sell virtual Linux servers.
Windows is an expensive effort. It requires a lot of design, development, testing, and support. Microsoft gets revenue from Windows licenses. Is the revenue from Windows worth the expense? Today, the answer is most likely "yes". But five years from now? Ten years from now? Will the revenue cover the expense?
I think of Windows as two similar but distinct products. The first is the Windows we know: an operating system that runs on PCs. This version of Windows not only hosts applications but also handles all of the hardware of the PC: memory, video, sound, USB ports, clocks and timers, keyboard, mouse, ... everything. Windows has a hardware abstraction layer with drivers for specific devices. The upper layers of Windows (memory management, task switching, processes, and application programs) doesn't worry much about the lower-levels. Upper-level functions use the hardware abstraction layer as an API to lower-level functions.
That set of lower-level functions is complex, and expensive to develop and maintain. (The upper-level functions are expensive, too.)
There is another Windows product, one that isn't used on PCs. Microsoft offers Windows in the cloud -- virtual servers and workstations. This Windows product runs the same applications as the "real" Windows that runs on PCs, but it has a very different lower level.
The lower-level functions for "real" Windows (the one on your PC) must contain code for thousands of devices, and perhaps more. There are many models of PCs, with different chip sets for audio, USB, video, and all of the other hardware bits of a computer. Microsoft does a pretty good job at making Windows work with current and old PCs. (I recently installed Windows 10 on an old laptop that initially had Windows Vista, and everything works except for the wi-fi connection.)
The story is different for the "virtual" Windows (the one that runs in the cloud). That version of Windows has the same upper-level functions, but the logic below the hardware abstract layer is just about non-existent. Data to and from devices doesn't go to the server; instead it gets routed to the client computer that is using the virtual computer. This second computer has the actual hardware -- the keyboard, the mouse, USB devices, audio devices, etc. Getting data to those devices is the responsibility of the client PC operating system.
If the virtual PC is running Windows and the client PC is running Windows, then Windows must talk to all of those devices. If not the virtual Windows PC, then the client Windows PC. With a Windows client, Windows must talk to the devices.
But is it necessary for the client to be Windows?
I think Microsoft is asking itself this very question.
Suppose that Microsoft were to drop the client part and focus on the virtual part of that configuration. Suppose Microsoft simply let the PC version of Windows die. What would happen?
For starters, Microsoft would lose the revenue from Windows licenses for "real" PCs. But it would also lose the expense of developing drivers and low-level functions. Keep in mind that there are lots of devices, and Microsoft has been very good at supporting them.
(Microsoft does a very good job of support, but they do not support every device that was ever made. Please don't complain to me because Microsoft doesn't support your ancient video card, or unusual disk drive, or odd-ball USB device.)
Why would Microsoft do that? Why would Microsoft walk away from all of that revenue? The answer is simple economics: Does the PC version of Windows pay for itself? Does the revenue from PC Windows cover the expense of hardware management? If it does, then there is an argument to keep providing Windows. If the revenue does not cover the expense... then the argument is to abandon that market.
It may be that Microsoft will keep support for real PCs, but a limited subset of hardware. (Perhaps only Microsoft's Surface tablets and laptops, or a limited subset of certified computers.) Such a world would be very different from today's land of PCs running Windows. Linux may step in and provide the client base for access to virtual PCs (be those virtual PCs Linux or Windows). Vendors such as Dell and Lenovo may develop their own operating systems, possibly based on Linux, and tuned to their hardware.
If Microsoft can successfully migrate a large percentage of application users (users of Office, Project, SQL Server, etc.) to their cloud-based virtual Windows desktops, then we might just see that new world.
Windows has been the key product for Microsoft. Or it was, in the 1990s and 2000s. Back then, Microsoft's was to provide everything, and have all Microsoft products connect. Windows was the platform. The Office suite was the set of common tools. Exchange provided directory and authentication services; Windows used it to log in users and Outlook used it to route e-mail and store organization calendars. SQL Server was the database, and also used by other tools such as Visual Studio and TFS.
That strategy worked in the days of networked computers. It doesn't work today, and Microsoft has changed its strategy. They moved away from the "Windows and everything for every user" strategy. They now offer cloud services and cloud-based applications. Microsoft is happy to sell virtual Windows servers from the cloud. They are also happy to sell virtual Linux servers.
Windows is an expensive effort. It requires a lot of design, development, testing, and support. Microsoft gets revenue from Windows licenses. Is the revenue from Windows worth the expense? Today, the answer is most likely "yes". But five years from now? Ten years from now? Will the revenue cover the expense?
I think of Windows as two similar but distinct products. The first is the Windows we know: an operating system that runs on PCs. This version of Windows not only hosts applications but also handles all of the hardware of the PC: memory, video, sound, USB ports, clocks and timers, keyboard, mouse, ... everything. Windows has a hardware abstraction layer with drivers for specific devices. The upper layers of Windows (memory management, task switching, processes, and application programs) doesn't worry much about the lower-levels. Upper-level functions use the hardware abstraction layer as an API to lower-level functions.
That set of lower-level functions is complex, and expensive to develop and maintain. (The upper-level functions are expensive, too.)
There is another Windows product, one that isn't used on PCs. Microsoft offers Windows in the cloud -- virtual servers and workstations. This Windows product runs the same applications as the "real" Windows that runs on PCs, but it has a very different lower level.
The lower-level functions for "real" Windows (the one on your PC) must contain code for thousands of devices, and perhaps more. There are many models of PCs, with different chip sets for audio, USB, video, and all of the other hardware bits of a computer. Microsoft does a pretty good job at making Windows work with current and old PCs. (I recently installed Windows 10 on an old laptop that initially had Windows Vista, and everything works except for the wi-fi connection.)
The story is different for the "virtual" Windows (the one that runs in the cloud). That version of Windows has the same upper-level functions, but the logic below the hardware abstract layer is just about non-existent. Data to and from devices doesn't go to the server; instead it gets routed to the client computer that is using the virtual computer. This second computer has the actual hardware -- the keyboard, the mouse, USB devices, audio devices, etc. Getting data to those devices is the responsibility of the client PC operating system.
If the virtual PC is running Windows and the client PC is running Windows, then Windows must talk to all of those devices. If not the virtual Windows PC, then the client Windows PC. With a Windows client, Windows must talk to the devices.
But is it necessary for the client to be Windows?
I think Microsoft is asking itself this very question.
Suppose that Microsoft were to drop the client part and focus on the virtual part of that configuration. Suppose Microsoft simply let the PC version of Windows die. What would happen?
For starters, Microsoft would lose the revenue from Windows licenses for "real" PCs. But it would also lose the expense of developing drivers and low-level functions. Keep in mind that there are lots of devices, and Microsoft has been very good at supporting them.
(Microsoft does a very good job of support, but they do not support every device that was ever made. Please don't complain to me because Microsoft doesn't support your ancient video card, or unusual disk drive, or odd-ball USB device.)
Why would Microsoft do that? Why would Microsoft walk away from all of that revenue? The answer is simple economics: Does the PC version of Windows pay for itself? Does the revenue from PC Windows cover the expense of hardware management? If it does, then there is an argument to keep providing Windows. If the revenue does not cover the expense... then the argument is to abandon that market.
It may be that Microsoft will keep support for real PCs, but a limited subset of hardware. (Perhaps only Microsoft's Surface tablets and laptops, or a limited subset of certified computers.) Such a world would be very different from today's land of PCs running Windows. Linux may step in and provide the client base for access to virtual PCs (be those virtual PCs Linux or Windows). Vendors such as Dell and Lenovo may develop their own operating systems, possibly based on Linux, and tuned to their hardware.
If Microsoft can successfully migrate a large percentage of application users (users of Office, Project, SQL Server, etc.) to their cloud-based virtual Windows desktops, then we might just see that new world.
Thursday, September 19, 2019
The PC Reverse Cambrian Explosion
The Cambrian Explosion is a term from archaeology. It describes a massive increase in the diversity of life that occurred half a billion of years ago. Life on earth went from a measly few thousands of species to hundreds of millions of species in the blink of a geologic eye.
Personal Computers have what I call a "PC Reverse Cambrian Explosion" or PC-RCE. It occurred in the mid-1980s, which some might consider to be half a billion year ago. In the PC-RCE, computers went from hundreds of different designs to one: the IBM PC compatible.
In the late 1970s and very early 1980s, there were lots of designs for small computers. These included the Apple II, the Radio Shack TRS-80, the Commodore PET and CBM machines, and others. There was a great diversity of hardware and software, including processors and operating systems. Some computers had floppy disks, although most did not. Many computers used cassette tape for storage, and some had neither cassette nor floppy disk. Some computers had built-in displays, and others required that you get your own terminal.
By the mid 1980s, that diversity was gone. The IBM PC was the winning design, and the market wanted that design and only that design. (Except for a few stubborn holdouts.)
One might think that the IBM PC caused the PC-RCE, but I think it was something else.
While the IBM PC was popular, other manufacturers could not simply start making compatible machines (or "clones" as they were later called). The hardware for the IBM PC was "open" in that the connectors and buss specification were documented, and this allowed manufacturers to make accessories for IBM PCs. But the software (the operating system and importantly the ROM BIOS) was not open. While both had documentation for the interfaces, they could not be copied without running afoul of copyright law.
Other computer manufacturers could not make IBM PC clones. Their choices were limited to 1) sell non-compatible PCs in a market and did not want them, or 2) go into another business.
Yet we now have many vendors of PCs. What happened?
The first part of the PC-RCE was the weakening of the non-IBM manufacturers. Most went out of business. (Apple survived, by offering compelling alternate designs and focussing on the education market.)
The second part was Microsoft's ability to sell MS-DOS to other manufacturers. It made custom versions for non-compatible hardware by Tandy, Victor, Zenith, and others. While "compatible with MS-DOS" wasn't the same as "compatible with the IBM PC", it allowed other manufacturers to use MS-DOS.
A near-empty market allowed upstart Compaq to introduce its Compaq portable, which was the first system not made by IBM and yet compatible with the IBM PC. It showed that there was a way to build IBM PC "compatibles" legally and profitably. Compaq was successful because it offered a product not available from IBM (a portable computer) that was also compatible (it ran popular software) and used premium components and designs to justify a hefty price tag. (Several thousand dollars at the time.)
The final piece was the Phoenix BIOS. This was the technology that allowed other manufacturers to build compatible PCs at low prices. Compaq had built their own BIOS, making it compatible with the API specified in IBM's documents, but it was an expensive investment. The Phoenix BIOS was available to all manufacturers, which let Phoenix amortize the cost over a larger number of PCs, for a lower per-unit cost.
The market maintained demand for the IBM PC design, but it wasn't fussy about the manufacturer. Customers bought "IBM compatible PCs" with delight. (Especially if the price was lower than IBM's.)
Those events (weakened suppliers, an operating system, a legal path forward, and the technology to execute it) made the PC the one and only design, and killed off the remaining designs. (Again, except for Apple. And Apple came close to extinction on several occasions.)
Now, this is all nice history, but what does it have to do with us folks living today?
The PC-RCE gave us a single design for PCs. That design has evolved over the decades, and just about every piece of the original IBM PC has mutated into something else, but the marketed PCs have remained uniform. At first, IBM specified the design, with the IBM PC, the IBM PC XT, and the IBM PC AT. Later, Microsoft specified the design with its "platform specification" for Windows. Microsoft could do this, due to its dominance of the market for operating systems and office software.
Today, the PC design is governed by various committees and standards organizations. They specify the design for things like the BIOS (or its replacement the UEFI), the power supply, and connectors for accessories. Individual companies have sway; Intel designs processors and support circuitry used in all PCs. Together, these organizations provide a single design which allows for modest variation among manufacturers.
That uniformity is starting to fracture.
Apple's computers joined the PC design in the mid-2000s. The "white MacBook" with an Intel processor was a PC design -- so much so that Windows and Linux can run on it. Yet today, Apple is moving their Macs and MacBooks in a direction different from the mainstream market. Apple-designed chips control certain parts of their computers, and these chips are not provided to other manufacturers. (Apple's iPhones and iPads are unique designs, with no connection to the PC design.)
Google is designing its Chromebooks and slowing moving them away from the "standard" PC design.
Microsoft is building Surface tablets and laptops with its proprietary designs, close to PCs yet not quite identical.
We are approaching a time when we won't think of PCs as completely interchangeable. Instead, we will think of them in terms of manufacturers: Apple PCs, Microsoft PCs, Google PCs, etc. There will still be a mainstream design; Dell and Lenovo and HP want to sell PCs.
The "design your own PC" game is for serious players. It requires a significant investment not only in hardware design but also in software. Apple has been playing that game all along. Microsoft and Google are big enough that they can join. Other companies may get involved, using Linux (or NetBSD as Apple did) as a base for their operating systems.
The market for PCs is fragmenting. In the future, I see a modest number of designs, not the thousands that we had in 1980. The designs will be similar but not identical, and more importantly, not compatible - at least for hardware.
A future with multiple hardware platforms will be a very different place. We have enjoyed a single (evolving) platform for the past four decades. A world with multiple, incompatible platforms will be a new experience for many. It will affect not only hardware designers, but everyone involved with PCs, from programmers to network administrators to purchasing agents. Software may follow the fragmentation, and we could see applications that run on one platform and not others.
A fragmented market will hold challenges. Once committed to one platform, it is hard to move to a different platform. (Just as it is difficult today to move from one operating system to another.) Instead of just the operating system, one will have to change the hardware, operating system, and possibly applications.
It may also be a challenge for Linux and open source software. They have used the common platform as a means of expansion. Will we see specific versions of Linux for specific platforms? Will Linux avoid some platforms as "too difficult" to implement? (The Apple MacBooks, with their extra chips for security, may be a challenge for Linux.)
The fragmentation I describe is a possible future -- its not here today. I wouldn't panic, but I wouldn't ignore it, either. Keep buying PCs, but keep your eyes on them.
Personal Computers have what I call a "PC Reverse Cambrian Explosion" or PC-RCE. It occurred in the mid-1980s, which some might consider to be half a billion year ago. In the PC-RCE, computers went from hundreds of different designs to one: the IBM PC compatible.
In the late 1970s and very early 1980s, there were lots of designs for small computers. These included the Apple II, the Radio Shack TRS-80, the Commodore PET and CBM machines, and others. There was a great diversity of hardware and software, including processors and operating systems. Some computers had floppy disks, although most did not. Many computers used cassette tape for storage, and some had neither cassette nor floppy disk. Some computers had built-in displays, and others required that you get your own terminal.
By the mid 1980s, that diversity was gone. The IBM PC was the winning design, and the market wanted that design and only that design. (Except for a few stubborn holdouts.)
One might think that the IBM PC caused the PC-RCE, but I think it was something else.
While the IBM PC was popular, other manufacturers could not simply start making compatible machines (or "clones" as they were later called). The hardware for the IBM PC was "open" in that the connectors and buss specification were documented, and this allowed manufacturers to make accessories for IBM PCs. But the software (the operating system and importantly the ROM BIOS) was not open. While both had documentation for the interfaces, they could not be copied without running afoul of copyright law.
Other computer manufacturers could not make IBM PC clones. Their choices were limited to 1) sell non-compatible PCs in a market and did not want them, or 2) go into another business.
Yet we now have many vendors of PCs. What happened?
The first part of the PC-RCE was the weakening of the non-IBM manufacturers. Most went out of business. (Apple survived, by offering compelling alternate designs and focussing on the education market.)
The second part was Microsoft's ability to sell MS-DOS to other manufacturers. It made custom versions for non-compatible hardware by Tandy, Victor, Zenith, and others. While "compatible with MS-DOS" wasn't the same as "compatible with the IBM PC", it allowed other manufacturers to use MS-DOS.
A near-empty market allowed upstart Compaq to introduce its Compaq portable, which was the first system not made by IBM and yet compatible with the IBM PC. It showed that there was a way to build IBM PC "compatibles" legally and profitably. Compaq was successful because it offered a product not available from IBM (a portable computer) that was also compatible (it ran popular software) and used premium components and designs to justify a hefty price tag. (Several thousand dollars at the time.)
The final piece was the Phoenix BIOS. This was the technology that allowed other manufacturers to build compatible PCs at low prices. Compaq had built their own BIOS, making it compatible with the API specified in IBM's documents, but it was an expensive investment. The Phoenix BIOS was available to all manufacturers, which let Phoenix amortize the cost over a larger number of PCs, for a lower per-unit cost.
The market maintained demand for the IBM PC design, but it wasn't fussy about the manufacturer. Customers bought "IBM compatible PCs" with delight. (Especially if the price was lower than IBM's.)
Those events (weakened suppliers, an operating system, a legal path forward, and the technology to execute it) made the PC the one and only design, and killed off the remaining designs. (Again, except for Apple. And Apple came close to extinction on several occasions.)
Now, this is all nice history, but what does it have to do with us folks living today?
The PC-RCE gave us a single design for PCs. That design has evolved over the decades, and just about every piece of the original IBM PC has mutated into something else, but the marketed PCs have remained uniform. At first, IBM specified the design, with the IBM PC, the IBM PC XT, and the IBM PC AT. Later, Microsoft specified the design with its "platform specification" for Windows. Microsoft could do this, due to its dominance of the market for operating systems and office software.
Today, the PC design is governed by various committees and standards organizations. They specify the design for things like the BIOS (or its replacement the UEFI), the power supply, and connectors for accessories. Individual companies have sway; Intel designs processors and support circuitry used in all PCs. Together, these organizations provide a single design which allows for modest variation among manufacturers.
That uniformity is starting to fracture.
Apple's computers joined the PC design in the mid-2000s. The "white MacBook" with an Intel processor was a PC design -- so much so that Windows and Linux can run on it. Yet today, Apple is moving their Macs and MacBooks in a direction different from the mainstream market. Apple-designed chips control certain parts of their computers, and these chips are not provided to other manufacturers. (Apple's iPhones and iPads are unique designs, with no connection to the PC design.)
Google is designing its Chromebooks and slowing moving them away from the "standard" PC design.
Microsoft is building Surface tablets and laptops with its proprietary designs, close to PCs yet not quite identical.
We are approaching a time when we won't think of PCs as completely interchangeable. Instead, we will think of them in terms of manufacturers: Apple PCs, Microsoft PCs, Google PCs, etc. There will still be a mainstream design; Dell and Lenovo and HP want to sell PCs.
The "design your own PC" game is for serious players. It requires a significant investment not only in hardware design but also in software. Apple has been playing that game all along. Microsoft and Google are big enough that they can join. Other companies may get involved, using Linux (or NetBSD as Apple did) as a base for their operating systems.
The market for PCs is fragmenting. In the future, I see a modest number of designs, not the thousands that we had in 1980. The designs will be similar but not identical, and more importantly, not compatible - at least for hardware.
A future with multiple hardware platforms will be a very different place. We have enjoyed a single (evolving) platform for the past four decades. A world with multiple, incompatible platforms will be a new experience for many. It will affect not only hardware designers, but everyone involved with PCs, from programmers to network administrators to purchasing agents. Software may follow the fragmentation, and we could see applications that run on one platform and not others.
A fragmented market will hold challenges. Once committed to one platform, it is hard to move to a different platform. (Just as it is difficult today to move from one operating system to another.) Instead of just the operating system, one will have to change the hardware, operating system, and possibly applications.
It may also be a challenge for Linux and open source software. They have used the common platform as a means of expansion. Will we see specific versions of Linux for specific platforms? Will Linux avoid some platforms as "too difficult" to implement? (The Apple MacBooks, with their extra chips for security, may be a challenge for Linux.)
The fragmentation I describe is a possible future -- its not here today. I wouldn't panic, but I wouldn't ignore it, either. Keep buying PCs, but keep your eyes on them.
Friday, September 13, 2019
Apple hardware has nowhere to go
Apple has long sold products based on advanced design.
But now Apple has a problem: there is very little space to advance. The iPhone is "done" -- it is as good as it is going to get. This week's announcements about new iPhones were, in brief, all about the cameras. There were some mentions about higher-resolution screens (better than "retina" resolution, which itself was as good as the human eye could resolve), longer battery life, and a new color (green).
The iPhone is not the only product that has little "runway".
The MacBook also has little room to grow. It is as good as a laptop can get, and competitors are just as good -- at least in terms of hardware. There is little advantage to the MacBook.
The Mac (the desktop) is a pricey device for the upper end of developers, and a far cry from a workstation for "the rest of us". But it, like the MacBook, is comparable to competing desktops. There is little advantage to the Mac.
Apple knows this. Their recent move into services (television and music) shows that it is better to invest in areas other than hardware.
But how to keep demand for those pricey Apple devices? Those shiny devices are how Apple makes money.
It is quite possible that Apple will limit their services to Apple devices. They may also limit the development tools for services to Apple devices (Macs and MacBooks with macOS). Consumers of Apple services (music, television) will have to use Apple devices. Developers of services for the Apple platform will have to use Apple devices.
Why would Apple do that? For the simple reason that they can charge premium prices for their hardware. Anyone who wants "in" to the Apple set of services will have to pay the entry fee.
It also separates Apple from the rest of computing, which carries its own risks. The mainstream platforms could move in a direction without Apple.
Apple has always maintained some distance from mainstream computing, which gives Apple the cachet of "different". Some distance is good, but too much distance puts Apple on their own "island of computing".
Being on one's own island is nice, while the tourists come. If the tourists stop visiting, then the island becomes a lonely place.
But now Apple has a problem: there is very little space to advance. The iPhone is "done" -- it is as good as it is going to get. This week's announcements about new iPhones were, in brief, all about the cameras. There were some mentions about higher-resolution screens (better than "retina" resolution, which itself was as good as the human eye could resolve), longer battery life, and a new color (green).
The iPhone is not the only product that has little "runway".
The MacBook also has little room to grow. It is as good as a laptop can get, and competitors are just as good -- at least in terms of hardware. There is little advantage to the MacBook.
The Mac (the desktop) is a pricey device for the upper end of developers, and a far cry from a workstation for "the rest of us". But it, like the MacBook, is comparable to competing desktops. There is little advantage to the Mac.
Apple knows this. Their recent move into services (television and music) shows that it is better to invest in areas other than hardware.
But how to keep demand for those pricey Apple devices? Those shiny devices are how Apple makes money.
It is quite possible that Apple will limit their services to Apple devices. They may also limit the development tools for services to Apple devices (Macs and MacBooks with macOS). Consumers of Apple services (music, television) will have to use Apple devices. Developers of services for the Apple platform will have to use Apple devices.
Why would Apple do that? For the simple reason that they can charge premium prices for their hardware. Anyone who wants "in" to the Apple set of services will have to pay the entry fee.
It also separates Apple from the rest of computing, which carries its own risks. The mainstream platforms could move in a direction without Apple.
Apple has always maintained some distance from mainstream computing, which gives Apple the cachet of "different". Some distance is good, but too much distance puts Apple on their own "island of computing".
Being on one's own island is nice, while the tourists come. If the tourists stop visiting, then the island becomes a lonely place.
Wednesday, September 4, 2019
Don't shoot me, I'm only the OO programming language!
There has been a lot of hate for object-oriented programming of late. I use the word "hate" with care, as others have described their emotions as such. After decades of success with object-oriented programming, now people are writing articles with titles like "I hate object-oriented programming".
Why such animosity towards object-oriented programming? And why now? I have some ideas.
First, we have the age of object-oriented programming (OOP) as the primary paradigm for programming. I put the acceptance of OOP somewhere after the introduction of Java (in 1995) and before Microsoft's C# and .NET initiative (in 1999), which makes OOP about 25 years old -- or one generation of programmers.
(I know that object-oriented programming was around much earlier than C# and Java, and I don't mean to imply that Java was the first object-oriented language. But Java was the first popular OOP language, the first OOP language that was widely accepted in the programming community.)
So it may be that the rejection of OOP is driven by generational forces. Object-oriented programming, for new programmers, has been around "forever" and is an old way of looking at code. OOP is not the shiny new thing; it is the dusty old thing.
Which leads to my second idea: What is the shiny new thing that replaces object-oriented programming? To answer that question, we have to answer another: what does OOP do for us?
Object-oriented programming, in brief, helps developers organize code. It is one of several techniques to organize code. Others include Structured Programming, subroutines, and functions.
Subroutines are possibly the oldest techniques to organize code. They date back to the days of assembly language, when code that was executed more than once was called with a "branch" or "call" or "jump subroutine" opcode. Instead of repeating code (and using precious memory), common code could be stored once and invoked as often as needed.
Functions date back to at least Fortran, consolidating common code that returns a value.
For two decades (from the mid 1950s to the mid-1970s), subroutines and functions were the only way to organize code. In the mid-1970s, the structured programming movement introduced an additional way to organize code, with IF/THEN/ELSE and WHILE statements (and an avoidance of GOTO). These techniques worked at a more granular level that subroutines and functions. Structured programming organized code "in the small" and subroutines and functions organized code "in the medium". Notice that we had no way (at the time) to organize code "in the large".
Techniques to organize code "in the large" did come. One attempt was dynamic-linked libraries (DLLs), introduced with Microsoft Windows but also used by earlier operating systems. Another was Microsoft's COM, which organized the DLLs. Neither were particularly effective at organizing code.
Object-oriented programming was effective at organizing code at a level higher than procedures and functions. And it has been successful for the past two-plus decades. OOP let programmers build large systems, sometimes with thousands of classes and millions of lines of code.
So what technique has arrived that displaces object-oriented programming? How has the computer world changed, that object-oriented programming would become despised?
I think it is cloud programming and web services, and specifically, microservices.
OOP lets us organize a large code base into classes (and namespaces which contain classes). The concept of a web service also lets us organize our code, in a level higher than procedures and functions. A web service can be a large thing, using OOP to organize its innards.
But a microservice is different from a large web service. A microservice is, by definition, small. A large system can be composed of multiple microservices, but each microservice must be a small component.
Microservices are small enough that they can be handled by a simple script (perhaps in Python or Ruby) that performs a few specific tasks and then exits. Small programs don't need classes and object-oriented programming. Object-oriented programming adds cost to simple programs with no corresponding benefit.
Programmers building microservices in languages such as Java or C# may feel that object-oriented programming is being forced upon them. Both Java and C# are object-oriented languages, and they mandate classes in your program. A simple "Hello, world!" program requires the definition of at least one class, with at least one static method.
Perhaps languages that are not object-oriented are better for microservices. Languages such as Python, Ruby, or even Perl. If performance is a concern, the compiled languages C and Go are available. (It might be that the recent interest in C is driven by the development of cloud applications and microservices for them.)
Object-oriented programming was (and still is) an effective way to manage code for large systems. With the advent of microservices, it is not the only way. Using object-oriented programming for microservices is overkill. OOP requires overhead that is not helpful for small programs; if your microservice is large enough to require OOP, then it isn't a microservice.
I think this is the reason for the recent animosity towards object-oriented programming. Programmers have figured out the OOP doesn't mix with microservices -- but they don't know why. They fell that something is wrong (which it is) but they don't have the ability to shake off the established programming practices and technologies (perhaps because they don't have the authority).
If you are working on a large system, and using microservices, give some thought to your programming language.
Why such animosity towards object-oriented programming? And why now? I have some ideas.
First, we have the age of object-oriented programming (OOP) as the primary paradigm for programming. I put the acceptance of OOP somewhere after the introduction of Java (in 1995) and before Microsoft's C# and .NET initiative (in 1999), which makes OOP about 25 years old -- or one generation of programmers.
(I know that object-oriented programming was around much earlier than C# and Java, and I don't mean to imply that Java was the first object-oriented language. But Java was the first popular OOP language, the first OOP language that was widely accepted in the programming community.)
So it may be that the rejection of OOP is driven by generational forces. Object-oriented programming, for new programmers, has been around "forever" and is an old way of looking at code. OOP is not the shiny new thing; it is the dusty old thing.
Which leads to my second idea: What is the shiny new thing that replaces object-oriented programming? To answer that question, we have to answer another: what does OOP do for us?
Object-oriented programming, in brief, helps developers organize code. It is one of several techniques to organize code. Others include Structured Programming, subroutines, and functions.
Subroutines are possibly the oldest techniques to organize code. They date back to the days of assembly language, when code that was executed more than once was called with a "branch" or "call" or "jump subroutine" opcode. Instead of repeating code (and using precious memory), common code could be stored once and invoked as often as needed.
Functions date back to at least Fortran, consolidating common code that returns a value.
For two decades (from the mid 1950s to the mid-1970s), subroutines and functions were the only way to organize code. In the mid-1970s, the structured programming movement introduced an additional way to organize code, with IF/THEN/ELSE and WHILE statements (and an avoidance of GOTO). These techniques worked at a more granular level that subroutines and functions. Structured programming organized code "in the small" and subroutines and functions organized code "in the medium". Notice that we had no way (at the time) to organize code "in the large".
Techniques to organize code "in the large" did come. One attempt was dynamic-linked libraries (DLLs), introduced with Microsoft Windows but also used by earlier operating systems. Another was Microsoft's COM, which organized the DLLs. Neither were particularly effective at organizing code.
Object-oriented programming was effective at organizing code at a level higher than procedures and functions. And it has been successful for the past two-plus decades. OOP let programmers build large systems, sometimes with thousands of classes and millions of lines of code.
So what technique has arrived that displaces object-oriented programming? How has the computer world changed, that object-oriented programming would become despised?
I think it is cloud programming and web services, and specifically, microservices.
OOP lets us organize a large code base into classes (and namespaces which contain classes). The concept of a web service also lets us organize our code, in a level higher than procedures and functions. A web service can be a large thing, using OOP to organize its innards.
But a microservice is different from a large web service. A microservice is, by definition, small. A large system can be composed of multiple microservices, but each microservice must be a small component.
Microservices are small enough that they can be handled by a simple script (perhaps in Python or Ruby) that performs a few specific tasks and then exits. Small programs don't need classes and object-oriented programming. Object-oriented programming adds cost to simple programs with no corresponding benefit.
Programmers building microservices in languages such as Java or C# may feel that object-oriented programming is being forced upon them. Both Java and C# are object-oriented languages, and they mandate classes in your program. A simple "Hello, world!" program requires the definition of at least one class, with at least one static method.
Perhaps languages that are not object-oriented are better for microservices. Languages such as Python, Ruby, or even Perl. If performance is a concern, the compiled languages C and Go are available. (It might be that the recent interest in C is driven by the development of cloud applications and microservices for them.)
Object-oriented programming was (and still is) an effective way to manage code for large systems. With the advent of microservices, it is not the only way. Using object-oriented programming for microservices is overkill. OOP requires overhead that is not helpful for small programs; if your microservice is large enough to require OOP, then it isn't a microservice.
I think this is the reason for the recent animosity towards object-oriented programming. Programmers have figured out the OOP doesn't mix with microservices -- but they don't know why. They fell that something is wrong (which it is) but they don't have the ability to shake off the established programming practices and technologies (perhaps because they don't have the authority).
If you are working on a large system, and using microservices, give some thought to your programming language.
Wednesday, August 28, 2019
Show me the optimizations!
Compilers have gotten good at optimizing code. So good, in fact, that we programmers take optimizations as granted. I don't object to optimizations, but I do think we need to re-think the opaqueness of them.
Optimizations are, in general, good things. They are changes to the code to make it faster and more efficient, while keeping the same functionality. Many times, they are changes that seem small.
For example, the code:
a = f(r * 4 + k)
b = g(r * 4 + k)
can be optimized to
t1 = r * 4 + k
a = f(t1)
b = g(t1)
The common expression r * 4 + k can be performed once, not twice, which reduces the time to execute. (It does require space to store the result, so this optimization is really a trade-off between time and space. Also, it assumes that r and k remain unchanged between calls to f() and g().)
Another example:
for i = 1 to 40
a[i] = r * 4 + k
which can be optimized to:
t1 = r * 4 + k
for i = 1 to 40
a[i] = t1
In this example, the operation r * 4 + k is repeated inside the loop, yet it does not change from iteration to iteration. (It is invariant during the loop.) The optimization moves the calculation outside the loop, which means it is calculated only once.
These are two simple examples. Compilers have made these optimizations for years, if not decades. Today's compilers are much better at optimizing code.
I am less concerned with the number of optimizations, and the types of optimizations, and more concerned with the optimizations themselves.
I would like to see the optimizations.
Optimizations are changes, and I would like to see the changes that the compiler makes to the code.
I would like to see how my code is revised to improve performance.
I know of no compiler that reports the optimizations it makes. Not Microsoft's compilers, not Intel's, not open source. None. And I am not satisfied with that. I want to see the optimizations.
Why do I want to see the optimizations?
First, I want to see how to improve my code. The above examples are trivial, yet instructive. (And I have, at times, written the un-optimized versions of those programs, although on a larger scale and with more variables and calculations to worry about.) Seeing the improvements to the code helps me become a better developer.
Second, I want to see what the compiler is doing. It may be making assumptions that are not true, possibly due to my failure to annotate variables and functions properly. I want to correct those failures.
Third, when reviewing code with other developers, I think we should review not only the original code but also the optimized code. The optimizations may give us insight into our code and data.
It is quite possible that future compilers will provide information about their optimizations. Compilers are sophisticated tools, and they do more than simply convert source code into executable bytes. It is time for them to provide more information to us, the programmers.
Optimizations are, in general, good things. They are changes to the code to make it faster and more efficient, while keeping the same functionality. Many times, they are changes that seem small.
For example, the code:
a = f(r * 4 + k)
b = g(r * 4 + k)
can be optimized to
t1 = r * 4 + k
a = f(t1)
b = g(t1)
The common expression r * 4 + k can be performed once, not twice, which reduces the time to execute. (It does require space to store the result, so this optimization is really a trade-off between time and space. Also, it assumes that r and k remain unchanged between calls to f() and g().)
Another example:
for i = 1 to 40
a[i] = r * 4 + k
which can be optimized to:
t1 = r * 4 + k
for i = 1 to 40
a[i] = t1
In this example, the operation r * 4 + k is repeated inside the loop, yet it does not change from iteration to iteration. (It is invariant during the loop.) The optimization moves the calculation outside the loop, which means it is calculated only once.
These are two simple examples. Compilers have made these optimizations for years, if not decades. Today's compilers are much better at optimizing code.
I am less concerned with the number of optimizations, and the types of optimizations, and more concerned with the optimizations themselves.
I would like to see the optimizations.
Optimizations are changes, and I would like to see the changes that the compiler makes to the code.
I would like to see how my code is revised to improve performance.
I know of no compiler that reports the optimizations it makes. Not Microsoft's compilers, not Intel's, not open source. None. And I am not satisfied with that. I want to see the optimizations.
Why do I want to see the optimizations?
First, I want to see how to improve my code. The above examples are trivial, yet instructive. (And I have, at times, written the un-optimized versions of those programs, although on a larger scale and with more variables and calculations to worry about.) Seeing the improvements to the code helps me become a better developer.
Second, I want to see what the compiler is doing. It may be making assumptions that are not true, possibly due to my failure to annotate variables and functions properly. I want to correct those failures.
Third, when reviewing code with other developers, I think we should review not only the original code but also the optimized code. The optimizations may give us insight into our code and data.
It is quite possible that future compilers will provide information about their optimizations. Compilers are sophisticated tools, and they do more than simply convert source code into executable bytes. It is time for them to provide more information to us, the programmers.
Monday, August 19, 2019
The Museum Principle for programming
Programming languages have, as one of their features, variables. A variable is a thing that holds a value and that value can vary over time. A simple example:
The statement
a = 1
defines a variable named 'a' and assigns a value of 1. Later, the program may contain the statement
a = 2
which changes the value from 1 to 2.
The exact operations vary from language to language. In C and C++, the name is closely associated with the underlying memory for the value. Python and Ruby separate the name from the underlying memory, which means that the name can be re-assigned to point to a different underlying value. In C and C++, the names cannot be changed in that manner. But that distinction has little to do with this discussion. Read on.
Some languages have the notion of constants. A constant is a thing that holds a value and that value cannot change over time. It remains constant. C, C++, and Pascal have this notion. In C, a program can contain the statement
const int a = 1;
A later statement that attempts to change the value of 'a' will cause a compiler error. Python and Ruby have no such notion.
Note that I am referring to constants, not literals such as '1' or '3.14' that appear in the code. These are truly constant and cannot be assigned new values. Some early language implementations did allow such behavior. It was never popular.
The notion of 'constness' is useful. It allows the compiler to optimize the code for certain operations. When applied to a parameter of a function, it informs the programmer that he cannot change the value. In C++, a function of a class can be declared 'const' and then that function cannot modify member variables. (I find this capability helpful to organize code and separate functions that change an object from functions that do not.)
The notion of 'constness' is a specific form of a more general concept, one that we programmers tend to not think about. That concept is 'read but don't write', or 'look but don't touch'. Or as I like to think of it, the "Museum Principle".
The Museum Principle states that you can observe the value of a variable, but you cannot change it. This principle is different from 'constness', which states that the value of a variable cannot (and will not) change. The two are close but not identical. The Museum Principle allows the variable to change; but you (or your code) are not making the change.
It may surprise readers to learn that the Museum Principle has been used already, and for quite a long time.
The idea of "look but don't touch" is implemented in Fortran and Pascal, in loop constructs. In these languages, a loop has an index value. The index value is set to an initial value and later modified for each iteration of the loop. Here are some examples that print the numbers from 1 to 10:
An example in Fortran:
do 100 i = 1, 10
write(*,*) 'i =', i
100 continue
An example in Pascal:
for i:= 1 to 10 do
begin
writeln('i =', i)
end;
In both of these loops, the variable i is initialized to the value 1 and incremented by 1 until it reaches the value 10. The body of each loop prints the value of i.
Now here is where the Museum Principle comes into play: In both Fortran and Pascal, you cannot change the value of i within the loop.
That is, the following code is illegal and will not compile:
In Fortran:
do 100 i = 1, 10
i = 20
write(*,*) 'i =', i
100 continue
In Pascal:
for i:= 1 to 10 do
begin
i := 20
writeln('i =', i)
end;
The highlighted lines are not permitted. It is part of the specification for both Fortran and Pascal that the loop index is not to be assigned. (Early versions of Fortran and Pascal guaranteed this behavior. Later versions of the languages, which allowed aliases via pointers, could not.)
Compare this to a similar loop in C or C++:
for (unsigned int i = 1; i <= 10; i++)
{
printf("%d\n", i);
}
The specifications for the C and C++ languages have no such restriction on loop indexes. (In fact, C and C++ do not have the notion of a loop index; they merely allow a variable to be declared and assigned at the beginning of the loop.)
The following code is legal in C and C++ (and does what you expect):
for (unsigned int i = 1; i <= 10; i++)
{
i = 20;
printf("%d\n", i);
}
My point here is not to say that Fortran and Pascal are superior to C and C++ (or that C and C++ are superior to Fortran and Pascal). My point is to show that the Museum Principle is useful.
Preventing changes to a loop index variable is the Museum Principle. The programmer can see the value of the variable, and the value does change, but the programmer cannot change the value. The programmer is constrained.
Some might chafe at the idea of such a restraint. Many have complained about the restrictions of Pascal and lauded the freedom of C. Yet over time, modern languages have implemented the restraints of Pascal, such as bounds-checking and type conversion.
Modern languages often eliminate loop index variables, by providing "for-each" loops that iterate over a collection. This feature is a stronger form of the "look but don't touch" restriction on loop index variables. One cannot complain about Fortran's limitations of loop index variables, unless one also dislikes the 'for-each' construct. A for-each iterator has a loop index, invisible (and untouchable!) inside.
For the "normal" loop (in which the index variable is not modified), there is no benefit from a prohibition of change to the index variable. (The programmer makes no attempt to change it.) It is the unusual loops, the loops which have extra logic for special cases, that benefit. Changing the loop index value is a shortcut, often serving a purpose that is not clear (and many times not documented). Preventing that short-cut forces the programmer to use code that is more explicit. A hassle in the short term, but better in the long term.
Constraints -- the right type of constraints -- are useful to programmers. The "structured programming" method was all about constraints for control structures (loops and conditionals) and the prohibition of "goto" operations. Programmers at the time complained, but looking back we can see that it was the right thing to do.
Constraints on loop index variables are also the right thing to do. Applying the Museum Principle to loop index variables will improve code and reduce errors.
The statement
a = 1
defines a variable named 'a' and assigns a value of 1. Later, the program may contain the statement
a = 2
which changes the value from 1 to 2.
The exact operations vary from language to language. In C and C++, the name is closely associated with the underlying memory for the value. Python and Ruby separate the name from the underlying memory, which means that the name can be re-assigned to point to a different underlying value. In C and C++, the names cannot be changed in that manner. But that distinction has little to do with this discussion. Read on.
Some languages have the notion of constants. A constant is a thing that holds a value and that value cannot change over time. It remains constant. C, C++, and Pascal have this notion. In C, a program can contain the statement
const int a = 1;
A later statement that attempts to change the value of 'a' will cause a compiler error. Python and Ruby have no such notion.
Note that I am referring to constants, not literals such as '1' or '3.14' that appear in the code. These are truly constant and cannot be assigned new values. Some early language implementations did allow such behavior. It was never popular.
The notion of 'constness' is useful. It allows the compiler to optimize the code for certain operations. When applied to a parameter of a function, it informs the programmer that he cannot change the value. In C++, a function of a class can be declared 'const' and then that function cannot modify member variables. (I find this capability helpful to organize code and separate functions that change an object from functions that do not.)
The notion of 'constness' is a specific form of a more general concept, one that we programmers tend to not think about. That concept is 'read but don't write', or 'look but don't touch'. Or as I like to think of it, the "Museum Principle".
The Museum Principle states that you can observe the value of a variable, but you cannot change it. This principle is different from 'constness', which states that the value of a variable cannot (and will not) change. The two are close but not identical. The Museum Principle allows the variable to change; but you (or your code) are not making the change.
It may surprise readers to learn that the Museum Principle has been used already, and for quite a long time.
The idea of "look but don't touch" is implemented in Fortran and Pascal, in loop constructs. In these languages, a loop has an index value. The index value is set to an initial value and later modified for each iteration of the loop. Here are some examples that print the numbers from 1 to 10:
An example in Fortran:
do 100 i = 1, 10
write(*,*) 'i =', i
100 continue
An example in Pascal:
for i:= 1 to 10 do
begin
writeln('i =', i)
end;
In both of these loops, the variable i is initialized to the value 1 and incremented by 1 until it reaches the value 10. The body of each loop prints the value of i.
Now here is where the Museum Principle comes into play: In both Fortran and Pascal, you cannot change the value of i within the loop.
That is, the following code is illegal and will not compile:
In Fortran:
do 100 i = 1, 10
i = 20
write(*,*) 'i =', i
100 continue
In Pascal:
for i:= 1 to 10 do
begin
i := 20
writeln('i =', i)
end;
The highlighted lines are not permitted. It is part of the specification for both Fortran and Pascal that the loop index is not to be assigned. (Early versions of Fortran and Pascal guaranteed this behavior. Later versions of the languages, which allowed aliases via pointers, could not.)
Compare this to a similar loop in C or C++:
for (unsigned int i = 1; i <= 10; i++)
{
printf("%d\n", i);
}
The specifications for the C and C++ languages have no such restriction on loop indexes. (In fact, C and C++ do not have the notion of a loop index; they merely allow a variable to be declared and assigned at the beginning of the loop.)
The following code is legal in C and C++ (and does what you expect):
for (unsigned int i = 1; i <= 10; i++)
{
i = 20;
printf("%d\n", i);
}
My point here is not to say that Fortran and Pascal are superior to C and C++ (or that C and C++ are superior to Fortran and Pascal). My point is to show that the Museum Principle is useful.
Preventing changes to a loop index variable is the Museum Principle. The programmer can see the value of the variable, and the value does change, but the programmer cannot change the value. The programmer is constrained.
Some might chafe at the idea of such a restraint. Many have complained about the restrictions of Pascal and lauded the freedom of C. Yet over time, modern languages have implemented the restraints of Pascal, such as bounds-checking and type conversion.
Modern languages often eliminate loop index variables, by providing "for-each" loops that iterate over a collection. This feature is a stronger form of the "look but don't touch" restriction on loop index variables. One cannot complain about Fortran's limitations of loop index variables, unless one also dislikes the 'for-each' construct. A for-each iterator has a loop index, invisible (and untouchable!) inside.
For the "normal" loop (in which the index variable is not modified), there is no benefit from a prohibition of change to the index variable. (The programmer makes no attempt to change it.) It is the unusual loops, the loops which have extra logic for special cases, that benefit. Changing the loop index value is a shortcut, often serving a purpose that is not clear (and many times not documented). Preventing that short-cut forces the programmer to use code that is more explicit. A hassle in the short term, but better in the long term.
Constraints -- the right type of constraints -- are useful to programmers. The "structured programming" method was all about constraints for control structures (loops and conditionals) and the prohibition of "goto" operations. Programmers at the time complained, but looking back we can see that it was the right thing to do.
Constraints on loop index variables are also the right thing to do. Applying the Museum Principle to loop index variables will improve code and reduce errors.
Labels:
constraints,
Fortran,
loops,
Museum Principle,
Pascal,
structured code
Subscribe to:
Posts (Atom)