Source control

At work we use SourceSafe for our version control, and I used SourceAnyWhere as the client. I would like to outline the facts and let you decide what happened for yourself.

01: I checked out my model (EcoModeler)
02: I added a new class.
03: Generated code.
04: Checked in the mode.

05: Checked out.
06: Added two new associations
07: Generated code.
08: Checked in.

09: Checked out.
10: Added a parameter to a method.
11: Changes a state machine diagram.
12: Checked in.

After each of the changes I would implement code in my application that used them, so if the changes were lost at any point during this process then I would notice because my app would no longer compile.

Today I checked out the model and noticed that my new class was missing. I backed up my generated source code and then regenerated code from the model. Using BeyondCompare I checked for differences and came up with the list of changes in the steps above.

Somehow the model in my source control had 3 revisions missing. I checked the history and sure enough there were no check in actions since June 27th. I had to recreate the changes in my model by reading the differences.

So, what do you think caused this problem?


UndoBlocks, SyncServer, and multiple EcoSpaces

In an ECO app I am writing it is very important that updates by other users are identified as soon as possible. This is because there will be multiple users all selecting jobs to do from a predefined list, and it is not only possible but also very likely that more than one user will select the same job at the same time (the job at the top of the list).

To implement this I chose to use the remote persistence feature of ECO and in particular its Sync Server feature. Every 5 seconds my client apps will contact the server and retrieve a list of updates made by other users, it will then apply those updates to the cache of its own EcoSpace. So when a user selects a job to do at the top of the list their app will stamp it as InProgress and update the DB, the job will then automatically disappear from the screens of all other users.

As I like to use undo blocks in my app to allow the user to cancel changes (using my DirtyObjectCatcher component) it is highly likely that during these synchronisation operations there will be an active undo block. As a result of this any changes applied to the cache via the sync' process will be caught by the undo block. If the user decides to cancel their changes then all values in the undo block will be undone, including the synchronised changes from other users. This isn't a great problem for me because I am using the TimeStamp feature in ECO to ensure that when I update the DB I am actually updating the same values I originally fetched, but it does mean that the user is looking at old data. For example

01: User A is looking at a list of jobs, they choose to action Job 1
02: User B sees Job 1 disappear from their screen and choose to action Job 2
03: User A sees Job 2 disappear from their screen.

So far, so good. Now remember, the change of state to Job 2 was caught by the undo block that was activated when User A started to edit Job 1.

04: User A decides to cancel their changes.
05: The active undo block reverses its changes, this includes the changes applied by the sync server.

As a result user A sees Job 2 reappear on their screen.

This didn't cause me an operational problem, because when actioning a job I do this...

01: Assign to current user
02: Update DB
03: If no exception then continue to edit
04: If OptimisticLockException occurs then unload the job and tell the user another user is working on the same job and ask them to select another + unload the job from the cache (will causes it to be reloaded with the new info and disappear from the screen).

This is essential anyway because the Sync server only makes it less likely to experience a conflict, it does not make it impossible (always use OptimisticLocking unless overwrites are acceptable!).

Still, I wanted to prevent the user from seeing this message as much as I possibly could. The answer is very simple, you just use a new instance of the EcoSpace for editing the job. The UndoBlock isn't actually needed now, but I still have it because the DirtyObjectCatcher provides a great way of providing validation feedback to the user. When the UndoBlock is reversed though it will revert to old values in the new EcoSpace instance, which is irrelevant because it will be disposed once the owning form is closed. Any updates to the data will appear in the main app within 5 seconds due to the fact that the second EcoSpace instance will also use remote persistence to save the changes which will in turn ensure that all other EcoSpaces (in the same app or on different machines) will be notified of the changes.

I think I might play with this technique some more. It looks like quite a nice way of working with ECO and multiple users!


CapableObjects announced

There are exciting times ahead! The team that brought you ECO for Delphi are now a separate company named Capable Objects (http://www.capableobjects.com).

ECO will still be part of the next release of Delphi, but according to the official statement (http://dn.codegear.com/article/3673>) and comments in the newsgroups it is quite obvious there will also be a version of ECO for Visual Studio!

In the past the ECO guys released patches for ECO bugs, unfortunately it was not always possible to provide a patch. With the guys now being a separate company they are free to decide their own release schedules. Instead of having to wait for a Delphi update they can now release updates as often as they wish. Just like the good old BoldSoft days when we used to get an official update really quickly if ever a critical bug was found. Not only that, but it would also seem that they will be shipping source code too!

But that's not all John!

The guys at Capable Objects have asked me to write documentation. I've been adding XMLDoc to the source code so the API help will be more up to date. As soon as possible I will be writing a quick start document for Delphi (and any other IDE's) too.

Can't wait! :-)