The last decade has seen object oriented programming (OOP) dominate the programming world. While there is no doubt that there are benefits of OOP, some programmers question whether OOP has been overrated and ponder whether alternate styles of coding are worth pursuing. To even suggest that OOP has in some way failed to produce the quality software we all desire could in some instances cost a programmer his job, so why even ask the question?
Quality software is the goal.
Likely all programmers can agree that we all want to produce quality software. We would like to be able to produce software faster, make it more reliable and improve its performance. So with such goals in mind, shouldn’t we be willing to at least consider all possibilities? Also it is reasonable to conclude that no single tool can match all situations. For example, while few programmers today would even consider using assembler, there are times when low level coding such as assembler could be warranted. The old adage applies “the right tool for the job”. So it is fair to pose the question, “Has OOP been overused to the point of trying to make it some kind of universal tool, even when it may not fit a job very well?”
Others are asking the same question.
I won’t go into detail about what others have said about object oriented programming, but I will simply post some links to some interesting comments by others about OOP.
- Richard Mansfield
- Intel Blog: by Asaf Shelly
- Usenix article: by Stephen C. Johnson (Melismatic Software)
- Department of Computer. Science and IT, University of Jammu
An aspect which may be overlooked.
I have watched a number of videos online and read a number of articles by programmers about different concepts in programming. When OOP is discussed, they talk about things like modeling the real world, abstractions and many complex concepts. But two things are often missing in such discussions, which I will discuss here. These two aspects greatly affect programming, but may not be discussed.
First is, what is programming really? Programming is a method of using some kind of human readable language to generate machine code (or scripts eventually read by machine code) so one can make a computer do a task. Looking back at all the years I have been programming, the most profound thing I have ever learned about programming was machine language. Seeing what a CPU is actually doing with our programs provides a great deal of insight. It helps one understand why integer arithmetic is so much faster than floating point. It helps one understand what graphics is really all about (simply the moving around a lot of pixels or blocks of four bytes). It helps one understand what a procedure really must do to have parameters passed. It helps one understand why a string is simply a a block of bytes (or double bytes for unicode). It helps one understand why we use bytes so much and what bit flags are and what pointers are.
When one looks at OOP from the perspective of machine code and all the work a compiler must do to convert things like classes and objects into something the machine can work with, then one very quickly begins to see that OOP adds significant overhead to an application. Also if a programmer comes from a background of working with assembler, where keeping things simple is critical to writing maintainable code, one may wonder if OOP is improving coding or making it more complicated.
Second is the often said rule of “keep it simple”. This applies to programming. Consider classic Visual Basic. One of the reasons it was so popular was that it was so simple compared to other languages, say C for example. I know what is involved in writing a pure old fashioned WIN32 application using the Windows API and it is not simple, nor is it intuitive. Visual Basic took much of that complexity and made it simple. Now Visual Basic was sort of OOP based, but actually mostly in the GUI command set. One could actually write all the rest of the code using purely procedural style code and likely many did just that. I would venture to say that when Visual Basic went the way of .NET, it left behind many programmers who simply wanted to keep it simple. Not that they were poor programmers who didn’t want to learn something new, but that they knew the value of simple and taking that away took away a core aspect of their programming mindset.
Another aspect of simple is also seen in the syntax of some programming languages. For example, BASIC has stood the test of time and continues to be the language of choice for many hobby programmers. If you don’t think that BASIC is still alive and well, take a look at this extensive list of different BASIC programming languages.
While some of these BASICs are object oriented, many of them are also procedural in nature. But the key here is simplicity. Natural readable code.
Simple and low level can work together.
Now consider this. What happens when you combine a simple language with the power of machine language? You get something very powerful. For example, I write some very complex code using purely procedural style coding, using BASIC, but you may be surprised that my appreciation for machine language (or assembler) also comes to the fore. For example, I use the BASIC language GOTO and GOSUB. How some would cringe to hear this. But these constructs are native to machine language and very useful, so when used properly they are powerful even in a high level language. Another example is that I like to use pointers a lot. Oh how powerful pointers are. In BASIC, I can create variable length strings (which are simply a block of bytes) and I can embed complex data structures into those strings by using pointers. In BASIC, I use the DIM AT command, which allows me to dimension an array of any fixed data type or structure within a block of memory, which in this case happens to be a string.
Appreciating machine code also affects my view of performance. Every CPU cycle counts. This is one reason I use BASICs GOSUB command. It allows me to write some reusable code within a procedure, without the need to call an external routine and pass parameters. The performance improvement is significant. Performance also affects how I view a problem. While I want code to be simple, I also want it to run as fast as possible, so amazingly some of the best performance tips have to do with keeping code simple, with minimal overhead and also understanding what the machine code must accomplish to do what I have written in a higher level language. For example, in BASIC I have a number of options for the
SELECT CASE structure. One option can optimize the code using jump tables (compiler handles this), one option can optimize if the values are only Integers or DWords. But even then the compiler can only do so much. What happens if a large
SELECT CASE has to compare dozens and dozens of string constants to a variable length string being tested ? If this code is part of a parser, then it really can slow things down. I had this problem in a scripting language I created for an OpenGL based 3D custom control. The 3D scripting language is text based and has to be interpreted to generate 3D OpenGL calls internally. I didn’t want the scripting language to bog things down. So what would I do ?
The solution was simple and appreciating how the compiled machine code would have to compare so many bytes in so many string constants, one quickly realized that the compiler alone could not solve this. I had to think like I was an assembler programmer, but still use a high level language. The solution was so simple, it was surprising. I could use a pointer to read the first byte of the string being parsed. Since the first character would always be a letter in the scripting language, this meant there were 26 possible outcomes. The
SELECT CASE simply tested for the first character value (converted to a number) which would execute fast. Then for each letter (A,B,C, …) I would only compare the parsed word to the scripting language keywords which started with that letter. This in essence improved speed by 26 fold (or better). I was breaking down a complex task into 26 smaller tasks.
The fastest solutions are often very simple to code. No complex classes needed here. Just a simple procedure to read through a text string using the simplest logic I could find. The procedure is a little more complex than what I describe, but this is the core logic of the routine. Simple solved the problem.
From experience, I have found that a purely procedural style of coding, using a language which is natural and simple (BASIC), while using constructs of the language which are closer to pure machine (or assembler) in that language produces smaller and faster applications which are also easier to maintain.
Now I am not saying that all OOP is bad. Nor am I saying that OOP never has a place in programming. What I am saying though is that it is worth considering the possibility that OOP is not always the best solution and that there are other choices.