Designing Classes that Model


Underneath the user interface, at the code level, you will probably consider building classes that model a real-world element. When done correctly, this is an ideal usage of object-oriented design. But classes such as these have their own set of problems, many of which are similar to the user interface problems.

Before I proceed with this lively and entertaining discussion, I need to clear up a definition: proxy class, or proxy object. A proxy object is an object that is instantiated locally on the computer that represents something that’s not on the computer. In order to interact with the outside entity, the rest of the software interacts with the instance of the class without any concern for how the class in turn interacts with the outside entity. As far as the software is concerned, the instance of the class is the entity.

For example, suppose you have a device that has the amazing ability to connect over wires that are present in the house, send out a sequence of carefully generated tones that a remote system hears, decodes, and uses to connect to another similar device. (Most people call this device a telephone.)

Now suppose you are building some software that controls the phone. The software is a phone dialer. It’s not for dialing into the Internet; rather, the software dials the phone line and you pick up the phone and hear the ringing, as another human answers the phone.

If you’re using C++ (or Java or any other object language), you’ll probably build a class that represents the phone. The class might have a member function called Dial, which takes a string that the phone will dial (such as "555-1212"). When the user of the program is ready to dial, she types in the number (or chooses the number from a list of saved numbers). She clicks the Dial button on the screen, which triggers some code. The code creates a new instance of the Phone class (or obtains an existing instance) and then calls the instance’s Dial function, passing the string.

The Phone class in this case is a proxy class. It represents an object elsewhere, and to use the class in your code, the rest of the code doesn’t even need to know how the class is ultimately controlling the telephone.

Another place people find proxy classes is in remote object systems (such as CORBA, or Common Object Request Broker Architecture). These are systems where you build a class library and put it on a remote computer. Then a local computer will use the remote library. The local computer will create an instance of a proxy class and call the methods in the proxy class, and everything seems local. However, the methods in the proxy class in turn send out data to the remote computer, causing the member functions of the class library to run on the remote computer. The local code feels like everything is local, even though the real code is running elsewhere. And then when the remote function is finished and returns a value, the value goes back over the wire to the proxy member function, which returns the value as if it had come up with the result on its own.

RULE

When you build classes that model devices, think in terms of proxy classes. Imagine that the classes are the device. To use the device, the other code uses the class, which represents the device.

As with most classes, the proxy concept has the advantage that if you remove the existing device and put in one with similar functionality, then you might have to change the class to accommodate the new device, but you won’t have to change the code that uses the class. For example, you might have a new device that isn’t really a phone; rather, it’s a device that has the ability to listen for the dial tone and generate the correct tones for the phone call. (A modem can do this, for example.)

This means you wouldn’t want to give your class a public member function such as this

 void GenerateDualTone(int Frequency1, int Frequency2); 

and require the users of the class to somehow know what frequencies to fill in to generate one of 10 digits plus a star or pound symbol. Further, you might not even want a function such as this

 void DialDigit(char digit); 

since the simplest function, Dial, should be all you need. After all, can you think of an example where code calling the class would just call DialDigit once and not again? Maybe if you’re designing such software you might have a special need, but for a generic phone-dialing class, such a need is hard to imagine.

Now remember, however, I’m not saying you shouldn’t have these other functions. Instead, I’m saying these functions shouldn’t be part of the primary public interface, unless your class is to be used in special situations where you need such functionality.

RULE

The public interface (that is, the set of functions deemed public) should be as simple and clean as possible, providing the primary way into the class.

But what if you want to provide for specialized usage for the more advanced programmers using this class? Then you have a choice here. Before I present you with the choices, however, don’t skip these and simply add these advanced functions to your public interface! You will confuse some of the other programmers. (Remember, there’s a reason you’re also an advanced programmer, right?)

Here are your choices. (And believe me, a lot of people have not considered these before.)

  • Create another class derived from your class; this class adds additional, more advanced (and possibly specialized) functionality in the form of its own public interface; the advanced users can use this class instead.

  • Put the advanced interface in the form of protected functions, and allow the advanced programmers to derive their own classes.

Now don’t just pick one of these choices and roll with it. Instead, consider when to use each. If you anticipate lots of people requiring the advanced usage, then by all means, use the first solution, and write the derived class yourself and ship it along with the other class as a class library. But if you anticipate only a few brave souls venturing into the advanced realms, then I would recommend simply making the functions protected and letting the users derive the classes themselves. If they’re advanced programmers like you are, they’ll figure out what they’re supposed to do.




Designing Highly Useable Software
Designing Highly Useable Software
ISBN: 0782143016
EAN: 2147483647
Year: 2003
Pages: 114

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net