Non-User Interface / Assisted user input

Non-User Interface / Assisted user input

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


juddaman posted on Monday, September 03, 2007

Hi all

The app I’m developing at one level is a typical forms-over-data app. Though additionally the “system” sometimes “helps out” by adding data. Let me explain, I have list of work slots for each day to track an employees time spent working. Every time a user opens or closes the win forms app I’m logging the time and appropriately adding a work slot to the list additionally while the app is open the work slots finish time stays in sync with the system time. While this is happening the user could come along and change the finish time, when they do this they become the “owner” of the value and the system must never change that time. Rather it must “work with it. Without going into anymore detail for now, has anybody else developed applications like this? My main issue is how to architect the app. At the moment I have a class that is passed the same Day BO as what the user sees (selects) it deals with making up the work slots and keeping the finish time in sync with the clock. This works okay but I’m just trying to see if there is a better way. Like is the “tracking / logging” business behavior, should this all be happening in the business layer somewhere or is it a UI thing. Any thoughts / resources to check out?

Thanks

George


RockfordLhotka replied on Tuesday, September 04, 2007

Seperation of concerns says that this is both UI and business.

The business rule is that the finish time floats until explicitly set by a user. The UI rule says that the display should update periodically to reflect the floating finish time.

In the business object the property could be something like this:

Private mFinishTime As Date
Private mFinishSet As Boolean

Public Property FinishTime() As Date
  Get
    CanReadProperty(True)
    If mFinishSet Then
      Return mFinishTime
    Else
      Return Now
    End If
  End Get
  Set(...)
    CanWriteProperty(True)
    mFinishSet = True
    mFinishTime = value
    PropertyHasChanged()
  End Set
End Property

Then the UI can just use a timer to continually re-read the value as needed.

As an optimization, you could expose mFinishSet through a read-only property so the UI could disable or short-circuit the timer. You'd probably mark this property as Browsable(False) to hide it from data binding.

juddaman replied on Tuesday, September 04, 2007

Hey Rocky,

Thanks for posting on this topic. For the part you specified I did do something like that by BO has a FinishOwner property, but this is actually checked in the UI, if the value is "system" in than sets the property to the system yime, you think this should be done with n the BO itself? The other bit of logic concerning this is that if the date property in the object with finish is not the same as the system date than don't change the time, get the default or user entered time, I guess this could go in the BO though.

I'm actually more concerned with the generation of the work slots part. Currently in the UI I have a class that looks in a file at the logged start times and based on this data adds workslots so:
private void UIMethod()
{
    foreach(int bitOfData in lotsofData)
    {
       if (bitOfData == 44)
       {
                XBO.WorkSlots.AddNew(bitOfData, "Hello");
        }
    }
}

Should I be doing this in the BO?


Should I be saying XBO.AddWorkSlotsFromLog(); or something? I guess for this to work I'd prob need to be storing the open close app log on the server not the client. I'd then need some kind of BO to handle writing log eneries maybe a AppUseRecordBO that maybe just had a  factory like:

public static void LogStart()
{
    AppUseRecordBO  x = DataPortal.Create<AppUseRecordBO>(new Criteria("Start",DateTime.Now));
    x.Save();
}

Do you think this could work? Is it ok to be calling save() in this way?

I actually have this App working so I'll prob progress carefully, but I'd really appreciate any pointers on this as I'm very keen on improving the design. The forms-over-data stuff is all sorted and I kind of just bolted this "automation logic" on, and its become the "ugly" code I dont want to look at! Any further help with the makeover would be much appreciated.

Thanks

George







RockfordLhotka replied on Tuesday, September 04, 2007

juddaman:
Hey Rocky,
Should I be doing this in the BO?

Here's a good rule of thumb to answer this question (in general).

Can you entirely destroy and replace your UI with a different UI and know that the required business functionality remains intact?

If not, then you have too much logic in the UI.

So if your work slot generation is important to the functionality of the app, then it belongs in the BL, not the UI.

Now I'm not saying the UI is unimportant. It is of critical importance because it guides the user through the processes and acts as an intermediary between the app and the user. But the UI must be considered expendable because UI technologies keep changing faster than business changes. Odds are that your UI will be replaced by WPF or Silverlight before the app itself has no value. So whatever UI you are writing today is temporary.

(whether that's true in reality or not, it is a good way to think about it)

Remember that objects are actors. It is too easy, especially with forms-over-data, to think of objects as smart data containers. But they are not. They are actors in the use case. Some objects act by collecting and validating data. Other objects may act by adding work slots.

Every object is an actor, with exactly one responsibility. That should be the design goal.

juddaman replied on Tuesday, September 04, 2007

Hiya
Thanks for that. Work slot generation is important to my app but here is my issue: within WinForms (or any client app) logging the users open and close of the app makes sense, they can leave it (the app) open all day (hide it to the tray) and close it at then end of the day. No problem. If the UI changes to a Web interface this is no longer true, would I log when they went to the start page and log close when they changed site? To me it seams the the behavouir is tied to the UI, in some way. This is kind of why I didn't put it in the Business Layer.

OK, I suppose it could go in there and if it made sense for the client to call the StartApp method it did, does this seam viable? I suppose this would mean I could have a web interface for the Buisness Layer that just had less features i.e. only manual data input. Is it possible to to create a BO that can use a different data store depending on the UI using it? This way I could store the users app useage log on their machine when they are using the WinForms UI. Actually though thinking about it, if I did this any logged data would then be unavalible on the Web. Maybe if the logged times (or any data) are important to the app they should be accessible by any UI? I guess the performance difference of writing a date and time to a file or to a RDBMS is probably fairly unnoticeble anyway. It's all good stuff :-)

Oh and one question about this:
Every object is an actor, with exactly one responsibility. That should be the design goal.

How do you define one responsibility? It seams some responsibilities can be very “wide” like “Maintain a Project” given to the Project object. “Maintain” includes many (what you could argue to be) other responsibilities – like Edit and Add. Any ideas on how to thnik sbout this?

  Thanks, George

juddaman replied on Wednesday, September 05, 2007

Any help with knocking this one on the head?

ajj3085 replied on Wednesday, September 05, 2007

juddaman:
Hiya
Thanks for that. Work slot generation is important to my app but here is my issue: within WinForms (or any client app) logging the users open and close of the app makes sense, they can leave it (the app) open all day (hide it to the tray) and close it at then end of the day. No problem. If the UI changes to a Web interface this is no longer true, would I log when they went to the start page and log close when they changed site? To me it seams the the behavouir is tied to the UI, in some way. This is kind of why I didn't put it in the Business Layer.


We had a locking system, where on logoff any locks the user had should be cleared.  We implemented this when the logout link was clicked (calling a Logoff method), but also when the Session expired. This ensured that it was always called, even if it was a few minutes later.  So I'm not sure I agree things change with the web.

Maybe that will help with the rest of your questions.

juddaman replied on Wednesday, September 05, 2007

Hi

I agree that the web changes things, that is kind of my concern. When you say a "locks the user had should be cleared" did that involve writing "business" data to your data store?

Regards

George

ajj3085 replied on Thursday, September 06, 2007

Well, my point was that the web actually didn't change anything.. it just adds an inactivity timer to a logoff.

This was before I ever heard of Csla, and we weren't doing things quite correctly.  At that time, we had "smart data objects," not what I would call business objects.  But loging off was a use case, and part of that use case was clearing the locks.  So in that sense, you can consider the lock updates as 'business data.'

If your use case calls for it, I don't see a reason why 'real' business data couldn't be saved to the datastore.

Copyright (c) Marimer LLC