Uses for non-visual Flex components

Brian LeGros | December 13th, 2007 | programming  

Recently, I've been interested in examining the features of non-visual components as it applies to Flex. I don't hear them talked about a lot (at least in the small part of the blog-o-sphere that I read), but I think there are some uses for these types of components that could really catch on in the community. I've tried to put together a sample application to show an example of some of the ideas I'm playing with in my head.

So the big place where I see non-visual components having a use is when attempting to bridge the stateless and stateful portions of a Flex application, mainly in the area of remote services. When I design a web service or remote object to be used by Flex, I typically build it in Java (or ColdFusion) and I design the service such that its methods operate in a stateless fashion. For example, when I call a method on my service, I don't expect previous calls to that method to influence the results of my current call; at least from the perspective of the caller. Additionally, I have the expectation that more information may be required when calling the method since the remote object receiving the call has no context in which to interpret the method call besides the method itself. Now I'm know an argument can be made about whether something truly is stateless or not, but that's not the goal of this post. Let's work with this ad hoc definition of stateless for now.

Flex provides us with a very simple, global means to get a hold of these services: RemoteObject, WebService, HttpService; there are other means by which to connect to remote services, but for now let's take the simple example of stateless RPC-based services. Typically in my Flex applications, I want to emulate a synchronous call from the application to the service (using something that implements IResponder or mapping the result/fault methods manually). Ideally I should have a class abstracting these calls to improve cohesion in the application; frameworks like to use command, delegate, or proxy classes, for example. During the emulation of this synchronous call I usually have my result/fault handler call out to a method on a class to change the state of an object (e.g. - setting values on the ModelLocator in Cairngorm), consequently firing propertyChanged events and/or custom events to update visual components via data binding.

All that being said, there are a couple of things with this approach that I want to address. First, I'm making the assumption that the class which abstracts the interactions with my service should also remain stateless. No where in the creation of the object am I changing its state so that the behaviors associated with the object may have a different context when executed. Second, I'm making the assumption that the behavior of this abstracting class must be separate from the data it uses. Propagating a change in an object's state via events is the back-bone of Flex data-binding. Not only that, but data binding is very simple to use and code, why shouldn't this simplicity be available in the ActionScript class abstracting the call to the remote service?

So that's enough conceptualizing for now, let's look at some example code. Please note the entire working example can be found at this location.

In this example, we have a very simple phone directory application. A SearchView exists which takes input from the user and announces a custom event (SearchEvent) passing that user input as its payload (i.e. - SearchCriteria). This event is handled by the Application class which in turn calls the find() method on an instance of SearchComponent. SearchComponent is a non-visual component which uses data-binding to propagate changes from the stateless world into my stateful Flex application. The code for SearchComoponent can be found below:

  1. package com.brianlegros.nvc_example.component
  2. {
  3.    import flash.xml.XMLDocument;
  4.    import mx.collections.XMLListCollection;
  5.    import mx.collections.ListCollectionView;
  6.    import mx.collections.IList;
  7.    import mx.collections.ArrayCollection;
  8.    import flash.net.URLRequest;
  9.    import flash.net.URLLoader;
  10.    
  11.    import com.brianlegros.nvc_example.vo.Employee;
  12.    import com.brianlegros.nvc_example.vo.SearchCriteria;
  13.    
  14.    public class SearchComponent
  15.    {
  16.       [Bindable]
  17.       public var locations : IList;
  18.      
  19.       [Bindable]
  20.       public var departments : IList;
  21.      
  22.       [Bindable]
  23.       public var employees : IList;
  24.      
  25.       private var data : XML;
  26.      
  27.       public function SearchComponent() : void
  28.       {
  29.          var request : URLRequest = new URLRequest("results.xml");
  30.          var loader : URLLoader = new URLLoader(request);
  31.          loader.addEventListener(Event.COMPLETE, function() : void
  32.             {
  33.                data = XML(loader.data);
  34.                
  35.                locations = findLocations();
  36.      
  37.                departments = findDepartments();
  38.             }
  39.          );
  40.          
  41.          this.employees = new ArrayCollection();
  42.       }
  43.  
  44.       private function findLocations() : ArrayCollection
  45.       {
  46.          var temp : ArrayCollection = new ArrayCollection();
  47.                  
  48.          for each(var item : XML in this.data.employee.location)
  49.          {
  50.             if(!temp.contains(item.toString()))
  51.             {
  52.                temp.addItem(item.toString());
  53.             }
  54.          }
  55.          
  56.          return temp;
  57.       }
  58.      
  59.       private function findDepartments() : ArrayCollection
  60.       {
  61.          var temp : ArrayCollection = new ArrayCollection();
  62.                  
  63.          for each(var item : XML in this.data.employee.department)
  64.          {
  65.             if(!temp.contains(item.toString()))
  66.             {
  67.                temp.addItem(item.toString());
  68.             }
  69.          }
  70.          
  71.          return temp;
  72.       }
  73.      
  74.            
  75.       public function find(criteria : SearchCriteria) : void
  76.       {       
  77.          var temp : ArrayCollection = new ArrayCollection();
  78.                  
  79.          for each(var item : XML in this.data.employee)
  80.          {
  81.             if(criteria.firstName.toUpperCase() == item.firstName.toString().toUpperCase()
  82.             || criteria.lastName.toUpperCase() == item.lastName.toString().toUpperCase()
  83.             || criteria.nickName.toUpperCase() == item.nickName.toString().toUpperCase()
  84.             || criteria.location == item.location
  85.             || criteria.department == item.department)
  86.             {
  87.                var employee : Employee = new Employee();
  88.                employee.firstName = item.firstName.toString();
  89.                employee.lastName = item.lastName.toString();
  90.                employee.nickName = item.nickName.toString();
  91.                employee.location = item.location.toString();
  92.                employee.department = item.department.toString();
  93.                employee.phone = item.phone.toString();
  94.                
  95.                temp.addItem(employee);
  96.             }
  97.          }
  98.          
  99.          this.employees = temp;
  100.       }
  101.    }
  102. }

There a few things to note about this component for the purpose of this example:

  • A method on a remote service/object is not actually being called, I'm using an XML document to simulate that process.
  • I am not actually emulating a synchronous call, I'm allowing the current thread to block on the method call. If I were to emulate the synchronous call, I would suggest using anonymous functions as the result and fault handlers for the remote service/object. The code in this example would be short and not warrant a named method mapping (this is done a lot in JavaScript when registering event handlers).
  • Yes, my coding style kinda sucks, get over it.

Now when the find() method is called it does not return anything, instead it updates the component's internal state via the employees property which then fires a propertyChanged event which is handled by ResultsView to populate a datagrid. Additionally, notice that when the object is constructed it makes a call to fetch location and department information to which controls in the SearchView are bound and updated when construction is complete. These values from these controls are used to filter the search performed by the user.

Going back to the conceptual, there are a few questions that come to mind:

  1. Aren't components supposed to be reusable? - From my POV, it feels like Flex has already done a great job of handling re-use through the RemoteObject, HttpService, and WebService classes. It seems that if re-usability is needed it would be at the service rather than the non-visual component. The non-visual component in my example is literally acting as a perspective for its service, or what potentially could be a group of services. Right now, however, I'm not sure if there are huge performance issues that may result from having multiple component perspectives for a single or series of services. I would assume for RemoteObject it may not be as big as a hit as it would be for a web service. Maybe this would be based on the remoting implementation you choose (i.e. - LCDS, BlazeDS, WebORB, Granite Data Services, etc).
  2. Aren't you just causing side-effects on objects? - In my opinion, it's not doing anything different than what Flex is doing with its visual components. In fact, what I think justifies this particular approach is the fact that you have the ability to notify anyone watching the object when its state has changed; I've always considered side effects as changes in state that I potentially didn't know about as the caller. The Flash movie instance is stateful; why not take advantage of this environment to add state to the classes abstracting our services? I'm building these non-visual components to satisfy the needs of my application, so I will know how they should behave and can to document that formally based on the constructs of the language. Now, if you ask me if this approach should be used for building an API-like interface to a set of remote services, then I would have to say no. The implementer of an API doesn't know how their code will be used in the context of an application, consequently keeping these components as stateless as possible is to the benefit of the API developer; context is limited to the execution of a method call. I think the Twitter API for Flash Developers is a great example of this.
  3. Where do I put all of these non-visual components? - This question I believe involves much more conversation about the implementation of these non-visual components. The example application is extremely simple and does not represent the issue of how to handle event propagation. In the example, all events are being propagated to the Application class and emulating a sort of global event system similar to those that I've seen in Flex frameworks with which I've worked. In fact, this is how easyMVC handles its event registration in the ControllerFactory; a ControllerEvent with a user provided type is registered on the Application and no matter where the event is dispatched, it's told to bubble to the Application to be handled by a mapped method in a custom Controller class. I have to admit that I like this approach much better than Cairngorm and PureMVC's approach of building their own global event system. I know both camps have their own reasoning for why they've done it, but I don't think that what Adobe has provided is worth re-writing. On the other hand, does the hierarchical nature of MXML bind visual component layout and construction too close such that without global event systems we can't be productive as Flex developers? On a side note, data binding in practice isn't always the answer to our problems; how a component can take advantage of these non-visual components and still interact with the components it needs to is a mystery to me. This may come back to the nature of MXML as well.
  4. Do I need a framework if I use this approach? - This is something I'm still trying to figure out. The biggest use of Flex frameworks I've found is a structured approach for making calls to remote services. I feel like frameworks have way too much boiler plate code and if this approach is practical, a good alternative may exist in place of adopting a framework. It seems to me like Flex frameworks have come from the mindset of the web world where stateless HTTP is king. We don't have to use the Front Page Controller pattern to build rich UI's; I think it's time to move on to different interpretations of the MVC pattern. I always find myself asking, did developers in the Java Swing world find themselves turning to a framework or were the constructs of Swing enough to be productive. If people were productive with Swing and it was a widget toolkit for AWT, why can't the same be true for Flex and Flash?

All this being said, this is just my latest idea. As you can tell, I still have a lot of unanswered questions. We are the process of implementing this approach on a much larger scale at work and hoping to solve the questions listed above. I'm always interested in feedback, so please rip this to shreds. I am far from experienced in this arena and am always open to what others have to say despite what some may think.

NOTE: For those who are interested, I began along this line of thinking based of the latest buzz-worthy topics in the programming community. It interested me as to how OSGI implemented their component architecture in Java w/o some language level support (e.g. - formal properties) and why it so popular. I was also intrigued by a proposal put together by Joe Noxel, from the Java Posse, regarding additions to Java for some of the language level elements already present in Flex. Additionally, SOA has come into debate by some of the more experienced professionals in software engineering and SCA (see Apache Tuscany as an example) has been identified as a potentially better alternative. So all this talk, combined with the little amount of component programming I've done with COM+ and .NET, made me wonder. If there is such a huge draw towards component-oriented design is there anything in Flex that we can do to take advantage of these practices? Does having formal properties and support for events as it presents itself in Flex aid developers with the tools necessary to utilize component-oriented design? Is one of those areas specifically the perspective of bridging the gap from the stateful component to the stateless service? Now I know a component has a much richer definition than I'm limiting it to, but this is just the point. To what extent can we, and should we, use components within Flex?

Architectual Styles - Part One : Introduction

Brian LeGros | July 21st, 2007 | series  

Just recently for my job, I completed a training packet for new hires that will hopefully aid us in an internship program we're hoping to start. In part of the packet I try to expose our new developers to architectural tools, concepts, and styles. This is meant to empower them to understand the designs they'll be asked to work with and begin to brainstorm about possible ways that we can improve our own process. What I'd like to do for my blog in this series of posts is go over those conversations and talk about the paths I choose to follow architecturally and why.

So as an introduction, let's talk about the types of software I build so my mindset can be understood. Web applications are obviously first on my list. The context in which I usually build these applications is to expose new or existing business processes via the web. Integration is a big issue I have to be address on a daily basis, not only with third parties, but internally with other teams in the department. These applications are usually written with a common subset of web technologies (XHTML, CSS, JavaScript, Flash) and then I usually find myself using some combination of ColdFusion, Flex, and/or Java. Typically these applications are constructed for an audience of users external to company, but more recently I am building "intranet" based applications as well. The other type of software I find myself building is that of components. Usually these components are constructed as services later to be integrated with an ever evolving SOA. I usually find myself using Java because of the cool stuff that the JEE world can provide with some pretty descent maturity (i.e. - JTA, JMS, JPA, etc). I really like to use Spring as a container for these JEE tasks as well rather than something like EJB. The intended audience for these components are usually developers within the same or other teams of the department.

With that being said, this is how I will be presenting this series of posts:

  1. Introduction
  2. Coupling and Cohesion
  3. Domains
  4. Layering
    1. Business
    2. Integration
    3. Presentation
  5. Styles
    1. Light-weight Design
    2. Heavy-weigh Design
  6. Preferences

Please understand that I'm taking an object-oriented approach to design in this series. I am also taking the approach of an upfront design rather than something like TDD/BDD which jumps right into code (that's a discussion for another day). I will use UML to help represent my thoughts (as best as possible) and will attempt to approach this from a language agnostic perspective. Look for more posts over the following weeks. I hope you enjoy the series!

NOTE : Please take what I have to say as my opinion and nothing else. Recently, my readership has spiked, so the last thing I want anyone to think is that I'm telling them how to design their software. These are practices that worked well for me and the last few companies that have employed me and I want to share them with the community.

Part 2 : Coupling and Cohesion >>

Ah, that’s how the Canonical Data Model fits in!

Brian LeGros | July 18th, 2007 | programming  

So over the last few months, myself and few other developers at work have been brainstorming on approaches to implementing an SOA. Now before I say anything more, realize I haven't read any books on best practices as far as building an SOA from scratch; I'm just getting into the area and still have mixed feelings about the approach. In any case, I was listening to good old Software Engineering Radio on the way home today (SOA Part 2a) and they were able to answer a question I had in the back of my mind for a while.

When the challenge of coordinating services came up, I was able to understand the purpose of an ESB and how helpful it could be as a tool. When the issue of communication and protocols came up, JMS seemed like a very natural and loosely coupled solution (I definitely liked the idea of messaging over RPC). With Max working on a PoC with Mule and ActiveMQ, I felt the need to explore the issue of a canonical data model and the challenges that came with using one.

From the SER episode I listened to today, I felt reassured that this portion of the SOA was definitely a difficult one to incorporate. What I was trying to get my head around was a way in which common data types could be exchanged between business processes and how the definition for those types could be shared. SER pointed out that there are a few aspects of the shared data model you have to consider:

  1. Business processes may require semantically different data attributes for similar data types (i.e. - a Customer data type may require different information in a Data Indexing service than an Order Processing service)
  2. Data types may require different views of their data attributes based on external factors such as quality of service (i.e. - a call center service may only need name, phone number, and last 4 of your SSN for performance reasons but an Billing service would require a more complete view of the Customer regardless of performance).

SER recommended approaching this issue from a modeling perspective and then utilizing versioning and something as ubiquitous as XML (via XSD, or maybe even OWL) to represent an additional data layer to be used by the SOA. Services can retain their own domain classes which could be based on data structures defined in XML. SER suggested that the lack of a rigidly typed Java interface, for example, offers more resilience when it comes to versioning the canonical data model. They went as far as to suggest that versions of the data model could be marked as semantically similar or different. If a version of a data type was deemed semantically similar then it may be possible to for its consuming APIs to upgrade to the latest version without the need to refactor. I did worry that versioning could potentially get out of hand and in the end all we'd be doing is producing data types which were tightly coupled to business process, but from what I'm hearing that may not be the case.

Additionally, they suggested that a canonical data model be evaluated for use within selective domains in the enterprise. In doing so, it may be easier for business processes which have a dependency on a similar data type to share the same data type definition without the baggage of needing an act of God to change the data type definition later down the road. This approach seems like a patch-work solution where a few groups agree on the same data type definitions rather than the entire enterprise, but I can't think of a better approach from my limited exposure to SOA.

I realize I have lots to learn about this particular style of architecture, but SER is always a great listen. They definitely give me new perspectives on the topics I'm interested in. Keep up the great work guys.

cf.objective() 2007 : Real World SOA: Building Services with ColdSpring and Transfer

admin | May 6th, 2007 | conferences  

Well, in my normal indecisive fashion, I'm giving the CF community its check mark back. Sean Corfeild fails to disappoint. Even though he's not working with Adobe anymore, he went into the details of how Adobe.com absorbed Macromedia.com and built a robust service layer used by "tons" of web applications. He outlined the basic necessities of building a SOA as below:

  • Data Dictionary (aka Canonical Data Model)
  • Service Directory for discovery purposes
  • Creation of software APIs as services (SaaS)

He gave some pretty cool statistics regarding SOA growth in the USA. He showed a study which revealed that SOA-based applications have grown by 20% over the last year and are expected to increase by 6% annually. His prime example of this was SalesForce.com, but I've heard nothing but bad things about their success, so who knows.

Sean outlined the distinction of 4 tiers commonly found in SOA:

  • Controller/Presentation
  • Service
  • Business/Local Model
  • Database/Persistence

In Adobe.com they implemented all of the tiers using ColdFusion and Oracle for the persistence tier. Here are a few points he made regarding good practices:

  • When creating services for the Service Tier, try to use stateless services which can be used to emulate business processes.
  • When requesting a service, authentication should be a major concern. Sean suggested using SSO solutions with randomized tokens being passed. When using this approach, it was mentioned that a policy for token clean-up should be addressed up-front.
  • When constructing datatypes for the canonical data model, consider using primitive types which are shared between environments.
  • Perform a full analysis of the protocols available in your environment and the ability of each environment to work with that protocol (e.g. - SOAP and Java not as easy as it may seem whereas with CF it's much easier).
  • When creating the canonical data model, expose the minimum amount of commonality in your data. Exposing information specific to some systems but not other may cause dependencies though misuse of the API and accidental tight coupling with consumers.
  • When creating a common exception data model, keep the means by which an error is reported as simple as possible. Distinguish success and failure. For success, return the result of the RPC call. For failure, return a basic exception model containing a type, message, and details. In doing so, programmatic mappings can occur as well human readable messages.
  • Solving caching concerns are difficult. If you can utilize an existing commercial protocol for messaging, like JMS, do so to avoid having to write code for this problem.
  • Unit test the crap out of everything.
  • Don't allow legacy data models to dictate your canonical data model. Start from scracth to avoid being stuck in stale models.
  • Avoid SOA explosion and extreme API granularity.

It was funny to see Sean say that they chose REST'ful web services instead of JMS for internal messaging. His reason was they could get things done more quickly with web services, but acknowledged JMS would have been a better solution and they got lazy.

This talk was extremely reassuring and a just a great talk. Great job Sean.

cf.objective() 2007 : Case Study : Adobe.com

admin | May 6th, 2007 | conferences  

Nothing much here, but it was cool to see how crazy Adobe.com really was in terms of setup. They has "tons" of applications effectively running uniquely in multiple JRun instances, load balanced across multiple Solaris machines, accessing a very simple database layer with some fail-over in mind. I think he said about 75-80% of the content for the site was static. Everything in terms of languages was mainly ColdFusion. They has some Flash and some Flex. What was really crazy, was to see an actual service layer modeled out which is used by each application. The service layer had other abstractions, like hooks into JMS, but it mainly was used with CFCs in the backend.

The session overall was very informative. It motivated me to realize that if you work towards the goal of SOA, it is possible, especially for a company like WestGate. We're gonna hit Sean Corfeild up for some good JMS suggestions later this weekend as a result of a tangent from the session, so that should be cool too.