-
Notifications
You must be signed in to change notification settings - Fork 24
Subroutines
Specs by Peter J. Farrell (peter@…)
- The Problem
- Exploring the Solutions
- Definition of a Subroutine
- The Solution in Mach-II: Subroutines
- In Closing
In previous versions of Mach-II, the issue of event chaining for the purpose of reusing snippets of XML has been a hot topic in the Mach-II community. The issue revolves around the disconnect between the event queue and the idea that announcing a new event should chain the event object (i.e. share the event object) between all announced events during the request lifecycle.
Possible solutions were proposed that would completely or optionally change the way events are announced or queued. While event-chaining may be useful in some situations, changing the manner in which the request lifecycle operates would radically change the fundamental concepts behind implicit invocation and event-handlers. This would also create unforeseen backwards compatibility issues in legacy applications. Also, changes like this would go against our tenant to remain backward compatible (within reason) with recent versions.
In the summer of 2006, when the event chaining issue was brought up, I went about to create a proof of concept that would execute another event immediately without queuing it in the event queue. The proof of concept used a filter and manipulated the Mach-II event manager directly. While the proof of concept worked and accomplished the same end result as a subroutine feature, it was a complete hack of the framework because it manipulated the framework directly and thus was prone to bugs when future versions of the framework are introduced.
Another solution is the EventChain
plugin by Aaron Lynch which is a workaround, but at least it works as expected. After careful consideration and discussion, it appeared that a solution built into the framework would be easier and more powerful. I let us define the word "subroutine" as its' definition impacted how we decided on our solution.
In computer science, a subroutine is a portion of code within a larger program, which performs a specific task and is relatively independent of the remaining code. The syntax of many programming languages includes support for creating self contained subroutines.
There are many advantages to breaking a program up into subroutines, including:
- reducing the redundancy in a program (i.e. by replicating useful functionality)
- enabling reuse of code across multiple programs
- decomposing complex problems into simpler pieces (this is claimed to improve maintainability and ease of extension)
- improving readability of a program
- hiding or regulating part of the program
The components of a subroutine may include:
- a body of code to be executed when the subroutine is called
- parameters that are passed to the subroutine from the point where it is called
- a value that is returned to the point where the call occurs
(the above bulleted points are excerpted from Wikipedia)
In Mach-II, subroutines would be used to "reuse" snippets of XML in an effort to reduce redundancy in the configuration file (matches from above: many advantages to breaking things up). When a subroutine is executed, it would execute XML commands in the subroutine immediately (matches from above: body of code) and would have access to the current event object that is available in the event that executed the subroutine (matches from above: parameters that are passed to the subroutine). Also, the subroutine can manipulate the event object by adding to it arguments such as rendered views or data from listener notifications (matches from above: a value(s) returned).
Let's pretend that you have bunch of widgets that need data before you can use them. However, you need these widgets in many different events. Instead of defining them in each event and thus having to maintain code that produces the same outcome, you would create a subroutine to encapsulate the behavior.
In the context of Mach-II, you would create a subroutine like this:
<mach-ii version="1.5">
... includes, modules, propterties, listeners, filters, plugins ...
<subroutines>
<subroutine name="doAdminWidgets">
<notify listener="widgets" method="getStatusWidgetData" resultArg="statusWidgetData"/>
<view-page name="admin.statusWidget"/>
<notify listener="widgets" method="getCoolWidgetData" resultArg="coolWidgetData"/>
<view-page name="admin.scoolWidget"/>
</subroutine>
</subroutines>
</mach-ii>
You would call a subroutine in your event-handler with the execute command like this:
<event-handler event="someAdminFunctionality" access="public">
<execute subroutine="doAdminWidgets"/>
. . . other commands . . .
</event-handler>
Any time the execute
command is encountered, the indicated subroutine will be executed immediately. Conversely, when an announce
command is encountered, the indicated event will be put into the event queue and executed later. Subroutines cannot be executed via the URL (like events that have the public access modifier) and can only be executed from an event-handler. As you can see, subroutines can make for some really powerful code reuse.
- You can execute subroutines from plugins and filters, but cannot execute them from within listeners. This is similar to not being able to clear the event queue from the listener, whereas you can clear the event queue from a filter or plugin (see How do I execute a subroutine from an event filter?)
- Subroutines can execute other subroutines, however, Subroutine A could execute Subroutine B, but Subroutine B cannot execute Subroutine A as this will cause a circular dependency.
- The
<subroutines>
tag section comes after the<event-handlers>
tag section in yourmach-ii.xml
configuration file. - A subroutine shares the same event object as the event-handler that executed the subroutine. Since the subroutine is not queued, any data placed in the event object by the subroutine is available to rest of the event-handler after the subroutine has finished processing.
Subroutines do not change the backwards compatibility of the framework nor would it force developers to use the feature. However, subroutines allow for the encapsulation of reoccurring XML commands that would add redundancy to the configuration and makes for easier building of grid layouts as subroutines which allows you to break things up. In short, subroutines allow you to encapsulate controller behavior in easy to execute bodies of code.