July 31, 2002
In some cases, even the goal is determined collaboratively and non-hierarchically. It is the warp-speed embodiment of Gandhi's maxim, "There go my people, I must run to catch up with them for I am their leader."Looks good. I do like Howard. This might be the book to persuade me to get a cellphone after many years of passive resistance...
Here's a useful construct for Groove tool developers, especially when working with third-party ActiveX controls for UI. The ElementQueue is really easy to use, but I'll preface this with some chat about MVC and threading to give an example of where I needed it. I'm sure you'll have other applications.
In the MVC (model-view-controller) structure, your tool will receive events from the model when its dataset changes - locally (because you did something at the UI, usually) or remotely (because another member in the space triggered a data change, which was disseminated to your device). Typically, you'll install some listeners in your controller (UI gluecode) to process these events when they happen, and change the current state of the UI to reflect the new information.
When your UI is built with an ActiveX control, you can hit threading issues. This is especially important where your ActiveX control is a facade onto a single-process application (ie. the control silently loads a full application in background): I've seen this with Acrobat and MapPoint. The pipe between "controller" and "view" might need to play nice.
function PropertyList_OnPropertyChanged( sName, pValue, bRemote )
Let's say that your UI is an ActiveX control, and it's busy right now. It won't be able to process your call to its .DoStuff() method (or whatever), and the default behaviour in these circumstances seems to be: die disgracefully. So we really want to queue the event until a later time when we know the UI has settled down.
For this, I use an "idle handler" (although you could easily use a timer instead). By registering as an idle handler, you have a function be called whenever the Groove UI thread has some spare time - this seems to be roughly every 20 milliseconds. The idle handler is a great place to perform occasional UI update, by reading from a queue of work-to-do. So let's set up an idle handler:
Now to set up an event queue, and a HandleQueuedCommands() function to dequeue work items.
Groove's ElementQueue API is just that: a FIFO queue of XML elements (children of a parent XML element; in this case, a temporary element created just to hold the queue). You can enqueue arbitrary pieces of XML, and dequeue them later. Since the payload is just XML, it's easy to wrap an event and its parameters into an element for the queue. You might want to queue many different types of command; just use elements with different names. It's not necessary to declare a formal schema for these elements, but naming them sensibly helps keep your code readable.
So, in Initialize(),
When you want to enqueue something - for example, an event called from your datamodel - just wrap it into an element and place it in the queue:
Then, when the UI is idle, look at the queue and handle any commands which we see there. You'll get the best performance if you process the whole queue in the idle handler (rather than just handling one queued command at a time).
function HandleQueuedCommand( pElement )
Of course there are several other ways to use an element queue. The queue could be persisted, or even disseminated (on an element in a PropertyList, for example) - that could be a nice foundation for a distributed-processing application.
July 27, 2002
butterfly.net is a "grid" server system for MMG. Nice. Dedicated NPC servers too. I wonder how they handle the data distribution and migration issues?
July 15, 2002
In the course of the last few weeks I felt that something had gone wrong with it: it began to feel like a burden to provide new content... I got bored of publishing links like: Look, Ma, a new link, found it all of my own!
JD Lasica, May 1997:
We're now on the cusp of a one-to-one "narrowcasting" network where each of us is able to summon up a finely tuned menu of choices: your favorite Boston Globe sports columnist; the New York Times' op-ed page; the latest golf news; and Dave Barry's latest musings...Isn't is strange: in the "push" bubble, all the talk was of how this changed delivery options for Big Media, but most missed the real game: in reducing the cost of publication to zero, "narrowcasting" means your daily news choices come from a million opinionated webloggers, and you can be one of them too.
July 12, 2002
Mike Helfrich, VP of "Applied Technology" at Groove (in other words, he takes some responsibility for getting people to use our stuff effectively), has a weblog! Way to go!
July 11, 2002
klogs vs. mailing lists
On the klogs mailing list, John Garside asks
What advantages do klogs have over lists such as (anThis is a surprisingly difficult question, and I'm choosing to write some rambling answers here rather than on-list because they might veer off topic (this itself is part of the answer, of course: lists tend to be topic-specific, but blogs/klogs are usually person-specific). It's somewhat easier to answer than a parallel question "klogs or newsgroups?" which might be raised.
A few dimensions of difference:
It's worth reiterating the fundamentals in common, too. Knowledge Management 101: "write it down". Documenting your immediate activity in a relevant place is valuable. It helps others find what you're talking about (now or later). It helps the author clarify - I've found this myself many times, that simply writing about current work is a very helpful context-switch, and forces you to continuously re-evaluate its structure and goals.
From the Groove Webinar, a PowerPoint presentation with some good descriptions of where Groove fits in to various modes of collaboration. This .ppt deck also includes some screenshots of existing MS/Groove technology links: the Outlook on-ramp, Word co-editing, Microsoft Project import/export, Messenger integration, and SharePoint Portal.
This last hasn't been de-geeked yet -- you can see all the portal metadata, with PROP_DAV_stuff, which means nothing to me -- but looks promising. (It's running on a server called BORG - this means nothing, but note that "Starfleet personnel are to maintain the utmost caution when encountering the Borg".)
July 10, 2002
Jon Udell has a good column about using the security features of email.
You can assert the validity and integrity of your messages, but no-one expects you to. You can automatically acquire public keys from others who sign their message, but no-one does so. Having acquired those keys you can encrypt messages to those people, but again, they don't expect you to do so.Great, thoughtful stuff. It's a pity this is such hard work!
If you'll excuse me banging on about the virtues of Groove [again]... it fixes this stuff. As many people have pointed out, Groove's solution is to create a new infrastructure, with some proprietary protocols and software -- of course in many ways the spam issue goes away if you make a walled garden. I'd like to address those things too.
Let's separate this into: transport, identity assertion, and openness.
Groove messages -- IMs and shared-space synchronisation -- are always strongly encrypted. They're also signed, meaning that you can always provably verify their authenticity. Crucially, you don't get a choice in this: it's all-crypto-all-the-time. User indifference, the biggest factor in the lousy take-up of strong crypto, is completely ignored.
Identity assertion -- the subject of Jon's piece -- is more tricky, and here I think we have a great set of solutions. In the beginning, anyone can create an identity (from scratch, with no certifier). That identity has a name, address (vcard) and some keys. Everything you do is signed and sealed with that identity's keys: your identity is always asserted, even if it's not certified. To other users you just appear as "John Doe", but anyone can authenticate your identity for their own purposes: once I know you're the real "John Doe", I can tell Groove that the real John Doe should always show me a "yes it's really him" icon by his name. Even if the name changes, the keys remain intact. You can give John Doe an alias for your own use (say, "John from Dorking") without breaking the strong authentication.
This begins to look interesting. Organisational certifiers, cross-certifiers, and full-on strong identities all the time. So we can automatically separate correspondents into several groups: members of my organisation, members of other organisations known to me, people I've authenticated myself, and don't-know-you-from-Adam.
Yesterday I had a complete comms outage: first the Net flaked out, then the phones went dead. The net connection came back up a couple of times during the day, but still with massive packet loss. This morning the network is back although the phones are still out.
Being held incommunicado, I learnt something about my dependency on these systems. Most of our software sucks.
My critical tasks for yesterday involved opening a VPN connection to the USA, transferring some files to a network share there, downloading a 25+mb installer, and accessing my build machine by VNC. Completely, completely impossible. The VPN connected (but died every few minutes). I spent an hour copying a half-dozen files across the network: several retries for each. VNC just wouldn't go.
July 09, 2002
I'm seeing 60% packet loss to the first router.
"Hello, BTOpenWorld technical support. Can you tell me your ADSL phone number please?"
Doh. And it'll take up to 48 hours for an engineer to open the trouble ticket ("because, you know, Oftel and all that.")
July 08, 2002
Taligent TalOS, aka Pink (1996):
TalOS was unique in its architecture... The end user experience revolved around a compound document-centric, multi-user networked, direct manipulation interface with infinite session undo. The principal interface theme was People, Places and Things. The networked interface represented remote users, as well as collaborative work spaces. In many ways it was more a graphic MOO than an traditional operating system.
January 1998, an almost unreadable archive:
Amy says, "some of the most interesting work in this area is the book Connections by Sproull and Kiesler. They found that real time chat helps more people be heard and lessons the dominance of higher-ranking participants, but also leads to disorganization and longer time to reach decisions"
July 05, 2002
Dynamics, rollback and rollforward
An ugly hack has been preying on my mind since I wrote, about the tour,
If a transaction "from the past" arrives, the database will unwind, then roll forward again after applying the new transaction... To catch any "futurity", I wrap a GUID inside each event, and maintain a reasonably-sized table of already-handled events.I knew that was ugly (and stupid and wasteful) when I wrote the code, too. There really had to be a way to ask Dynamics whether it's currently rolling back or forward, or processing commands for the first time.
There is, of course. It's in Dynamics, and I only stumbled across it this morning whilst debugging something else, so now I applied it onto the tourcode too. This improves performance, reduces the memory footprint (no need for a stupid hashtable now), reduces network traffic (no need for a GUID on the event elements), and improves reliability too. Whenever you want to track state dynamically in a Groove tool, you should know about this.
The interface to look at is IGrooveCommandContext2; this is accessible by a property on IGrooveDynamicsManager. So you can get this in Script by
var pDynMgr = PropertyList.OpenProperty(PROPERTY_DYNAMICS_MANAGER);
then look at the properties on this interface, which tell you more than you ever needed to know. The RollbackRollforward property is true if this is part of a rollback or rollforward.
New trailer - looks good. (via Dylan).
July 04, 2002
July 03, 2002
I'm sure this is not an economic proposition: homemade digestive biscuits. But they taste good, they're fun to make, and it's about the easiest recipe I know. Tonight we had a problem with the oatmeal, though: only porridge oats left in the cupboard, and in a fit of "can't transport this electrical stuff" we gave away the whizzing mixer thing last week. So, after ten minutes trying to push oats through a sieve...
Quantities are whatever you like. 1 = 100g or 4oz, for a good plateful.
Groove Tour: index
Recap: five pieces of not-very-deep doc.
Is this useful? Any big questions raised? Say so.
If you've not run the tour yet, it's here.
Groove Tour: UI
Finally, I think this is the home stretch. The tour has a user interface, and it's very simple, and it's HTML.
Well, if I needed something really flexible (especially for interactive work), I'd build custom UI. But the tour's display-UI requirements were: look good, and be easy to edit. The "easy to edit" might have been better served with RTF (which is well supported by Groove's TOM-based richedit control), but plugging in tables and pictures would have been harder. So, HTML.
The "variable substitution" piece is useful: it understands a range of embedded references. These include
I've used this sort of "HTML inside Groove" view in quite a few tools now. It still takes a non-trivial amount of development effort (to build the template page, script helpers etc), but if you need a clean, flexible, not-very-interactive UI it's definitely the way to go.
July 01, 2002
Following from the tour discussion, I want to ramble awhile about "structured code-containers", as I think it's an interesting perspective.
Mostly any software system (of any size) is a framework for stringing together pieces of code. The DOS/Windows filesystem and PATH is a framework for finding and launching executables (albeit a fairly uninteresting one). At another extreme, Web Services with WDSL and UDDI is a decentralised framework for having different pieces of code - hosted in different places - execute when different events happen. OO programming in general puts code into a containment structure which
Groove Tour was designed to be that, too.
The core of Groove is pretty open - and very very flexible - from the same viewpoint. There's an optional "text/binary phase boundary" so you can wrap compiled code behind any COM interface, but you can also write code in script (and most Groove tools are script). The first-level container is an XML document (a tool template, typically). The next-level container is an XML database (the templates storage, or the shared-space storage, or the account storage).
So, this is another thing in common between all these interesting systems: a deliberate commingling of code and data. Storing code in a database, and being able to manipulate that same database from code.
Tour: Dynamics and EIS
"Dynamics" is the name for Groove's transactional synchronisation stuff. This takes care of ensuring that commands for tools' engines are disseminated to each endpoint in a shared space, and processed in the right order. The result is that when you take a static view of a shared space, you're guaranteed to see a consistent state, and that this state will tend to be the same as the state on any other endpoint.
To freeze a shared space while you look at it (enumerating over records, for example), open a transaction (for read-only or read-write access): pTelespace.OpenTransaction(). When you commit() the transaction, any changes are applied and disseminated.
Looking at a dynamic view of the shared space (by listening to sequences of events from its engines), you'll see a more complex picture: if a transaction is interrupted halfway through processing and you open a "read" transaction to look at a snapshot, the database might need to unwind. If a transaction "from the past" arrives, the database will unwind, then roll forward again after applying the new transaction.
In the case of the tour, things could become difficult to track (were I using many transactions in the processing), but, it turns out, events pretty much arrive in the expected sequence. This is because I consciously minimised the number of "wrapped" transactions; generally, everything which happens is atomic and has no dependency to past or future events. So my propertylist listeners have an easy job. To catch any "futurity", I wrap a GUID inside each event, and maintain a reasonably-sized table of already-handled events. There's something to be said for belt-and-braces defensive programming, but in this case it turns out that's just overhead; it doesn't get used.
(It likely would, if the space ever had more than two members!)
In part two, I showed a couple of snippets of the tour script (the client script lives in groove/data/ToolData/groove.net/GrooveTour, if you care to dig in further). The script is a data-file containing structured code, which runs against events (That in itself is worth further discussion, sometime...!). Now, where do these events come from? They're wrappers around COM events fired by pieces of Groove (the EIS server, the workspace, the account, the telespace, or tools).
Much of the code at the server is simply providing nice, type-safe, script wrappers around these existing event services. In the tour, part of the ease-of-use comes from choosing an appropriate level for these wrappers; and part comes from providing a "tool" context object with each event, which immediately puts you in the right place. At the server script there's also always a "chat" object which provides an interface to the chat tool. In many ways (not least for debugging), chat is the commandline.
[ /* more blogroll to follow */ ]
The views expressed on this weblog are mine alone and do not necessarily reflect the views of my employer.