Problem Statement

In component-based software development, software components and application programming interfaces (APIs) tend to be developed concurrently in different locations with asynchronous lifecycle. In practice, new versions of software components often change and so require applications that use the components to be changed. Typically, conflicts among software components are commonly encountered when integrating software components together. Detecting and resolving conflicts by incorporating changes and/or upgrading versions of components are crucial in component-based software maintenance. However, in current practice, conflicts are usually resolved in an ad-hoc fashion by all parties involved after it happened. Updating the software in a distributed environment is not trivial. Components in a component-based system are interdependent to each other.

In studies on the evolution of component-based software and APIs, several researchers have examined the changes in real-life software systems. Recent research showed that the majority of compatibility-breaking changes between major releases of five popularly used APIs are refactoring changes. Refactoring changes are not trivial in nature and many of them break the compatibility in component-based systems. Many refactoring tasks such as changing the name or interface of a global function can potentially have a global scope since refactorings often cut across module boundaries and cause changes to many parts of a system. E.g., every part of the system that uses that global function will have to change. Importantly, the complexity of changes is largely exposed in component-based software development in which multiple users refactor code simultaneously.

The state-of-practice process is for all developers to check in their code before they leave for the weekend. A senior designer then makes global changes (e.g., refactoring changes) and commits the refactored code. Upon their return, developers check out the refactored version. However, by forcing refactorings to be performed only by a few people at a certain time, opportunities for parallel code improvement are lost. Therefore, automating the process of integrating concurrent refactoring changes in component-based software development is necessary.

To address the component-based software update with refactored programs, we provide a method to integrate changes including refactoring and editing changes to both a component and the one that uses it. The method includes a formalism for the dynamic composition of refactoring sequences in multi-user environments. The formalism allows us to formulate the dynamic composition of refactorings, to automatically check the validity of compositions, and to resolve potential conflicts caused by concurrent refactorings.

The formalism provides the theoretical foundation for our refactoring-aware software updating tools in which one is designed to be used for online (run-time) and one for offline (source code) update. The source code merging/updating tool, which is built as part of our MolhadoRef SCM system, automatically resolves more conflicts (even changes to the same lines of code). Because it takes into account the semantics of refactorings, the updating is also more reliable: there are no compile errors after merging and the semantics of the two versions to be merged are preserved with respect to refactoring operations.

To address the online update issue for mission-critical systems, we have also developed an online updating framework based on Virtual Execution Environment (VEE). The framework uses the aforementioned formalism to guide the update process at the run-time level. Furthermore,the update environment manages update for running applications without the need for special code modification. The framework suggests an extension to VEE to take the change logs, which record changes to API and client components, and apply proper updates to the running system without human intervention and without shutting down the system. It also allows different types of updates, since it relies on the general formalism and it does not require a specially compiled application for the update target. Using this framework, we implemented an extension to Jikes RVM, an open source JVM, that applies changes found in the change logs to the running application. We also performed an experimental study to measure the overhead of the extension and the effect on application responsiveness during the update process.