Back Room Front Room 2
Back Room Front Room 2
Back Room Front Room 2
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.