您的位置:首页 > 其它

Dependency injection with Flex

2009-09-22 13:51 281 查看

Dependency injection with Flex

In previous articles I have written on Flex Development, I have stated that one of the good things about developing applications in Flex is how close to Java development it feels. Not to say that Java is the only language in which to develop, but if you work in a language/platform day in and day out to pay the bills, working with something new that is similar to a language/platform that you already know is a plus in my book. Specifically you will learn:

The Interface construct in ActionScript 3.0 and how it is functionally equivalent to Java interfaces.

How to use Interfaces in ActionScript 3.0 to achieve dependency injection.

How to use a simple form of dependency injection within Flex.

Requirements

In order to make the most of this article, you need the following software:

Flex 3 SDK

Download

Flex Builder 3

Try

Buy

Eclipse 3.3

Try

Prerequisite knowledge

For this article, familiarity with Flex Builder, although not required, would be helpful. Familiarity with object-oriented techniques is assumed as well as strong familiarity with ActionScript 3.0.

Understanding dependency injection

It is generally considered good object-oriented design to limit the responsibilities of a class to one thing (there may be times when, as a developer, you may need to be flexible with this rule, but I am talking in general terms here). To abide by this rule, most objects work with collaborating objects to fulfill their responsibilities. But where do these collaborating objects come from? Typically, without dependency injection, you would instantiate collaborating objects in your components. This creates tight coupling between objects, which makes your app more difficult to maintain over time and harder to unit-test your components. Dependency injection is, in very rough terms, when you would use a framework or container to "inject" the collaborating objects into the respective objects that need them (see a more formal definition). This ends up being a very powerful pattern. You can develop your objects and test them independently (mocking out collaborators if any) and "wire" them together to build your application. The Spring framework is a ubiquitous DI framework in the Java development world.

I'll use a subset of the Spring Framework, Spring-MVC, as an example. In Spring-MVC you have Controller objects that handle inbound requests from a client; in this case, assume a web-browser. In most web applications today, there is a database or datastore on the back end of the application containing information that needs to be retrieved and displayed to the user. Suppose a user enters a search to list books by author. In the simplest terms, the Controller object accepts the request, pulls the author name out of the request parameter, hands that name off to the BookService object and expects a list of book titles in return, and then sends that list of titles back in response to the user request. The Spring framework handles setting the BookService object into your Controller object (configured through XML or annotations, but that is beyond the scope of this article). And the fact that your BookService object implements a Java interface means that changes to the implementation of the service object are invisible to the Controller object. That is a very good thing. As long as the parameters and return type of the method don't change, the Controller object should not care at all how the service does its job. But what does that have to do with Flex development?

Dependency injection through ActionScript 3.0 interfaces

The Interface construct is what gives dependency injection its power. You have a bunch of objects that rely on each other to do their work, and instead of expecting a particular implementation of an object, which, if changed, would required changes in all dependent objects, the objects are only concerned with the contract specified by the interface, so implementation changes can be made seemlessly and testing is a much easier task. Well, guess what: ActionScript 3.0 supports the same Interface construct that makes writing loosely coupled code so much easier.

One would use Interfaces the same way you would in Java:

Define your interface. An ActionScript 3.0 interface could look like:

package com.example {
public interface Controller {
public function search(searchParams:Object, callback:Function=null):void
}
}


Define a class that implements the interface.
package com.example {
public class HttpController implements Controller{
private var _httpService:HTTPService= new HTTPService();

public function search(searchParams:Object, callback:Function=null):void {
details omitted for clarity
}
}
}


In the example above, you have a Controller interface and an implementation, HttpController, that will be used to communicate with the back end of your application to execute searches. HttpController is using the Flex object HTTPService to do the work of sending the search request and handling the response. You can see that the HttpService object is instantiated in the HttpController class. So why not inject the HttpService class as well? The point to having an interface is that you can change the implementation seamlessly to suit the needs of your application. In this case, if you needed another mechanism for searching, you would simply write a new implementation or modify the existing one.

Dependency injection, Flex-style

Here's where the rubber meets to road, so to speak. You have seen what dependency injection is and its importance in good application design. But how do you achieve that in a Flex application? As an example, say you have created a component to accept user input and display search results. This component is really a container of sorts, so you have extended the Panel class to hold the various objects to complete your search functionality. Additionally, you have defined your component's behavior entirely in an ActionScript class (no
<script></script>
tags in your MXML files!). Here's an example of what an extended Panel object could look like (with details omitted for clarity) in an ActionScript file:

public class SearchPanel extends Panel{
private _searchController:Controller;
public function search(text:String):void {
this._searchController.search(text, this.callBackFunction);
}
public function set searchController(searchController:Controller):void {
this._searchController = searchController;
}
public function get searchController():Conroller {
return this._searchController;
}
}

The salient point from the above example is the instance variable,
_searchController
of type
Controller
and the getter and setter methods that have the same name as the variable sans the "
_
" character. Next, take a look at the MXML file called SearchPanelView.mxml representing the visual properties for your component (again, some details omitted for clarity):

<?xml version="1.0" encoding="utf-8"?>
<SearchPanel xmlns="bbejeck.example.*"
xmlns:comp="bbejeck.example.*"
xmlns:mx="http://www.adobe.com/2006/mxml">
<comp:HttpController id="searchController" />
</SearchPanel>

From the example MXML file above, there are a couple of key points:

The line
<comp:HttpController id="searchController" />
defines the controller component to be used by the SearchPanel class. Take note that the class name in the definition is "HttpController," while the type of the
_searchController
instance variable only expects a type of
Controller
, it does not matter what the implementation is.

The
id
attribute matches the name of the getter and setter functions in the SearchPanel ActionScript class.

When the SearchPanelView.mxml file is loaded by the Flex application, the "HttpController" object is instantiated then the corresponding setter method in the SearchPanel class that matches the
id
attribute is called, injecting your Controller implementation into the SearchPanel class

When you need to change your search functionality, you can either change the HttpController object, or define a new implementation and modify the SearchPanelView.mxml file, either way your SearchPanel code does not need to change at all.

Conclusion

You have seen how to use dependency injection in Flex. The Flex application will inject into your components what objects are defined in the MXML file where the
id
matches a corresponding setter method. We are essentially getting a basic DI container for free by using Flex.

This leads us to some conclusions:

When building applications, instead of focusing on building the application itself, you focus on what individual components are needed to build the application and what these components need to do their jobs. What you end up with is a large amount of "ready to go" components that just need some "callback" or service objects implemented in order to build the application. Code reuse is very high and the time it takes to build new applications is substantially reduced.

Unit testing is much easier. Now, if you have components that have interface-based collaborators, when you are testing those components you can manually call the appropriate setter methods and supply mock objects that implement the correct interface but provides expected behavior for the test.

Where to go from here

For a great example of dependency injection used in Flex, make sure to check out the Spark architecture in Gumbo, the next release of the Flex framework.

The examples for this article were pulled from a previous article I have written on Flex development, and the code examples there use the same type of dependency injection discussed here.

Several open-source projects have been developed to provide a formal Dependency Injection framework for Flex development. Some are:

Swizframework

Prana

Smartypants

While there are may excellent books on Flex programming, I have found the following to be particularly helpful:

Essential ActionScript 3 by Colin Moock

Advanced ActionScript 3 with Design Patterns by Joey Lott and Danny Patterson

About the author

Bill Bejeck is a software engineer for Near Infinity in northern Virginia. When not playing with his daughters, he spends too much time on his laptop. You can send your comments to Bill via e-mail.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: