views:

113

answers:

3

I'm not sure how to construct the question but I'm interested to know what do you guys think of the following situations and which one would you prefer.

We're working at a client-server application with winforms. And we have a control that has some fields automatically calculated upon filling another field. So we're having a field currency which when filled by the user would determine an automatic filling of another field, maybe more fields.

When the user fills the currency field, a Currency object would be retrieved from a cache based on the string introduced by the user. If entered currency is not found in the cache a null reference is returned by the cache object. Further down when asking the application layer to compute the other fields based on the currency, given a null currency a null specific field would be returned. This way the default, implicit behavior is to clear all fields. Which is the expected behavior. Just to make it more clear, when the user enters a "not available currency" he gets notified, of course, but also the fields that depend on the currency entered should be cleared out. This is done by setting the specific control values to null.

What i would call the explicit implementation would be to verify that the Currency object is null in which case the depending fields are cleared explicitly.

I think that the latter version is more clear, less error prone and more testable. But it implies a form of redundancy. The former version is not as clear and it implies a certain behavior from the application layer which is not expressed in the tests. Maybe in the lower layer tests but when the need arises to modify the lower layers, so that given a null currency something else should be returned, i don't think a test that says just that without a motivation is going to be an impediment for introducing a bug in upper layers.

What do you guys think?

+2  A: 

Explicit is better than implicit. - The Zen of Python, by Tim Peters

As I understand the whole thing, with the explicit way you get readability with a little redundancy, but I always prefer this over some obscure, magic behavior (something not obvious on first sight).

Dinu Florin
A: 

The way I understand your question is you are comparing whether you should rely on NullReferenceException or null object to determine the next action.

Here are my thoughts:

  1. if you want to rely on exception, wrap it in your own application exception such as CurrencyNotFoundException. The callers will need to check for that exception and behave accordingly. This way it's much clearer what happens under the hood.
  2. if you expect the situation where currency is not to be found from the cache occur frequently, you may want to stay away from exception (it's not an "EXCEPTION" from the normal case). You may want to opt for null object pattern. With the pattern, you return a NullCurrency object back. The caller may have matching display strategies, and one of those would be NullCurrencyDisplayStrategy. This way, you would never have to rely on the null check. The returned object is a valid object within its business domain.

Hope that helps

ronaldwidha
I knew that my explanation was pretty lame. Sorry for that. The currency cache right now returns a null object. Based on null the application layer returns again null for the dependent fields, which reapplied on the view would clear the controls
Silviu
+1  A: 

First of, Dinu Florin is right, explicit usually is better than implicit (but one size does not fit all, so there are exceptions).

Second, I am not sure if I understood your problem correctly, but you may want to take a look at the Null-Object Pattern. The idea is, that your backend should always return a valid data-object (Currency-object in your case), even if no data is available. In that case, a special Null-Object is returned. This object implements the same interfaces as a normal data-object, but it may contain special values for the fields. It should be designed in such a way, that your application does not have to distinguish between a valid data-object and a Null-object.

I do not know if that may suit your needs, and it may just not be applicable in your case, but you have to determine that for yourself.

Space_C0wb0y
Your answer, i think is the ideal case to which we should tend...but our legacy code is far from that. We are trying to move it in the right direction. But there are a lot of forces to fight back, not considering the code...
Silviu