• Rezultati Niso Bili Najdeni

2.4 The Object Model

2.4.2 Objects

Objects play a key role in the way we comprehend the world from a very young age. Interaction with physical objects is essential for children’s development.

Babies will, at a crucial stage, gain an understanding that objects have an identity and continue to exist even when they leave the child’s perception, a concept known as object permanence. From this aspect of human cognition an object can be something tangible or visible, something that can be intellectually understood or something to which a thought or action can be directed [6]. Objects in software development do not have to relate to the real world and can relate to some invention of the design process that can in collaboration with others achieve some higher-level behavior. Considering these aspects allows for a more refined definition as suggested by Smith and Tockey who state that “an object represents an individual, identifiable item, unit, or entity, either real or abstract, with a well-defined role in the problem domain” [34]. Every object, therefore, has a state, behavior and identity. Similar objects share the structure and behavior defined in their common class. An object can also be labeled as an instance, these terms are interchangeable [6].

2.4.2.1 State

To explore the notion of state consider the operation of a coffee machine. Usually a person interacts with such objects by inserting money and making a drink selection. The machine then outputs a cup and mixes the coffee powder, water and milk in different quantities depending on the chosen drink type. If the user

operates on different states, each of which requires a specific action to proceed.

Booch, therefore, defined state as a property which: “encompasses all of the (usually static) properties of the object plus the current (usually dynamic) values of each of these properties” [6].

A property can be described as “an inherent or distinctive characteristic, trait, quality, or feature that contributes to making an object uniquely that object” [6].

State of the coffee machine, for instance, is one of its properties. The ability of the machine to collect money is another. They are both static or fixed properties that contain a dynamic value (both the state of the machine and the quantity of money change during operation). Properties can also hold static values which stay the same from the moment an object is created until it gets destroyed. One such property would be the machine’s serial number. Similarly, the property of an object can in some cases be dynamic. Each property holds a value that can be quantitative, or represent another object. For instance, a car drives at a certain speed (property with a numerical value), but it also has an engine (property denoting an object).

2.4.2.2 Behavior

Booch et al. define behavior as “how an object acts and reacts, in terms of its state changes and message passing” [6]. Therefore behavior represents an objects outward activity. Objects interact through operations that represent actions per-formed on objects meant to elicit a response. Operations are labeled differently depending on the programming languages. Languages like C++ use member functions, in pure object-oriented languages objects are passing messages, while in Java and LabVIEW operations are declared as methods. Regardless of the name, behavior is only partly affected by the message or the operation invoked;

the object’s state plays an equally important role. The coffee machine can only produce a beverage if enough money has been inserted. The process will deduct the price of the drink from the inserted change during selection, thus changing the state of the machine. Therefore, an operation is a function of the objects

36 Software Design Principles

state and the operative arguments (e.g., the amount of change the user inserts) which has the potential to alter the state of the object. This leads to a more refined definition of an object’s state where “the state of an object represents the cumulative results of its behavior” [6]. Booch et al. identified five typical kinds of operations that can be performed on an object [6]:

• modifier: an operation that alters the state of an object,

• selector: an operation that accesses the state of an object but does not alter the state,

• iterator: an operation that permits all parts of an object to be accessed in some well-defined order,

• constructor: an operation that creates an object and/or initializes its state,

• destructor: an operation that frees the state of an object and/or destroys the object itself.

The last two operations represent the necessary infrastructure for the existence of an object, while the first three types can be used during the objects lifetime.

Depending on their behavior an object might be classified as active or pas-sive. Active objects contain their own thread of control, while passive objects do not. Therefore, active objects commonly act autonomously and can display behavior with out any actions from other objects, while passive object can only display behavior when acted upon. Thus, active objects serve as the roots of control. Systems with multiple threads tend to usually employ multiple active objects, while sequential systems usually have a single active object which serves as the manager, controlling an event loop that invokes operations of other objects.

Other types of sequential systems consist of only passive objects, where control is distributed among them.

2.4.2.3 Identity

Khoshafian and Copeland defined identity as “that property of an object which distinguishes it from all other objects” [35]. They further note that “most

pro-approaches are problematic as they compromise the identity of an object.

The problem with identification via variable names is that objects can be accessed in various ways and bound to multiple variables, therefore making it impossible to know if different variables are referring to the same object as the objects themselves contain no identifiable features. For instance, let us assume that an object has two variables pointing to it. This problem is called structural sharing and means that a single object is known under two names. If the first pointer is now used to destroy the object, the second pointer will keep pointing to the memory location where the object was last seen. Meaning that the second pointer will now hold a completely meaningless, random value; the pointer be-comes a dangling reference. A third problem is encountered when both pointers start pointing at a different object. At that point the object is lost causing a memory leak meaning that the space in memory taken by it can never be recov-ered as there is no longer any way of accessing that object and deleting it. Some programming languages like Java use a process called garbage collection to remove memory leaks during operation, while in others like C++ the reserved memory is only released once the program is concluded. In languages without garbage col-lection these memory leaks can cause significant issues, especially when dealing with long-running programs.

As mentioned previously databases typically assign a unique identifier to an object and use that value as an objects identity. One of the problems here is that the identifier cannot be allowed to change, even though it is a user-defined descriptive value. For instance, a company’s department might use the name of the department as its identifier and have it replicated in each employee object to keep track of where they work. However, the department’s name might need to change in the future, causing a discontinuity in the department’s identity and update problems for all the employees working there. It is also impossible for identifier keys to identify every object in a relational model. For instance, an employee object could have an attribute referring to their spouse by name. If their spouse joins the company at some point in the future it would cause a dis-continuity in the identity of the spouse. Another problem occurs when the choice

38 Software Design Principles

for what determines an objects identity key changes. For example, two compa-nies are merging. One previously used an employee number for identification, while the other used a national identification number. After the merger, one of the companies needs to change its identification keys, causing a discontinuity in identity for all of their employees.

Khoshafian and Copeland offer some suggestions for mitigating these problems inspired by languages with strong identity support [35]. One of the suggestions proposes the use of surrogates where every object of any type is associated with a globally unique surrogate from the moment it is created. This makes it possible to check if two variables reference the same object by comparing their surrogates.

When an object is deleted, dangling references can be found by searching for dan-gling surrogates. Garbage collection can be implemented by storing the number of times an object is referenced and keeping it updated. The approach also fixes discontinuity issues as the surrogate provides a unique, global, static identifier with no semantic connection to the object in question.

2.4.2.4 Relationships Between Objects

A relationship incorporates all the assumptions that two objects make about each other, including which operations the objects are able to invoke and what resulting behavior is expected. Booch et al. points out two types of object relationships that are of particular interest [6]:

1. links and 2. aggregation.

Links The term link is derived from Rumbaugh et al. who define it as a:

“physical or conceptual connection between objects” [36]. An object uses its links to collaborate with other objects. As stated by Booch et al. a link denotes a specific association through which an object (client) requests services from another object (supplier), or through which an object may navigate to another [6].

1. Controller: This object sends messages to other objects, but does not receive any itself. It operates others.

2. Server: This object can only receive messages. It is operated upon.

3. Proxy: This object can both send and receive messages. It can both operate and be operated upon and is typically used to represent real-world objects.

Before object A can talk (send a message) to object B through an existing link between them, it needs to see object B. The question of visibility is more important during implementation, rather than analysis where it can often be ignored. These decisions are still important as they determine the scope and level of access between linked objects.

When a message is passed through a link, the two objects in sync. Synchro-nization is pretty simple for sequential programs, as it only requires invoking the desired method. However, with multiple control threads, the approach needs to be more sophisticated. As active objects contain their own thread of control, passing messages between them should pose no issues. However, passing mes-sages to passive objects could cause issues of mutual exclusion. For instance, a passive object can receive an operation while its already busy processing another operation from a different active object in a separate thread. Both operations can now be accessing and changing the same data, at the same time causing un-expected behavior and unpredictable issues. Therefore, when an active object is linked to a passive one, synchronization must be approached in one of three ways [6]:

1. Sequential: The correct operation of the passive object is guaranteed only when one active object is present

2. Guarded: The correct operation of the passive object is guaranteed for multiple threads of control, but mutual exclusion must be achieved through collaboration between active objects

40 Software Design Principles

3. Concurrent: The correct operation of the passive object is guaranteed for multiple threads of control, and mutual exclusion is guaranteed by the sup-plier (the passive object itself)

Aggregation In contrast to the link that describes a peer-to-peer client/sup-plier relationship, aggregation describes a hierarchical whole/part relationship, where the whole otherwise known as the aggregate can navigate to its parts.

Aggregation is therefore a specialized type of association.

Aggregation indicates a containment that can, but does not have to be physi-cal. For instance, a car physically contains an engine, wheels, a transmission box, etc. Meanwhile, a driver can uniquely own a car, thus forming an aggregation relationship, but the car is in no way a physical part of the driver himself.

Links and aggregation have different costs and benefits between them. Links permit looser coupling between objects, while aggregation provides encapsulation of the parts, hiding them as secrets of the whole [6].