C H A P T E R 6
■ ■ ■
Objects and Design
Now that we have seen the mechanics of PHP’s object support in some detail, in this chapter, we step
back from the details and consider how best to use the tools that we have encountered. In this chapter, I
introduce you to some of the issues surrounding objects and design. I will also look at the UML, a
powerful graphical language for describing object-oriented systems.
This chapter will cover
- Design basics: What I mean by design, and how object-oriented design differs from
procedural code - Class scope: How to decide what to include in a class
- Encapsulation: Hiding implementation and data behind a class’s interface
- Polymorphism: Using a common supertype to allow the transparent substitution
of specialized subtypes at runtime - The UML: Using diagrams to describe object-oriented architectures
Defining Code Design
One sense of code design concerns the definition of a system: the determination of a system’s
requirements, scope, and objectives. What does the system need to do? For whom does it need to do it?
What are the outputs of the system? Do they meet the stated need? On a lower level, design can be taken
to mean the process by which you define the participants of a system and organize their relationships.
This chapter is concerned with the second sense: the definition and disposition of classes and objects.
So what is a participant? An object-oriented system is made up of classes. It is important to decide
the nature of these players in your system. Classes are made up, in part, of methods, so in defining your
classes, you must decide which methods belong together. As you will see, though, classes are often
combined in inheritance relationships to conform to common interfaces. It is these interfaces, or types,
that should be your first port of call in designing your system.
There are other relationships that you can define for your classes. You can create classes that are
composed of other types or that manage lists of other type instances. You can design classes that simply
use other objects. The potential for such relationships of composition or use is built into your classes
(through the use of class type hints in method signatures, for example), but the actual object
relationships take place at runtime, which can add flexibility to your design. You will see how to model
these relationships in this chapter, and we’ll explore them further throughout the book.
As part of the design process, you must decide when an operation should belong to a type and when
it should belong to another class used by the type. Everywhere you turn, you are presented with choices,
decisions that might lead to clarity and elegance or might mire you in compromise.