Saturday, September 10, 2005

Design in C++, code in C

When I came fresh out of college, I was a huge fan of C language. Actually, to be frank, I was in love with C. I had the attitude of discouraging Java programmers in college (this attitude is still there and I will justify it in some other post). Not much emphasis was there on C++ in my college and nobody bothered to learn C++. I just wrote a few programs in C++ because I was learning Qt GUI toolkit. Apart from that, I never thought seriously about C++. But things have changed since then, and now I feel much better while using C++.

What's the big deal about learning OO stuff and languages like C++? To answer that question I am providing an example from own experience during the college days. In my 1st year, I used to work on VT100 terminals in a computer lab, and there I was inspired by text based programs like PICO and PINE available on Unix machines there. There was no GUI and we were alien to the Windows world.

I felt a striking difference between these programs like PINE and the ones I used write during C assignments. My C assignments used the C standard I/O library, but looking at those PINE programs I felt that they didn't use this C stdio. They had menus and each key press was followed by some response on the screen. I did not have to press ENTER key to get a response. I learnt enough of Unix and terminal I/O stuff in the coming years, so that I could finally manage writing programs which responded to single key presses. But that wasn't enough for me. I still wanted the look and feel of text based menus. I figured out a way to do this.

I reasoned that I should scan for single key presses in a while loop and process each key input. So I used a switch/case mechanism to handle each key input. The idea was to draw the screen after each key press. Each key press changed some parameters (say, index of the menu item to be highlighted) and the screen was redrawn based on those parameters. Initially I had only one menu. And the parameter needed for its drawing was the index of current menu item. Then I tried displaying two menus. This required two indexes and another variable to indicate which of the menus was active. Things got complicated when I added things like OK/Cancel buttons. I had to keep track which of the menus/buttons were active. Then after a lot of work I added UI elements like check box, list box, a line editor, and finally full brown multi line text editor. I also wrote data structures for these beasts (menus, buttons, editor etc.). I implemented functions to draw each of these on the screen. My mechanism was simple. Get a key press, search through the myriad of structures to find the one corresponding to the active UI element on the screen, update some field of the structure, and then redraw that UI element. The code, although understandable to me, had become a big mess (luckily, everything looked nice on the screen, and many Unix guys were impressed with my character based UI).

Did you notice something there? This is the way a typical C programmer thinks. Starting from the main(), he goes statement by statement, function by function and accomplishes whatever he wants to do. He tries to see the entire program as a sequence of statements, groups frequently occurring statements into functions and calls them when required. The problem comes when you have a hell lot of statements (code) and data at your disposal. You are engulfed by a myriad of data structures and functions. This is exactly where object oriented design comes to your aid.

Central to OOP is the key idea that the code and data in your program are related. You have some data and some functions to manipulate them. You club these to make an Object (or class, there is a slight difference between class and object, but let's not bother too much about it). So what's the great deal? I am still calling functions one after another. Right! But there is very different way of thinking which emerges from clubbing code and data into an object. You make the object responsible for all its functions. The object presents a set of functions through which it can be manipulated. The user interacts with the object without any knowledge of the way the object implements its features. The advantage here to the programmer is that he is able to think on a higher level, dividing the program into a set of independent and responsible objects and focuses more on the interaction between various objects. You no longer modify the object's data directly, just make a request to the object for a particular action and the object does its job properly.

To top it all, the OOP languages introduce the powerful feature of inheritance and polymorphism. When you find that some objects behave in a very similar way, you abstract the common features and put them in a base class. The objects are derived from this base class and inherit all the properties of base class from it. The client accesses the object through the base class interface only. This has an advantage if in future you want to add another derived class. The client code uses only the base class and need not be changed. This leads to fairly extensible designs.

So let's see how much does this OOP help in my text based UI example. First I could create classes for each kind of UI element, having only two features for the time being: they know how to draw themselves, and they can process any key press. Since all these UI elements have these two common features I could as well create a base class UIElement and have them derived from this class. This has an important advantage in UI design. Say I needed a complex UI, say a list box where some entries are plain strings and some are check boxes. This would not be problem at all, because a list box is a list of UIElements and it does not care what kinds of UI elements are actually there in the list. While populating the list box we can then add normal strings as well as check boxes without any pain.

To take our example further, let's say I want to change the color scheme of the UI elements. We could have a class ColorScheme and we change the drawing function of UIElement so that it worked in coordination with this ColorScheme class. The client code does not change. Notice that since now each UI knows how to process key press, I don't have to put a big switch/case in main() to handle user input. These are conveniently delegated to individual UI elements.

So much of OOP! Now which language should I use in practice. For C lovers the choice is definitely C++, and there is something divine in pointers which I like so I would not opt for Java. Where does this leave the good old C? Well, we need to make the objects responsible enough and for that we need the if/else, switch/case, while/for/do while, library functions and other C stuff. So it is down to implementation details when we should start thinking in C. Think in terms of objects/classes during the design phase and think of C while writing code. That's what the title of this post says: "Design in C++, Code in C"

0 Comments:

Post a Comment

<< Home