Having been writing software since the days of CPM (and before), I can appreciate how far computers have come. If anyone thinks an Atom CPU is slow, try writing software for the Commodore 64 with a CPU which was only 1 mhz in speed. Yet despite all the changes in computers over the years, to me, it is still just a matter of working with bits and bytes. ASCII text are just bytes. Numbers are just bytes. Graphics is simply moving a lot of bytes around really fast. I know, that sounds a bit over simplistic, but it leads to a point.
In the old days, operating systems were simply a set of APIs which encapsulated basic functionality one could build upon. They provided access to the hardware (i.e., keyboard, mouse, screen). They provided basic user interface elements (anyone remember Geos for the Commodore 64). They were the building blocks of which software was based. Even Windows from the days of 16 bit Windows was simply a set of APIs which you could build upon.
Something changed though over the years. Object oriented programming took over and it wasn’t enough to just use it to build higher level abstractions on top of the operating system, but it began to take the place of simple APIs in the core of operating systems. I believe that object oriented programming may be at the core of what makes operating systems and software too complex so that each new generation requires more and more powerful hardware just to keep up.
While I appreciate the goals of OOP, such as code reuse, I am not so sure that it really accomplishes what it was intended to solve. What can make software and even an operating system powerful is simplicity, not complexity. Just for a moment, consider the inherent complexity of OOP. Just ask someone to explain the meaning of common terms of OOP and you quickly find that which was supposed to be simple is actually an overly complex concept. For example, was it abstraction?
Just do a Google search to find the answer and rather than a clear cut answer, one finds that there really isn’t a clear definition. Here is one discussion where someone asks this question and just take a look at the variety of answers he gets.
Now, define something like subroutine or function. Not too difficult, is it. Subroutines and functions are the simplest constructs of reusable code. Early APIs were simply a set of prewritten subroutines or functions of which software could build upon. Need a font ? Call a simple operating system API like
CreateFont and you get an index (or handle) to an available font. What could be simpler ?
Now, some may feel the objects are the necessary higher level constructs of which modern software must be built upon, but is this true? I don’t think so. Why do I say that? Because as a developer of tools for programmers, my job is to design higher level constructs to make programming easier for other programmers and after spending ten years building a GUI engine (in its fifth generation now), I have come to the conclusion that one can build high level GUI libraries without object oriented programming and guess what happens when you do? You get smaller, less resource hungry software.
Yes, with so much emphasis today on mobile platforms, we need smaller, less resource hungry software. So how can one provide the higher level functionality that programmers require, without using object oriented programming?
The Three Tiered Building Block Approach
Have you ever played with Lego blocks? The amazing thing about Legos is that with a good assortment of different blocks, one can build an almost unlimited variety of models. The blocks come in different degrees of complexity from just rectangular blocks to wheels, windows, etc. Most blocks are totally reusable too.
Building software, even an operating system, can be done in a similar fashion. The difference with software though is that the less complex building blocks can be used to build the more complex blocks for the ultimate in code reusability. I will refer to this as a “three tiered” design. What is that?
Basically the three tiers are:
- Low level functions (or subroutines)
- Medium level functions (or subroutines)
- High level functions (or subroutines)
All operating systems must have some low level functionality to build upon and one can build an API to provide the lowest level of functionality available to all software that runs on it. Some may feel that one must build this functionality upon objects, but it need not be so. True, data types which the core operating system (even higher level apps too) will use to track tasks may need some structure, but simple types or structures which most programming languages provide is sufficient for this. The core set of APIs can be very low level. Low level functions should be of a single task nature, for example, create me a font or a drawing brush.
The next step is to build the medium level APIs, which are built upon the low level APIs. Medium level APIs will combine multiple tasks together to provide more complex user interface features. For example in Windows, if I wanted to prepare a drawing surface (a memory DC with a bitmap selected into it), it requires multiple steps (create a DC, create a bitmap, select a bitmap into the DC). Yet, the Windows API doesn’t provide this functionality in a simple API. It should have though (and that is the kind of thing I write into my GUI libraries). It is this medium design which may be lacking in operating systems. By building even more complex user interface features into this medium level, it provides programmers with even more choices and makes software development faster.
Lastly, with an extensive medium level set of APIs (which builds upon the low level), now we can start building the higher level APIs. High level APIs should provide functionality which would have taken hundreds of lines of low level or dozens of lines of medium level code. The more extensive the low level and medium level APIs are, the more high level APIs can be created.
By using a procedural based approach using such a three tiered system, I strongly believe that operating systems could be designed to be simpler, faster and smaller, which is exactly what we need today for our mobile platforms.
Does this approach work?
Yes it does. While I don’t develop operating systems, I do develop GUI engines that sit on top of the operating system. To me, the WIN32 APIs are the low level functions I build upon and my job is to build the medium level and high level constructs on top. By using this three tiered approach with purely procedural style coding (APIs upon APIs) and avoiding the use of objects, I find I can software with an amazingly small footprint which requires minimal hardware resources. I design software with the mindset of “write it so it can fit on a floppy disk”. Ok, we don’t use floppies anymore, but you can get the picture. Small is beautiful and efficient!
There are a number of open source operating systems in development and likely more coming. But has anyone ever considered this more simplistic approach? If they did, I would not be surprised to someday see small tablets which are super thin and with multiple days of battery life, but are full blown computers rather than simply an ebook. The three tiered approach lends itself to the “smaller, faster” goal which Bob Zale (creator of TurboBasic and PowerBasic) always encouraged. Maybe those old timers knew something which today's programmers haven’t learned yet. While I am not saying that OOP should never be used, the above three tier approach could lead to faster, smaller operating systems and software.