Beyond Java - Bruce Tate [12]
In the late 1970s and into the 1980s, APIs for things like presentation systems began to organize the interfaces into logical actions, called events, around objects, like windows and controls.
In 1980, the United States Department of Defense commissioned the Ada programming language, which offered some of the features of OOP, like encapsulation and inheritance.
Companies like IBM and Microsoft delivered toolkits to let their users express object-oriented ideas in procedural languages. The most notable were IBM's System Object Model and Microsoft's Component Object Model.
C++ let C developers use C procedurally, and also develop object-oriented applications, side by side.
Java was invented, combining many of the inventions along the way.
Figure 2-1. This timeline shows the slow commercial acceptance of object-oriented programming
Unfortunately, C++ came with its own sorts of problems.
The C++ Experience
As programmers wrestled with OOP, they also dealt with issues related to their chosen language . Visual Basic developers began to understand that the language and environment may be simple, but it is prone to poor performance and poor designs, leaving customers stranded with slow applications that they could not extend or maintain.
In C++, server-side developers found performance, but discovered another challenge. They did application development using a systems programming language. New terminology like memory-stompers and DLL Hell gave testament to the frustration of the masses. Simple problems dogged them.
Pointer Arithmetic
With C++, a pointer could point to any block of memory, regardless of whether it was the intention of the programmer. For example, consider the simple program in Example 2-1. It moves a block of memory from one location to another, and inverts it. Unfortunately, the example is off by 1. The code touches memory one byte beyond the from block. You would probably not see the error right away. You'd see it later, when you tried to manage the memory of this block, or another one. C and C++ compilers often manage memory with a linked list, and the pointers to the next block in the list sit just outside the allocated blocks! These types of errors hurt systems developers, and absolutely murdered applications developers, who didn't have the background to effectively troubleshoot these types of problems. Reliability also suffered.
Example 2-1. Move and invert a block of memory
// move and invert from_block into to_block with size size
int i;
for(i=0; i } Nested Includes The problem goes something like this. In C++, you specify interfaces to your methods, with other supporting information, in a header file, or .h file. For example, in MySQL, you have a main include file that has these includes (I've omitted most of the code for brevity): #ifndef _global_h /* If not standard header */ #include ... #include ... #ifdef _ _LCC_ _ #include #endif ... #include "mysql_com.h" #include "mysql_version.h" That doesn't look so bad, until you consider that some of these includes are compiled conditionally, so you really must know which compiler directives are set before you can decide definitively whether something gets included. Also, one of your include files might include another include file, like this line in mysql_version.h: #include In truth, this MySQL tree goes only three levels deep. It's an excellent example of how to code enterprise software in C++. It's not usually this easy. Any dependency will have an include file, and if that code also has dependencies, you'll have to make sure those include files and their associated libraries get installed
One of my most vivid and frustrating memories from working with IBM came from porting a C++ application that had include files nested 37 layers deep. It can be a very difficult problem to manage, especially for inexperienced developers.