Speaking at 360Flex this April

23 03 2012

360Flex: Maven by Example





Adobe: Official Maven support is coming

11 10 2011

I recently spent a lot of time at AdobeMAX hassling the Flashbuilder team on what the deal is with Flex and Maven, and we’ve finally been given the word: support is coming – we just don’t yet know what form it’s going to take.

Step One: Hosting the framework artifacts

The first step towards Maven support is for Adobe to start hosting their releases in a Maven-friendly way. They have admitted that this is on the cards for them, but steered away from specifics. They have two real options here – either they submit their artifacts to Maven Central or they set up and deploy to their own public Nexus. Many of us in the community would like to see the former before the latter. Having AS3/Flex/AIR projects build out of the box without requiring any external repository would be a great start (Maven Central is referenced in every execution via the super POM). Currently while the Flexmojos plugin now lives in Maven Central, we’re still reliant on the community (specifically @velobr) to deploy the latest JARs, SWCs and RSLs to Sonatype.

Nevertheless, if Adobe were to host a Flash artifact repository, it could become the central repository for the community to deploy their own open source libraries. This could include tools such as unit testing libraries (FlexUnit, ASUnit), mocking tools (Mockolate, Fluint), micro-architectures (Robotlegs, Parsley), utilities (as3corelib, AS3Signals, RxAS), etc. This would then be the go-to for all Flash developers new to Maven. And, we could finally answer the question plaguing all Maven/Flash newbies: Where are my dependencies???

Step Two: Either sponsor, fork or replace Flexmojos

The next step is for Adobe to decide what to do with Flexmojos – the open source Maven plugin that compiles Flash artifacts. Because it’s open source, they don’t want to usurp the hard work of the community and completely take it over as-is. As I see it, they can either fork it in its current state, sponsor it with funding and their own development team, or start again from the ground up and target Spark and above. In its current state, Flexmojos 4 (4.0-RC2 is the latest) is well equipped to deal with the needs of Flash projects up to and including Flash Player 10.3 (albeit with some bugs). Going forward however, we have no assurance that Flex 4.6 or AIR 3 will be supported out of the box, and I have doubts that the community alone will keep the pace.

Moreover, many of us Flash/Maven advocates are in enterprise development and find it hard enough to convince our customers to rely on an open source initiative that isn’t maintained by Adobe, let alone officially supported or sponsored. If Adobe get behind a Maven plug-in and put their stamp on it, we’ll have a much easier time advocating it to our clients.

Step Three: Integrate with Flashbuilder

Last but not least, is Flashbuilder (FB) integration. The current situation is fairly dismal. Flexmojos 3.9 was the last to officially support the flexbuilder/flashbuilder goal – the process which generated the project structure in Eclipse from your POM (creating and configuring .project and .actionScriptProperties among others). It’s been removed from Flexmojos 4 and there is currently no robust way to keep FB abreast of the latest changes in your POM. You can run the old 3.9 goal for partial results in FB 4.5, but it’s more hassle than it’s worth. Keeping large teams in sync across a complex project is cumbersome at best (and don’t get me started on checking in .project files).

While m2eclipse – the Maven-Eclipse plugin – provides the functionality required to run Maven within Flashbuilder, it is not integrated with the Flexmojos plugin. Put simply, m2eclipse is a lot less powerful with Flashbuilder than it is with typical Java projects in Eclipse. Updated your POM with a different Flex SDK, added some dependencies or a new runtime module? Fine, just make sure to tell all the developers to update their workspaces manually – otherwise either switch to IntelliJ or wait for Flashbuilder 5 (we hope).

Looking forward

The first step in a long process has begun. Adobe are taking the plunge into Maven compatibility and it seems the Flashbuilder team are our best hope for the future of the union. We know support is coming, but how exactly it will pan out is still up for debate. Hopefully we’ll have an answer before the end of the year, but I won’t be holding my breath.

The latest

Want to keep abreast of the latest developments, here’s a list of people to follow:





YCNYC: A lost opportunity.

27 09 2011

Man, was I looking forward YCombinator’s (YC) first New York event last night. Shrouded in secrecy and anticipation, I was eager to see the people behind the famous incubator – the enigmatic Paul Graham (PG) and some of the other power brokers from the West Coast. What I wasn’t anticipating was an event with an unclear theme, little insight and a collection of anecdotes from some of the most respected people in the industry.

organization: 5 ⁄ 5

If you’ve ever tried organizing an event with well over 1000 pax, you know it is no mean feat. The fact that the line of attendees stretched well around the block and yet moved smoothly gives true credit to an incredibly well-run event. The space itself was well laid-out, and everything flowed together beautifully. Even the complimentary beer and pizza was a pleasant – if a little cliched – surprise. Kudos to the event manager.

Yet I would have given that all up to hear something I didn’t already know. To be amazed. To be wowed. These are some of the best and brightest from the tech scene in the US and they can’t even get themselves together to create an engaging event?

this is Paul Graham

When PG took the stage, it was a non-event. I was expecting great fanfare but no, he simply strode onto stage and started speaking. Yet the crowd truly loved him. It’s hard not to – he is casual and unassuming. He radiates good-naturedness and oozes integrity right down to his polo and shorts. But the feeling I experienced was somewhere between admiration and embarrassment. This was clearly a man in the know, though why he was so obviously distracted I have no idea. The short breaths, the continual ummms, the pacing, the hand-written notes, the lost placing. Perhaps he’s not a great speaker, but I’m not so sure. This man is by all accounts one of the most influential in the tech startup scene across the US, and he reeked of unpreparedness.

He mentioned that they weren’t sure how receptive New York would be to the event. From the turnout, it was evident that we were drinking the Kool-Aid as much as there were in the Valley. Surely YC had known the interest levels from the booking form which closed some weeks back – yet PG didn’t seem to have a clear direction in his speech.

He wavered between a friendly familiarity with YC – peppering his talk with anecdotes on alumni and VCs in one breath – then going on to expound on thoughts as to why environment plays such a heavy effect on motivation. There was no introduction about YC, the school, their process – it was more a working theory on why the East Coast is vastly different to the West. One story painted eastern VCs as less savvy than their Californian counterparts; great to know, but why do you think that is PG?

He suggested East Coasters should take the plunge – join the YC school for a few months. But he didn’t even touch on the process they use to choose startups. What are they looking for? Obviously hardworking individuals who are passionate and dedicated, but what else? Personal traits or characteristics? Emotional maturity? How about the kinds of achievements they’ve accomplished? What about matching founder personalities? Which characteristics suit which in his experience?

He did touch on key point in regards to New York and tech talent: the spectre of Wall Street. In no uncertain terms, he outlined that the challenge facing us developers in New York was resisting the monetary rewards of the financial sector. He then laid out the benefits of the startup life as opposed to that of Wall Street. It is a relevant discussion, and one that I think leads to an interesting debate. Unfortunately there was no real forum to this speculation, and it was left at that.

His entire speech was essentially the introduction to the evening and yet there was no clear message. There was no point. What were we really doing there Mr Graham?

the Q and the A

After PG’s speech came the Q&A. I feel they (or at least Alexis Ohanian) honestly tried to put some interactive content into the evening, and should be commended for it. Nonetheless, it would have helped to have given the audience some forewarning as to the event theme and structure to help us ask more poignant questions. If I knew PG was going to get specific on Startups vs Wall Street or even West vs East Coast VCs, I definitely would have had a few questions up my sleeve.

Perhaps a better alternative is to ask live questions from the audience, allowing us to digest the information we’ve been given and ask relevant questions that follow from what has been presented.

alumni presents

After the Q&A came the YC alumni presentations.

While some of the founders’ stories of hardship were tough, sleeping on the floor of an office and using your shirt as a towel are definitely first-world problems. As anyone who’s ever tried to make it in a startup will tell you – back to back 18 hour days are nothing. Facing eviction, the degradation of family and close relationships, weight gain, sleep loss, deterioration of health, endless stress – are all part-and-parcel of founding a startup.

What I’d like to hear more of is how they dealt with the depression, the emotional stress. When they were in the Trough of Sorrow, how did they find the strength to keep going? How did they resist the sway of those who sell them exactly what they want to hear, all because they are so emotionally tied to their venture that they’re easy game for anyone with half a trick?

What we got was the same old mantra: work hard, build it first, stick it out, believe in yourself, listen to your users, it’s gonna be tough. There’s only so much you can hear the same rhetoric before the condescension kicks in.

It would be remiss of me not to point out two standouts from these presentations. The first was the founder who mentioned PG’s The Process graph, outlining the typical phases a startup lives through. The other was from the Airbnb designer & founder who mentioned one of PG’s directives “do things that don’t scale” – focus on the users you have and wow them in some non-technical manner.

startup.com ⁄ jobs!

After a few of the alumnis had done their rounds, it was becoming apparent that there was indeed a common theme to their decks. This beer-and-pizza event was a mere talent scout. (Ye gads!) Presenter after presenter repeated the same tired lines: IF you’re curious about startups BUT not yet ready to take the leap of faith THEN join us instead.

Now I don’t begrudge them hunting out talent – and hats off to them for being open about their businesses and heartaches – but I would have found their bitter pills much easier to swallow if I knew that’s what I was in for in the first place.

Here’s an idea. Why not setup small stands at the event with someone from their recruiting team to promote their startup to the engineers? Hardly revolutionary, but it gives attendees somewhere to go if they’re interested and want to continue the conversation about some company they’re curious about. People mill about and meet over a particular startup – perhaps it’s the problem trying to be solved, maybe it’s their design or energy. By having the stands it effectively channels people of a particular interest to a certain area – a handy feature when you’ve huge crowd of people in a large space.

networking

PG mentioned in his speech to mark your name badge with an ‘X’ if you were on the hunt for a cofounder. There was a lot of chatter about the networking, but little in the way of structure.

In terms of networking, who was in the audience? There were a few thousand people milling about and only YC really knew the makeup of the crowd. I made a few introductions and asked some questions but my guess is inconclusive at best. Why not have a presenter ask some questions of the crowd. Say, hands up or some such – give everyone an idea of roughly who was there for what. To me it seemed like mostly developers sprinkled with some founders and ex-founders though I’m just guessing.

How about a system established prior to the event where attendees wear either an accessory or article of clothing based on what they offer and what they’re looking for. Perhaps a tie if you’re an MBA looking for a tech. Maybe a vest for investors. Black T-shirts for developers of course. Or what about creating a twitter board where people could add their handles to notice boards based on skills/roles and people could look them up online based on categories. You could search out talent and try hunt them down at the gig.

the aftertaste

Although it is too late to avoid being labeled a cynic, I felt as though the whole evening was merely a big YC circus meant to drum up enthusiasm for engineers to work for startups. There were mixed messages from PG and the startups themselves, and they oscillated between treating us as peers and as admirers. On the one hand, they’d be talking about the scene, their stories and their failures, and on the other they were endlessly filling our ears with tripe about hard work and endurance, “you can do it” and a can-do attitude.

In all honestly, I wouldn’t have minded so much if there was more transparency about the stated goal of the event, and a little more targeting to the different categories of developers and founders in the audience.

Takeaways:

  • Be transparent: don’t keep us in the dark, tell us what the purpose of the event is. Tell us more about YC and what you do.
  • Be consistent: there was no real theme to the event; no strong message other than “work hard”, “don’t give up”.
  • Tell us what we don’t know: we’ve come to see some of the best talent in North America, teach us something we can’t learn online (we know to “find a problem to solve” by now).
  • Innovate: use your creative talent to generate a more interactive event. Take live audience questions, poll us, have a East Coast VC defend their turf, allow for quick 30 second audience pitches, generate networking interest with methods to break up the crowd into relevant groups.
  • Engage: talk to us, learn who we are and what we represent.
  • Share: take what you learn from us and share it back to the community.

YCombinator, this is New York city and if the turnout is anything to go by – we love you. We adore you. Tell us more about your incubator. Blow our minds with your insights and your prescience.





Selective removeAll() addition to as3-signals

22 09 2011

This post and code is related to my fork of as3-signals. The fork is from the latest version of as3-signals 0.9-BETA.

Summary of additions

  • ISlot.applyTo(value:*):void
  • ISlot.doesApply(value:*):Boolean
  • SlotList.filterNotAppliesTo(value:*):SlotList
  • SlotList.findNotAppliesTo(value:*):SlotList

Summary of modifications

  • IOnceSignal.removeAll(appliesTo:* = null):void

Details

This backwards compatible addition to as3-signals chiefly allows the removal of all listeners for a given instance or class type. It keeps the convenience of the removeAll function but provides a mechanism to prevent removal of listeners not bound to the current instance or class.

The removeAll() method allows for an optional parameter which will then removeAll slots that applyTo the given parameter, if any.

Essentially, this allows us to asynchronously clean up after a class or instance without affecting any listeners from other classes and without having to define our anonymous functions or closures.

Reasoning

A signal – as a promise – may be reused across instances and classes. For example, a service that is managed by an IOC container may cache signal calls, or a model may use signals to notify of changes. When the signal is shared across various types (either directly via the IOC container, or indirectly cached within an instance) we don’t want to removeAll() lest we remove functional code in other classes (that may well have been written by other developers).

Example

Update Sept 23: Changed the example to use Robotlegs and Mediation

Let’s look at an example to follow this through. This example below illustrates usage when marshalling updates of a model to a view (using covariant mediation to an interface) via a Mediator. Chiefly, the problem arises when an asynchronous cleanup method is called (in this case `onRemove()`), it needs to remove all of the listeners applied to by this instance but not remove listeners that may be used elsewhere.

public class LogModel
{
	protected var updateSignal:ISignal;
	protected var logs:Vector.<LogItem>;
	
	public function get update():ISignal
	{
		return updateSignal ||= new Signal();
	}
	
	public function set logs(collection:Vector.<LogItem>):void
	{
		logs = collection;
		update.dispatch(logs);
	}
}

public class SomethingMediator extends Mediator
{
     [Inject]
     public var model:LogModel;
	 
	 [Inject]
	 public var view:IDoesSomething;
	
     override public function onRegister():void
     {
        model.update.add(function(collection:Vector.<LogItem>):void
		{
			view.logs = collection;
		}).applyTo(this);
     }
  
     override public function onRemove():void
     {
          model.update.removeAll(this); //removes all listeners applied to this instance only
     }
}

Usage (pseudo-code):

//setup values
const logModel:LogModel = new LogModel();
injector.mapValue(LogModel, logModel);

//map interfaces to a mediator 
mediatorMap.mapMediator(IDoesSomething, SomethingMediator);
const viewA:IDoesSomething = new DoesSomething();
const viewB:IDoesSomething = new DoesSomething();

//register mediators for our views (creates two instances of SomethingMediator)
mediatorMap.registerMediators(viewA);
mediatorMap.registerMediators(viewB);

trace(logModel.update.numListeners); //2 - one listener from viewA.onRegister() and one from viewB.onRegister()

mediatorMap.removeMediators(viewA);

trace(logModel.update.numListeners); //1 - one listener from viewB.onRegister()

mediatorMap.removeMediators(viewB);

trace(logModel.update.numListeners); //0




Cleaning up after closures in Flash

19 08 2011

If you haven’t experimented much with closures yet – whether in your Flash/Flex projects, Javascripting or while tinkering with Lua – it’s time to start. In case you’re a little nervous about those pesky memory leaks in Flash, here are some ways to cope.

Pampas Fractal

» 

Much of the following code is bundled into an example Flex project that compares the various closure techniques around a custom Timer class.

Check the code on Github.

What are closures?

Many people think of closures as anonymous functions – probably because that’s the common form they take – but they are more than that. They are scoped, inline functions that provide a “closure” over a collection of free variables (within the function scope).

Check out the Wikipedia entry on closures..

Why use them?

  • They allow the hiding of state (negating the need for maintaining async state in the class) as each closure defines its own variable scope that are available to all nested closures; and
  • Because they’re easier to follow than continually jumping to functions defined at a type-level.

Take a peek

In the below example, we have two closures – the first defines the userEvent property and someVariable, the second adds to that with it’s own scope of serviceEvent. You see how the inner closure has access not only to that state within itself, but also to that of the outer closure, as well as that of the init() function AND the class itself. Welcome to the scope chain. Read the AS3 docs on Function Scope.

public class SomeClass
{
	protected var view:ISomeView;

	public function init():void
	{
		var functionSaysSo:Boolean = true;
	
		userAction.addEventListener(UserEvent.LOGIN, 
			function(userEvent:UserEvent):void
			{
				//this is outer closure 
			
				//define a variable in the outer closure's scope
				var someVariable:String = "something";
			
				service.addEventListener(ServiceEvent.RESULT,
					function(serviceEvent:ServiceEvent):void
					{
						//this is the inner closure

						if (functionSaysSo)
						{	
							view.notify(userEvent.username, serviceEvent.result, someVariable);
						}
					});
				
				//async call
				service.start(userEvent.username, userEvent.pass);
			
			});
	}
}

Tip: If you find yourself contesting the readability assertion from before, don’t fret – it’s early days.

Cleaning up after yourself

Like any listener, using a closure as an event listener can create memory leaks if not properly cleaned up. Luckily, we have a few options up our sleeves to avoid this.

Use weak references? [Short answer: no]

Clean, simple and easy, we could simply add closures as weak references.

userAction.addEventListener(UserEvent.LOGIN, 
	function():void
	{

	}, false, 0, true);	

This keeps the code trim, however it introduces its own problems. If the variable you are listening to lives (is scoped) within another closure or a function definition, it will get cleaned up after the function completes (and before the event might fire). Without a strong reference to that variable, it is a target for garbage collection and you will end up with unpredictable results.

For example, in the following, there is nothing holding onto the timer instance to ensure after the function ends (and before the timer completes) that the timer will still exist and dispatch the TIMER_COMPLETE event.

public class SomethingWeak implements IDoesSomething
{
	public function doSomething():void
	{
		var timer:Timer = new Timer(1000,-1);

		//WARNING! Nothing is holding a reference to timer - GC candidate
		timer.addEventListener(TimerEvent.TIMER_COMPLETE, 
			function(evt:TimerEvent):void
			{
				//something happened!
			}, false, 0, true); 

		timer.start();
	}
}

1. Name your handlers

To improve on this, simply define your handlers locally, and you can remove them within your listeners:

» Aug 30: Updated to inline definition

public class SomethingNamed implements IDoesSomething
{
	public function doSomething():void
	{
		var timer:Timer = new Timer(1000,-1);
		
		var timerHandler:Function;
		
		timer.addEventListener(TimerEvent.TIMER_COMPLETE, timerHandler = function(evt:TimerEvent):void
		{
			//something happened!
			
			//cleanup after ourselves
			timer.removeEventListener(TimerEvent.TIMER_COMPLETE, timerHandler);
		});

		timer.start();
	}
}

2. Use arguments.callee to remove them during execution

Even better, we can take advantage of a little known feature in AS3 called arguments.callee, and not even have to name our function:

public class SomethingCallee implements IDoesSomething
{
	public function doSomething():void
	{
		var timer:Timer = new Timer(1000,-1);
		
		timer.addEventListener(TimerEvent.TIMER_COMPLETE, 
			function(evt:TimerEvent):void
			{
				//something happened

				//cleanup after ourselves
				timer.removeEventListener(TimerEvent.TIMER_COMPLETE, arguments.callee);
			});

		timer.start();
	}
}

3. Use type-level handlers to remove from separate call

Alas, what if you need to clean up based on another method or event later in the piece (say when a mediator is disposed)? You’ll need to define your handler at a type-level to retain a reference of it:

» Aug 30: Updated to inline definition

public class SomethingDisposable implements IDoesSomething, IDisposable
{
	//handler is now defined at a type (class) level
	private var timerHandler:Function;
	
	//we have to also scope the timer to the type level in order to remove listeners
	private var timer:Timer;
	
	public function doSomething():void
	{
		timer = new Timer(1000,-1);
		
		timer.addEventListener(TimerEvent.TIMER_COMPLETE, timerHandler = function(evt:TimerEvent):void
		{
			//something happened!
		});

		timer.start();
	}
	
	public function dispose():void
	{
		if (!timer) return;
		
		timer.removeEventListener(TimerEvent.TIMER_COMPLETE, timerHandler);
		
		//for completeness sake
		timer.stop();
		timer = null;
	}
}

At this point, you may be wondering why bother with a closure, when you could simply define the handler as a private method? In this particular example, there is no difference unless you wanted the handler to access the timer instance itself in the handler.

4. Use Signals

There is a final alternative – use the as3-signals library. AS3 Signals is a library that provides an alternative to using Flash Events within your APIs. Using Signals, there are a handful of alternatives to clean up after your closures. Every signal implements ISignal, and it’s that interface we’ll focus on.

ISignal.addOnce()

ISignal.addOnce() prescribes attaching a handler which is called once when the signal dispatches and is removed immediately. Below we use a NativeSignal to wrap the TimerEvent.TIMER_COMPLETE, allowing us to avoid attaching and removing event listeners ourselves. We also now return a Signal which gives the user of the class a strongly-typed signal to what they expect.

public class SomethingSignalsAddOnce implements IDoesSomethingWithSignals
{
	public function doSomething(index:int):ISignal
	{
		//create a Signal to return
		const response:ISignal = new Signal(int);

		const timer:Timer = new Timer(index * 100,-1);

		//create a signal from the Timer event
		const signal:NativeSignal = new NativeSignal(timer, TimerEvent.TIMER_COMPLETE, TimerEvent);

		//once TIMER COMPLETE has occurred, we can dispatch our signal - ISignal.addOnce() ensures that any listeners to Timer will be cleaned up
		signal.addOnce(function(evt:TimerEvent):void
		{
			//tell response that something happened (as opposed to dispatching an event, we dispatch the signal)
			response.dispatch(index);
		});

		timer.start();

		return response;
	}
}

This is often very useful, but not always optimal. We may not always want to listen only once – say if we need to selectively remove the listener based on certain conditions. Sometimes we may only want to remove the listener based on another asynchronous event (as in #4 above).

Signals and arguments.callee

Alternatively, we could use the arguments.callee property and do a conditional remove when required (after 5 ticks in the below example):

public class SomethingSignalsCallee implements IDoesSomethingWithSignals
{
	
	public function doSomething(index:int):ISignal
	{
		//create a Signal to return
		const response:ISignal = new Signal(int);
		
		const timer:Timer = new Timer(100);
		
		//create a signal from the Timer event
		const signal:NativeSignal = new NativeSignal(timer, TimerEvent.TIMER, TimerEvent);
		
		var numTicks:int = 0;
		
		signal.add(function(evt:TimerEvent):void
		{
			if (numTicks++ == 5)
			{
				response.dispatch(index);
				signal.remove(arguments.callee);
				timer.stop();
			}
		});
		
		timer.start();
		
		return response;
	}
}

You might wonder if you can use arguments.callee within nested closures – and the answer is yes. Just be aware that each closure has its own definition of the arguments.callee, and it overrides the value from any outer closures.

ISignal.removeAll()

ISignal also expose the convenience method: removeAll(). This can help us when we need to remove listeners in response to another method call.

public class SomethingSignalsRemoveAll implements IDoesSomethingWithSignals, IDisposable
{
	private var timerSignal:ISignal;
	private var timer:Timer;
	
	public function doSomething(index:int):ISignal
	{
		//create a Signal to return
		const response:ISignal = new Signal(int);

		timer = new Timer(500);

		//create a signal from the Timer event
		timerSignal = new NativeSignal(timer, TimerEvent.TIMER, TimerEvent);

		timerSignal.add(function():void
		{
			response.dispatch(index);
		});

		timer.start();

		return response;
	}

	public function dispose():void
	{
		timer.stop();
		timerSignal.removeAll();
	}
}

Be careful using removeAll() – if your class aggregates the signal as above, and it never leaves the containing type, fine. However, there may be occasions when you pass a signal around between various classes (as we do with the response signal above). In these classes, using removeAll() could present unwanted results if one developer inadvertently removes listeners that another class attached.

Conclusions

Whichever way you use closures, you need to remember to clean up after yourself, less you end up leaking memory in the Flash player. Asynchronous programming is here to stay (take node.js and Reactive eXtensions for .NET as examples) and we’re lucky that Actionscript – built on ECMA – supports it natively. As long as you’re aware of the consequences of attaching inline handlers, you can use closures and the async model in general to design a different approach to solving common asynchronous problems. While it takes a little getting used to, I wholeheartedly recommend giving it a shot – you might just like it.





Book Review: Too Big to Fail

12 08 2011

Too Big to Fail on Amazon.com

An ex-colleague recently told me to safely ignore Andrew Ross Sorkin’s Too Big To Fail – “it’s little more than propaganda”, he said.

Undeterred, I ploughed through the tome, finding it well-written and informative. While it may have defended certain individuals, it by no means came across as biased; though perhaps I’m just naive.

Where The Big Short is a fascinating yet brief look at a few key players in the crisis who bet against the market, Too Big to Fail is an exhaustive look at the events that occurred during the credit crisis in 2008. It follows an impressive cast of individuals, from the US Treasury, through the Federal Reserve, and just about every major investment bank in the US.

I confess that getting though the book took some effort. Not because there wasn’t ample drama and conflict, but chiefly because there was just so many characters to familiarise with.

Much of the book centres around the fall of Lehman Brothers and the attempts of all and sundry to save it. The book makes much of both Dick Fuld, the ex-CEO of Lehman who, by all accounts, tried dearly to save the firm, and Hank Paulson, the US Secretary of the Treasury under Bush, who struggled relentlessly to prevent an economic meltdown (perhaps that’s the said propaganda?).

Sorkin has evidentially put a lot of work into researching the events of the time, and the book reads surprisingly well; often throwing in well-placed reminders regarding character relationships touched on in the past. I particularly like the occasional inconsequential commentary by those present (eg. he looks fit for his age) or throwaway body-language queues that lead nowhere, immersing the reader in the situation.

While the book focuses primarily on Lehman, it also covers most of the other major events during the crisis. In particular, the buyout of Bear Stearns by JP Morgan for $2 a share with support of the US government (later revised to $10), AIG being propped up by the government shortly letting Lehman fall (by not providing government assistance to any of the buyers) and the eventual takeover of Merrill Lynch by Bank of America.

The question of whether or not the US government were to blame for the depth of the crisis by not saving Lehman remains to be seen. Pick up a copy and make up your own mind. At the very least you’ll see how they do things on the other side of Wall Street.





UI mediation sucks. Mediate behaviours, not views.

7 08 2011

Code for this post can be found on Github.

In this post, we’re going to look at how the variance utility for Robotlegs allows mediation against interfaces rather than concrete classes. Apart from the gains in decoupling, we can mediate purely against behaviours, rather than specific implementation. And, as we’re talking interfaces, a UI component can implement as many interfaces (behaviours) as it likes!

Libraries used in this post:

Why use mediation at all?

Mediation is a design pattern that performs the job of managing communication between parts to decouple logic. In terms of modern MVC frameworks, mediators are typically employed to monitor UI pieces from the outside in, so that the UI has no references to the framework whatsoever. The common alternative is the Presentation Model pattern (PM) that typically involves injecting in one or more presentation models to the UI component. As such, the UI component is thus coupled to the particular PMs it uses. That said, when mediating against classes (rather than interfaces, which we’ll get to), we couple the mediator to the UI, which is suboptimal.

Why Robotlegs?

Robotlegs (RL) is a lightweight (50KB) and prescriptive library for MVCS applications. Out of the box it provides us with Mediation, IOC container and Dependency Injection via the familiar [Inject] metadata (thanks to SwiftSuspenders).

Regular (invariant) mediation

Take some UI component: (SomeComponent.mxml)

<s:VGroup>
    <fx:Script>
        //the mediator will tell me when something happens
        public function asyncReturned():void
        {
            //something happened!
        }

        private function onClick(evt:MouseEvent):void
        {
            //tell whoever's listening to do something
            dispatchEvent(new ControlEvent(ControlEvent.START));
        }
    </fx:Script>

    <s:Button label="Start" click="onClick(event)" />
</s:VGroup>

A mediator for this component might look like (SomeComponentMediator.as):

public class SomeComponentMediator extends Mediator
{
    [Inject]
    public var view:SomeComponent;

    [Inject]
    public var service:ISomeService;

    private var viewHandler:Function;
    private var serviceHandler:Function;

    //called when UI component is added to stage and mediator assigned
    override public function onRegister():void
    {
        //handle control events responding
        viewHandler = function(evt:ControlEvent):void
        {
            serviceHandler = function(evt:ServiceEvent):void
            {
                //some where later on tell the view it is done...
                view.asyncReturned();
            }
            service.addEventListener(ServiceEvent.COMPLETE, serviceHandler);

            service.doSomething();
        }

        //attach the listener
        view.addEventListener(ControlEvent.DO_ASYNC, viewHandler);
    }

    //called when UI component is removed from stage, prior to mediator being destroyed
    override public function onRemove():void
    {
       service.removeEventListener(ServiceEvent.COMPLETE, serviceHandler);
       view.removeEventListener(ControlEvent.DO_ASYNC, viewHandler);
    }
}

Via the ADDED_TO_STAGE event, Robotlegs wires up an instance of a mediator for each UI component it finds. All that it requires is that you map in the mediator:

IMediatorMap.mapMediator(SomeComponent, SomeComponentMediator);

Don’t like extending base classes or want your own implementation of mediation? No problems just implement IMediator instead.

So why covariance?

Because there are some problems here with mediating directly to views:

  • A UI component can only have one mediator;
  • The mediator is tightly coupled to the UI control.

So, what if we wanted to map to an interface instead? We could include the Robotlegs Variance Utility (as a library to our project), and tweak our mediator mapping call to:

IVariantMediatorMap.mapMediator(ISomeComponent, SomeComponentMediator);

The above example becomes:

<s:VGroup implements="ISomeBehaviour">
	<fx:Script>
		//the mediator will tell me when async returns
		public function asyncReturned():void
		{
			//something happened!
		}

		private function onClick(evt:MouseEvent):void
		{
		     //tell whoever's listening to do something
		     dispatchEvent(new ControlEvent(ControlEvent.START));
		}
        </fx:Script>

    <s:Button label="Start" click="onClick(event)" />
</s:VGroup>

Using this interface:

[Event(name="startAsync",type="ControlEvent")]
public interface ISomeBehaviour
{
	function asyncReturned();
}

And the mediator becomes:

public class SomeComponentMediator extends Mediator
{
    [Inject]
    public var view:ISomeBehaviour;

    //... (as before)

}

And voila – we’ve solved both problems in one fell swoop! A UI control can implement as many interfaces as it needs, and our mediates now mediate against a behaviour rather than a concrete UI piece.

So now what?

There’s still room for improvement. Flash has no way to enforce that the class – SomeComponent – will actually dispatch the ControlEvent. If we’re writing these interfaces – these behaviours – we want a contract that explicitly states which events should be fired. Better yet, we’d like the option to state if these events are a functional level or a type level.

Enter Signals, stage right

Signals provide an alternative to events. They are designed to be used within APIs and class libraries, rather than replacing events altogether (Flash events are well suited to UI hierarchies). Where events fire and are handled at a type (class) level, signals live at the variable level. Not only can we pass them to and return them from methods, we can also enforce their presence in types that implement our interfaces. Check out an earlier post on Signals.

By including the lightweight Signals SWC, we have access to the ISignal contract and some common implementations.

Our interface from before now becomes:

public interface ISomeBehaviour
{
    function asyncReturned();

    function get start():ISignal;
}

Our view becomes:

<s:VGroup implements="ISomeBehaviour">
    <fx:Declarations>
        <signals:Signal id="startSignal" />
    </fx:Declarations>

    <fx:Script>
        //the mediator will tell me when something happens
        public function asyncReturned():void
        {
            //something happened!
        }

        //provide access to the type-level signal
        public function get start():ISignal
        {
            return startSignal;
        }
    </fx:Script>

    <!-- Here we actually send the message to the mediator -->
    <s:Button label="Start" click="start.dispatch()" />
</s:VGroup>

We actually now have a property start, exposed from the view that implements the interface, that we can attach and remove handlers to in our mediator.

And so our mediator finally becomes:

public class SomeComponentMediator extends Mediator
{
    [Inject]
    public var view:ISomeComponent;

    [Inject]
    public var service:ISomeService;

    private var serviceSignal:ISignal;

    override public function onRegister():void
    {
        //handle control events responding
        view.start.add(function():void
        {
            serviceSignal = service.doSomething();

            serviceSignal.add(function():void
            {
                //when the service returns, notify the view
                view.asyncReturned();
            });
        });
    }

    override public function onRemove():void
    {
        serviceSignal.removeAll();
        view.start.removeAll(); //clean up any listeners
    }
}

So what now?

Grab the code on Github and have a play around. For ease of use, I’ve included the dependencies along with the source.








Follow

Get every new post delivered to your Inbox.