Design Suggestions Request

Design Suggestions Request

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


lefty posted on Monday, April 30, 2007


I'm about to start working on a project to port a fairly large legacy application over to newer technology (Mainly C#, SQL Server 2005, and most likely CSLA).  We love the way CSLA handles the validation rules and the business objects, and OOing the application is going to make mantaining it about a million times easier.  I'm hoping someone will be willing to give us some suggestions and let us know what parts of our ideas are doable or not with CSLA, and if there are better ways of doing it then what we're planning.

To start the legacy application is basically a fat client loan origination system written in Progress that was originally ported over from old mainframe code.  It keeps track of our loan applications as well as the current status of the applications.  All the business logic exists within the client and it's rather chatty, so it only works on the local network.  It's also pretty old and over the years all the new features that have been hacked in have made it slightly unstable.  It's very similar to a mainframe application were they make changes on various screens and save the changes each time before changing screens.

There are some features we currently have that we would want to try an mimic as closely as possible in the new version.  Currently we have an audit system that only audits selected database fields in a generic audit table.  This makes it very easy to audit and display only the 10-15 fields that we care about in the order that they were changed showing the old value, new value, when it was changed and by who.  This audit log gets used regularly by the supervisors and ease of use is important.
We also have record locking in the database so that only one person can edit/view an application at a time.  The locking does get in the way sometimes, but because of the way the business works it's somewhat common for 2 people to attempt to access the same application at the same time, so we would need someway to deal with that.
We also currently have "on-the-fly" validation for each field.  This is something that that we absolutely want to keep.  Each time an agent edits a field there is a list of field rules that run that verify the data, lookup data in the database to fill into other fields, etc.  An example would be the interest rate getting filled in to a read-only field automatically after the loan amount and term are entered.
The current system is also very easy to update.  The client resides on our file server and I can update individual screens on the fly without having to install anything extra to the users computers.

What we're looking at is setting it up as an ASP.NET application using CSLA.  AJAX would be used to provide the rich UI and do validation call-outs to the server so that we don't need to rewrite the validation rules in the UI.  It could also be easily updated at a central location (the web server) without requireing installs at every workstation, and would work for remote users as long as the AJAX wasn't too crazy.  From everything I've read in these forums I think we're going to go with a trigger based audit system with history tables, however I'm not sure how to display the history data to the users yet in a easy to understand format..

Concurrency is about the only thing we're running into with this method, because I don't really want two people editing the same data at the same time.  The method of checking a timestamp field before update would work, but I don't want the agent entering a bunch of data and then when they go to save they find out that everything they did was rejected.

At this point we currently don't have any directives about how we have to implement it, so we aren't locked in to the ASP solution.  Please let me know if there are any suggestions or pointers on how to implement these ideas or any better ways to do it.

Thanks
Jeff

JoeFallon1 replied on Monday, April 30, 2007

Jeff,

All of this sounds like a good approach.

The concurrency issue can be solved in many ways. The one you describe above is the "frustrating" version for a user.

Since it is a common experience for more than 1 users to try to edit the same document, you can try implementing an application level locking mechanism. This can be a separate database table that stores information about the document being locked. You insert a row to lock a docuemnt and you delete the row to unlock the document. When your user requests a document you first attempt to acquire the lock. You look in this table and check to see if the doctype and doc PK are in the table. If not, you can acquire the lock and then insert those values (plus others you may want to track).

When another user attempts to acquire the same document, they won;t be able to get the lock and you can tell them that User X is editing the document beginning at time Y.

When the user is done editing the document and they save it successfully, you can remove the lock.

Things to watch out for:

1. Users abandoning their edit in "unapproved ways". e.g. let session expire, close browser, etc.

We trapped for many of these occurences and attempted to release the lock. This works in 90% of all cases, but there are still odd ways that a lock can be abandoned.

2. You need to provide an Admin UI to release a given lock. This allows your users to call this Admin and tell them they need to be able to edit a locked document. The Admin can check with the current user to see if they are really still editng the document or not and then they can remove the lock.

Joe

 

 

 

lefty replied on Tuesday, May 01, 2007

Thanks everyone for the suggestions, I think they are going to help with our design.

Patrick.Roeper replied on Saturday, November 03, 2007

I had to resurface this thread because I expect I will need to deal with this concurrency issue myself in the near future.

I like the design that Joe mentioned, mainly because I can extend this to not only locking BO's but also for locking certain UI's that only 1 person should be in at a time. However, my concern stems from the following case:

Object A is not in a locked state.
User 1 needs to access Object A for read-only purposes.
User 1 obtains lock for Object A.
User 2 needs to access Object A for edit purposes.
Object A is currently locked by User 1.

The solution is to not lock Object A for users who only need read-only access, but I am at a loss as to how I could come up with an elegant solution to this. From the perspective of an end user, I would not want to be "overly burdened" by having to open a form in a different way just to achieve read-only access.

I would love to hear some suggestions on possible UI designs for this. We are using WinForms for presentation. The only thing that is popping into my head right now is examining the modifier keys when a user is opening an interface..

Thanks.

rsbaker0 replied on Sunday, November 04, 2007

We started with a similar application migration and have avoided locking entirely.

There are several ways to implement concurrency, but we have chosen to implement what we call "changed values concurrency" and not do any locking. First change to a field from a loaded object "wins", any others result in a concurrency exception when the "stale" but changed object is saved. However, two users can independently update separate fields in the same object and both updates can succeed.

We chose this approach mainly because it requires no database-specific features (e.g. timestamp columns), nor does it require any alteration of the database schema. Also, the odds of two users really wanting to edit the same object are low because of the way the data is partitioned, so we mainly wanted to ensure integrity of the data. This approach works well except for contrived situations (e.g. one user updates city, another updates zip code).

With code generation, it's easy to capture original values of properties in the property setter when they are changed to they are available to the concurrency implementation. Also, we have situations in which the logic itself really needs to know if a specific field was changed at the time the object is saved -- e.g. IsDirtyProperty("PropertyName"), and the concurrency mechanism doubles for this purpose. Not only that, but we also have a field-level auditing mechanism for any field in the database, and this becomes almost trivial to implement with this concurrency mechanism in place.

JoeFallon1 replied on Monday, November 05, 2007

Patrick,

I just ran into that issue and I resolved it by adding an optional parameter to my factory method.

Public Shared Function NewBO(ByVal key As Integer, Optional ByVal useEditScreen As Boolean = True) As BO

useEditScreen  is passed to the DataPortal by my Criteria class and then I only acquire the lock when it is True.

(On my Read Only screen I obviously set it to False.)

If useEditScreen Then
 
Lock = Applock.GetLock(key)

  If Not Lock.LockAcquired Then
    Throw New ApplicationException("Record is locked by " & Lock.Username & " via the use of " & Lock.LockDescription & ".")
 
End If

End If

Joe

david.wendelken replied on Monday, April 30, 2007

Overall, I think your approach makes good sense.

lefty:


Concurrency is about the only thing we're running into with this method, because I don't really want two people editing the same data at the same time.  The method of checking a timestamp field before update would work, but I don't want the agent entering a bunch of data and then when they go to save they find out that everything they did was rejected.

I think you will have that problem with any application that uses a pooled database connection that is only kept open just as long as necessary for any one task.  Each trip to the database is unconnected to the prior trips. 

The best way to test whether that feature is a requirement or a wish is to assign price tag and a timeline just for that feature.  Here's an example, with fictional numbers, of course:

"This feature will add 2 months to the project timeline and cost an additional $50,000 in labor for an application of our size.  The two months delay will mean that the $10,000 a month projected savings will also be delayed, for a total cost of $70,000.  To put that in perspective, that equates to 7,000 lost data collisions, at an estimated $10 labor cost apiece.  Our staff tells us that we can expect 50 collisions a month, for a break-even point in 11 and 1/3 years."

If the numbers work out like that, it may not be a requirement any longer....

 

ajj3085 replied on Monday, April 30, 2007

If you want that rich UI (especially if you have the BO keep the rules for the calcuations, which you should) I suggest a WinForms application.  Nothing beats a desktop app for a rich experience.  Deploy using ClickOnce, and you're all set.  You can even ensure that the framework itself is installed prior to installing your application (and if need be, any additional components that would require installation).

Copyright (c) Marimer LLC