Vision Fundamentals
Overview
The information used in the decision making process can be integrated from many disparate sources. Commercial sources of public information such as economic, demographic, financial, and product data are often combined with internally generated data such as operating statistics and forecasts. A fundamental requirement of any database management system is that it provide a consistent framework in which to structure your information.
Many database management systems are designed around the individual databases you use. Vision assumes that the data provided in the commercial and internal databases represents only one part of your information resource. As an object-oriented database management system, Vision allows you to store data and the rules for interrelating and using this information. In addition, Vision treats the dimensions of time and currency as integral components of your database.
Basic Terminology
Objects are the fundamental building block in Vision. For example, the number 3, the country Great Britain, GM's common stock, and the baseball player Babe Ruth can all be thought of as Objects. Objects are the basic unit of information representation.
A Property is an attribute of an object whose value can be assigned and updated. For example, the properties of a company could include its sales, earnings, and name. The properties of a country could include its gross national product and official languages.
A Method is an operation which can be performed on an object. For example, you could count the number of characters in a string, produce a balance sheet for a company, and compute a batting average for a baseball player.
Vision is designed around the concept of communicating objects. Objects interact with one another via a process known as Sending a Message. A Message is a request for an object to return the value of one of its properties or execute one of its methods. The object receiving the request is known as the Recipient Object. The only way to interact with an Object is through one of its messages. Messages can ensure the modularity of the system because they specify the type of operation desired, but not how that operation should be accomplished for a particular type of object.
The nature of an object's messages depends on the type of object it represents. Objects representing numbers understand messages that compute arithmetic functions; however, it would not be appropriate to define a property sales for a number (i.e., the number 3 does not have a sales value). Sales is a meaningful property to define for a company; however, it would not be meaningful to add two companies (e.g., GM + Ford) directly, although it is meaningful to think about adding the sales values of these companies.
It is useful to classify objects based on common properties and operations. For example, GM, Xerox, and IBM have the same properties (e.g., sales, earnings, company name) and respond in the same way to specific operations. A Class is used to describe a group of similar objects. GM, Xerox, and IBM are Objects that could belong to a class known as Company. The United States, Great Britain, and Germany are objects that could belong to a class known as Country. 3, 17.2, and -.23 are objects that belong to a class known as Number.
Each individual object is known as an Instance of the class. Each instance of a class has a distinct value for each of the properties defined for its class. All instances of a class will respond to the same set of messages, using the same methodology for carrying out any of its operations. Perhaps the easiest way to understand the relationships among classes, instances, and messages is to think of them in terms of a table. Each class can be thought of as a separate table. The instances of the class form the rows of the table. The messages of the class form the columns in the table. A sample tabular representation for the class Company is shown below:
This tabular organization is similar to the relational database model. However, in most relational systems, the actual data that can be found for the values in the columns are restricted to a fixed set of simple data types: integer, real, string, and date. No such restriction exists in Vision. For example, all companies are part of an industry. In the relational model, the value of industry would probably be stored as a string or number in a company table. This value would then be used to query an industry table in order to access information about a company's industry. In Vision, the object representing the company's industry is stored directly as the value of the industry property. As a result, the simple expression:
gm industry namecould be used to access the name of GM's industry.
By providing a mechanism for linking tables, Vision offers additional modeling power not present in relational systems. Class Specialization provides a means for defining a new class that Inherits common properties and operations from another class. A class that is a specialization of another class is called a Subclass. For example, bank companies are similar to industrial companies in many ways, yet they have certain characteristics that are unique to banks. You may want to create a class BankCompany as a subclass of the class Company. The object Citibank could be defined as an instance of this new class.
A class inherits both the properties and methods of its Superclass the class from which it was created. All instances of a class are also considered to be instances of its superclass. This organization is illustrated below:
New properties and methods may be defined by the subclass. For example, banks have a value for outstanding loan balance and standard companies do not. The property loansOut could be defined for the class BankCompany to record loan balance values for banks. The company GM would not recognize the message loansOut because it is not a bank company. The company Citibank would respond to this message because it is a bank company. Both GM and Citibank would respond to any messages defined for the class Company, such as name and sales.
A subclass may also redefine a method that is defined by its superclass. If a method is redefined by a subclass, instances of the subclass will use the new method.
New classes are always created as a subclass of an existing class. A subclass is in all respects a class and can therefore have subclasses itself. For example, the class SavingsAndLoan can be created as a specialization of the class BankCompany.
A class actually has a sequence of classes from which it inherits properties and methods not defined by the class itself. This sequence begins with a class' superclass and continues with its superclass' superclass, and so on. The inheritance chain continues until the class named Object is encountered. The class Object defines messages that are available to all objects in the system.
Properties, Methods, and Messages - Overview
This section provides a basic overview for defining messages. More detailed information is available.
In the Vision language, objects communicate with one another by sending messages. The instances of a class all respond to the same messages. The message determines what type of operation the recipient object should perform. The recipient object's class determines the manner in which to actually perform the operation indicated by the message.
For example, the expression:
gm salessends the message sales to the company named gm. The definition of the message sales for the class Company may simply look up the value of GM's sales property. Alternatively, the expression:
autoIndustry salessends the message sales to the industry named autoIndustry. The definition of the message sales for the class Industry could be a method that computes the total aggregate sales for all companies defined to be a part of the automotive industry.
Four types of message can be defined:
You do not need to know what type of message has been defined in order to use the message. In all cases, the form:
object messageNameis used to request that the recipient object carry out the specific function indicated by the message.
Fixed Properties are defined for storing information that does not need to be maintained over time. The general form for creating a fixed property is:
className defineFixedProperty: 'propertyName' ;where className is the name of the class for which you are defining the property and propertyName is the name of the message which will be used to access the property.
For example, you could define a property to store the year in which a company was founded as shown below:
Company defineFixedProperty: 'yearFounded' ;The value of a property for any instance of the class is NA by default. The yearFounded property can be updated for instances of the class Company as illustrated below:
gm :yearFounded <- 1935 ;You place the : character in front of the property name to indicate that you want to return the Intensional Form of the property. This form responds to a variety of messages including the assignment message which is used to update the property. When the : is not prepended to the property name, the value of yearFounded for gm is accessed:
gm yearFounded
You may want to retain the values for a property over time. The general form for creating a Time Varying Property is:
className define: 'propertyName' ;where className is the name of the class for which you are defining the property and propertyName is the name of the message which will be used to access the property.
For example, you could define a property to track company sales over time as shown below:
Company define: 'sales' ;Initially, this time series property will not have any points in it for any instance of the class and the value of this property will be NA. The sales values for gm for 1993, 1994, and 1995 could be updated as illustrated below:
gm :sales asOf: 93 put: 96371.63 ; gm :sales asOf: 94 put: 102813.00 ; gm :sales asOf: 95 put: 101781.00 ;Again, you place the : character in front of the property name to return it in a form that can be updated. In this case, the asOf:put: message is used to update the time series property.
The sales values can be accessed as shown below:
gm salesreturns the most recent sales and
gm :sales asOf: 94returns the sales as of year-end 1994. A time series property returns its value as of the current evaluation date which is the current date by default. The asOf: message can be sent to the intensional form of a time series (i.e., the form returned by prepending the : character) to override the default access date.
Class Constants are defined for storing information that is identical for all instances of a class. The general form for creating a class constant is:
className define: 'constantName' toBe: object ;where className is the name of the class for which you are defining the class constant and constantName is the name of the message which will be used to access the constant for any instance of the class and object is the object which should be returned whenever this message is sent to any instance of this class.
For example, the message isCompany could be defined to return the Boolean object TRUE for all companies as shown below:
Company define: 'isCompany' toBe: TRUE ;The message can be defined to return FALSE for all other objects as shown below:
Object define: 'isCompany' toBe: FALSE ;This message can be evaluated for gm using the expression:
gm isCompanyThis expression returns the value TRUE. The expression:
3 isCompanyreturns the value FALSE.
Methods are used to define procedures. The general form for creating a method is:
className defineMethod: [ | methodName | . . . ] ;where className is the name of the class for which you are defining the method and methodName is the name of the message which will be used to execute the method.
For example, a method to compute the price to earnings ratio for a company can be written as shown below:
Company defineMethod: [ | peRatio | price / earnings ] ;This method can be executed for the company gm using the expression:
gm peRatioThis method assumes the messages price and earnings are defined as messages for the class Company as well.
As indicated earlier, you need not know that the message sales was defined as a time series and that peRatio is actually a method that accesses time series properties. For example, the price to earnings ratio for GM for 1994 can be accessed in the same manner as sales, as illustrated below:
gm :peRatio asOf: 94In this case, all data required by the peRatio method is accessed as of 1994.
Methods can be defined to require one or more parameters. The general form for creating a multi-parameter method is:
className defineMethod: [ | methodWithParam1: p1 param2: p2 param3: p3 ... | . . . ] ;where className is the name of the class for which you are defining the method and methodNameWithParam1:param2:param3: is the name of a three parameter method which will be used to execute the method.
For example, a method to compute the price to earnings ratio for a company using a supplied price could be written as shown below:
Company defineMethod: [ | peRatioWithPrice: inputPrice | inputPrice / earnings ] ;This method can be executed for gm using the expression:
gm peRatioWithPrice: 73.25This method assumes the message earnings is defined as a message for the class Company and divides the supplied price by this value.
The intensional form of a message was briefly introduced earlier as a way to update properties. Another use of this form is for viewing the definition of a method. For example:
gm :peRatiodisplays the definition of the method peRatio instead of evaluating it. If you wish to display the definition of a method that has multiple parameters, you must supply "dummy" values for each parameter. For example, the expression:
gm :peRatioWithPrice: 0displays the definition of the peRatioWithPrice: method. If the method has several parameters, you only need to place the ":" in front of the first one to display its contents, but you must supply a value for each parameter.
Classes and Instances - Overview
This section provides a basic overview for defining classes and instances. More detailed information is available.
Classes provide a basic tool for organizing your information. Vision comes with many built-in classes including Number, String, Date, List, and TimeSeries. All instances of a class respond to the same set of messages and use the same set of methods to do so. All instances of a class have the same number of properties and use the same names to refer to them.
You can define new classes as needed as illustrated below:
!Company <- Object createSubclass ;New classes are always created as a subclass of an existing class. Any number of subclasses can be created. For example:
!BankCompany <- Company createSubclass ; !InsuranceCompany <- Company createSubclass ; !SavingsAndLoan <- BankCompany createSubclass ; !Industry <- Object createSubclass ;The resultant class hierarchy is illustrated below:
The showInheritance message is used to display the class hierarchy for a specific class. For example:
Company showInheritanceAll objects respond to the message instanceList by returning an object representing the list of all the instances in a class. All List objects respond to the message count. Therefore, the expression:
Company instanceList countreturns the number of instances in the class Company. This count should be one immediately after the class has been created.
Th createInstance message is used to create a new instance for a class. For example:
!ibm <- Company createInstance ; !gm <- Company createInstance ; !citibank <- BankCompany createInstance ;
A subclass inherits both the properties and the methods of its superclass. The objects gm and ibm will respond to all Company messages. The object citibank will respond to all BankCompany messages which includes the set of messages defined for the class Company.
New properties, constants, and methods may be defined by the subclass. For example, you can define a property loansOut for the class BankCompany:
BankCompany define: 'loansOut'The object gm would not recognize the message loansOut because it is a Company. The object citibank will respond to this message because it is a BankCompany.
The subclass may also redefine a method that is defined by its superclass. If a method is redefined by a subclass, the instances of the subclass will use the new method. For example, a valid operation to perform on a company is to generate its balance sheet. The message balanceSheet could be defined to mean collect the required company data and produce a report in balance sheet format. The method to accomplish this operation would be defined as part of the class Company. Since a bank company would require different data and format for its balance sheet, this method could be redefined for the class BankCompany as outlined below:
Company defineMethod: [ | balanceSheet | ... get company data ... display company balance sheet format ] ; BankCompany defineMethod: [ | balanceSheet | ... get bank company data ... display bank balance sheet format ] ;All instances of the class BankCompany would use the second method when responding to the message balanceSheet. All other companies (i.e., non-bank companies) would use the first method, defined for the class Company. Although different methods would actually be executed, the request for gm's and citibank's balance sheet would look identical:
gm balanceSheet ; citibank balanceSheet ;In the first case, gm is the recipient object and balanceSheet is the message. Since gm is an instance of the class Company, Vision would look for its definition there. In the second case, citibank is the recipient object and balanceSheet is the message. Since citibank is an instance of the class BankCompany, Vision would look for its definition there. Since a definition of balanceSheet does exist for the class BankCompany, it is used. If no definition had been found, the definition at the class Company would have been executed. Notice that you do not have to specifically request a different report based on the type of company being analyzed.
When a message is sent to an object, Vision searches for its definition starting with the object's class. If the message is not found, the superclass' definition of the message is used. If the message is not defined by the superclass either, the superclass' superclass is used, and so on through the inheritance chain. The search terminates at the class Object. If the message definition is still not found, an appropriate error message will be returned.
It is sometimes useful to access the version of a message defined at the superclass of the object. All objects respond to the message super. For example, the expression:
citibank super balanceSheetcreates Citibank's balance sheet as though it were a standard company.
Review
This section has introduced many new concepts. The major points are summarized below:
- To create a new class, send the message
createSubclass to an existing class:
!testClass <- Object createSubclass ;
- To display the inheritance hierarchy for a class:
testClass showInheritance ;
- To create a new instance of this class, send the class the
createInstance message:
!test1 <- testClass createInstance ;
- To count the number of instances in a class:
testClass instanceList count
- To create a new property for this class that does not vary over
time:
testClass defineFixedProperty: 'startDate' ;
- To assign a value to this property:
test1 :startDate <- 951231 asDate ;
- To access this value:
test1 startDate
- To create a new property for this class that varies over time:
testClass define: 'rating' ;
- To assign values to this property for May, June, and July 1995:
test1 :rating asOf: 9505 put: 10 ; test1 :rating asOf: 9506 put: 13 ; test1 :rating asOf: 9507 put: 15 ;
- To access the most recent value:
test1 rating
- To access the June 1995 value:
test1 :rating asOf: 9506
- To create a new method:
testClass defineMethod: [ | sample | "This Method Displays The Rating Value " print ; rating print ; ] ;
- To execute this method:
test1 sample
A final example should be useful for unifying these concepts. Suppose that the class Industry is defined to have three properties: codeNumber, name, and growthRate. An object named autos is created as an instance of this class and its values are initialized.
!Industry <- Object createSubclass ; Industry defineFixedProperty: 'codeNumber' ; Industry defineFixedProperty: 'name' ; Industry define: 'growthRate' ; !autos <- Industry createInstance ; autos :codeNumber <- 3711 ; autos :name <- "Automotive" ; autos :growthRate asOf: 95 put: 10 ;
The class Company can be defined to respond to the message industry by returning the object representing the company's industry. For example:
!Company <- Object createSubclass ; Company defineFixedProperty: 'industry' ; !gm <- Company createInstance ; !ford <- Company createInstance ; !chrysler <- Company createInstance ; gm :industry <- autos ; ford :industry <- autos ; chrysler :industry <- autos ;The expression:
gm industryreturns the object representing the auto industry as its value. The expression:
gm industry codeNumberreturns the number 3711 and the expression:
gm industry namereturns the string Automotive.
A method could be defined for the class Company that computes expected sales based on the company's industry growth rate:
Company define: 'sales' ; gm :sales asOf: 95 put: 1000 ; ford :sales asOf: 95 put: 500 ; chrysler :sales asOf: 95 put: 100 ; Company defineMethod: [ | expectedSales | sales * ( 1 + industry growthRate / 100 ) ] ;The expression:
gm expectedSalesreturns the value 1100, the expression:
ford expectedSalesreturns the value 550, and the expression:
chrysler expectedSalesreturns the value 110.
Properties can refer to lists of objects. For example:
Industry defineFixedProperty: 'companyList' ; autos :companyList <- gm, ford, chrysler ;can be used to assign a list of auto industry companies into the companyList property defined for the class Industry. The expression:
autos companyListreturns the list of companies in the automotive industry. If you wanted instances of the class Industry to respond to the message sales by computing the total sales for the companies in the industry, you could define this method as shown below:
Industry defineMethod: [ | sales | companyList total: [ sales ] ] ;The expression:
autos salescomputes the total sales for the automotive industry. The expression:
gm industry salesproduces the same value. The expression:
gm sales / gm industry sales * 100computes GM's percentage of the automotive industry's sales.