.NET and me Coding dreams since 1998!

10Jun/083

Adobe Air 2008 Tour – Prague

For a few of you reading my blog, this blog post would most definitely come as a big surprise knowing how passionate iPhone 172
I am about SIlverlight and all related stuff.

Well, although I believe that the real thing is Silverlight, I wanted to check out how the “other side” looks like.

Considering the facts that level of my previous experience with DW, Flex, Flash and Air was zero and the fact the sessions have been presented in Staropramen brewery building I anticipated a lot of cool thing to learn and some beer to be drink.

Both of my expectations were fulfilled.

Before I start

Before I start “pasting” my notes and observations from the OnAir  Adobe day, I can not avoid mentioning first the other event organized last week by Microsoft here in Prague, “Silverlight for developers”

Not to be too much inflammatory here, I would just say that I was really disappointed with this Microsoft event.
I was there only one hour because I didn’t want to waste of more time but during that time:

  • I saw a demo how small “flash like” games you can make with Silverlight
  • I saw a demo how with Silverlight 2.0 can make media player
  • I saw a bunch of false information's about competitors (e.g. Flash/Flex not supporting web service calls)
  • I saw whole one slide about Silverlight architecture shown in about 15 seconds and 4 sentences
  • I saw the same egg example used at literally every Silverlight presentation here

What I didn’t saw there in that one hour is:

  • Presenter excitement about breaking and revolutionary new technology SL truly is
  • Business value Silverlight has (beside games and video players)
  • That Silverlight is NOT media player plug in
  • A big picture about how Silverlight relates to ADO Net Data Services, FeedSync, Entity framework etc
  • Why I should choose Silverlight instead of Ajax, WPF, Flex, Flesh, Air etc

Anyhow, I saw a bunch of people taking notes so I guess the decision to make sub L100 session was the right one after all for majority of developers attending the presentation.

Keynote

Keynote was done by Ryan Stewart (rstewart@adobe.com,twitter:ryanstewart) who is Adobe Program Manager.

His main points were that Flash is deployed to 99% of the computers with 8 million installations/day, with a very efficient flash sandbox update mechanism (when they roll out Flash 9 it took them only 12 months to complete update of most of Flash 8 sandboxes runing on client computers)

He pointed that they have a long wining tradition of being the trend setters (Acrobat reader 1993, Adobe Flash 1995, Adobe Air 2008)

Then he outlined their vision with a nice diagram showing the Adobe ecosystem where Flash covers the web needs, AIR desktop segment with Flex  providing client framework for both of them

<place for diagram>

Flash 9 has significant improvements in areas of multilingual support and localizations enhanced visual performances (with GPU hardware rendering, Rich media support and Dynamic streaming (streams optimized per user bandwidth), 3d visual effects (transitions and transformations)

Most of the thing they mentioned as new in Flash 9 I can see similar to Silverlight/IIS7 stack and that is great because Flash/Silverlight crosspolination would bring only benefits to us developers

And then he mentioned what is Adobe Air… :)

image

“Adobe AIR enables web developers to use existing technologies to build and deploy rich Internet applications on desktop

My first reaction was:”Dough?”. I came here to see how Air compares to Silverlight and realized that they are not competing at all. In fact they are two technologies taking totally opposite directions:

  • Silverlight takes direction where he moves desktop programing model (WPF, .NET) to web by executing “desktop” code in SL sandbox
  • Adobe Air is opposite allowing web programing model (jscript, html, css) to be executed on AIR Sandbox allowing us doing the desktop applications using Web technologies

I would say that behind that technology differences, there are two different business models Adobe and  Microsoft are playing on:

Adobe plays on the fact that web applications and web developers are already deep into the enterprise so reusing the already built web applications “free of charge” in desktop environment and the same skill set of web developers. Sales pitch: “you already have the site. desktop enable it!”

Microsoft sales pitch (IMHO) is slightly different:“We know how hard is to do web development so we have a sandbox which removes the need for web development. You just do the “client like" development without having to face the same problems you are facing now.”

Ryan then show couple of demos, how RIA desktop application can look

image

image

image

He showed web application application done for NY Times http://www.shifd.com/ which has support for Air and demo how web site and client application cooperate. He also showed how you can SMS the data and told that iPhone support exist. Having the same app running on multiple platforms (Air and Silverlight) looks very important to both Adobe and Microsoft which I can understand considering how Mobile market is getting more and more business value .

shifdexample

 

He summarized at the end why we would like to do to RIA AIR development at the end:

- Persistent connection (offline support)
- Branded experiences (not limited by browser, pick your won window shapes etc)
- Desktop functionality (file system, notification windows, SQLLite local DB support)
- Data access (REST, HTTP, SOAP - same as you do in Web)
- Efficient development 

Building AIR application can be done free (There is free AIR free SDK and Flex SDK) but for best productivity use:

-  Adobe products –> Fx, Dw, Fl (support for debugging, packaging for Air) or
-  Eclipse Aptana  which is 3pty tool plug in for Eclipse

Air future: Air 1.5 version would sync with Flash Player 10, sync up with WebKit capabilities.

For more general level information's he recommend use of a central URL: http://www.adobe.com/go/ria 

Hello world  in Adobe AIR

Mike Chambers (www.mikechambers.com)  then had a small session showing how to do do hello world application using Flex Builder and AIR

He pointed that Flex Builder is built on top of Eclipse.

It was standard presentation where he created new Flex Project, picked on second screen that he wants to create desktop application and the default project was created (check out Flex 3 help file for how to build AIR applications with Flex 3 for detail instructions)

Default project has two application files:

AIRHelloWorld.mxml root application file which would be compiled to swf containing markup and ActionScript/JScript code
AIRHelloWorld.xml - application description file (defines metadata needed by runtime: filename, files needed etc)
Some of the elements defined in application setting xml file are:

  • <id> - unique app identifier com.mikcehambers.AIRHelloWorld (not seen by users)
  • <name> - name of application (user sees, add/remove programs, shortcuts etc)
  • <version> - exposed to application used for auto update
  • <description> simple description which would appear on installation screen
  • <initalwindow> - elements specifying how app launch and how it looks when launch
  • <systemchrome> – values: STANDARD/NONE) – standard gives the standard windows chrome regardless of what OS user have,  none gives opaque window, without maximize, minimize buttons, title bar etc
  • <transparent> (used in combination with systemchrone -> none with true window allows having irregular shape windows)
  • <visible> default false! Once the app is ready to go set it to true (Dynamic layout)

Note: Adobe MXML looks very, very similar to XAML!. Not sure if they have cool stuff like extensions, dependency and attached properties etc, but I can read MXML markup code without any problem

Once the hello world app got a button in center of window and a AIR logo image in right corner, Mike exported it to release build (Project/Eporrt to release build menu item). Interesting thing regarding the building process is that AIR applications HAVE TO digitally signed (one of wizard steps ask for certificate location – with an option of temp signing in)

This is how installing AIR application looks like
image image

And the message I got on my lap top after that :) (installed app was still working after that )

image

After hello world app was done he spoke about jscript to Air book and Flex reference poster, pointed to  www.tostring.org web site which contains online version of those books and to http://onair.adobe.con/blogs/tour as place where to go to grab presentation material from presentations made on tour.

Adobe AIR done with Jscript

This presentation was done by Kevin Hoyt (khoyt@adobe.com, http://blog.kevinhoyt.org) which started his presentation by doing a demo of CleVR.com site done in AIR where he uploaded couple of his panorama photos he made yesterday with his 10 MPix camera. The site took couple of his pictures and stitched them into one panorama wide picture. He emphasized couple of times that the pictures are very big and that the AIR app is smart enough to melt them together resolving their intersections automatically.

Who said Silverlight DeepZoom? :)

He used FlexSDK (can be downloaded from here  for free) together with Notepad (whatever the OSX name for Notepad app is) and showed how a simple standard HTML page with standard HTML tags would execute on on desktop.
Beside the free tools, DEV could download the Dreamweaver CS4 beta from labs.adobe.com or download a AIR extension for Dreamweaver CS3. Another option is 3pty plug-in for Eclipse called Aptana which contains (beside other things) a lot of examples how to do most of  the common activities with AIR.

He presented then very important file in FlexSDK, AIRAliases.js which performs mapping of AIR types to jscript classes.

That’s how while working with jscript classes you are using in fact the AIR. He showed a demo of how from jscript code he can  write files to local hard drive using the mapped functionality

He pointed also to two different commands for adl and adt (where adl allows testing air application without installation – useful for real world development)

Integrating HTML, JavaScript and ActionScript ("ScriptBridging")

Kevin Hoyt also did the next presentation called script bridging where he show different examples of integrating different scripts.

He was using on this presentation Flash CS3 to show couple of demos:

  • Drag & drop functionality
  • Accessing CSS elements directly from AIR
  • How to create a browser wit some cool extensions
  • How FlexBuilder enables browser DOM debugging directly in ActionScript.

An example of how to access DOM he used was through htmlLoade class, something like this

web.htmlLoader.window.document.getElementById('txtName').value;

An example of how to access flash library from AIR

air.FileStream = window.Runtime.flash.filesystem.FileStream

He showed also a demo of jscript application reading the content of the zip file using the library.swf ActionScript library done by David Cheng directly by jscript. According to him, this approach allows us (even if we want still to  keep jscript applications to enrich them with functions they wouldn’t have without script bridging.

At the end he mentioned that on his blog (http://blog.kevinhoyt.org) example with zip library, custom hrome and custom grid done with CSS and jscript can be found

Czech Flex user groups

After the lunch (Staropramen beer, lots of tasty food on a perfect day – thanks Adobe! :) ) we had two short presentations on Czech/Slovak.

First one was presentation of Flex user group done by Juraj Michalek (www.flexgarden.net).
Key points: bunch of Air and Flex online seminars on their site and he said they are very willing to provide their help through their Flex user group at
flexgarden@googlegroups.com

Second presentation was done by authorized Adobe partner which host the   www.flash.cz site with more then 60 articles for beginners  on flash and flex and also with expert answers provided for Flex developers.

Deploying and updating AIR applications

Platform Evangelistsimage
Serge Jespers
serger@adobe.com
http://sergejaspers.com

Jasper showed how to deploy and update AIR application in 3 simple and straightforward steps

  1. Get your application signed
    Adobe AIR application have to be signed by some certificate so during the installation of AIR application publisher identity would be known (green icon). He mentioned that most of certificates we have now would probably be ok for AIR. In case we don’t have any certificate he recommended buying one for $299/year from thawte.com)For a limited number of applications uploaded to Adobe AIR Marketplace , Adobe would provide complimentary code signing certificate (http://adobe.com/go/marketplace )
    Once we have the certificate, signing application is very easy: all we need to do in Step 2 of publishing AIR application we need to provide location of certificate file and password and that’s all.
  2. Deploy your application
    Bad way to do that – zip air app and provide a link on site – sucks big time
    Good way: use installation badge which is kind of customized installation screen where user clicks on install button
    and the application install application and AIR (after showing two security informational screens) .
    Adobe provides 3 types of badges: standard, beta and custom.
    1. Standard is available in AIR SDK, ready to use now but only with standard use cases. Source available
    2. Beta badge – available on http://labs.adobe.com. Cool new look and extra features (can show video, help functionality)
    3. Custom badge – developer have to define everything. Most powerful, but also most complex to implement
  3. Update your application in five simple steps (Adobe “ClickOnce”)
    1. Check from application if server contains XML update file  containing information on current application version
    2. Check then if installed application is older then version on server
    3. Create instance of the Updater class
    4. call Updater.Update method
    5. Updater would close AIR app, install new version and then restart the Application

Application update – DONE!

==============================================

AIR API Overview

Daniel Dura
www.danieldura.com, ddura@adobe.com 
Platform evangelist, Adobe

iPhone 113iPhone 114DB support darag&drop clipboardmisc

All of the examples he presented are available on his web site illustrating all of the common usage scenarios.

He was speaking about 6 major API function groups

  1. Window API major API features:
    - Multi window support
    - Transparent windows
    - Window types  (Standard, Utility and Lightweight)
    - Z-Ordering
    - Always in front window
  2. File I/O major API features:
    - Full Read/Write access
    - Native File dialogues (save, select, select mutliple, directory)
    - Async and Sync APIs
    Note: I really don’t get why Adobe supports async mode. Due to the fact that browser is single threaded, file I/O operation would block the whole browser. To me that feature looks like a nice rope Adobe gave us DEV to hang ourselves :)
  3. Database support
    SQL Lite DB support
    Zero setup single file
    SQL Lite stores all data in one file using applicationStorageDirectory comand –> (Silverlight IsolatedStorage)
    SQL Lite supports transactions and the sql code executes 10x faster when using transactions (reducing number of file I/O operations)
    To me SQL Lite is trying to do exactly the same as Microsoft Compact SQL Server with more limited stack of operations.
  4. Drag & Drop/Clipboard
  5. Web services support
    He showed an example how to detect internet connectivity status by pininging google.com  by doing something like this
    new UrlRequest(www.google.com) class
    request.method="HEAD";
    URLMonitor(reuest)
    monitor.addEventListner(StatusEvent.STATUS, handle_status)
    monitor.start();
  6. Misc - Encrypted local store
    - dock notifications
    - idle notifications

  

Google App Engine

Dion Almer, cofounder ajaxian.com, works at Google code

iPhone 121iPhone 123

At the beginning he showed http://prague.360cities.net/ flash application powered by google maps  which looks to me as Microsoft Deep Synth competitor (Altpught DeepSynth is much more serious, compare their example with the one from 360cites site)

The rest of the session he was speaking about Google app engine which should help building developers scalable sites in Python for free (to up to 5 million page views)

Another Interesting thing (I’m sure my friend Lorenzo Bolognini already knows about it)  is that Django Python framework is fully supported (except ORM features)

http://code.google.com/appengine

Another interesting question he answered was”

“What if popular JavaScript libraries were available and shared in the browser?“

Well, instead of each one of us hosting jscript libraries, Google host at http://code.google.com/apis/ajaxlibs/ jscript libraries for jquery, 

Data intensive AIR Applications

Andrew Shorten

iPhone 126iPhone 128  iPhone 130

I was expecting a lot from this sessions because seeing what Adobe has to offer in this area is very important for LOB applications/sites, but I get the least from this session.

The reason why lays in the fact that most of his presentation was wrapped around Adobe specific Blaze DS and Live Cycle server which are providing server side infrastructure for efficient RPC type of communication.

He showed example from http://www.jamesward.com/census on what performance gain usage of Adobe servers  brings to game which looked nice but he mentioned that the data transmitted is in binary format (AMF3) with RPC which is not very firewall friendly. In post RPC era I believe we are messaging should be done by open protocols on firewall friendly ways

The difference between the Blaze DS server and Live Cycle server (beside Blaze being Open Source solution) is that Live Cycle server supports offline scenarios allowing applications talking to services to work even application would be offline and Live Cycle Data Service server would take care about  synchronization and conflict resolution once the Internet connection would be up again.

Live Cycle Data Management services have XML configuration file (like the BlazeDS has) where user defines SQL adapters with the sql scripts. Original CRUD operations are modified there to support the offline/online updates which occurs on commit (and use the xml defined data). So we have a XML file filled with dynamic SQL statements. Good thing that none of the DBE were not attending because I’m sure there would be DBE yelling  in that moment.

To me this example looked very familiar with “Astoria offline” demo from Mix ‘08 and I am feeling much more comfortable with solution based on REST Atom services/ FeedSync based solutions (which is btw free) versus something which looks like closed Adobe product.

Couple of useful links:

Blaze DS
http://opensource.adobe.com

Live cycle (additional options as support for offline, conflict resolution etc)
http://www.aobe.com/products/livecycle (1 CPU license for free)

http://www.adobe.com/devnet/livecycle

AIR + Ajax

Andre Charland, CEO, Nitobi.com
Enterprise Ajax book, RobitReplay.com, InsideRIA blog
http://blogs.nitobi.com
http://www.insideria.com
twitter.com/andrecharland

 iPhone 135iPhone 138   
   iPhone 146 iPhone 140 iPhone 148

This guy REALLY likes jscript. According to him we should be all doing jscript everywhere and anytime. And the examples he showed give him a lot of credibility in that :)

Why Ajax in AIR?

- Code reuse (we already have a bunch of jscript code)
- Skill reuse (we already have a bunch of jscript developers)
- HTML is REALLY good at some things ( build blog reader only in flash is not having sense)
- maintain UI patterns (same UX for web and desktop)
- JavaScript interest in DEV community is growing  (important if you are hiring)

He showed some data graphs about sales of programming languages books showing that jscript interests is growing rapidly.

He demo couple of very interesting applications using AIR:

  • AIR twitter client: www.getsnitter.com (jQuery, custom chrome, transparent, word count, notifications)image
  • SalesForce.com desktop client done in AIR (adobe tree controls, drag and drop of vCards)
    image
  • Robotreplay – story of usability with youtube example where everything user is not looking directly is blurred
  • MacDoc wanna be – fisheye , jscript, css and png files rotating
  • Spreadsheet like greed  (Wizard defining data binding of grid, column mapping, live scrolling or paging etc
    Dreamweaver creates php, jscript, css)
  • Nice bubble tooltip creation tool
  • ReadAIR – jQuerty built google reader clone
  • Snippetly – stores code snippets in SQL LIter (writen in jscript using Mootool linrary)
  • VOIP and SMS in AIR demo
    Tabria  client which calls the phones of both of people in chat using the local lines and allows them to talk over the Tabria network and/or to send SMS messages

Then he was speaking about some usability pitfalls in AIR:

- Keyboard shortcuts
- Minimize, move close when "chromeless"
- Mouse hints, invitations, tool tips

Activity indicators have to be implemented explicitly

At the end he mentioned that http://www.nitobi.com/air has bunch of useful links

nitobi.com/air
has bunch of links

AIRconditioning

Lee Brimelow
Platform evangelist/Adobe

http://www.gotoandlearn.com (free video tutorials about flash)
http://www.theflashblog.com  (all of the slides he was presenting should be there)
(worked at frogdesign  before adobe)

iPhone 152      iPhone 163
Lee did awesome job showing us what we can do with AIR in very funny way. His presentation started with “Flash vs Flex” where he recommended:

  • use Flex when in need for : Application layout, data binding, superior coding expereince, components sets
  • use flash when in need for: Animation, Video etc…

He then started doing his demos:iPhone 156

  1. Windowing demo He presented an application creating different types of windows (Normal, Utility
    and Lightweight) combined with different Chrome options (System, Custom (Opaque) and
    Custom (Transparent). He also showed “staying on top” of windows and full screen mode  where air capture keystrokes even in full screen mode.
    Examples he used to show this were:
    - Hell’s kitchen custom chrome video player, 
    - a nice sidebar staying always on top with a collection of buttons producing different farts
    (Seeing that no one is laughing on that, he said “This would be really funny in US”)

    - Boss application
    He opened a game and a Safari with PiratesBay site where he typed CS3 and the list of pirated version with pirated serial keys downloads appeared (really funny), and then he press the boss key and  
    iPhone 159iPhone 160iPhone 161
    - Papervision 3D
    Thanks to using of GPU hardware acceleration, he showed really fast 3d carousel with live videos

  2. Menu-ing API
    He presented that AIR supports OSX Application menu and WindowsLinux window menu (menu attached to application window, under title bar)
    Developer have to do checks in the code during the run time to see if a given type of environment supports some type menu or not. He showed support for Dock menus (Mac only) and System tray menu(windows).
    An example he used to demo the functionality is called :SpitEmOut and it is awesome minimalistic video player with snapshot capabilities , where every snapshot taken is randomly aligned around video player
     iPhone 167iPhone 170iPhone 169
    When he was showing that context menu is not containing any “About Adobe Flash” entries (fully customizable) he called that “no Adobe usual crap in menus”   Hilarious …
  3. File class
    Worth of mentioning here (which was not mentioned before) is that AIR is in advantage over the Flash 9 with file related functions, but Flash 10 would have all the AIR file features (writing to local disk, reading from disk etc). The size of encrypted local storage is 10 Mb per application and encryption used is the default one of the user OS
    Example he tried to show to us was downloading FLV file from you tube but that didn’t work (my guess due to WiFi network being down at that time)
  4. Drag & drop functionality
    Supported D&D modes:
    - Application <->Desktop
    - Application <-> Application
    - Application <-> Browser
    You can customize the drag & drop picture.
    Example: Flash video player dragging the FLV video file to video player example
  5. OS Interaction.
    Supported: - Launch on user login mode
    - File associations (full manipulation)
    - Tracking user presence (application is aware of user being idle where idle threshold must be more then 5 seconds) - Control over application invocation and termination through appropriate events
    - Only one instance of one AIR app can run at the same time
    Example:
    Vista UAC
    ------------------iPhone 168

    The example he had was targeted to Microsoft and Vista UAC. He made a  little app which was after user was idle for 5 seconds popping up a dialog with a message like "Are you sure that you want to move mouse?"  in a dialog box looking like Vista dialog box (grayed background, system colors etc)
    A bit to much Mac-ish for my taste. Speaking about Macs: guys from Adobe looked really surprised when they saw a minority of people raising hands on “Who’s Mac owner”… I guess that’s because in US Mac has much higher penetration in the Adobe user group. Each one of the presenters was using Mac for its presentation

    FileTyper virus

    -----------------------------
    With AIR you can associate any file type on user computer to AIR application. He showed an example where he switched application handling the FLV files to start up his GoogleAds AIR application.
    I can see a bunch of people trying to do the same thing and I am not sure how AV software would prevent this because in a sense it is not real virus but the effect (in case of most users) would be the same as you have Trojans in your computer
    WiFI example
    -----------------------------
    AIR can get information from Wireless card about available networks. He used this example to show us how to pass start up parameters to AIR application. Also he showed network connectivity  AIR functionality together with cross application communication (AIR to AIR, AIR to SWF (through local connection)

Conclusion

Adobe organized great event here in Prague where even persons like me (new to Adobe ecosystem) get a lot of important information's.

To me the most important thing I was hoping to get answer on was: How Adobe offerings compare to Microsoft Silverlight stack.

The answer I got can be summarized as: Adobe doesn’t have a chance on long run. The only thing they have huge advantage is  Flash plug in penetration (99% of browsers) but IMHO is just matter of time when MS would get similar figures with SL.

Here’s the comparison (although it is hard to figure out what to compare “AIR vs SL” or “AIR vs WPF’

Languages

Adobe is limited to ActionScript and jscript. Silverlight supports CLR (C#, VB)  and  DLR langauages (Iron Python and Iron Ruby) - including even php support through Phalanger project.

The decision Microsoft made in SL 2.0 to get rid of the jscript in favor of .NET languages is perfectly fine with me.

Tooling

Although I was surprised with how good Flex Builder 3 and Flash IDE’s are (thanks to Eclipse) my opinion is that they are still not match to VS IDE offerings (standard with or without plug ins).

Microsoft Blend in version  2.5 is “still not right there” but it is making big steps toward being designer friendly tool. IMHO, all Blend needs is mainstream adoption from designers which would bring significant feedback “from the trenches” which is only thing Blend team need. I am not even sure that the people criticizing it is not criticizing it because mostly “it is different then Flash”… Ah, time would tell about this

Very important difference here between the platform is that (according to demos I saw) there is no “code behind” in Adobe case (markup and ActionScript code are mixed) which definitely makes  life difficult in case of multiple personas working on the same file (conflict resolutions etc)

DB support

Microsoft SQL Compact and Adobe SQL Lite look like doing the same thing on same way (no installation, app local database). I am biased a bit, but SQL Compact coding model (standard ADO NET code) looks more robust and powerful then the one I saw for SQL Lite

Web services

We are living in SaaS and S+S era, so Adobe proposal of using propitiatory AF3 binary format with RPC communication style looks not very convincing.
In Microsoft stack we have WCF supporting a bunch of different messaging protocols. There are also ADO NET Data Services with their RESTfull AtomRss API.

LiveCycle offers a offline mode with syncing and conflict resolution, but having FeedSync and Astoria already and Astoria Offline prototyped at Mix ‘08 removes that advantage for me.
The big differences here are :

  • FeedSync and Astoria can work with ANY sync and data provider
  • MS Offering basically comes for free

Web/Win/Mobile code reuse

Adobe AIR tries to bring the html/jscript support to the desktop, which has sense on short term but I don’t think anyone would really like to do their desktop applications coding in jscript. Also, Adobe take on mobile phones support is that they al support jscript, html and most of them Flash which might and might not be true, but still (AFAIK) requires serrate coding

Having SL as “a subset of WPF” and heavily investing into the WPF/Blend with the whole machinery MS has would (I’m sure) bring much more code reuse in case of SL/WPF then the Adobe offering. Mix ‘08 mobile demo showed SL supported on Nokia phones and windows mobile powered smart phones where the same application written for WEB/WIN would works on Mobile thanks to the WPF built in scaling features

Summary

We didn’t saw any demo about acceptability, internationalization features etc.. which are the features supported very well with SL… Having whole stack of supporting technologies (Entity framework (it will get right in V2), SQL Data services), best customer support (books, videos, MS evangelist, training etc) most of those technologies totally free with source code available makes this a clear choice to me:
Silverlight rules! :)

Filed under: Uncategorized 3 Comments
9Jun/081

Design for testability – Auto Mocking Container (AMC) – Part 9

On my quest to design for testability, I've already covered:

My today’s post would be covering AutoMockingContainer (AMC) in both “standard” and “service locator based” versions

What is auto mocking container (AMC)?

I’ll use the example from original Elutian blog post (where the concept of AMC is first mentioned) where the test setup code looks like this:

[SetUp]
public void Setup()
{
  _service1 = _mocks.CreateMock<IService1>();
  _service2 = _mocks.CreateMock<IService2>();
  _service3 = _mocks.CreateMock<IService3>();
  _serviceWeAreTesting = 
       new DefaultServiceWeAreTesting
            (_service1, _service2, _service3);
}

This example applies transparent dependency injection style described in previous post with a class expose a constructor accepting many interface parameters "(“services”) to which class functionality is dependable on.  On first look, there is nothing wrong with the example above but once you would be doing serious testing you would probably find out two things:

  • (PIA) during test creation you would probably feel that it is too much “plumbing” code to be done to support testing
  • (REAL PIA) long after once the tests would be done someone would add to that class constructor another parameter (“service4”) and each one of the tests you created would start crashing although probably the functionality you were testing is not relying on _service4 at all.

To tackle those two issues, smart people at Elutian combined Rhino mocks and Windsor container to tackle those problems.

Using AMC the same test setup code would look like this:

[SetUp] 
public void Setup() 
{ 
  _mocks = new MockRepository(); 
  _container = new AutoMockingContainer(_mocks); 
  _service = _container.Create&lt;DefaultServiceWeAreTesting&gt;(); 
} 


As you can see, in case of AMC we construct AutoMockingContainer with MockRepository instance thrown as parameter.

That allow’s us to replace explicit mock creation and concrete constructor invocation with AMC container Create method which accept as generic type parameter the type we plan to test.

Windsor would then find out the constructor which needs to be used and for each one of the service interfaces (if they are not in container) would create a dynamic mock class implementing given interface (thanks to Rhino mocks).

so now when we have this initialized writing the test is much simpler and looks like this (taken from the same Elutian blog post)

[Test]
public void DoWork_Always_AsksOtherServices()
{
  using (_mocks.Unordered())
  {
    _container.Get&lt;Service1&gt;().DoWork();
    _container.Get&lt;Service2&gt;().DoWork();
    _container.Get&lt;Service3&gt;().DoWork();
  }
  _mocks.ReplayAll();
  _service.DoWork();
  _mocks.VerifyAll();
}

As you can see, we are not explicitly constructing service class and registering services to container. AMC container already created instance and add components to container in setup method so all we need to do in test is to use them.

Obviously:

This is much shorter to be written –> issue #1 is solved.

Even if we would add additional  constructor parameter the AMC would recognize that IService4 was added and it would add its mock to container effectively preserving the test not depending on IService4 runable  –> issue # 2 resolved

(To get AMC source code which you can compile on your box and use, click here)

Auto mocking container and Unity

As I mentioned above, the AMC solution given above is for Castle Windsor IoC framework and my IoC framework lately become Microsoft Unity (due to the reasons stated in DFT Unity post), so I did little search for Unity AMC and found out that Roy Osherove implemented it already.

Roy provided in that blog post example how test looks:

[Test]
public void MockTwoDependenciesForAConstructor()
{
	MockRepository mocks = new MockRepository();
	AutoMockingUnityContainer container =
        	new AutoMockingUnityContainer(mocks);

	container.WillReturnAStubFor<ILogger>();
        container.WillReturnAStubFor<IEmailer>();

	using (mocks.Record())
	{   
		//Tell our mock to return true when this method is called
        	container.Resolve<ILogger>().IsLogFileFull();
                LastCall.Return(true);	
	}

	//runner class takes both of these mocks in its constructor
        Runner runner = container.Resolve<Runner>();
        Assert.IsNotNull(runner);
}

Well, although his implementation is VERY cool way of “create mock and inject it to container”  it is not (at least how I get it) the AMC like the one Elutian guys did because I am still expected to define stubs and inject them to container explicitly (although on short&easy way)  (issue #1 still exist).

But, #2 (more important one) is handled with this because test code not depending on the additional dependency wouldn’t crash.

So, all in one, if you do IoC with Unity go to mentioned Roy blog post and copy paste the Unity AMC source code for your own usage.

Auto mocking container – my way

Well, as I presented in previous post, currently the way I am writing and testing my code is that I declare internal constructor accepting the dependencies and perform mock injection without using of any IoC framework.

But, even for me issues #1 and #2 are not a big problem (I don’t mind declaring mocks and I WANT my test to crash when tested lass change so I have to check out the tests), I can imagine that for some of people this wouldn’t be the case. For them, testing on the simplest possible way with #1 and #2 resolved would be “have to” requirement.

The good news here is that there is solution for this almost “out of the box” thanks to the design decisions I made in previous posts:

  • I would have Facade component (ServiceLocator) encapsulating concrete IoC framework usage
  • Default constructor performs “poor man dependency injection” using the ServiceLocator

If we think about what the problem really is AMC tries to solve we would come up with something like this:

“When IoC container is asked to retrieve a type implementing some interface and that mapping is not defined, return a mocked instance of the interface.”

And that is exactly what I would do…

Modifying ServiceLocator

ServiceLocator class is going to support testing mode when instead of IoC container exception throwing (for cases of no type can be retrieved from IoC container for a given interface) ServiceLocator would create a new mocked instance. Something like this:

using System;
using Microsoft.Practices.Unity;
using Rhino.Mocks;

namespace Facade
{
    public static class ServiceLocator
    {
        private static readonly MockRepository _mockery 
            = new MockRepository();
        private static readonly UnityContainer _unityContainer
            = new UnityContainer();

        public static bool TestMode { get; set; }

        public static void InjectStub(I instance)
        {
            _unityContainer.RegisterInstance(instance
                , new ContainerControlledLifetimeManager());
        }

        public static T Retrieve<T>;()
        {
            try
            {
                return _unityContainer.Resolve<T>();
            }
            catch (ResolutionFailedException e)
            {
                if (TestMode)
                {
                    return _mockery.DynamicMock<T>();
                }
                throw new InvalidOperationException(“Can't resolve dependency.”;, e);
            }
        }
    }
}

As you can see service locator now has dependency to Rhino mocks (MockReporsitory class) which is ok IMHO. There is also TestMode new boolean property which represents the way to switch ServiceLocator from production to test mode. Retrieve method now puts IoC Resolve method call inside of try block. In catch block there is conditionalization based  on TestMode value: in case ServiceLocator is in test mode mocked instance is returned and in case ServiceLocator is in production mode Unity exception is been bubbled up.

And that would be all what we need to do to support custom AMC.

Writing tests using custom AMC

Now when we have the AMC container done, let’s check out how the test from last blog post would look like now with custom AMC used.

Let add first additional dependency to UserManager constructor so we would have the right use case for AMC (original constructor had only one IUserProvider in which case AMC usage doesn’t have sense)

So the UserManager class would look after that modification something like this

    public class UserManager : IUserManager
    {
        private readonly IUserProvider _userProvider;
        private readonly ISomeOtherDependency _someOtherDependency;

        public UserManager()
            : this(ServiceLocator.Retrieve<IUserProvider>(),
                   ServiceLocator.Retrieve<ISomeDependency>()) { }

        internal UserManager(IUserProvider userProvider, ISomeDependency someDependency)
        {
            _userProvider = userProvider;
            _someOtherDependency = someOtherDependency;
        }

        #region IUserManager Members
        public int NumberOfUsersActiveInLast10Days(string userName)
        {
            var userCollection = _userProvider.GetUserCollection();
            var result = 0;
            foreach (var user in userCollection)
            {
                if (user.Name.StartsWith(userName) 
                    && user.LastActivity > DateTime.Now.AddDays(-10))
                    result++;
            }
            return result;
        }
        #endregion
    }

Note that constructor now have additional parameter of ISomeDependency type.

The test similar to the one from last post but this time using the AMC would look like this:

    [TestFixture]
    public class UserManagerTest
    {
        private MockRepository mockRepository;

        [SetUp]
        public void Test_Init()        
        {
            mockRepository=new MockRepository();
            ServiceLocator.TestMode = true;
        }

        [Test]
        public void GetActiveUsers_TestCaseOfZeroUsers_WouldReturnEmptyCollection()
        {
            IUserProvider userProvider = 
                mockRepository.DynamicMock<IUserProvider>();
            ServiceLocator.InjectStub(userProvider);

            using (mockRepository.Record())
            {
                Expect.Call(userProvider.GetUserCollection())
                    .Return(new List<User>());
            }
            using (mockRepository.Playback())
            {
                // using public ctor(NO EXPOSED PARAMETERS)
                var userManager = new UserManager();
                int numberOfUsers= userManager.NumberOfUsersActiveInLast10Days(“X”);
                Assert.IsTrue(numberOfUsers == 0);
            }
        }  
    }

Couple of key moments here:

  • In test init method I switch ServiceLocator to “test mode” –> command him to return mocks for all types not stored in IoC container in the moment of their retrieval request
  • In test method I am explicitly adding to ServiceLocator ONLY instance of IUSerProvider (which is related to this test) .
  • ISomeDependency parameter is not mentioned anywhere in the test (solution to #1)
  • I am using the default constructor. That is giving me the solution to #2 which looks very strange on first sight but once one would realize that behind that default constructor is ServiceLocator based poor man dependency injection things get clearer.

Again, I am aware that this approach to AMC is probably unique (I didn’t saw anything like this on the web) but I just choose to do the AMC through component design and not by some AMC framework (although that is perfectly fine choice with me too)

Conclusion

Although I like to keep things in my own hands as much as possible, I see a lot of value coming from AMC usage in writing tests for people who like the AMC idea.

For people not sure “which pill to take” there comes the list of pros and cons I found on the web (here and here)

Pros

  1. Can be easier to maintain and write tests/Can lead to easier test maintainability.
  2. Allows easier focus on testing interaction.
  3. Automatic testing the services construction via the IoC container.

Cons

  1. Speed/performance?
  2. It could make the test a little less readable in terms of understanding what gets injected and what the actual dependencies are.

 

What’s next

My DFT blog post series stops here because I am getting fed up writing about unit testing and not having fun doing it is a sign for switching gears :)

I have recently some real world experience on MVP design pattern appliance in real world scenarios so I plan to write couple of posts describing my thoughts on how to solve common problems most of the people face doing MVP (tackling complexity, communication controlpage, need for HttpContext in presenter, composite UI communication, Front controller routing  etc) so in case you are doing WebForm classic ASP NET development and you care about testing your UI stay tuned

Useful links for AutoMockingContainer

http://blog.eleutian.com/2007/08/05/UsingTheAutoMockingContainer.aspx

http://www.ayende.com/Blog/archive/2007/06/08/The-Auto-Mocking-Container.aspx

http://blog.eleutian.com/2007/02/23/TestsAutoMockingIoCContainer.aspx

AMC custom implementation source code can be found here

 

Filed under: Uncategorized 1 Comment
8Jun/084

Design for testability – Transparent and opaque dependencies (part 8)

On my quest to design for testability, I've already covered:

(In case you don't know what IoC containers are, I advise you to take a peek at Part 4 of this series first before continuing  with this article.In case you are not familiar with Microsoft Unity IoC framework which I would be using in this post read part 7)

Intro

Before I start, I would like to recommend you to subscribe to Alt.NET mail list where you have daily top notch discussions about various ultra interesting subjects.
One of April subjects was Are Opaque Depencies Bad? (Mockist TDD's effect on design) where you can see that some of very smart people were stating that Opaque dependencies are sometime acceptable compromise because they encapsulate complexity and the component dependency information we get anyhow are not that valuable.

IMHO that is wrong because of the reasons I would state in this post and which can be summarized as:

  • writing tests for components implementing opaque IoC style is much harder
  • transparent IoC helps identifying controls which “do too much” – in general the  one with very big number of dependencies are maybe candidate for investigating if there is SoC violation

Opaque dependencies

In most of code in the same example I was using in previous posts in design for testability series, I was writing code similar to this:

using System;
using System.Collections.Generic;
using Facade;

namespace Example.UserManager
{
    public class UserManager : IUserManager
    {
        #region IUserManager Members
        public int NumberOfUsersActiveInLast10Days(string userName)
        {
            IUserProvider userProvider=ServiceLocator.Retrieve<IUserProvider>() ;
            IList<User> userCollection = userProvider.GetUserCollection();
            int result = 0;
            foreach (User user in userCollection)
            {
                if (user.Name.StartsWith(userName) 
                    && user.LastActivity > DateTime.Now.AddDays(-10))
                    result++;
            }
            return result;
        }
        #endregion
    }
}

In first line of my the NumberOfUsersActiveInLast10Days method, an instance of type implementing IUserProvider has been retrieved and then used it in next line to get list of all users.
Once the list of users would be retrieved from DAL provider class, method code iterates and filters out all of the users which name starts with given string and which were active in last 10 days.

As you can see the usage of service locator is “hidden” into the method code and invincible outside of that method.

In other words, if we would check out the code using that method 

using System;
using Example.UserManager;
using Facade;

namespace Driver
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            UserManager userManager=new UserManager();
            int activeUserCount = userManager.NumberOfUsersActiveInLast10Days(”DB”);
            Console.WriteLine(activeUserCount);

            Console.ReadKey();
        }
    }
}

we wouldn’t get any clue that UserManager has any dependency on ServiceLocator and UserManagerProvider.

This style of implicit usage of IoC framework where IoC framework is embed directly into the members using it, is called opaque dependency injection.

According to my personal experience opaque style is something looking very appealing to people new to IoC because it is a way of implementing IoC with “nothing changed”, so usually it is considered as “acceptable compromise” :)

Testing the opaque dependencies

Let see why I found this opaque style bad on example of how making test for this NumberOfUsersActiveInLast10Days method would look.

The test I would write would have to verify that for no users in database which have username starting the with given string, program would return zero.

I am sitting in black box testing camp (no testing of private method and looking at the code being tested maximally discouraged)  so I usually start my tests writing the playback code

        [Test]
        public void GetActiveUsers_TestCaseOfZeroUsers_WouldReturnEmptyCollection()
        {
            using (mockRepository.Record())
            {
                // no clear idea what to mock here
            }
            using (mockRepository.Playback())
            {
                var userManager = new UserManager();
                int numberOfUsers= userManager.NumberOfUsersActiveInLast10Days(“X”);
                Assert.IsTrue(numberOfUsers == 0);
            }
        }  

Well, as you can see after writing the playback code representing the ways how the code would be used, I don’t have clear idea what I should mock in record section so the test wouldn’t fail.

The only way how I can write the test is to run the test, get error

System.InvalidOperationException: The current type, Example.UserManager.IUserProvider, is an interface and cannot be constructed. Are you missing a type mapping?

then add code to record phase mocking that, run the test again, check out additional error messages etc.

Not  very pleasant and productive way to get the final test result which in case of opaque dependency looks like

        [Test]
        public void GetActiveUsers_TestCaseOfZeroUsers_WouldReturnEmptyCollection()
        {
            using (mockRepository.Record())
            {
                var userProvider = mockRepository.DynamicMock<IUserProvider>();
                Expect.Call(userProvider.GetUserCollection())
                    .Return(new List<User>());
                ServiceLocator.InjectStub(userProvider);

            }
            using (mockRepository.Playback())
            {
                var userManager = new UserManager();

                int numberOfUsers= userManager.NumberOfUsersActiveInLast10Days(“X”);
                Assert.IsTrue(numberOfUsers == 0);
            }
        }  

Transparent dependencies

Transparent dependency injection style requires explicit definition of dependencies in class constructor, exposing clearly what are the dependency class has.

UserManager class written in this way would look like this

using System;
using System.Collections.Generic;
using Facade;

namespace Example.UserManager
{
    public class UserManager : IUserManager
    {
        private readonly IUserProvider _userProvider;

        public UserManager():this(ServiceLocator.Retrieve<IUserProvider>())
        { }

        internal UserManager(IUserProvider userProvider)
        {
            _userProvider = userProvider;
        }

        #region IUserManager Members
        public int NumberOfUsersActiveInLast10Days(string userName)
        {
            IList<User> userCollection = _userProvider.GetUserCollection();
            int result = 0;
            foreach (User user in userCollection)
            {
                if (user.Name.StartsWith(userName) 
                    && user.LastActivity > DateTime.Now.AddDays(-10))
                    result++;
            }
            return result;
        }
        #endregion
    }
}

If we look at the NumberOfUsersActiveInLast10Days method we would see that ServiceLocator class is not been used nay more there. Method now uses userProvider field without knowing how the _userProvider field is been initialized.

We have also two constructors:

  • Internal constructor accepting the parameter of IUserProvider data type and store its value into the _userProvider field
  • Public default constructor not accepting any parameters but which uses the ServiceLocator to retrieve from IoC container service implementing the IUserProvider interface and then calling internal constructor passing that service to internal constructor parameter

“Dude, this is no transparent dependency…”

Usually examples I was finding on net wouldn’t look like the just given example. The internal constructor would become public and the current default constructor doing poor man dependency injection through ServiceLocator wouldn’t exist at all.

Their rationale is that the UserManager would always be constructed using IoC framework which would automatically perform the injection during the IoC container construction time.

In real enterprise development that is often not true because we could have in existing code base a lot of places doing already doing UserManager  mgr=new UserManager() (constructing without the usage of IoC) so that implicit IoC dependency injection  wouldn’t work for them.I guess also that updating all of the current code just to be able to serve the IoC framework wouldn’t be probably very high on “resource allocation list“ spreadsheet, so we could count on the fact that this “legacy” code would stay like it is now.

What I am doing in my approach is basically switching that implicit IoC dependency injection with explicit one. The major difference here is that I am basing my IoC class design on default constructor and not on some specialized one. That’s why when code construct the class, in both cases (using IoC or new keyword) the result is the same – automatic service resolution and dependency injection. In other words, all this would work with any legacy code using the UserManager class.

Another significant gain (IMHO) from my approach is that I am hiding the complexity from production code (only default constructor exposed) while still having the same IoC concepts in place.

After all, having class design “open for testing but closed for code noise” is the whole point of this DTF blog post series.

“Dude, this is transparent dependency, just it is V2” :)

Testing the transparent dependencies

Once we have our code restructured testing is much more easier and even possible without using the ServiceLocator at all.

Writing the test in this case would show me during the Playback definition that UserManager class have a constructor accepting the IUserProvider class which would lead me to the conclusion what I need to mock in order to have this test done without “run until not complaining” approach I described in opaque test example above.

So first we would add to AssemblyInfo.cs file of UserManager appropriate assembly attribute

[assembly: InternalsVisibleTo(&quot;UserManager.Test&quot;)]

After this User.Test assembly would  get access to UserManager internal constructor above so the test would look like this

        [Test]
        public void GetActiveUsers_TestCaseOfZeroUsers_WouldReturnEmptyCollection()
        {
            IUserProvider userProvider = mockRepository.DynamicMock<IUserProvider>();
            using (mockRepository.Record())
            {
                Expect.Call(userProvider.GetUserCollection())
                    .Return(new List<User>());
            }
            using (mockRepository.Playback())
            {
                var userManager = new UserManager(userProvider);

                int numberOfUsers= userManager.NumberOfUsersActiveInLast10Days(“X”);
                Assert.IsTrue(numberOfUsers == 0);
            }
        }  

Couple of things to note in this example:

  • I am not using ServiceLocator at all for implementing this test.
  • I am using internal UserManager constructor to inject UserProvider mock.
  • While writing the line using the internal constructor I realized (from constructor signature) that I need mocked instance of IUserProvider (first line of the test method)

Conclusion

IMHO, using of transparent dependency significantly simplifies the test making. The approach here I presented (with internal constructor) is variation of standard implementation made to hide the complexity and remove the rope from the hands of TDD unskilled developers. Applying it could enable having a small “TDD core team” of people doing component level design and enabling IoC (with all of the benefits) and all other developers totally unaware of the IoC class design which should reduce training costs and increase IoC adoption chances in organizations not applying it.

What's next?

My next blog post would be on how AutoMockingContainer (AMC) makes testing easier in cases we are using transparent  dependency injection style so in a sense with this blog post makes complete explanation on how to test IoC based components done with transparent dependency injection style

Source code of the examples (opaque and transparent) presented in this post can be found here

Filed under: Uncategorized 4 Comments