• Keine Ergebnisse gefunden

4. Software Engineering & Design 37

4.5. Dependency Injection & Aspects

The considerations of the last section take concepts into account that rely on the knowl-edge and use of pure Java. Pure Java has the advantage that language basics and usage are well established and can be taught and learned quickly. At TU Berlin, a 4 hour, one

term class for engineers is sufficient to teach students the basics they need to attend the class that teaches application of MATSim. But, pure Java has some limitations and is conceptually not straightforward as one needs at least delegation, well designed in-terfaces, and factories to handle extensibility up to a certain limit. Tools that are not standard Java but enableDependency Injectioncan help, but may increase overhead for getting started. This section discusses if and how Dependency Injection might improve extensibility.

4.5.1. Dependency Injection & Spring

Dependency Injection is a more specific name for a concept that is also referred asInver- Inversion of Control &

Dependency Injection

sion of Control (IoC)(Fowler, 2004a). What does Inversion of Control or Dependency In-jection mean? Before a software module can be constructed, the dependencies required by the module must be instantiated. Dependency Injection provides conventions to specify the dependencies of modules apart from their source code. A Dependency In-jection mechanism constructs software modules. Thereby, it reads the specification, instantiates the dependencies, and injects them into the module.

In the advanced calculator example of the preceding section a specific factory has to be instantiated before an Calculator implementation can be used. This establishes a dependency from the Calculatorto the ExpressionFactory. The dependency was re-solved by a custom main(..) method for each variant of the calculator. This stops the debug or print functionality being a plugin (Fowler, 2004a).

The Springframework9 is an addition to standard Java. Its rich, highly modular, and Spring well documented set of features can reduce programming overhead in Java

standalone-and web-application development. At time of writing, the recent release documenta-tion (Johnson et al., 2013) covers topics as, e.g., modules for dependency injecdocumenta-tion, data access and validation, or a language extension of Java forAspect-Oriented Programming.

In the following example, the calculator example is constructed with theIoC container of Spring.

4.5.2. Dependency Injected Calculator

The components of the calculator example (Sec. 4.4.2) are assembled with Spring’sDe- Calculator Assembly

pendency Injectionmechanism10. For each extension of the calculator a differentmain() method is required. Therein, the different parts of theCalculatorare instantiated and plugged together. In the advanced design, this main() consists of the following steps

— instantiate theExpressionFactoryand theCalculator, instruct theCalculatorto use the factory, and compute the result.

9seewww.springsource.org/, last access 14.02.2013

10Examples for the calculator in this section can be retrieved viagit clone https://github.com/

dgrether/diss.git−−branch springbranchon the command line if git is installed properly.

Applying Spring’s dependency injection mechanism, the main() method do not have

Potential Spring

Assembly to be rewritten for every variant of the calculator. Listing 4.12 shows a potential ap-plication of Spring’sApplicationContextto push assembly of the calculator to a XML file: calculator.xml. The ApplicationContext automatically instantiates all modules (beans) configured in the XML file and injects their dependencies. Afterwards, from -ApplicationContext a completely configuredCalculatorinstance can be retrieved to calculate the result.

public static void main(String[ ] args) {

ApplicationContext context = new FileSystemXmlApplicationContext( new String[ ] {" ./ src / main / config / calculator . xml "} ) ;

Calculator calc = context.getBean(Calculator.class) ; System.out.println(" Result :␣" + calc.calculate( ) ) ; }

Listing 4.12: main method using spring for the calculator example

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" ..>

<bean id="expressionFactory" class="de.dgrether.diss.expressions.defaultimpl.

DefaultExpressionFactory" />

<bean id="calculator" class="de.dgrether.diss.AddCalculator">

<property name="factory" ref="expressionFactory" />

</bean>

</beans>

Listing 4.13: Dependency Injection with spring & XML for the advanced caculator example

An example Spring XML configuration for the advanced calculator is shown in List-ing 4.13. The first<bean..>element states that theDefaultExpressionFactoryshould be available within the container under the id"expressionFactory". The second<bean..>

element then advices Spring to instantiate anAddCalculatorand pass the object with id

"expressionFactory"viaAddCalculator.setFactory(..)to thisAddCaculatorinstance.

The presented example applies a pure XML configuration to Spring’s Dependency

In-Findings

jection. In principle, the XML configuration of each<bean..>element can contain any number of NAME→ VALUE properties. These are set to the instance via appropri-atesetNAME(VALUE) methods. Alternatively, the specification of the dependencies and parameters can be defined via Java code.

4.5.3. Discussion

For the calculator example, the steps to instantiate and run the application can be

en-Example

coded in four lines of code. Assembly of real software, however, is normally more complicated, the number of lines of code increases rapidly. The more complex the as-sembly, the higher is the possibility that domain specific code is mixed with code for

component setup and assembly. In consequence code reuse and combination of plugins gets harder.

The preceding example illustrates the straightforward use of Dependency Injection. Dependency Injection

Additional components can be plugged into a core software without touching the core components. There is no need for customizedmain(..)methods. This results in a de-coupling of object initialization and production code. If core software and plugins are developed by project contributors that do not work in the same group or do not even share a jointly modified codebase, decoupling is considered very helpful. For plugins, the advantage is obvious. In contrast, the assembly of core software modules via exter-nal configuration files and Dependency Injection does not have to ease the development process. A configuration, that is spread over several files, may not be administrable for some projects (Fowler, 2004a). If Dependency Injection for core software proves bene-ficial depends on the development process, the preferences of team members, and the size of the modules. Thus, an advice cannot be provided on this level of abstraction.

If component assembly is taken by Spring the Abstract Factory pattern to provide exten- Factories sions gets dispensable. Both, Abstract Factory and Dependency Injection help to make

“a system independent of how its products are created and composed”and make a system con-figurable with“multiple families of products”(Gamma et al., 1995, p. 88). However, De-pendency Injection cannot enforce independence of how the products are“represented”.

Neither the relationship between object families that shall be used together is enforced, nor the use of interfaces. Thus, Abstract Factory may still be required in addition to de-pendency injection. Possibly not on the top level of a software, but for the inner design of complex modules that are target of further development and extension. Then, the abstract factory implementations provided in the calculator example could be replaced by a more intuitive implementation. Their application should be reconsidered, if Java is extended by additional language concepts.

For the Java programming language exist additions that provide Aspect-Oriented Pro- Aspect-Oriented Programming

gramming (AOP)functionality, e.g., Spring orAspectJ11. The available features for aspect-oriented programming depend on the addition. With the aspect-aspect-oriented addition of Spring, aspects can be applied the same way as in AspectJ, except that only a 80 % sub-set of AspectJ’s functionality is available. Readers that are not familiar with AOP but know design patterns can view aspects as something similar to a Friend or Visitor Pat-tern implementation that is available as native concept of the programming language.

As a seamless addition to Java, aspect orientation offers “another way of thinking about program structure”(Johnson et al., 2013, p. 193). Aspect orientation may ease extensibil-ity of Java as horizontal extensions can be realized by aspects. With the new language constructs, however, one would also expect new pitfalls. For a rather small domain, as the transport modeling domain for that MATSim is developed, sorting out oppor-tunities and pitfalls may be overwhelming. Introducing aspect programming may be similarly difficult as changing the programming language (Sec. 4.2.4).

11seeeclipse.org/aspectj/, last access 15.02.2013

4.5.4. Conclusion

Overall, Dependency Injection and other features of Spring could help to ease

develop-Spring for MATSim

ment of MATSim. Especially for plug-ins, dependency injection is considered helpful.

For the core software, this is not obvious and should be subject to further discussion by core developers.

Other Spring features as, e.g., the standardized access to data structures can also help to focus more on the domain, i.e., the modeling of transportation. However, in a commu-nity like MATSim where developers are not necessarily computer scientists one could not expect each developer to read 717 pages technical manual before getting started.

Instead, a subset of Spring features can be defined. Then, a faster briefing of developers may be provided.

At the time of writing, the developer team12is of the opinion that a spring-like config-uration of MATSim can also be achieved by making the set-up process of a simulation sufficiently sequential, scriptable, and pluggable. Sorting out the set-up process in such a way would also be a pre-requisite before moving to a framework like Spring. Also, at the point the MATSim components are not considered to be sufficiently general to justify a move to a component framework.