1. Black Boxes

A METHOD CONSISTS OF INSTRUCTIONS for performing some task, chunked together and given a name. After giving a chunk of instructions a name, you can accomplish a potentially very complicated task by writing a single instruction. Instead of worrying about the many, many steps that the computer might have to go though to perform that task, you just need to remember the name of the method. Whenever you want your program to perform the task, you just call the method. Thus, methods are a major tool for helping programmers deal with complexity by hiding it -- a powerful concept computer scientists call "abstraction."

A method is sometimes said to be a "black box" because you usually use methods without concerning yourself with what is inside them (this is especially true of C# API methods, since you didn't write them, and you have to go to extra trouble to look at the instructions inside them). A black box is an engineering metaphor for a device that performs certain functions when the user interacts with it by operating controls on the box called the interface. The gadgetry inside the box that performs the functions (called the implementation) is usually not open to inspection, which is why the term "black box" is used to describe such devices. Examples of real world "black boxes" include things like your television, your car, your VCR, and your refrigerator. Although a determined user can open them up to see how they work, most people never do. Instead, they interact with the device using its interface -- the controls provided -- without thinking about how the device does its work. For example, you can turn your television on and off, change channels, and set the volume by using the buttons on it, all without understanding what's happening inside. Black boxes and methods have a lot in common, so before we dive into the nuts and bolts of method design, let's talk about some design principles that are common to both.

A black box consists of an interface (visible) and an implementation (hidden). A physical black box might have buttons on the outside that you can push, dials that you can set, and slots that can be used for passing information back and forth. Since we are trying to hide complexity, not create it, we have the first rule of black boxes and methods:

The interface should be fairly straightforward, well-defined, and easy to understand.

Most people find the basic controls on a TV simple enough to operate. Thus, a TV's interface adheres to this rule. VCR's and copiers, on the other hand, have notoriously complicated interfaces; their designers have been less successful at achieving this goal. In the computer science arena, consider the String.IndexOf() method. Its interface is fairly simple: give it a single parameter (a character), and it gives back the position of that character.

The second rule of black boxes and methods is that

To use a black box, you shouldn't need to know anything about its implementation; all you need to know is its interface.

In fact, it should be possible to change the implementation, as long as the behavior of the box, as seen from the outside, remains unchanged. For example, when the insides of TV sets went from using vacuum tubes to using transistors, the users of the sets didn't even need to know about it -- or even know what it means. Similarly, it should be possible to rewrite the inside of a method, to use more efficient code, for example, without affecting the programs that use that method.

Of course, to have a black box, someone must have designed and built the implementation in the first place. The black box idea works to the advantage of the implementor as well as of the user of the black box. After all, the black box might be used in an unlimited number of different situations. The implementor of the black box doesn't need to know about any of that. The implementor just needs to make sure that the box performs its assigned task and interfaces correctly with the rest of the world. This is the third rule of black boxes:

The implementor of a black box should not need to know anything about the larger systems in which the box will be used.

In a way, a black box divides the world into two parts: the inside (implementation) and the outside. The interface is at the boundary, connecting those two parts.

By the way, you should not think of an interface as just the connection between the box and the rest of the world. The interface also includes a specification of what the box does and how it can be controlled by using the elements of the physical interface. It's not enough to say that a TV set has a power switch; you need to specify that the power switch is used to turn the TV on and off!

To put this in computer science terms, the interface of a method has a semantic as well as a syntactic component. The syntactic part of the interface tells you just what you have to type in order to call the method. For example, when you're using the C# API, the lines that say things like "static int ToInt32(string val)" specify the name of the method, how many parameters you have to supply, and what data type is returned. The semantic component specifies exactly what task the method will accomplish. In the C# API, this part is specified in the English description that accompanies the method interface. To write a legal program (one that compiles), you need to know the syntactic specification of the method. To understand the purpose of the method and to use it effectively, you need to know the method's semantic specification. I will refer to both parts of the interface -- syntactic and semantic -- collectively as the contract of the method.

The contract of a method says, essentially, "Here is what you have to do to use me, and here is what I will do for you, guaranteed." When you write a method, the comments that you write for the method should make the contract very clear. (I should admit that in practice, methods' contracts are often inadequately specified, much to the regret and annoyance of the programmers who have to use them.)

For the rest of this chapter, I turn from general ideas about black boxes and methods in general to the specifics of writing and using methods in C#. But keep the general ideas and principles in mind. They are the reasons that methods exist in the first place, and they are your guidelines for using them.

Methods are not the only example of black boxes in programming. For example, a class is also a black box. We'll see in a later chapter that a class can have a "public" part, representing its interface, and a "private" part that is entirely inside its hidden implementation. All the principles of black boxes apply to classes as well as to methods.