Saturday, June 25, 2011

Context may be key to blended learning

I have been reading two excellent books recently, John Medina’s Brain Rules

Sunday, May 15, 2011

Why web will win the mobile app race

Everyone wants a mobile app, banks, health funds, airlines, pubs and all sorts of marketers want us interacting, playing with and using their mobile apps. This is fine and dandy, and is a Good Thing for the future of humanity, but … which OS do you want to target?

Is your app going to target iPhone, Android, Blackberry, Windows Phone 7 or (heavens!) Symbian?

The right answer will, of course, be all of the above. It really isn’t hard to figure out, and there is a precedent you see.

What do you do if you want to target users on MacOS, Windows 7, Linux (a bazillion flavours itself), Google OS or (heavens!) Unix?

The answer to that question is you created a web app, because the browser environment was designed to be (reasonably) neutral between vendors. The same paradigm exists in the mobile world. Creating a specific OS version just limits your app to that OS, and who wants that?

However there is one big difference, the mobile app needs to deal with being occasionally (dis)connected, right? Solving that problem has been hard enough that mobile apps are still sprouting up that basically show content offline.

Riding to the rescue of the beleaguered user comes HTML5 with its cache manifest offering to give web apps a completely sane way of specifying what content should be held offline and what resides online. The  only problem is the memory limits most browsers place on the cache – except for Opera they all only let you have 5MB (or 10MB if you are on IE) – and in these days of fast connections and rich media that simply isn’t enough to get the job done.

There are various ways around this, with Google Gears, Microsoft Sync Framework and Flash also offering ways of getting offline storage to work, and there are some jQuery plugins that hint at the promise of getting this working in a framework that leaves the browser sensitivities to someone else (although I’m always leary of potentially leaky abstraction layers).

Personally I don’t care how we solve the problem of sufficiently large offline storage, but I think the future of web development demands that solve it we must.

In the meantime we will continue to see niche agencies offering native applications for various phone OSs, but not necessarily delivering the value the business needs because the cost is so high to develop cross-platform apps – and some other applications that target specific OS flavours, most notably Apple iOS or Android, and get away with that because the user base can be targeted that way (for now).

EDIT – 23rd Jun 2011

GigaOM recently weighed in, telling us that native mobile apps were beating HTML5 ones. One commenter, Roshan Shrestha, mentioned that:

“I see that many of the apps are just a wrapper against an HTML browser component. Most of them do not store much data locally and require internet connection, so these are basically web apps.”

I agree that most apps could be web apps, and I think it will end up there, but not yet. In the meantime everyone needs an Android app, wants an iPhone app and should have a Windows Phone 7 app.

Thursday, March 10, 2011

Arthur Douglas Burgess

I just got delivered a very nice present. The National Library of Australia maintains an online archive of Australian newspapers for the last hundred years or so called Trove (http://trove.nla.gov.au/). A couple of weeks go I found a reference to my grandfather on my mother’s side, and a few days ago I ordered a copy of it via PDF. Thanks to the miracles of scanning + the internet, here it is:

Arthur Douglas Burgess Biography

My other grandfather was also involved with Fairfax and the Sydney Morning Herald, but in the capacity of a typesetter on the printing presses.

Wednesday, March 09, 2011

Is knowledge all there is?

I spent a fair bit of time this week helping a client with their information strategy and information management policy. Their definition of information included “Emails, Databases, Documentation and Knowledge”, which is a mixed bag if ever I saw one!

Clearly they needed to get a better handle on what they were dealing with, so I introduced them to a little pyramid that I had worked on several years ago (back when I was thinking about pursuing a career in knowledge management). I call this the Wisdom Pyramid, and use it to help differentiate between raw data, meaningful information, contextualised knowledge and applied wisdom.

Wisdom Pyramid

Wisdom Knowledge Information Data Pyramid

The example I usually use to bring it to life is that of a traffic light changing colour from amber to red.

At a data level there is a single bit of information, isolated from context and basically without meaning, unless one is familiar with that particular data type.

That data becomes information when meaning is given to it so that a human can more easily understand it.

The information becomes knowledge when context is considered, in this case that the traffic light is one I am heading towards.

Wisdom is exhibited when that knowledge is applied to my situation, so that I stop the car at the red light.

The pyramid is pretty useful, although there is a catch with wisdom as we only call an action wise when knowledge is applied correctly to a situation. Incorrect application is at worst foolish, and at best thoughtless.

Much ado has been made about the management of corporate knowledge, especially the attempt to capture explicit knowledge, although tacit knowledge is also sometimes acknowledged as something that must be transferred. The real issue however is how do we inculcate wisdom into our staff so they make wise decisions and not foolish ones?

“Take hold of my words with all your heart; keep my commands, and you will live. Get wisdom, get understanding; do not forget my words or turn away from them. Do not forsake wisdom, and she will protect you; love her, and she will watch over you. The beginning of wisdom is this: Get wisdom. Though it cost all you have, get understanding.”
Proverbs 4:4-7 (NIV translation)

You grow wisdom by growing people, and that’s where most knowledge management should start – tools are useful (and Elcom has some good KM tools) but mentoring, teaching and encouraging wisdom in our people is where the real benefits come from.

Friday, February 11, 2011

Fresh design!

In case you’re reading an RSS feed, I have updated my blog design to use a core Blogger template, and done some (slightly) artistic tweaking to get a look that I’m happy with.

Thursday, February 10, 2011

Occasionally (Dis-)Connected is the Future

As web application developers we tend to build for always connected scenarios. They simplify the problem of web development and allow us to keep the complexity of our solution hidden on web and application servers back at corporate headquarters.

Pity the poor rich GUI developer who needed to handle both connected and disconnected modes – mainly for corporate management with laptops. This requirement increased the complexity of their applications and forced sharing of business logic with the client GUI layer. Recently mobile developers have realised the need to provide the same service, and with HTML5 web developers are now being pushed to as well.

At the same time, the ability of any client machine to get connected is increasing dramatically. Modern cities provide plentiful sources of free, commercial public and private wifi services, and most modern telecommunications devices allow for secondary use as internet modems.

It is now clear that most web applications/websites are likely to be accessed via mobile devices, and there are far more people with internet access via their mobile devices than via landlines/roaming broadband.

One might wonder whether disconnected clients still need to be supported, or whether the vast majority of clients in the vast majority of locations are best handled by assuming connected, always-on access?

The problem with this thinking is that it ignores a fundamental truth:

“Space is big. Really big.” – The Hitchhikers Guide to the Galaxy

hubbledeepfield

OK, so these are not all apps that will be used in space (has the first iPhone gone to space yet?), but they can’t all assume that the user is always connected.

There are two fallacies with the premise of always-on access, the first is assuming that most people’s situations mimic the developers’ own ultra-connected, hyper-geek, lives, the second is limiting “everywhere” to the points on the daily commute. For most people in the world, in most places, there are going to be frequent losses of signal – even in Australia most telcos can’t get reliable mobile signal to all urban locations, let alone cover the vastness of our Outback.

Of course mobile developers know this is a problem, and might decry that their app can handle the phone losing and resuming signal flawlessly. But is there still value in the app when it is disconnected?

The most interesting opportunities lie with providing access to applications that can still provide value during the occasional disconnection – these are the applications that will be truly useful all the time and everywhere. For example the mapping application on my Nokia N85 can operate with three levels of connection:

  1. Connected to the internet and GPS.
    In this mode I get the latest map updates and can tell where I am on the map.
  2. Connected to GPS only.
    In this mode the maps used are the ones stored locally but my current location is derived from GPS.
  3. Disconnected.
    In this mode the maps are available to be read, queried or manually moved around on, but my current location is not available.

Even in the most disconnected mode the maps are useful, I can lookup addresses and perform most of what I would have with an old-school street directory. When they connect further I get increasing amounts of value. Because of this sort of disconnected operation, the map and email applications are the most useful aspects of the phone to me (the other is the clock). They are more useful than a static application because they can occasionally connect and update themselves.

There is a term for this sort of behaviour that web developers have coined with websites that offer substantial value for all browser clients, but increase their value for some special browser clients.

Progressive enhancement

The point is to view the extra potential as something great to have, but not necessary for the application to fulfil its value proposition.

I really think this is the killer feature for a mobile app – provided of course that there can still be a value proposition in the disconnected mode. I also think that the best mobile apps will be web apps that respond and adapt to the restrictions of the mobile space rather than custom built ghetto-apps that can only prosper in one particular mobile OS. But that can be another post …

Wednesday, November 17, 2010

Dependency injection our way

Like most everyone else practicing automated unit testing the developers at Elcom Technology have the issue to deal with of how to handle dependency injection – that is the exposure of a given object’s dependencies on other objects outside of the object so that the calling object can be made responsible for acquiring those dependent objects. In general this is most easily done by exposing said dependencies in the object’s constructor as required parameters – thus ensuring that the calling objects knows it needs to supply them when new'ing the object. So far, so good.

Recently (as of CM v7.2) we have introduced the Elcom.API library in an attempt to use the adapter pattern to present a more cogent, safer and easier to use interface to our CommunityManager.NET web CMS product. This is all well and good, but it means that to ensure testability we now have chains of dependencies throughout our application code – and declaring something a dependency of object A, when it is required by that object only to call object B, which then only needs it to call object C, creates some very smelly code.

Clearly we needed a dependency injection framework of some sort, but what should we use? Like Uncle Bob we didn’t want our DI framework to leave code smell throughout our projects. Well, we already have an object with all static/shared methods called Current. We use this to give an easy way of accessing some current state items, such as:

Dim a = Current.Configuration.ConnectionString
Dim b = Current.Configuration.EncryptionSettings
Dim c = Current.Configuration.ShortDateFormat
Dim d = Current.HttpContext
Dim e = Current.UrlId
Dim f = Current.User
Dim g = Current.UserId

Now we want to expand that to offer this sort of syntax to give easy access to services/repositories:

Dim myContSvc As Content.IContentService = Current.Service.ContentServiceGet()

That would give a simple way for object B to instantiate an IContentService without needing to declare it as a dependency to object A (but object C should still declare this in its constructor). For this to be truly useful, we have to be able to wire up the Content.Service container at runtime from either a configuration file (the default behaviour) or from code (during testing).

Sidebar: On DI Containers

To digress briefly, you will notice that the Current.Service container is a custom-built one, rather than a Unity or other DI framework’s container. The reason for this is twofold:

  1. We want to minimise our product’s dependencies on other products or open-source projects.
  2. We want developers using our product to be able to know in their IDE whether a given service can expect to be found wired up in the container, hence our use of methods like ContentServiceGet() and SecurityServiceGet().

That second reason is very important given that we are still actively developing the Elcom.API and pushing it out across all of our product’s many modules. One version of CommunityManager.NET may have very different abilities to the next one, and our partners’ developers may be dealing in multiple versions at once – hence the need for good IDE support.

Saved by the Static Property

So we like the syntax afforded us by static/shared methods, but they present problems when it comes to setting the values during testing. We looked at lots of options, including using delegates or even events, but they all made production code smelly in order to aid testing, and that didn’t sit well with us.

What we ended up doing was creating an IServiceContainer interface which declared all the types of services that could be returned, and using a factory within the Current.Service method to build a DefaultServiceContainer from a configuration file. We then provided a Current.ServiceContainer object which would contain the concrete version of IServiceContainer being used and which could be overwritten when testing.

''' <summary>
''' This holds the concrete implementation of IServiceContainer that is used. This is writable in order to help testability.
''' </summary>
''' <value>The concrete implementation of IServiceContainer that is used by Current.Service (or that is created by that function).</value>
Public Shared Property ServiceContainer As IServiceContainer = Nothing

Public Shared Function Service() As IServiceContainer
Dim currentContainer As IServiceContainer

If ServiceContainer IsNot Nothing Then
' retrieving the previously created one (or the testing one if its been written by our tests)
currentContainer = ServiceContainer
Else
Dim factory As New ContainerFactory

currentContainer = factory.ServiceContainer

' obviously we need to store/cache this and not just instantiate each time, so put it back into Current.ServiceContainer
ServiceContainer = currentContainer
End If

Return currentContainer
End Function

This approach works really well, provided you don’t mix production and testing code in the same application instance, which we never do. It doesn’t offer a generic container for developers to use for custom projects built on CommunityManager.NET – but there is nothing stopping them using Unity or other generic containers for their own purposes.

In case you’re wondering this has become a pattern we’re using across the Current object’s static/shared methods, including of course Current.HttpContext. Our caching at the moment is still fairly primitive (stick the object in the static property), but we are looking at making improvements in that area in this release too. If nothing else we have a proxy for Session objects that can be swapped at test time for something not dependent on web projects (although ASP.NET cache is available outside web projects anyway, See Scott Hanselman’s reference to using HttpRuntime.Cache outside ASP.NET).