Evolve: Using Components to Improve on Dependency Injection
Evolve is a lightweight tool for creating, wiring up and executing JavaBeans, allowing them to be treated as full components. Developers can use Evolve to graphically describe JavaBeans and also optionally generate the Java code for the setters and getters. It supports four primary activities: creating or importing JavaBeans, wiring these up to make more complex components, reusing and evolving them, and executing them. The Evolve system includes the following parts:
- Component Model with Connectors: This is a hierarchical component model with full connectors which make it simple and intuitive to express detailed structures.
- Resemblance and Evolution: These two constructs provide the support for component reuse. Resemblance is a form of component inheritance. Evolution builds on this to allow the structure of an existing system to be remodeled, without destroying the original definition. These facilities can be used to create variants of a system, or to switch in test components.
- Backbone Interpreter: Backbone is the component language and runtime environment which executes the programs created in Evolve. It’s an open source domain-specific language that allows JavaBeans to act as components, and to be wired up according to the component model. The interpreter reads in the text files, and uses the instructions to instantiate and connect up the beans. JavaBeans have a representation in Backbone and also in Java code. Composite components, formed by wiring together JavaBean instances, only have a Backbone representation however.
- UML2 Wiring Editor: This is a graphical editor for connecting the components using UML2 Component Diagrams and State Charts. JavaBean Code Generator: This is an optional component that can be used to define and generate setter/getter code for JavaBeans. Evolve also makes it easy to import and wire together existing beans.
Evolve has static error checking of models or configurations. It also allows different variants of a system to be created by using the evolution constructs, and all permutations are automatically checked.
Version 1.0.2 of the tool was released this week. Evolve's runtime is open sourced under the Apache License. The graphical tool is commercial and there's a community version.
InfoQ spoke with Andrew McVeigh, creator of Evolve framework, about the features and future road-map of the product. Responding to a question on the main motivation behind the development of Evolve, Andrew said that when he was working on a large component-based enterprise project which was being customized for several banks, it was very hard work to predict the way in which the software needed to be made extensible. Evolve is the result, where evolution of software is on an equal footing to creation.
InfoQ: How is Evolve different from traditional Dependency Injection (DI) techniques? What advantages does it offer over the traditional DI solutions?
Well, they both are used to connect up components/beans to make a system, and they allow components to be switched in and out for testing etc. So, they perform similar functions. There are two big differences though between Evolve and DI.
The first is that Evolve uses a full component model with connectors. This gives you a lot more power to describe the way that components are interconnected in a system. It's a bit like wiring up chips on a circuit board. With DI when you get issues with connecting two beans to refer to each other, or it's difficult to show the dynamic structures in your architecture etc, you are really bumping up against the lack of a proper component model. So that is one benefit Evolve brings.
The second big difference is that Evolve integrates two powerful component constructs which effectively let you design with the power of version control, at an architectural level. These are the key to the advanced reuse and evolution facilities. Using these you can evolve components without destroying the originals. Remarkably, any software you build using Evolve is always extensible. Extension and creation are completely aligned.
InfoQ: Can you discuss the typical application development process using Evolve framework - in terms of how different phases like modeling, design, development, testing, and deployment are performed - compared to a traditional application development process that's not using Evolve?
It's a great question. As an experiment, imagine how your own processes might change if every system you created had a complete link between the architecture and the code, and was guaranteed to be extensible. It basically means that design and coding become two sides of the same activity, and that you take a more agile approach to creating applications knowing that you can always extend or evolve. There's a lot less upfront planning required, and it's a very liberating way to develop.
The other difference is that because the component model is hierarchical, you can use very fine-grained components without the traditional problem in DI of having too many components to manage in your architecture. In Evolve you zoom in or out, viewing the system from the right level regardless of how many components there are.
So, Evolve is a lot more amenable to all parts of an application. We've used it for fine-grained things like creating and reusing GWT forms, we've used it for coarse-grained things like making services.
InfoQ: What are the limitations of the Evolve approach?
I think one of the biggest issues is simply that working with Evolve requires a mindshift. It flies in the face of accepted wisdom that says (a) that architecture and implementation are disconnected and (b) that extensibility must be pre-planned and factored in. It's been really difficult to get across that Evolve does not have these issues.
A more obvious limitation is that we don't yet have the extensive integration frameworks layered on top of our approach. On the other hand, the fundamentals of our approach are hugely powerful, so we are excited to see what can be built and how it will differ from existing toolkits.
Finally, Evolve currently requires the use of setter injection. Unlike DI, we allow complete flexibility when wiring up, and constructor injection clearly can't cope in the general case. e.g. when you have bidirectional links between components and other complex structures. We are looking at relaxing this constraint when the wiring up is not particularly complex or falls into the constrained DI wiring patterns.
InfoQ: What is the future road-map of the project?
We are finishing off a team version, which allows many developers to collaborate in real-time on a single system. Then we'll work on an Android version to let you use all these facilities to make mobile apps. Finally, it turns out that the evolution and extensibility support in Evolve makes it ideal for creating plugin architectures, and we are looking into that heavily.