The Problem with Google Wave: User Experience

Google Wave is no more. For those who remember the sound of the jaws of the tech mainstream dropping when Google showed the demo at Google I/O, that may come as a shock. For those who tried to use it, it’s probably less of a shock. I kind of liked ReadWriteWeb’s take:

Why did Wave fail? Maybe because if you don’t call it an “email-killer” (and you shouldn’t) then you’d have to call it a “product, platform and protocol for distributed, real time, app-augmented collaboration.” That’s daunting and proved accessible to too few people.

To say that people don’t get collaboration or that Wave was ahead of its time is a cop out. Wave IS an awesome product. Real-time collaboration IS changing how the world works together. On the Flash side that is one of the reasons I’m so excited about Collaboration Services; real-time collaboration is fantastic.

But this was a case of Google’s user experience coming to bite them. Some people love the minimalistic experience of Gmail. And it worked a few years ago when it was first introduced, but the iPhone has shown how critical a great user experience is to user adoption. And frankly, Google’s user experience hasn’t changed much since the Gmail days and the applications are starting to feel dated. That’s not a big issue when you’re doing something as straightforward as email, but when you’re trying to completely change how people communicate, you need to provide a user experience that abstracts the technology and just makes it easy. Have we seen that done before?

iPhone

Exactly. Wave was a great technology showcase but it was not a great product. Google had the chance to fundamentally change communication on the web but they didn’t have the design chops to put it in a package that was useful to people and instantly easy for them to dive into. You can’t do an 80 minute demo for something that’s this big of a shift in thinking.

Hopefully Google takes this to heart and realizes that technology isn’t good enough. When you’re being revolutionary you have to design a user experience that makes the technology feel second nature.

New Project: Flex Collaboration Library

I’ve been digging deeply into the dark crevices of Adobe Flash Collaboration Service (AFCS) for my session on creating collaborative components at MAX this week. One of my examples is a collaborative map so I relied heavily on the Yahoo Maps example that ships with the AFCS SDK. One of the things I like about the Yahoo Maps example is that it includes a class that extends ArrayCollection and includes some hooks for collaboration. It’s essentially a collaborative ArrayCollection, and I rewrote parts of it for my own example and have found it to be very useful across a lot of my projects.

I realized that it could lower the barrier to entry on AFCS if some of the Flex classes that people rely on a lot had “automatic” support for collaboration via AFCS. So I took the class I created based on the Yahoo Maps example and tried to make it as “drag-and-droppable” as can be for someone who wants to start using AFCS. It merges two concepts, the ArrayCollection concept, and the CollectionNode concept from AFCS. CollectionNodes let you store any piece of data on the server and let multiple people add/change/remove information from the collection. Events are fired so that any time someone changes a piece of data it can be updated across all of the connected clients.

What I’ve done with my SharedArrayCollection class is put all of that logic into a single class that extends ArrayCollection. Developers can use the SharedArrayCollection just like they would use an ArrayCollection but the difference is that the SharedArrayCollection is automatically enabled for multi-user collaboration with AFCS. The only major difference is that instead of listening for a collectionChange Event you listen for a CollectionNodeEvent.

I’m still hacking out the basics and after MAX I’ll try to provide an example use case so people can see exactly how it works. I’ve put everything up on GitHub under the Flex Collaboration Library project. I’m hoping to make the SharedArrayCollection more bullet proof and then create more AFCS-enabled Flex classes and components. Let me know if you find a bug or if you find this at all useful.

The Web Way vs the Wave Way vs the Flash Collaboration Services Way

afcs_logoAnil Dash has a post worth reading up on his blog that talks about the “Web Way” versus the “Wave Way” and why Google Wave won’t succeed because it doesn’t really fit the same pattern of successful web technologies. He makes 4 general points to define the “Web Way”:

  • Upgrades to the web are incremental. Instead of requiring a complete overhaul of your technical infrastructure, or radical changes to existing behaviors, the web tech that wins is usually the sort of thing that can be adopted piecemeal, integrated as needed or as a normal part of updating one’s websites or applications.
  • Understanding new tech needs to be a weekend-sized problem. For a lot of web developers, long before they start integrating a new protocol or platform into their work, they hack together a rough demo over a long weekend to make sure they truly grasp how it works. And a weekend-scale implementation on a personal site usually translates roughly into a 90-day implementation cycle in a business context, which is a reasonably approachable project size. (In tech, three days in personal effort often translates to three months of corporate effort.)
  • There has to be value before everybody has upgraded. This is basically a corollary to Metcalfe’s Law. While we know networks increase in value as they add more nodes, the nature of web tech is that, in order to be worthwhile, it has to provide value even if the people on the other end haven’t upgraded their software or web browsers or clients or servers. Otherwise you’re shouting into an empty room.
  • You have to be able to understand and explain it. Duh.

The entire post goes on to explain details of where Wave fits and where Wave fails. But as I read it I couldn’t help see it as a ringing endorsement of Flash and especially Adobe Flash Collaboration Service (AFCS). Before I dive in, I understand that Anil’s “The Web Way” has an inherent requirement that everything be “open”. Flash and AFCS probably won’t fit in most people’s definition of “open” as it relates to the web. In this case, I think that’s part of the benefit. Anil looks at Wave from the developer perspective and he provides a list of technologies required to use Google Wave and add real-time collaboration to your web application:

  • Federation (XMPP)
  • The robot protocol (JSONRPC)
  • The gadget API (OpenSocial)
  • The wave embed API (Javascript)
  • The client-server protocol (As defined by GWT)

That’s a lot of stuff for a developer to know and understand if they want to start building something that interoperates with and leverages the technology behind Google Wave. Now think about a Flash developer who wants to add real-time collaboration to their web application. They’ve got no real new protocols to learn (RTMP behind the scenes but not necessarily exposed in such a way that developers need to understand it), no new languages to learn, no new client-server protocol, it’s just ActionScript and(/or) Flex, and some new APIs. Then your application is real-time enabled. So let’s look at the four “Web Ways” and see how they apply to AFCS.

  • Upgrades to the web are incremental. With the pods and APIs for AFCS, it’s pretty damn easy to just integrate it with your current application. There is no rewriting from scratch and you can literally just add an AFCS component and enable collaboration for your application. As you dig deeper, the service gets more complex and you can do more with it, but to start, it’s dead simple.
  • Understanding new tech needs to be a weekend-sized problem. If you’re a Flash developer already, all you’re learning are a few new APIs. You still have to understand the fundamental issues behind real-time collaboration if you want to create complex components, but you’ve got the core development skills to create those applications so you can focus on learning the theoretical stuff and not the code stuff.
  • There has to be value before everybody has upgraded. This is my favorite, because it’s one of the benefits of Flash. AFCS has 2 versions, a Flash Player 9 version and a Flash Player 10 that adds some more audio support. If you’re targeting Flash Player 9 then 98.8% of the web can see your application and with Flash Player 10 it’s 86.7%. No one has to upgrade anything to see your new real-time enabled application.
  • You have to be able to understand and explain it. With AFCS you can easily add real-time collaboration features like video chat, whiteboarding, and shared data into your Flash-based application. I think that works.

Now again, I understand that openness is a pretty core part of what the web is. But there has always been a trade off between openness and innovation when it comes to the web. And even in cases where “open” can be innovative, like with Google Wave, everyone else has to catch up. With AFCS, even though it may not fit with the wider definition of the “Web Way” you can take advantage of the cutting edge technology that everyone is excited about and ensure that it’s 1) easy to build and 2) easy for your customers and users to view.

Thanks to Sachin for tweeting the link to Anil’s post. I didn’t take the time to read it until I saw he did.

Week of AFCS Revisited: SharedObject

After my trainwreck post on using CollectionNode in AFCS Nigel suggested that I try to recreate my example using the higher level APIs instead of trying to build everything from scratch with NodeCollection. As I mentioned in the previous post, the AFCS team did a great job of creating very basic APIs like CollectionNode and then building on top of those to make APIs that are easier to use. SharedObject is a perfect example of that.

Here’s what I wanted to accomplish: Create a basic multiplayer game where players try to match colors with each other using a ColorPicker. Using the SharedObject class it’s really pretty easy. The first thing I did was set up a room where guests are automatically promoted and no username/password is required. Then I used a combination of AFCS components and Flex components to create a user interface for entering a display name, picking the color, and showing how many players there are:

<rtc:AdobeHSAuthenticator id="auth" />
     <rtc:ConnectSessionContainer id="cSession" 
          authenticator="{auth}" 
          roomURL="{_roomURL}"
          synchronizationChange="cSession_synchronizationChangeHandler(event)"
     <mx:Panel id="panelColor" title="Pick a Color!"
          horizontalCenter="0" verticalCenter="0" alpha=".3" 
          width="200" height="200" enabled="false"
          <mx:ColorPicker id="color" change="color_changeHandler(event)" width="100%" height="100%" />
          <mx:Label text="Playing with {cSession.userManager.userCollection.length - 1} other people" />
     </mx:Panel>
 
     <mx:TitleWindow id="tw" horizontalCenter="0" verticalCenter="0"
          <mx:TextInput id="username" width="150" text="Enter A Username" focusIn="{username.text = ''}" />
          <mx:Button id="btnLogin" label="Login" click="btnLogin_clickHandler(event)" /> 
     </mx:TitleWindow>
</rtc:ConnectSessionContainer>

Nothing major there, notice we’re using the userManager class to get the number of other users in the room (and that it’s bindable). The big thing is the synchronizationChange event handler. In that function we’re going to configure our node and create the SharedObject.

public var sharedColor:com.adobe.rtc.sharedModel.SharedObject;
 
protected function cSession_synchronizationChangeHandler(event:SessionEvent):void
{
     if( event.type == SessionEvent.SYNCHRONIZATION_CHANGE )
     {
          var config:NodeConfiguration = new NodeConfiguration();
          config.userDependentItems = true;
 
          sharedColor = new com.adobe.rtc.sharedModel.SharedObject();
          sharedColor.sharedID = "color";
          sharedColor.setNodeConfiguration(config);
          sharedColor.subscribe();
          sharedColor.addEventListener(SharedObjectEvent.PROPERTY_ADD, onPropertyChange);
          sharedColor.addEventListener(SharedObjectEvent.PROPERTY_CHANGE, onPropertyChange);
          sharedColor.addEventListener(SharedObjectEvent.PROPERTY_REMOVE, onPropertyRemove);
     }
}

We have to use the full namespace when we reference the SharedObject in AFCS because it conflicts with the normal Flash SharedObject. We first do a check go make sure we’re in a SYNCHRONIZATION_CHANGE event and then start setting things up. The only change I make to the default NodeConfiguration is to make it so that when a user leaves the room, they take their items with them so we don’t have “ghost” matches. That’s done by setting the userDependentItems property to false.

Next we create our SharedObject. I give it a sharedID of “color” and then make sure the application is subscribed to the SharedObject so that it sees any changes. Finally I set up event handlers for whenever a property is changed, added, and removed. The add and change properties use the same function, onPropertyChange.

Let’s first take a look at how we create the SharedObject; something that happens whenever we change our color selection.

protected function color_changeHandler(event:ColorPickerEvent):void
{
     sharedColor.setProperty(cSession.userManager.myUserID,color.selectedColor);
}

We use the setProperty() method on the SharedObject to give it information. A SharedObject is just a name/value pair, or in this case, a propertyName/value pair. I set the propertyName to the userID so we can know where the color came from and then set the value to our selected color. Whenever we set that property it will create a property change event and call our event handler.

protected function onPropertyChange(event:SharedObjectEvent):void
{
     if( event.propertyName != cSession.userManager.myUserID)
     {
          if(event.value == color.selectedColor)
          {
               var user:UserDescriptor = cSession.userManager.getUserDescriptor(event.propertyName);
               sharedColor.removeProperty(cSession.userManager.myUserID);
               Alert.show("You matched with " + user.displayName + "!");
          }
     }
}

This is where the game starts to happen. The way AFCS works is that when you change something locally inside of your application it is sent to the server and then you get a change event when it comes back. This is so you can be sure the change was successful. In our game we want to make sure that we’re not dealing with the event we just sent so I use the propertyName property and compare it to myUserID to see if it’s the user’s own event. If it isn’t, we look for a match using the value property and our selectedColor. If we have a match I use the UserManager class to get the display name of the matched user and pop up an alert box to show that we found a match.

The other thing I do is to call the removeProperty() method on the user’s SharedObject. I ran into an issue where when a user selected a color that matched another one, the other user would get the popup but there was no easy way to notify the user who selected the color that it was a match. I solved this by removing the property which would then trigger a PROPERTY_REMOVE event and fire our event handler.

protected function onPropertyRemove(event:SharedObjectEvent):void
{
     var user:UserDescriptor = cSession.userManager.getUserDescriptor(event.propertyName);
     if( event.propertyName != cSession.userManager.myUserID && user != null)
     {
          Alert.show("You matched with " + user.displayName + "!");
     }
}

It looks similar to our change event handler. I first get the user information for the popup and then I check a couple of things. First, I make sure that the event isn’t coming from the current user, but the user I have the match for. I also want to make sure that the SharedObject wasn’t removed by someone just logging out (remember our NodeConfiguration settings). If my user is null then that means the user is gone and the event fired because the user left the room and not because I specifically removed it.

That’s pretty much all there is to it. You can grab the project here or I’ve embedded the game below (and here’s a direct link), so feel free to play and see if you can match colors!

Flash Builder and Flash Catalyst Betas Now Available

Flash Builder Flash Catalyst LogoWe just dropped the bits for both the Flash Builder beta and the Flash Catalyst beta. These represent a big jump in how people are going to work with the Flex Framework and I’m happy to see the hard work of the teams now available to everyone. So grab the bits and start creating some Flash content. Important: If you installed the MAX public beta, check the bottom of this post for some instructions that will help you through some install problems that may come up.

Keep in mind that we’re still early for both Catalyst and Builder. We won’t have everything we want in Catalyst 1.0 but this beta represents a HUGE step over what some of you saw at MAX last year so we’re making a lot of progress. It’s snappy, it’s tightly integrated with the CS4 tools, and it opens up a whole world of design centric tooling for the Flex Framework. What makes this all possible are the fundamental changes to the Flex SDK for Flex 4. We’ve completely separated the logic from the look of a component which means designers and developers can collaborate without stepping on each others toe’s. We’ve abstracted the layouts so you can dynamically change the layout of components creating some very cool looking components. We’ve integrated Flash Builder with a lot of your favorite backend technologies so it’s easy to consume and generate services to connect to data.

I’ve created a screencast to help people check out the new features. It goes through the workflow of moving from a PSD to Flash Catalyst and on to Flash Builder when you want to bring in real data.

Flash Catalyst Tutorial

There are a lot of resources to make sure you get up to speed quickly using the new tools. Here’s a good list:

If you’re having trouble uninstalling the MAX preview and installing the public beta, give these steps a try:

  • Uninstall Catalyst
  • Download the Mac version of the Repair tool from this page: http://www.adobe.com/support/contact/licensing.html
  • Run the Repair tool with the default options.
  • After the Repair is complete, re-install Catalyst and enter the SN when prompted by the installer.

Demo of Real Time Facebook Collaboration with the Flash Platform

Today we announced that we’re going to be working with Facebook to help Flash Platform developers continue to create great applications on the world’s best social platform. You can find a lot of good developer information on our new Facebook Developer Center. Since we’re dealing with social content, I figured it would be fun to combine Adobe Flash Collaboration Services and Facebook for a real time social collaboration experiment. Using the excellent getting started tutorial and AFCS, I created a simple app. When you load it, you’re a guest and you can see people using the whiteboard, chatting, and sharing files. If you want to collaborate with everyone else, you need to log into Facebook. The application pulls your name and geographic information from Facebook and lets you publish content. The application is here and you can grab the source files here. You’ll need to make sure pop-ups are enabled to connect to Facebook.

As I said, the application is pretty basic. I’m using default pods from AFCS and the basic Facebook authentication. The only thing remotely unique is that I’m pulling in the user data from Facebook and using the AFCS APIs to change the APIs:

public function onConnect(event:FacebookEvent):void
{
var call:FacebookCall = facebook.post(new GetInfo([facebook.uid],[GetInfoFieldValues.ALL_VALUES]));
call.addEventListener(FacebookEvent.COMPLETE,onComplete);
}
 
public function onComplete(event:FacebookEvent):void
{
fbUser = (event.data as GetInfoData).userCollection.getItemAt(0) as FacebookUser;
cSession.userManager.setUserRole(userId,UserRoles.PUBLISHER);
cSession.userManager.setUserDisplayName(userId,fbUser.first_name + " " + fbUser.last_name + " (" + fbUser.current_location.city + ", " + fbUser.current_location.state + ", " + fbUser.current_location.country + ")");
}

The first function gets called when we connect; we use the new AS3 Facebook library to get information about the user. Then after that is complete, we set the user data to a FacebookUser object and use the AFCS APIs to change the user name and the room “role” so that the user can publish content to the room.

I kind of threw this together at the last minute, so expect bugs. I apologize in advance if (when) you run into them.

MindManager Web – Online Mind Mapping with Flex

mindjetA couple of weeks ago Mindjet released an online version of their mind mapping software built entirely on the Flash Platform. It’s a pretty slick app but I also like how they’ve made it part of their core offering and added features like real-time collaboration and web conferencing/chat inside the app. One of the things about Flash is that it makes it really easy to incorporate those into your application and mind mapping is a great use case.

You can try MindManager Web for free for 30 days. I’m a big fan of their desktop client, so hopefully we’ll see an AIR application based on this down the road. Congrats to the MindManager team!

Fun with Flash and SAP’s NetWeaver Platform

Mrinal twittered today about a project he’s been working on and it took me on a pretty cool tour of what’s going on with SAP, NetWeaver, and Flash. NetWeaver 7.0 supports something called “Flash Islands“, which are basically SWF files inside of Web Dynpro interfaces, which is the user interface for SAP’s NetWeaver platform. Using ExternalInterface interface, you can pass data from Web Dynpro and a Flex/Flash application.

What’s cool is to see the most cutting edge parts of the Flash Platform being used in an enterprise setting like SAP NetWeaver. Mrinal has an example of Ribbit working, letting you make phone calls from NetWeaver, and there is an example of Cocomo collaboration by Mogens Enevoldsen, which shows off building a social network in SAP.

2009 is going to be a gigantic year for real-time data and collaboration. This is something that, arguably, the Flash Platform does better than anyone else, so I think it’s going to be an exciting year for Flex developers as they get to show real world examples of things that most people are just starting to think about.

CoCoMo – Collaboration for Every Developer

Along with the Flash Platform news, we’ve released CoCoMo, one of the coolest products at Adobe. CoCoMo is basically a framework that lets you add collaboration to any Flex application out there. It comes with a few basic components like video chat, text chat, and whiteboards, but it also includes hooks so that you can build your own real-time collaborative application.

Real-time collaboration on the web is something that I think has just barely hit it’s stride. CoCoMo uses the Flash Platform, AMF, and our various server products to enable any developer with the power to create a collaborative application. You can host it all on Adobe’s servers and we’ll take care of the hardware infrastructure for you. So basically you can now take any Flex application and add video chat, whiteboards, or your own personal collaboration requirements to it and start differentiating yourselves from customers.

This is a big, big deal. I can’t wait to see what people do with it. You can check out my interview with the CoCoMo folks on AdobeTV for more info.

Building Collaboration Into Your Web Apps

TechCrunch UK has a blog post up about Collaboration Web Apps that will help you beat the econonmy-related tightening purse strings of the corporate world. It’s a good post with a lot of good tools but it made me realize that we should be louder externally about how Adobe is helping with collaboration.

Of course we’ve got Connect Pro and even Connect Now, which gives you a free meeting room you can use and includes text chat, video chat, and screen sharing. But what’s better than that? Being able to add collaboration components to your own applications. That’s where CoCoMo is going to come in. You can check out more at the Collaborative Methods blog. We’re exposing almost all of the functionality from Connect Now into components that you can use inside of your own Flex applications. Even better, CoCoMo will provide all the hooks you need to add a real-time collaborative element to your application. There’s a recording available from a meeting with the CoCoMo team if you’re interested in more info.