08.01.2013 Views

Back Room Front Room 2

Back Room Front Room 2

Back Room Front Room 2

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

32<br />

ENTERPRISE INFORMATION SYSTEMS VI<br />

semantics of the other layers. The composite pattern<br />

determines all transitions between different layers of<br />

abstractions that make sense in such a system. The<br />

Component objects conform to the following<br />

observation by Koestler (1967) with regard to<br />

holons:<br />

they “...should operate as an autonomous, selfreliant<br />

unit which, though subject to control<br />

from above, must have a degree of<br />

independence and take routine contingencies in<br />

its stride, without asking higher authority for<br />

instructions. Otherwise the communication<br />

channels would become overloaded, the whole<br />

system clogged up, the higher echelons would<br />

be kept occupied with petty detail and unable<br />

to concentrate on more important factors”<br />

(Koestler, 1967, p.55)<br />

However, there are two important differences<br />

between our view of a complex software system and<br />

the holon view of the real world. Firstly, the holon<br />

hypothesis explains the structure and behavior of an<br />

“implemented” system (e.g. living organism), but it<br />

does not explain the abstractions needed for the<br />

development of a system. Short of further analysing<br />

the evolution of living organisms, we suggest that a<br />

large system that works is always a result of an<br />

evolution of a small system that was built using a<br />

supportable hierarchical structure reminiscent of<br />

holon structures. Therefore, the development process<br />

must start with a simple architectural design that<br />

proposes a hierarchy of layers of abstractions. It is<br />

crucial then that this architectural design is obeyed<br />

in the implemented system.<br />

Secondly, hierarchical structures found in nature<br />

tend to be relatively static. Their structure does not<br />

change much over time but behavior can moderatly<br />

change. On the contrary, hierarchical structures in<br />

software must support change much more readily.<br />

Enterprise information systems and business<br />

applications change in structures and in behavior<br />

(after all company structures, product and employee<br />

classifications, plant operation specifications, and<br />

many other aspects of business are in a constant state<br />

of flux). The design for change demands a special<br />

attention to dependency management, which is<br />

discussed next. It also explains the principle (that<br />

undeprins the composite pattern) to „Favor object<br />

composition over class inheritance” (Gamma et al.,<br />

1995, p.20). Inheritance model works poorly on<br />

dynamic structures.<br />

3 DEPENDENCY MANAGEMENT<br />

A dependency between two system objects exist if a<br />

change to the object that supplies a service may<br />

necessitate a change in client objects that demand<br />

that service.<br />

If all dependencies in a system are identified and<br />

understood, the system is said to be supportable, i.e.<br />

the system is understandable, maintainable and<br />

scalable. A necessary condition for supportability is<br />

that a sheer number of dependencies is tractable.<br />

Consequently, a task of software engineer is to<br />

minimize dependencies (Maciaszek and Liong,<br />

2004).<br />

In software systems, dependencies can be<br />

identified for objects of varying granularity –<br />

components, packages, classes, methods. The<br />

dependencies between more specific objects at lower<br />

levels of granularity propagate up to create<br />

dependencies at higher level of granularity.<br />

Accordingly, dependency management necessitates<br />

a detailed study of the program code to identify all<br />

relationships between data structures and code<br />

invocation between software objects.<br />

Figure 2 shows an example of quite troublesome<br />

dependencies in a simple program. The example<br />

refers to three Java classes AAA, XXX, and YYY. YYY<br />

is a subclass of XXX. AAA obtains a reference<br />

varA1 to YYY when instantiating it, but it keeps<br />

this reference as XXX type.<br />

When operA1() is called, it invokes<br />

operX1() on the superclass XXX. However,<br />

operX1() calls operXY1(). The operation<br />

operXY1() exists in the superclass, but it is<br />

overridden in the subclass (as shown in the Class<br />

Specification window). Accordingly, the overridden<br />

method is called in a down-call to YYY (because<br />

varA1 refers to YYY).<br />

The operation operA1() executes also<br />

operXY2() on the superclass XXX. Again, because<br />

operXY2() is overridden in YYY, the execution<br />

involves a down-call to YYY. However, the<br />

overridden method is an extension of the parent<br />

method. The parent method is invoked in an up-call<br />

to XXX.<br />

This simple example illustrates difficulties faced<br />

by developers and maintainers when trying to<br />

understand and maintain dependencies in the code.<br />

Interestingly, the example is not demonstrating any<br />

bad programming practice. It only illustrates how<br />

one of the dominant reuse techniques, namely<br />

implementation inheritance, “naturally” results in<br />

unduly complex, perhaps even unsupportable, code.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!