Thursday, March 24, 2005

Building privacy into software

Scott's Rules of Reuse for Java

Scott's Rule of Reuse # 1:

ALL VARIABLE DATA MUST BE PRIVATE

NOTE: There is only one exception to this rule: final static variables (aka class constants). Otherwise, there are to be no exceptions to Scott's rule #1. Ever.

The reason for this is that a class must be in total control of its state. If someone makes a change, the class must have a chance to know about it. If we leave variables non-private, some other class can change our state w/o us knowing.

The only way variables are to be changed is via methods defined in the class, preferably a setXXX() method. Initially the set method is simply changing the value. However, later on, we can add code to the set method to

- add validation to ensure the value is acceptable
- fire events to tell others that the value has changed
- update other state when the value changes
- log that the value has changed

If the variable is non-private, the set method might not be called when it changes, so we cannot guarantee to be able to fire a property change, validate, etc.


All Data Must Be Private!

I could go on and on about this forever, but I'll try to keep it brief: All data defined in a class must be private!

I may sound a bit like an "OO-purist" when I say this, but I view this from a practical standpoint, having been burned by not doing it...

Making data (by data I mean class and instance variables) non-private allows another class to change their values without the owner of that data knowing about the change. If the owner doesn't know about the change:

- the owner has no control over the value; it could be outside the intended range of the data
- the owner cannot know the value has change, and cannot respond if needed
- the owner cannot tell others that the value has changed
- the owner cannot allow others to veto the change


On top of these problems, if you ever decide to change your code to allow other classes to listen for changes, or restrict bounds on a variable, you would need to find every reference to the data and change it. This can be very painful if the class were a public library that many people had used in their own code.

Even worse, you cannot change the implementation of the data without changing the users of that data. For example, suppose you had an integer instance variable to keep track of some ID for a list node. Perhaps you had done some research and decided that the memory cost of keeping that ID was more expensive than recomputing it the few times it was needed. If ID were only available via an accessor, all you would need to do to affect the change is to remove the instance variable and change the getID accessor to compute the ID and return it. Far simpler than creating the getID accessor and going back and changing every reference to x.id...

Privacy is the key to true encapsulation. All manipulation of an object's state must be done by the object itself!

Once you use accessors to read/write class/instance data, that data is instantly available as a JavaBean property!

2 comments:

Anonymous said...

heh heh... thanks for reading... (and sending me a note!) As you invited, I will Mock you here! But I'll be nice, as you're just misinformed ;)

You're actually the first person I've heard of taking me on about this...

The key to reuse is being open, not blindly following "old-school" purism.

Encapsulation is all about protection, not hiding.

The whole "hiding" notion comes from simulation. Simulation programming is rather specialized, and requires that all interaction be exactingly modeled. This means if modeling people, we can see what they look like, but we can't see how many kidneys they have...

We can only ask the questions that they allow us to ask. (They may not want to talk about their kidneys).

For simulation, this is ideal, and that's where the purist point of view comes from. The trouble is, most purists didn't adapt to changing conditions and sensibilities...

For most non-simulation programming, this is dreadful.

Why?

Let's suppose the object hides most of its data, and we want to create an editor for it. We would then need to create methods in the object that display text fields, checkboxes, and what have you in the object.

Ewwww.

What if we want to display it differently? What if we find better widgets to more easily edit it?

And what if we don't have the source to modify to add these features?

Poof. Useless object.

Today's design best practices are all based on delegation. Objects expose their data (but protect it!) so other objects can do interesting things with that data. The UI asks for data, displays it, gets user input, and asks to change the data.

Very clean and simple.

Based on the note you sent me, I think you might be confusing privacy of information with privacy of variables.

Variable privacy applies to programming language constructs, and this is what my Rules of Reuse (which was a newsgroup rant against someone who claimed get/set was evil) are talking about.

Information privacy is another matter entirely.

User interfaces shouldn't display data that the user doesn't "need to know".

Some users need to see a social security #, while others do not. This type of protection has nothing to do with having get/set methods; it applies to if/how the data is presented.

We can control this in three ways:

1) The object doesn't have get/set. This means no one can see the data, regardless if they really need to. Bad news...

2) The user interface just doesn't display it. Probably not a good plan, as you'd have lots of access code in the UIs, and some UIs may not play well...

3) The business logic layer can apply a decorator that hides the data for those who don't "need to know.". By wrapping the objects in a decorator that returns a dummy value or throws an exception, we hide the data when necessary. This works beautifully, as all UIs behave properly, and we have full control of the information privacy

So my bottom line is to keep the objects open so anyone can play nicely with them, but apply patterns like decorator to block access when needed.

Of course my article has the "Bobcat" clause: if you think you could argue for hiding a particular piece of data to the Supreme court with Bobcat Goldthwait as your lawyer, go for it!

Later,
-- Scott

Anonymous said...

I just re-read what you sent me, and I think I misinterpreted what you said... Silly me...

Now that I read it again, sounds like you weren't disagreeing with me. Darn! I was hoping for a fight!

Heh heh...

Anyway, it was nice to be able to add a little more detail and address your mention of Social Security # so I could clarify variable vs information privacy.

Later!
- Scott