Why Not XML?
Jakob Jenkov |
When designing Butterfly we considered using an XML format for configuration like several alternative DI containers do (Spring, Nano etc.). In fact Butterfly was originally born with a simple XML configuration format. The idea was abandoned later however, due to two major annoyances in XML based configurations:
- The original XML format was not flexible enough.
- XML Formats are verbose = tedious to write and hard to read.
Especially the facts that XML formats tend to be verbose weighed heavily against an XML format. Spring's XML configuration files can be quite verbose and therefore tedious to write, and hard to read afterwards. That is why we ended up designing a script language tailored for dependency injection configuration.
Here is an XML example:
<bean name="dependency" class="com.myapp.Dependency" singleton="false"/> <bean name="bean" class="com.myapp.Bean"> <constructor-arg ref="dependency"/> <constructor-arg value="param2"/> <property name="value" value="3"/> </bean>
This example configures a factory named "dependency" and a factory named "bean". The "bean" factory creates a Bean instance and injects a product from the "dependency" factory into its constructor, along with the value "param2". Then it calls setValue(3) before returning the Bean instance. The "bean" factory is a singleton by the way.
You may think that The above Spring XML code is concise, but then look at the corresponding Butterfly Container Script:
dependency = * com.myapp.Dependency(); bean = 1 com.myapp.Bean(dependency, "param2").setValue(3);
This is both more concise and looks more like Java code.
Here is an example of Spring's List injections:
<bean name="dependency" class="com.myapp.Dependency" singleton="false"/> <bean name="bean" class="com.myapp.Bean"> <constructor-arg ref="dependency"/> <constructor-arg value="param2"/> <property name="value" value="3"/> <property name="someList"> <list> <value>a list element</value> <ref bean="myDataSource" /> </list> </property> </bean>
Here is how simple that is in Butterfly Container Script:
dependency = * com.myapp.Dependency(); bean = 1 com.myapp.Bean(dependency, "param2") .setValue(3) .setSomeList(java.util.ArrayList() .add("a list element") .add(myDataSource));
In this example a java.util.ArrayList() instance is created inside the call to setSomeList(). As you can see the List.add() method is called twice to add the string and myDataSource factory product to the list. This code is both shorter and looks more like Java than Spring's XML.
The fact One of the advantages you get when designing your own language is the freedom to e.g make methods that return void chainable. Like the add() method calls are chained above. In fact, a List / array shortcut has been implemented in Butterfly Container Script. Using this shortcut you could write the above like this:
dependency = * com.myapp.Dependency(); bean = 1 com.myapp.Bean(dependency, "param2") .setValue(3) .setSomeList(["a list element", myDataSource]);
The [] around the values in the setSomeList() call signals that the values are to be put inside a List or array, depending on the setSomeList() parameter type.
Tweet | |
Jakob Jenkov |