The technical details of using C# to create classes and interfaces are fairly easy to master. The difficult thing to master is good design of those objects. This section gives you an introduction to object-oriented design (OOD), class design, and interface design.
Introduction to Object-Oriented Design
Object-oriented design isn't just about designing objectsit's about designing objects properly. When you are designing objects, two distinct areas of thinking are involved. You can either design an object that performs a specific, discrete task that is done when creating tools, or you can design an object that is a model or representation of a concept within the problem domain of the application. For example, you can create a class called CustomerManager, which is a tool-type object, or you can create a class called Customer, which models the real-world attributes and behaviors associated with a customer. The reality is that a little of each pattern is often used in commercial applications. This section illustrates some of the principles and concepts associated with designing classes and interfaces.
Before the advent of object-oriented programming environments and languages such as C++, Java, and the .NET Framework, programming was procedural. In other words, your program started at some fixed point, and then invoked a series of subroutines in sequence to produce the desired result. More robust programs could be written by adding logic, looping, and conditional operators to the procedural code, but the code never actually modeled any real-world scenarios.
Classes are abstractions of real-world concepts used to allow developers to think in terms of the problem at hand rather than having to translate the problem into a series of convoluted procedures.
A class has attributes, which are essentially discrete pieces of information about the class. An attribute can either affect the class itself (referred to as a static member in C#) or it can affect instances of the class (instance members). An example of an attribute would be a field or a property of a class, such as ID, or members that are specific to a certain problem domain, such as Density, Volume, Price, or Age.
A class also has operations (referred to as "methods" in C#), which are the tasks that a class (or an instance of that class) can perform. These operations can range from simple constructors for initializing data, to complex operations that can consume valuable resources such as CPU time, memory, and so on.
When you design a class, you decide which attributes and operations the class will provide, as well as the accessibility of those attributes and operations. Accessibility refers to whether the class member can be accessed by other class members, by members of descendant classes, by code outside the class definition, or by code outside the assembly in which the class is defined.
This chapter does not discuss what constitutes good class design. The purpose of this chapter is to give you the knowledge you need to start writing object-oriented code with C#. If you want to do some further reading about object-oriented design, you should consult Object-Oriented Analysis and Design with Applications (2nd edition), ISBN 0805353402, Addison-Wesley Professional.
Visual Studio 2005 includes a tool that allows you to do class design within the IDE. You can create class diagrams from classes that you have already coded, and you can also generate classes from the diagrams you have drawn.
Figure 5.1 illustrates a class design in progress. It is an incomplete design of an object hierarchy representing vehicles. An object hierarchy like this could be used for various kinds of business problemsanything from selling cars to performing intense analysis of crash test results.
Figure 5.1. A work-in-progress class design.
In the next section of this chapter, you will see how to take your class designs and turn them into code written in C#.
The difference between an interface and a class is one that might not be immediately obvious if you're new to object-oriented programming. A class is an encapsulation of attributes and operations that may or may not inherit from another base class (the CLR does not support multiple inheritance). An interface is a contract that defines the attributes and operations that a class must implement in order to satisfy the conditions of the interface.
For example, you can have a class that exposes a property called Color that might indicate the color of the object. You can also create an interface called IColorable. Any class that then implements that interface must define a property called Color. So, the essential difference between classes and interfaces is that classes are the definitions of abstractions of real-world entities, and interfaces are requirements and constraints to which all classes bound to the interfaces must conform. You will see more of how this works in the next section, where we get into some real object-oriented code.
Naming Conventions for Interfaces and Classes
By convention, as well as by recommendation of many designers, interface names typically begin with a capital "I" and are often descriptive words. Classes should not begin with any set prefix character and are almost always nouns. Both class and interface names should have their first letter capitalized, and the first letter of each word if there are multiple words joined in a class or interface name, for example, SportsCar, Customer, CustomerManager, Account, AccountsPayable.