Request for MS-Word-like undo and questionable "CSLA policy" on EditLevel

Request for MS-Word-like undo and questionable "CSLA policy" on EditLevel

Old forum URL: forums.lhotka.net/forums/t/6904.aspx


Andreas posted on Wednesday, May 06, 2009

Hi,

 

I have two questions:

 

  1. I would like to implement an undo operation that works nearly like MS-Word. The main difference is that the user is able to undo changes even after he pressed the save button. I think many users expect this kind of undo for business applications as well. Of cause, this can result in a inconsistency nightmare if you work with a relational database underneath when data relations don't exists any more after you pressed CancelEdit() and then Save(). But there are a lot of situations when this would make sense and can be easy implemented. This behavior is not supported by standard CSLA (maybe in the future ;-). Any suggestions how to implement this behavior today?

 

  1. Why must the EditLevel of child objects always match the parent EditLevel (in BB and BLB)? Is this only because CSLA policy defines that parent/child operations should be controlled by the parent only? We can think of several scenarios in our application where it would make sense to control undo (and Save) operations on single child level as well as on parent level. But this leads to different EditLevel values which again results in CSLA exceptions…. 

Regards,

Andreas

 

RockfordLhotka replied on Wednesday, May 06, 2009

Andreas:
  1. I would like to implement an undo operation that works nearly like MS-Word. The main difference is that the user is able to undo changes even after he pressed the save button. I think many users expect this kind of undo for business applications as well. Of cause, this can result in a inconsistency nightmare if you work with a relational database underneath when data relations don't exists any more after you pressed CancelEdit() and then Save(). But there are a lot of situations when this would make sense and can be easy implemented. This behavior is not supported by standard CSLA (maybe in the future ;-). Any suggestions how to implement this behavior today?

 

Implementing undo at this level of detail is quite difficult, and usually can't be done entirely at the business layer - it requires participation from the UI layer as well.

 

I have no plans to implement this type of undo capability into CSLA.

 

Andreas:

 

  1. Why must the EditLevel of child objects always match the parent EditLevel (in BB and BLB)? Is this only because CSLA policy defines that parent/child operations should be controlled by the parent only? We can think of several scenarios in our application where it would make sense to control undo (and Save) operations on single child level as well as on parent level. But this leads to different EditLevel values which again results in CSLA exceptions…. 

The edit level behaviors in CSLA exist to serve data binding. Which also means they are limited to the range of concepts data binding supports.

But moreover, n-level undo is a form of transactional operation, and a transaction always has a "root" or top-level control point where the transaction starts and ends. This isn't a CSLA thing - this is just the nature of transactional systems.

If you have scenarios where you want to control undo at different points, then each of those points needs to be a root object - the top-level control point for the transaction.

RockfordLhotka replied on Wednesday, May 06, 2009

I guess I could be more clear on the edit level exception issue.

For many years CSLA .NET did not throw these exceptions. It was up to the UI developer to do the right thing - and to test to make sure they did the right thing. If they didn't do the right thing, then data binding would become confused and the app would slowly quit working - revealing very hard to debug issues that could waste days of time and cause serious user frustration.

Based on the reality that these problems were so bad that they'd eventually make CSLA have a poor reputation (who'd want to use a framework that makes it so easy to create bugs that are that hard to find and fix???), I added the exceptions.

The result is that n-level undo is less flexible than it was a few years ago. But the result is also that 99% of people building Windows Forms, WPF or Silverlight UIs can have some confidence that their UI code actually works.

Unfortunately this means the 1% (or less) of people who wanted to do strange and innovative things are blocked. In this case the needs of the many do outweigh the needs of the few, or the one.

William replied on Friday, May 08, 2009

Here is a related question on EditLevel and IsSavable. The implementation for IsSavable property checks IsDirty and IsValid flags. Should it check for EditLevel > 0 as well? This is being enforced in the Save() method.

// Core\BusinessBase.cs
public virtual bool IsSavable
{
  get { return (IsDirty && IsValid); }
}

// BusinessBase.cs
public virtual T Save()
{
  T result;
  if (this.IsChild)
    throw new NotSupportedException(Resources.NoSaveChildException);
  if (EditLevel > 0)
    throw new Validation.ValidationException(Resources.NoSaveEditingException);
  if (!IsValid && !IsDeleted)
    throw new Validation.ValidationException(Resources.NoSaveInvalidException);
  if (IsDirty)
    result = (T)DataPortal.Update(this);
  else
    result = (T)this;
  OnSaved(result);
  return result;
}



Marjon1 replied on Friday, May 08, 2009

I think the logic here is that IsSavable is just an easier way to check if an object is actually requires saving and is in a valid state.
We use it throughout the UI to enable save buttons, etc. However, the EditLevel would generally be > 0 because it is still in data-binding mode.

However, before doing the save it is expected that the object would have ApplyEdit would be called and if it hasn't been then the save shouldn't occur.

RockfordLhotka replied on Friday, May 08, 2009

That is an interesting point, but that isn’t practical. The reason is that many people bind their Save button to IsSavable, but the final ApplyEdit() isn’t called until Save is clicked…

 

Rocky

 

Copyright (c) Marimer LLC