Object Orientation

To make best use of Zope, you will need to have a grasp of the concept of object orientation. Object orientation is a software development pattern that is used in many programming languages (C++, Java, Python, Eiffel, Modula-2, others) and computer systems which simulate "real-world" behavior. It stipulates that you should design an application in terms of objects. This chapter provides a broad overview of the fundamentals of object orientation from the perspective of a Zope developer.

Objects

In an object-oriented system (such as Zope), your application is designed around objects. Objects are self-contained "bundles" of data and logic. It is easiest to describe them by comparing them to other programming concepts.

In a typical non-object-oriented application, you will have two things:

  • Code. For example, you may have a bit of logic in the form of a Perl script in a typical CGI-based web application which sucks employee data from a database and displays a table to a user.
  • Data. For example, you may have employee data stored in a database such as MySQL or Oracle that your code operates upon by reading or changing it. This data exists almost solely for the purposes of the code that operates upon it; it has almost no value without the code.

 

In a typical object-oriented application, however, you will have one thing, and one thing only:

  • Objects. Objects are collections of code and data wrapped up together. For example, you may have an "Employee" object that represents an employee. It will contain data about the employee, such as a phone number, name, and address, much like the information that would be stored in a database like MySQL or Oracle. However, the object will also contain "logic" (code) that can manipulate and display this data.

 

In a non-object-oriented application, your data is separate from your code. But in an object oriented application, both your data and your code is stored in one or more objects, each of which represents a particular "thing". Objects can represent just about anything. In Zope, the Control_Panel is an object, Folders which you create are objects, even the Zope "root folder" is an object. When you use the Zope "add list" to create a new item in the Zope Management Interface, you are creating an object. People who extend Zope by creating Products define their own types of objects which are then entered in to the Zope "add list", allowing you to create objects from them. A product author might define a "Form" object or a "Weblog" object. Basically, anything which can be described using a noun can be modelled as an object.

Object-orientation as a programming methodology allows software developers to design and create programs in terms of "real-world" things like Folders, Control_Panels, Forms, and Employees instead of designing programs based around more "computerish" concepts like bits, streams, and integers. Instead of teaching the computer about our problem by descending to its basic vocabulary (bits and bytes), we use an abstraction to teach the computer about the problem in terms of a vocabulary which is more natural to humans. The core purpose of object orientation is to allow developers to create, to the largest extent possible, a system based on abstractions of the natural language of a computer (bits and bytes) into real-world things (Employees and Forms) that we can understand more quickly and more readily.

This idea of abstraction also encourages programmers to break up a larger problem by addressing the problem as smaller, more independent "sub-problems". This allows developers to define solutions in terms of these "sub-problems". When you design an application in terms of objects, the pieces which eventually come to define the solution to all the "sub-problems" of a particular "big" problem are objects.

Attributes

An object's data is defined by its attributes. For example, an attribute of an Employee object might be named "phone_number". This attribute will likely contain a series of characters which represent the employee's phone number. Other attributes of an Employee object might be "first_name" and "last_name", which are respectively, series of characters which represent the employee's first name and the employee's last name. Another attribute of an employee object might be title, which would be a series of characters representing the employee's job description.

An object typically uses attributes to store elements that describe itself. For example, "phone_number", "first_name", "last_name" and "title" describe an employee in a particular way. It may help to think of the set of attributes belonging to an object as a sort of "mini-database" which contains information representing the "real-world thing" that the object is attempting to describe. The complete collection of attributes assigned to an object defines the object's state. When one or more of an object's attributes are modified, the object is said to have changed its state.

Special kinds of web-editable object attributes in Zope are sometimes referred to as Properties.

Methods

The set of actions which an object may perform is defined by its methods. Methods are code definitions attached to an object which typically perform an action based on the attributes belonging to the object on which the method is defined. For example, a method of an Employee object named "getFirstName" may return the value of the object's "first_name" attribute, while a method of an Employee object named "setFirstName" might change the value of the object's "first_name" attribute. The "getTitle" method of an Employee object may return "Vice President" or "Janitor".

Methods are similar to functions in procedural languages like C. The key difference between a method and a function is that a method is "bound" to (attached to) an object, so instead of operating solely on "external" data that is passed in to it via arguments, it may also operate on the attributes of the object to which it is bound.

Some objects in Zope are actually called "methods". For example, there are DTML Methods, SQL Methods, and External Methods. This is because these objects are meant to be used in a "methodish" way. They are "bound" to their containing Folder object by default when called, and the logic that they contain typically makes reference to their containing Folder. Script (Python) objects in Zope act similarly through their concept of "Bindings".

Messages

In an object-oriented system, to do any useful work, an object is required to communicate with other objects in the same system. For example, it wouldn't be particularly useful to have a single Employee object just sitting around in "object-land" with no way to communicate with it. It would then just be as "dumb" as a regular old relational database row, just storing some data. We want the capability to ask the object to do something useful. More precisely, we want the capability for other objects to ask our Employee object to do something useful. For instance, if we create an object named "EmployeeSummary", which has the responsibility for collecting the names of all of our employees for later display, we want the EmployeeSummary object to be able to ask a set of Employee objects for their first and last names.

When one object communicates with another, it is said to send a message to another object. Messages are sent to objects by way of the object's methods. For example, our EmployeeSummary object may send a message to our Employee object by way of "calling" its "getFirstName" method. Our Employee object would receive the message and return the value of its "first_name" attribute. Messages are sent from one object to another when a "sender" object calls a method of a "receiver" object.

When you access a URL that "points to" a Zope object, you are almost always sending that Zope object a message. When you request a response from Zope by way of invoking a Zope URL with a web browser, the Zope object publisher receives the request from your browser. It then sends a Zope object a message on your browser's behalf by "calling a method" on the Zope object specified by the URL. The Zope object responds to the object publisher with a return value, and the object publisher returns the value to your browser.

Classes and Instances

A class defines an object's behavior and acts as a constructor for an object. When we talk about a "kind" of object, like an "Employee" object, we actually mean "objects constructed using the Employee class" or, more likely, just "objects of the Employee class". Most objects are members of a class.

It is typical to find many objects in a system that are essentially similar to one another save for the values of their attributes. For instance, you may have many Employee objects in your system, each with "first_name" and "last_name" attributes. The only difference between these Employee objects is the values contained within their attributes. For example, the "first_name" of one Employee object might be "Fred" while another might be "Jim". It is likely that each of these objects should be members of the same class.

A class is to an object as a set of blueprints is to a house. Many houses can be constructed using the same set of blueprints; likewise many objects can be constructed using the same class. Objects that share a class typically behave identically to each other. If you visit two houses that share the same set of blueprints, you will likely notice striking similarities: the layout will be the same, the light switches will probably be in the same place, and the fireplace will almost certainly be in the same location. The shower curtains might be different in each house, but this is an attribute of each particular house which doesn't change its essential similarity with the other. It is much the same with instances of a class. If you "visit" two instance of a class, you will interact with both instances in essentially the same way: by calling the same set of methods on each. The data kept in the instance (by way of its attributes) might be different, but these instances behave in the same way.

The behavior of two objects constructed from the same class is similar because they both share the same methods. Methods of an object are not typically defined by the object itself, but instead are defined by the object's class. For instance, the Employee class defines the getFirstName method, and all objects that are members of that class share that method definition. The set of methods that are assigned to a class define the behavior of an object.

The objects which are constructed by a class are called instances of the class or (more often) just instances. For example, the Zope Examples folder is an instance of the Folder class. The Examples folder has an id attribute of Examples, while another folder may have an id attribute of MyFolder, but they are both instances of the same class, and behave identically. All of the objects that you deal with using the Zope management interface are instances of a class. Typically, the classes from which these objects are constructed are defined in Zope Products, which are created by Zope developers and community members.

Inheritance

Sometimes it is desirable for objects to share the same essential behavior, except for small deviations from each other. For example, you may want a ContractedEmployee object to have all the behavior of a "normal" Employee object except that you must keep track of a tax identification number on instances of the ContractedEmployee class that is irrelevant for "normal" instances of the Employee class.

Inheritance is the mechanism that allows you to share essential behavior between two objects, while customizing one with a slightly modified set of behaviors that differ from or extend the other.

Inheritance is specified at the class level. As we learned above, classes define behavior, and if we want to change object behavior, we almost always need to change its class.

If we base our "ContractedEmployee" class on the Employee class, but add a method to it named "getTaxIdNumber" and an attribute named "tax_id_number", the ContractedEmployee class would be said to inherit from the Employee class. In the jargon of object orientation, the ContractedEmployee class would be said to subclass from the Employee class and the Employee class would be said to be a superclass of the ContractedEmployee class.

When a subclass inherits behavior from another class, it doesn't need to sit by and accept the method definitions of its superclass. It can override the method definitions of its superclass. For instance, we may want to cause our ContractedEmployee class to return a different "title" than instances of our Employee class. In our ContractedEmployee class, we might cause the getTitle method of the Employee class to be overridden by creating a method within ContractedEmployee which has a different implementation. For example, it may always return "Contractor" instead of a job-specific title.

In Zope, inheritance is used extensively. For example, the Zope "Image" class inherits its behavior from the Zope "File" class, because images are really just another kind of file, and they share many behavior requirements. But the "Image" class adds a bit of behavior which allows it to "render itself" by printing an HTML tag instead of causing a file download. It does this by overriding the index_html method of the File class.

Object Lifetimes

Object instances have a specific lifetime. This lifetime is typically controlled by either a programmer or a user of the system in which the objects "live".

Instances of web-manageable objects in Zope like Files, Folders, DTML Methods and such span from the time the user creates them until they are deleted. You will often hear these kinds of objects described as persistent objects. These objects are stored in Zope's object database (the ZODB).

Other object instances have different lifetimes. There are object instances in Zope which last for a "programmer-controlled" period of time. For instance, the object that represents a web request in Zope (often called REQUEST), has a well-defined lifetime. Its lifetime lasts from the moment that the object publisher receives the request from a remote browser until the response is sent back to that browser. It is then destroyed automatically. Zope "session data" objects have another well-defined lifetime. These objects last from the time that a programmer creates one on behalf of the user via his code until such time that the system (on behalf of the programmer or site administrator) deems it necessary to throw away the object in order to conserve space or indicate an "end" to the user's session. This is defined by default as 20 minutes of "inactivity" by the user for whom the object was created.

Summary

Zope is an object-oriented development environment. Understanding Zope fully requires that you grasp the basic concepts of object orientation. You should attempt to understand attributes, methods, classes, and inheritance before setting out on a "for-production" Zope development project.

For a more lighthearted description of what object orientation is and how it relates to Zope, see Chris McDonough's Gain Zope Enlightenment by Grokking Object Orientation. For a more comprehensive treatment on the subject of object orientation, buy and read The Object Primer by Scott Ambler. There are also excellent object orientation tutorials available on the Internet. See The Essence of Objects chapter of the book "The Essence of Object Oriented Programming with Java and UML". There is an extensive Object FAQ available at Cyberdyne Object Systems.