Code Reuse

By now you may have gotten the impression that object-orientated programming (OOP) often involves a lot of typing. But this is because OOP is not just about writing the current program, but the next version, and any similar programs. Only the smallest programs have no future development path, so it pays to take a little more trouble. OOP aims to provide a good foundation for further development.

Making code more reuseable is a practical way of improving programming productivity. Classes are often easier to reuse than libraries of plain functions (although they still have their place.) For example, it is easier to use string than to use the C-style string manipulation functions like strcpy(), and so forth.

Class frameworks are effectively customizeable applications. By modifying the framework's behaviour with inheritance, you can write powerful graphical user interface (GUI) programs with a single page of code. This has probably been the most successful kind of object-oriented code reuse.

Reusable Objects and Functions

A goal of software engineers is to build the best possible system with the least amount of effort. There is no intrinsic value in hard work; the definition of efficiency in engineering is the amount of work you can get done with a given expenditure of energy. Sir Isaac Newton said that if he saw further than most, it was because he stood on the shoulders of giants; we can borrow from Newton to say that many giants have labored to produce excellent software libraries. Many of the existing libraries are free, but even if you do have to pay for them, remember that reinventing the wheel is nearly always more expensive. It takes a lot of effort to create a good new C++ string class, and the community of programmers will not thank you for doing things differently from everyone else. The standard library will often have all you need.

Code reuse is about as old as programming itself. Reusing routines or functions works very well for well-defined mathematical operations such as the trigonometric functions. Any working programmer soon develops a collection of useful functions (for example, functions for trimming strings or filename extensions), and it would be silly to wrap such things up in a class. In such a case, it is more appropriate to use namespaces.

In object-oriented software development, the class is the unit of reuse. Rather than a loose collection of functions for manipulating character strings (as in C), C++ provides the standard string class. The rest of the program (that is, the client code) can ignore the details, trust the implementor, and deal with a convenient high-level abstraction. It is worth putting effort into producing high-quality software components because they can make more than one project easier.

Using an Existing Framework

Consider the following (silly) abstract class, which again deals with the general problem of computers washing their hair:


class HairNight {
public:
  virtual void find_shampoo() = 0;
  virtual void lather() = 0;
  virtual void rinse() = 0;
  virtual int no_of_times() = 0;
  virtual void dry_hair() = 0;

  void wash_hair()
  {
    find_shampoo();
    for(int i = 0, n = no_of_times(); i < n; i++) {
       lather();
       rinse();
    }
    dry_hair();
  }
};

Because this class is abstract, you cannot construct a real object of this type, but only use it in derivation. HairNight contains no information about how to find the shampoo or wash the hair, but it knows how to put all these together. A real derived class has to fulfill the contract and supply real versions of the pure virtual functions. This is the essence of a class framework; it relies on clients to adapt its abstract functionality.

The most common use for class frameworks is graphical user interface (GUI) applications. There is no standard C++ library for handling graphics and GUI applications. Many of the class frameworks used for GUI development, particularly on PCs, are both proprietary and odd. But the same concepts are common to all GUI application frameworks: GUI applications supply you with an application, and you customize it by overriding virtual methods.

NOTE

Hopefully, when the International Standards Organization committee reconsiders the C++ standard in a few years, there will be sensible proposals for windowing classes and grapics, in the same way that the (Abstract Windowing Toolkit) AWT is standard for Java.


YAWL

The original purpose behind Yet Another Windows Library (YAWL) was to take the tedium out of Windows programming. A small class framework is more useful in demonstrating GUI programming than large proprietary beasts such as the Microsoft Foundation Classes (MFC) and Borland's Visual Control Library (VCL). With YAWL, you can produce a standalone 60KB executable GUI program.

A basic GUI application can inherit most of its behavior from a YAWL application window. For example, consider the business of drawing trees, which is discussed in Chapter 6, in the section “Drawing Trees with Turtle Graphics.” One serious downside of that style of turtle graphics is that the output is not persistent and would disappear if the window were resized or other changes were made. Here is the YAWL version of a program in which the window can be resized arbitrarily and the tree will be redrawn in scale:


#include <tg-yawl.h>
#include <sstream>
using namespace std;

#include "tree.h"

class MyWin: public TGFrameWindow {
public:
 void tg_paint(TG& tg)              // override
  {
// starting in the middle, draw the tree
   tg.go_to(50,10);
   draw_tree(tg,20,0.7,ang,0.1);
  }

 void tg_mouse_down(FPoint& p)     // override
 {
   ostringstream out;
   out << '(' << p.x << ',' << p.y << ')' << ends;
//  change the window caption
   set_text(out.str().c_str());
 }
};

int main()
{
  MyWin w;
  w.show();        // make the window visible
  w.run();         // respond to events
  return 0;
}

This short YAWL program demonstrates the basic principle of class frameworks. Our class MyWin derives from TGFrameWindow, and overrides the methods tg_paint() and tg_mouse_down() to do application-specific work. First, an application frame window is constructed and made visible through the use of show(); the application starts processing events when run() is called. When the user closes the window, run() returns, and the program ends.

To do anything useful, you need to respond to events (often called messages) from the operating system and from the users. People often have difficulty with event-driven programming because it is so foreign to the usual way of doing programming. People are accustomed to being fully in control, able to issue commands when they choose—at least in the domain of software. Busy personal assistants do not have this luxury; they must be prepared to drop anything to answer the phone, and generally their work priorities are externally determined. Real-world programs are like busy personal assistants; they must take their cues from the environment and be prepared to multitask.

The application window, for instance, may be called on to repaint itself at any point. The framework calls the tg_paint() method when this happens, passing it a valid turtle graphics object. Because tg_paint() is virtual, if your window class overrides tg_paint() then you can run any graphics code you like whenever the window needs to repaint itself. In a similar way, when the user clicks on the window, the tg_mouse_down() method is called and will be passed the scaled coordinates.

When to Use Object-Oriented Programming

You can use any user-defined type as a base class; it does not make sense to extend or specialize ordinary numbers, in the same way that you cannot overload operators for ordinary numbers. The reason is that people already have a good idea of the behavior of numbers, and it would be upsetting to change this. Similarly, you should treat std::string and the standard containers as if they were built-in types.

Object-orientation is like the efficient organization of a business; ideally, everyone should have clearly defined roles. When the business expands, the responsible classes can expand their roles without being distracted by other duties. It is important to plan ahead for expansion, for both businesses and software systems. Therefore, object-oriented designers spend a lot of time on design because they are already thinking of the next version. As a group of programmers builds up a body of reusable classes, any similar projects become much easier. For example, if you are building human resources systems, an Employee class (especially if it is readily extensible) can save you a lot of coding.

The extra investment involved in object-orientation is not always needed. If you are building a small command-line utility, for example, it is usually not necessary. Sometimes functions are the best solution. Unless you might later decide to vastly expand the utility's functionality and build a GUI application; then object-orientation will save the day.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.220.152.139