Get/Set vs Public Variables

M

Marc Gravell

Just yet another viewpoint...

Validation in the setter is perfect for things that can *never* be
valid, i.e. invalid format, out-of-range, too large, etc. However, it
can get tricky if your business rules cross-reference each other. The
classic example is the DateTimePicker, where Min / Max / Value fight
with eachother; the issue is that you place a dependency on the caller
both setting the right properties *and* setting them in the right
order - which can easily require a 3rd intermediary state.

In such cases, a more explicit Validate() method is useful, but I
agree that this generally belongs to the business entity itself
(unless it is a proxy, in which case all bets are off).

A useful model here is IDataErrorInfo; for starters, if you implement
this it will *automatically* display the messages to the user in some
controls (DataGridView, for example) via an error blob. And it isn't
hard to hook regular bindings to it as well (a bit more manual,
though; and note you need to use the indexer-variant). But more
importantly: it provides a simple method your data-layer can query:

IDataErrorInfo errObj = obj as IDataErrorInfo;
string errMsg;
if(errObj != null && !string.IsNullOrEmpty(errMsg =
errObj.Error)) {
throw new DataException(errMsg);
}

Although any similar "are you happy with yourself?" method would
suffice ;-p
(but is nice to be able to use the same code at both UI and DAL,
without having to do anything special)

Marc
 
P

Paul Werkowitz

Am Wed, 6 Feb 2008 07:23:00 -0800 (PST) schrieb Jon Skeet [C# MVP]:
Well, you've already dismissed the important reasons as being
unimportant to you:
1) Discriminating between implementation and API
2) Binary compatibility of old code running against new implementation
3) Source compatibility of old code compiling against new
implementation
and, not to forget the new dependency properties etc. of WPF, to add to the
list.

If these reasons are important (or only one of them, mainly the first) -
yes, then we should use properties. But: for most objects, these
requirements are not si important. More than 90% of the property
implementations I have seen are simple setters and getters without any
functionality, and never will need any. I still have the opinion that these
are superfluous things.

I agree that there are situations where they are useful, or even necessary.
You named some.

At the moment, if I want to use databinding for example, I have to use
properties on my business object. The properties are all empty, because my
validation etc. is done otherwise. (Most of it could not be done in setters
anyway, because validity of one data element heavily depends on other data
elements in the same object). Fortunately, this is alleviated with the
auto-property feature of .NET 3

Those are all good enough reasons for me, but apparently not enough
for you.

So, you access all of your data in every object of ll your applications
only via properties. OK - and how many of theses properties are really
empty? And will probably stay empty during the lifetime of the product?

Greetz
Paule
 
P

Paul Werkowitz

Am Wed, 6 Feb 2008 09:39:55 -0600 schrieb Scott Roberts:
I disagree. The business object should enforce business logic.

Of course it should! But we were talking about properties (of the BO).
Thats a different thing.

Validity definitions must be near the business data, and be accessable by
all agents that can change business data. So the rules should be in some
form accesible by the program. MS Application Building Block (or so, forgot
the name) for example, uses C#-attributes to specify validation rules.

In WPF, validation logic can be specified with the binding.

But never in setters of the business object!

The maximum
length of of a field, required values, range checks, etc. are all business
rules. Does the data provider arbitrarily decide the max length of a field?
No, it's based on a business rule - which should obviously go in the
business layer.

Absolutely. But it should not be coded in a setter. That's my point: then U
cannot use it in other places!
GUI validation is worthwhile, but it doesn't absolve the business object
from the responsibility of ensuring valid data. If you rely on the "data
provider" to ensure proper data states then you are spreading your business
logic all over the place.

I did not say that the validation logic must be placed in the GUI. I said
that the validation must be performed in the GUI. That is a differnet
thing. Again: The Data and the rules that define validity of that data must
be in one place AND must be accessible from all parties that can modify
that data - e.G. the GUI.

Greetz
Paule
 
P

Paul Werkowitz

Am Wed, 6 Feb 2008 11:50:10 -0600 schrieb Scott Roberts:
Well, the setter is obviously not called when the object is created. If the
GUI tried to put a blank value into the property an exception would occur,
which is exactly what should happen.

Right. But if this happens then we have a programming error. GUI must have
acces to validation rules and not allow to put invalid data into a BO.
Instead, GUI should show some info to the user etc...
If you don't put business rules in your BOs, then what *do* you put in
there?

Sorry, my wording was wrong. I meant: "... not to be implemented in
setters". Business rules should of course be defined near the BO.

Greetz
Paule
 
P

Paul Werkowitz

Am Thu, 7 Feb 2008 15:37:32 -0600 schrieb Rene:
Paul,

There is nothing wrong with having an object holding an invalid state.
Things don't have to crash. The problem would be if you try to save the
invalid object data to a database for example.

Or use it in any other context...., yes!
When a new object gets instantiated it could have a collection of broken
rules (one of them being last name can't be blank). When the user set the
value of last name to a valid name you can remove that broken rule, if the
user the set the value to blank again you add the broken rule back again.

The moment the user tries to save the object into the database you can check
the broken rules collection and throw an error if broken rules are found.

That is a very interesting approach, and I use a variation of it for a long
time. I have a isValid-Function that calculates that set of broken rules
(as you named it) on the fly (does not store it). I use that on the GUI for
example to provide users with appropriate feedback (yellow an red markers
near controls, info panel etc.). --- But I don't need no accessors for
that.
Having the business rules right in the getter and setter is a logical place
to have them.

Not necessarily. I calculate it on the fly, when needed. Caching is not
necesary, and is more hassle than use. So, down to the bones, I say: I
don't care whats in the object, as long as I can determine its validity
state at any time I need to.

Paule
 
P

Paul Werkowitz

Am Thu, 7 Feb 2008 14:21:29 -0800 (PST) schrieb Marc Gravell:
Validation in the setter is perfect for things that can *never* be
valid, i.e. invalid format, out-of-range, too large, etc. However, it
can get tricky if your business rules cross-reference each other. The
classic example is the DateTimePicker, where Min / Max / Value fight
with eachother; the issue is that you place a dependency on the caller
both setting the right properties *and* setting them in the right
order - which can easily require a 3rd intermediary state.

In such cases, a more explicit Validate() method is useful, but I
agree that this generally belongs to the business entity itself
(unless it is a proxy, in which case all bets are off).

Full ack.

Paule
 
J

Jon Skeet [C# MVP]

So, you access all of your data in every object of ll your applications
only via properties. OK - and how many of theses properties are really
empty? And will probably stay empty during the lifetime of the product?

Many - but I don't need to worry about binary or source
incompatibilities if I *do* need to do anything. Where's the harm?
Writing a property takes seconds with appropriate templates etc. The
only real downside IMO is that the code is then there, potentially
being obtrusive in your class. That's reasonably easily solved with
regions.

With C# 3 there's even less reason not to use properties, as automatic
properties let you follow best practices with just a single line of
code.
 
A

Arne Vajhøj

Paul said:
First, more tahn 90% of properties I saw in my life are simple setters and
getters without any useful functionality.

Second, chances are really low that a construct like

class Person
{
string name;
string firstname;
}

EVER will need any functionality in getters and setters for the two string
fields.
- Binding to external code? No. When someone ref-binds to a public variable
and this is later changed to a property, we must change the statement and
recompile. Big deal? IMO, no.

Not for small programs. But for large scale systems it can be
a huge problem.

Component A and B both uses component C, component A need some
new functionality in C, when that is added B does no longer run
or build, so B has to be changed, and tested, test and delays cost
the company 500000 USD - do you think management consider that
no big deal ?
Of course, there are situations where this is sinply wrong. If I must
anticipate the situation that my implementation might change, I definitely
am better off with properties. But for > 90% of all classes with data
members this is NOT the case. And if I make a mistake here, the cost is low
- mostly recompilation, and some syntax errors. Definitely not worth to
make everything private.... - at least until auto-properties were invented.

Definitely worth doing.

It costs practically nothing. You declare the fields private and let the
IDE generate the public property.

And can save you a ton of problems later.

And yes - it may only be a few percent of properties that will ever
need functionality beyond default.

But the problem is that we do not know what those few percentages
are when we write the code.

Code tend to be used much longer than original intended. 10-25 years
are not unrealistic.

Nobody can guarantee that a given field will not need to be changed
for so long a time span.

Arne
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top