Fetch and Object Return

Fetch and Object Return

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


acgritt posted on Tuesday, May 12, 2009

I have seen and read through several of the various posts on the subject of whether it is better to return an empty object or throw an exception.  In our case we would prefer to return null if during a Fetch 0 records were returned via the DAL call.  I have not seen a way to do this currently but I may have missed something.  Is there a way from within the DataPortal_Fetch method to inform the factory that you want it to return NULL rather than an empty object or is there a property I am not aware of on the BusinessBase/ReadOnlyBase that would signify that it is an empty object that would be different from a normal New object?

An example of what I am talking about would be if you have two users that are viewing the same ReadOnly list of object.  UserA selects an Item from the list and deletes it.  UserB then goes and selects the same item from the list to edit it.  Obviously at this point that item (and the list for that matter) is invalid but the check for if the item exists is not made until in the DataPortal_Fetch call for the editable version of the object.  It would most likely confuse the user if they selected an Item and were then presented with the edit screen and all the fields were empty.  On a similar note, exceptions do tend to be costly which can affect application performance.  Also these exceptions seem to be wrapped in other exceptions so other developers would have to know to look through the inner exceptions to know what the problem really was (ie communication failure vs no data).  However, if the Get method returned a null object or a null value was returned in the event args for an async event handler, or if there was a separate property on the base objects that could signify that the object is empty, it could easily be checked and the user could be alerted without impacting performance.

Marjon1 replied on Tuesday, May 12, 2009

Depending on how your objects are setup, if you had an id field that had a default value of 0 and expected it be populated as part of your fetch method. As part of you factory method you could check that field and if it wasn't populated return null.

Or your developers could known that they should check that value themselves.

Public Shared Function GetObject(ByVal Id as integer) as BusinessObject
Dim tmpObj as BusinessObject = DataPortal.Fetch(Of BusinessObject)(new Criteria(Id))
if tmpObj.Id return nothing
else
return tmpObj
End Sub


There are no specific properties to specify that an object is empty, but that doesn't mean you couldn't add one to a base class if you need it yourself, you would just need to remember to populate it on every fetch.

rsbaker0 replied on Wednesday, May 13, 2009

We had this same issue coming from our legacy C++ application to CSLA. With recordset type technology, an empty result set is specifically indicated (e.g. IsEOF etc.), but CSLA doesn't work this way.

DataPortal_Fetch is handing you an object to populate, so the only option is to be sure you can test the result to see if it is empty. One possibility might be to set the object as New (e.g. IsNew returns true), since an object that is actually fetched from the database will always be "old". Another possibility is that the primary key, if any, would be null or not initialized.

In our case, we have wrapped all the data portal calls with factory methods that will return null if no object matches the query.

Of course, when fetching collections, an empty collection is easy enough to check for.

ajj3085 replied on Wednesday, May 13, 2009

I'd go the exception route. Exceptions aren't expensive in that your user won't notice anything different had you not gone the exception route.

It's the clearest thing to do; you don't have the data (anymore) that you expect, so the conditions of the fetch contract have been broken.. so an exception seems most appropriate. You're application isn't going to slow to a crawl because you catch exceptions.

As far as "looking though inner exceptions" you should throw a custom exception. If you like, your factory method can check for that specific exception, or look at the BusinessException from a DataPortalException. That will ensure you only need to trap the business exception (other exceptions should probaly be let go).

acgritt replied on Wednesday, May 13, 2009

Personally I agree that Exceptions are really the way to go, but I had just taken a poll of some of the other developers and they were all "I want it null" so I thought I would ask.  Part of the difficulty is that when working with several developers spread across multiple locations trying to get everyone to implement the logic in a consistent manner can be difficult.  However, I think I will go with the Exception myself and then catch that in the factory method and do the return null from there.  Thanks for the feedback, it was very helpful.  Part of me is just a bit surprised that built into the object framework there isn't something to say that the objects are "empty" that would be different from checking for New or Old.

ajj3085 replied on Wednesday, May 13, 2009

Hmm... sounds like an architech is needed. :-)

Null is all well and good, until they forget to check for the method returning null and now you have a hard to find NullReferenceException.

Catching in the factory method and returning null would probably be the best route you can take, given your constraints.

You could build your object in such a way as to support an empty concept... maybe just adding an IsEmpty flag, if you really wanted to do that. However, I think that would be more complicated and lead to harderto maintain code down the line, because now you have to worry about setting the flag correctly, etc.

acgritt replied on Thursday, May 14, 2009

ajj3085:
Null is all well and good, until they forget to check for the method returning null and now you have a hard to find NullReferenceException.


True, but on the same note, the UI developer could forget to check for returning exceptions which could cause just as much difficulty in finding them.  Plus depending on what kind of logging you have it may be a moot point either way.

ajj3085:
I think an empty object would be better, but even then.. what do you do with an empty object that's represeting data that no longer exists? Not much, except maybe tell the user it doesn't exist anymore.


Overall I wouldn't mind returning an empty object but the only issue I see with that is there is nothing built into the base objects to say that the object is empty other than to check certain properties to see if they have values.  I suppose the other thing that could be done is that a Validation rule could be created to say that if it is Old and the Id or other property is not a valid value then the object isn't valid.  No matter what way I really go with it really comes to the UI developer to know that they should be checking something to validate the object.

JoeFallon1:
Rather than just doing it their way I think you should fight a bit harder to do it the CSLA way.


This being our first attempt at implementing the CSLA in it's true form, I would like nothing better than to start it right and do it all the CSLA way.  I was more just curious as to what the CSLA way really was in this instance and what should be done.  I know I could easily modify our copy of the framework code to add an IsEmpty to the bases and then clear it when Get/Read/Set/Load Property is called but I would really prefer to keep the CSLA the way it is to make it easier to upgrade in the future. 

Adam

Marjon1 replied on Friday, May 15, 2009

JoeFallon1:
Rather than just doing it their way I think you should fight a bit harder to do it the CSLA way.


This being our first attempt at implementing the CSLA in it's true form, I would like nothing better than to start it right and do it all the CSLA way. 
acgritt:
I was more just curious as to what the CSLA way really was in this instance and what should be done.  I know I could easily modify our copy of the framework code to add an IsEmpty to the bases and then clear it when Get/Read/Set/Load Property is called but I would really prefer to keep the CSLA the way it is to make it easier to upgrade in the future. 

Adam

Adam,
One of the things that you can and should do is create your own classes that inherit BusinessBase, etc so that any little changes like this can be made within your own class and you don't have to make changes to the CSLA core. Then all your own objects would have an IsEmpty property with a default value of false, and it is up to you as a developer to remember to set it to true on a fetch if no data is present.

I would strongly recommend this, and you can extended the other objects like BusinessListBase, ReadOnlyBase, etc, as needed. There are certain things you can't do due to fields/properties being private but they are far and few between and you can generally work around them.

acgritt replied on Friday, May 15, 2009

Marjon,

Thanks for that point of view.  That is one that I hadn't considered (I don't know why I hadn't) and certainly solves my issues in a nice clean way.  Even the other developers here agree with it.  Thank you very much.

Adam

rsbaker0 replied on Wednesday, May 13, 2009

ajj3085:
I'd go the exception route. Exceptions aren't expensive in that your user won't notice anything different had you not gone the exception route. It's the clearest thing to do; you don't have the data (anymore) that you expect, so the conditions of the fetch contract have been broken.. so an exception seems most appropriate.

I'm curious as to the motivation for this.

Fetching data using criteria that retrieves no results seems me to be a normal case, not an exception condition.

Also, there is the issue of orthogonal treatment. It's evidently fine to retrieve a collection that contains no elements, but not to retrieve attempt to retrieve a single object that matches the same criteria?

 

ajj3085 replied on Wednesday, May 13, 2009

rsbaker0:
Fetching data using criteria that retrieves no results seems me to be a normal case, not an exception condition.


I guess it depends on your application design, but a readonly object refering to something which no longer exists I wouldn't think to be the normal case. It can happen in the normal course of events, but I'd argue that such a condition is much less likely than things going "normally." Again, I suppose it depends on the use case as well though.

rsbaker0:
Also, there is the issue of orthogonal treatment. It's evidently fine to retrieve a collection that contains no elements, but not to retrieve attempt to retrieve a single object that matches the same criteria?


I think the subtle difference is that you still got the object you asked for, it just happens to be an empty collection.

My main argument here is that getting an empty collection back won't cause hard to find exceptions, because you still DO get an object back. In the singleton case though, a UI developer forgetting to test for a null return value can introduce harder to find errors. You can work with an empty collection, perhaps add items to it then save it. You can't do anything with a null reference.

I think an empty object would be better, but even then.. what do you do with an empty object that's represeting data that no longer exists? Not much, except maybe tell the user it doesn't exist anymore.

Of course, maybe my thinking is skewed, because I don't allow deleting of "root" objects in most cases anyway, for historical reasons.

JoeFallon1 replied on Wednesday, May 13, 2009

No need to doubt yourself Andy! Your thinking is spot on. If I hadn't gone down the road of returning and empty object 5 years ago I would be usnig exceptions myself - for exactly the reasons you stated.

To the OP:
I think the devs who want you to return Null are asking you to do something that is not the normal .Net way of handling these things. Rather than just doing it their way I think you should fight a bit harder to do it the CSLA way. In the long run it will make just as much sense and you won't have odd issues to worrry about down the road.

Joe

rsbaker0 replied on Thursday, May 14, 2009

JoeFallon1:
No need to doubt yourself Andy! Your thinking is spot on. If I hadn't gone down the road of returning and empty object 5 years ago I would be usnig exceptions myself - for exactly the reasons you stated. To the OP: I think the devs who want you to return Null are asking you to do something that is not the normal .Net way of handling these things. Rather than just doing it their way I think you should fight a bit harder to do it the CSLA way. In the long run it will make just as much sense and you won't have odd issues to worrry about down the road. Joe

It seems to me that the natural analog of this is a the SELECT statement in SQL.

If you SELECT something that doesn't exist in the database, you don't get an row full of empty values, nor does SQL throw an exception that indicates you submitted a query for something that doesn't exist. You get "nothing". Null seems reasonable way to indicate this. An empty object strikes me as odd, although I can see how it might conveniently solve some databinding issues that otherwise have to be programmed around.

Whatever mechanism is chosen requires that the developer implement some test or exception handling to distinguish a valid returned object from one that wasn't there.

 

Copyright (c) Marimer LLC