Co-operative Systems Engineering Group (CSEG)
Department Of Computing
Lancaster University
Lancaster, LA1 4YR.
E-mail: pemberto@comp.lancs.ac.uk
With computer applications forming the information backbone of many large organisations it is becoming increasingly important to make software architectures adapt to cope with changing external organisational requirements. Software is required to adapt to evolving working practises and procedures, therefore a new approach to software design is required. Traditionally, the majority of design effort has hinged on functional application requirements. Now software designers are forced to produce software architectures that are capable of evolving with the organisation, rather than the organisation needing to adapt itself to use its legacy software in a new context. In this short paper we describe the concepts of middleware, reflection (i.e. self-discovery), and its advantages in terms of the ability to guide software evolution.
Software must be flexible enough to support embryonic work requirements. To incorporate “maintenance phase” changes we propose a process of design for evolution where the careful application of software engineering principles helps lead to more evolvable and reusable component based software architectures. We show how to apply self-discovery (called reflection) to support evolution through self-reasoning and adaptation, where a software component can query itself and make internal modifications to adapt to new external requirements. We also look at the application of middleware technologies that can be used to glue our adaptable components together, allowing them to communicate. Middleware is important as it enables a separation of concerns between processing, application level logic, and its communication infrastructure. Concern separation is an important first step towards evolvable software.
Software plays an increasing role in virtually every industry sector. Without software and information systems many organisations could not function in the same capacity as is currently achievable. Such systems range from those dealing with bank account details managing customer transactions when money is withdrawn from an ATM, through to systems dealing with the management of information and its distribution within organisations (i.e. workflow systems). All such software applications have common design requirements in terms of maintainability, of which we consider evolution as a sub-phase of this particular component of the software life cycle (maintenance also being concerned with error correction). Such systems typically need to cope with evolving services and data whose evolution needs to be supported by the application architecture.
Within the REFLEX project we propose the use of reflective, self-adaptive, component based architectures that can help simplify the cost and effort required when evolving a system to cope with changing external factors. We show how the incorporation of techniques such as componentisation, and loose coupling using middleware to separate out application specific concerns from communication services can help achieve our design goals. We also compare our approach with Enterprise Java, which apart from providing a 3-tier concern separation between data, processing logic and presentation, is far too static to be classed as a dynamically evolving architecture.
We define evolution as,
“A maintenance phase change in a system that occurs due to external,
usually commissioning organisational driven changes.”
With maintenance phase costs often being responsible for up to 60% of the total development cost of systems it is important to design the software architecture from the outset to reduce potential costs in later phases. Therefore we require support for evolution as working practices change. Adaptive components that communicate using a middleware brokering service provide the opportunity to do this.
Such evolutionary change may be small. For example, the change in the rate of basic income tax of a payroll system; conversely, large changes may be required that necessitate modification in the behaviour of the internal program logic. For example, changing the actual calculation method in the payroll program. In the case of changing the level of basic income tax, a good software design should not involve the hard coding of this rate into the application program. Therefore such an evolutionary change should only require the update of an external property defined in say an XML configuration file, for example. Applications that necessitate user “workarounds” in order to achieve a task demonstrate the failure of systems to adapt as the demands and tasks required by them change and evolve. For example, a proprietary data format may prevent information interchange between applications. With technologies such as XML we can solve these problems and have a common data format that we can evolve as required. For instance, an application may only be able to extract information from the XML file whose tags it understands. Another application may be able to extract further information from the tags that the previous application could not recognise. In other words information contained in the file that is not recognised is ignored. In either case we have with technologies like XML a common shared data format that at a basic level can be understood by many components that in the worst case are able to extract some common data from the file, such as classification information, or indexing terms. The data can be passed on to a specialised component once the data type is determined. This is not possible with software having so called closed information interchange formats that are application specific. The key to evolvable software applications is therefore one of openness.
Changes in poorly designed software architectures[1], require components to be re-engineered before they can continue to be used. Software architectures are able to shift development focus away from lines-of code towards coarse-grained components and their overall connection infrastructure through the middleware software layer. Taking such an approach during software design should yield large reductions in maintenance phase costs required to implement evolutionary change, and even possibly allow for dynamic reconfiguration if this is seen as a necessary goal for application availability.
Software architecture is the style and method of design and construction of strategic patterns and policies that shape a system. When applying a software architectural style we can decouple common functionality from the application allowing for the orderly arrangement of components into applications. To aid evolution software architectures should allow for,
Furthermore, we can also define dynamically adaptable systems as those that need to adjust in some way to accommodate changing environmental conditions during runtime. Such systems may also be termed as reactive systems. For example, a continuous media video streaming application may need to change its compression algorithm to cope with degraded network conditions to avoid network saturation. Other applications may only require redeployment evolution where it is sufficient to make the system change after the current set of transactions have completed and then re-deploy the application whilst queuing waiting transactions and reinitialising the state of the whole application. The later is the same architectural approach of enterprise JavaBeans, described later in the document. With REFLEX we are looking at supporting more dynamic adaptations or “on-the-fly” changes.
The architectural approach to achieve the application’s evolutionary requirements should be policy free. The policy (i.e. dynamic adaptation, or redeployment) ought to be left to the application level, i.e. the component architecture from which the application is built should impose as few constraints as possible. That is it should be open in terms of, for example, network protocol, configuration policy (i.e. dynamic, or off-line EJB style reconfiguration), component granularity, distribution, etc.
Figure 1 - RComponent N-tier Solution
Evolution can occur at a number of levels in a given software architecture,
with changes persisting both over the short and long term. Such changes are
usually unexpected and therefore of an unpredictable nature. Typically they
involve user workarounds in order for the existing application to cope with its
newly evolved requirements. We propose RComponents to help solve such
evolutionary problems. The application logic with RComponents is designed to be
accessed through the RComponent ORB (Object Request Broker). The ORB provides
services whereby we can reflect out the interface of the application logic to
the rest of the components that make up the application. Through the ORB we
also gain location transparency (i.e. the services of the application logic can
be accessed independently of their location on the network), and we can add new
behaviours and interfaces to the application logic without disrupting other
processing. The middleware provides the communication facilities between
components (see Figure 1).
RComponents are designed to help incorporate evolution through adaptive change occurring as part of,
q
Short-term change requirements, for example,
¨ Local adaptations, involving a small, localised change. For example, user specific customisations.
¨ Data evolution, i.e. a behavioural adaptation where the component reacts to some continuously changing external stimuli. For example, adapting data streams depending upon resource availability.
¨ Service evolution, a non-localised adaptation. For example, the addition of logging code to component methods.
q Long-term change requirements, for example,
¨ New service integration. For example, a new client application running on a low-power PDA could be introduced into the software architecture that is required to interact with the application, e.g., a WAP enabled mobile phone.
¨ Paradigm/process shifts, for example the move to Internet banking from a less distributed banking model, or the shift from £ bank accounts to € accounts.
Many companies are struggling to achieve scalable, maintainable, and highly available information systems to meet the demands of their customers. To implement an evolvable solution to these problems a robust server-side platform consisting of a runtime environment, middleware services, development and management tools is required to provide a realistic implementation platform allowing for greater development efficiency through component specialization. Such components can provide specific application logic that can be reconfigured and reused as processing requirements change. Such support technologies are being evaluated and reflection services implemented in the REFLEX project at Lancaster University. This allows the organization to focus on solving the business problem at hand rather than implementing core application support services. This is similar to the EJB approach. Enterprise Java provides a container environment that handles transactional support, security, database connectivity, and component management. What it does not provide is dynamic adaptability. The REFLEX project intends to solve this problem.
A Distributed Information Management (DIM) system is a typical "enterprise application" implying,
· High scalability
· High availability
· High reliability
· Good security
· Transactional support
· And a distributed processing architecture.
Enterprise applications require access to a variety of infrastructure level services, including,
· Distributed communication services (typically provided through the middleware)
· Naming and directory services (again middleware related)
· Transaction services
· Messaging services (asynchronous messaging events)
· Data access and persistence services
· Resource-sharing services
A distributed information management system can be considered as a specialisation of a generic enterprise application dealing specifically with the management and flow of information between individuals within a particular organisational domain. Information management can therefore be defined as,
“The planning, budgeting, control and exploitation of the
information resources in an organisation.”
The term encompasses both the information itself and the related aspects such as personnel, finance, marketing, organisation and technologies and systems. Typically middleware such as CORBA does help data integration between existing legacy information services by providing “interface wrappers”. What existing middleware does not support is the adaptation of the code to fit into its new environment.
During the early 90s, there was a shift from the traditional two-tier, client-server distributed architecture model to application architectures of the more flexible three-tier model. This new architectural style enables the separation of business logic from system services and the user interface. Application logic is placed in the middle tier. Such architectures can better exploit middleware services such as transaction monitors, message-oriented middleware, and object request brokers (ORBs), giving a potential direct architectural path to application implementation. With the pressure of information access from the Internet, this has lead to the demand for quickly downloadable lightweight, and easy to deploy thin-clients that have access to organisational information, for example share dealing from a WAP phone. The three-tier architectural model allows more flexible multi-client access to such information, and allows for the exploitation of thin clients particularly suited to ubiquitous platforms. Due to its separation of concerns it also lends to evolve-ability,
Before the development of middleware platforms such as CORBA (geared towards client-server architectures) and Enterprise Java (3-tier), developers have had to build such reusable services by hand. The advent of flexible middleware has allowed the leverage of (re)configurable standardized components, enabling the development of readily scalable applications to meet changing business conditions. This can be achieved because we have filtered out the logic of the application and compartmentalised the software architecture therefore refocusing developer effort away from core services to the coding of program “business” logic.
In multi-tier architectures, the client application contains only presentation logic. The business logic and data access logic are partitioned into separate components and deployed on one or more servers. Multi-tier applications have to interact with a variety of middleware services. An application server manages and recycles system resources, such as processes, threads, memory, database connections, and network sessions on behalf of the applications, and also provides access to infrastructure services, such as naming, directory, transactions, persistence, and security. It also manages the middle-tier components that provide the logic behind the application. In the case of a 3-tier application the application display components (i.e. user interface) can be re-written independently of the business logic making client migration to portable devices more straightforward. If we take the three-tier architecture and combine it with meta-level introspection, and configuration management services then we have a strong evolvable architecture for enterprise class applications.
Figure 2
- Enterprise Java Architectural Model
Enterprise Java (or J2EE – meaning the Java2 Enterprise Edition) was introduced in 1998 by Sun Microsystems as an architectural platform for the development of enterprise class applications (see Figure 2). J2EE is an evolution of several Java technologies, such as Java Database Connectivity (JDBC), Java Remote Method Invocation (RMI), Java Message Service (JMS), and Java Naming and Directory Interface (JNDI). The cornerstone of J2EE is the Enterprise JavaBeans (EJB) technology, a standard for building server-side components. As can be seen the Java Enterprise framework provides a very feature rich platform for the implementation of re-deployable data driven distributed applications.
EJBs provide location transparency, componentisation, and a multi-tier architecture with defined interfaces and standardised communication protocols. The enterprise middleware container service also provides generic support for the management of transactions, persistence and component location and activation. The model is also highly customisable and therefore ideally suited to meeting the needs of evolvable DIM applications whilst focusing the developer on the application logic and removing the need to re-implement core services.
J2EE’s underlying component model supports customisation without requiring access to component source code. Application behaviours and runtime settings are defined at deployment time through a set of attributes (called component properties) that can be changed at deployment time via XML descriptor files associated with each component. Configuration tools are usually provided by the application server’s vendor, which support application creation, deployment and bean configuration. XML files are used by the EJB container to specify the EJB’s activation, transaction, and persistence model. All middle tier logic components are fully managed by the EJB container for the application clients. Therefore with Enterprise Java as an architectural framework we have a readymade flexible, adaptable structure for evolvable software in distributed information management systems
. The problem with the
EJB container is that it is a black box, with imposed policies for security,
activation, and persistence. There is little support for reflection at runtime,
and therefore it is difficult for a component to reason about its environment
(i.e. the EJB container) and modify itself as a result of external stimuli.
Apart from the lack of
reification Enterprise Java has good support for separation of concerns, but
still suffers from inflexibility due to the inherent limitations of the
three-tier architecture, and it can be difficult to adapt legacy components to
operate within the EJB container. The container-based approach can tend towards
a monolithic heavyweight server, which does not have the flexibility to spread
processing concerns throughout nodes as an unrestricted N-tier architecture.
To conclude, EJB has a
restricted degree of “openness”. We are limited to 3 core EJB types (i.e.
stateful, stateless, and messaging beans), and the policies for security, and
activation are hidden from the application level and may not be appropriate in
all applications. Reification, of these services where the policy is made
explicit to the application is required. Therefore the policy imposed by the
container can be swapped dynamically without the need to fully re-deploy the
applications. Currently such a lack of openness within these areas of
Enterprise Java limits the potential for dynamic application evolution. The
move towards reflective components, and middleware polices should help remove
these problems.
Recent
moves from poorly structured software architectures to those using middleware
services have improved the maintainability of applications. 3-tier
architectures have separated communication requirements from business level
processing. Current advances such as reflective components, and middleware
allow non-implicit transaction and security policies to be employed. We are
therefore able to implement applications that are self-monitoring, adaptive,
and open; and therefore policy free. Such changes can be reactive in response
to external environmental factors, such as evolving working practices, or can
be the result of a process or paradigm shift.
Reconfiguration
allows us to add new knowledge into the processing system, or change existing
logic. Our brief overview of Enterprise Java has shown that although EJB
provides for the separation of concerns in the 3-tier architecture, truly
adaptive applications require reflection through middleware services and
processing components, whereby the application logic and its communication
infrastructure can respectively react to unexpected and unpredictable change.
Performing this change in a controlled and safe manner where the application
makes explicit the changes through its reflective nature should be the goals
for the next generation of component, and middleware services.
[1] An architecture can be defined as a particular configuration of application components and communication “connectors” connected to perform a specific application task.