Q & A on a recent VSM Article

One of my last Visual Studio Magazine article discussed object validation and  object invariants.

I received a great email discussing questions about how to handle UI validation in this world. My recommendation in the article was that classes should be responsible for their own state. Furthermore, they should enforce that validity at all times. Objects are easier to use if they are always valid.

The question can be boiled down to "what about objects that provide the backing store for UI controls? How do you let the user edit a type and still mandate that it's always valid?"

As an example, let's imagine a set of UI fields to edit an address in the United States. You could code that imaginary Address type to query some map service and determine if the address really existed. For an Address object to pass its validity checks, all fields would need to be consistent.

However, users can't edit this type of Address type. Change the city, and the state and zip code are no longer valid. Change the zip, and the city and state are no longer valid. No matter what order a poor user tries, she cannot get past the first field to edit the other fields necessary to get the Address back in a valid state.

Yes, it's a problem. The reader posed two ways to solve this consistency issue.

For one, you can loosen the definition of 'valid' to allow the type to be invalid for a while. Other code would test stricter conditions when an Address object was being saved to persistent storage.

I don't like that approach. It weakens the concept of valid until it's almost meaningless. Weakening the concept of 'valid' simply pushes the test to other code: any type that uses an Address object must now perform extra tests because a 'valid' address might not really exist. It might be one of those weakened concepts of 'valid' to allow editing.

His second approach was to introduce two classes that represent an "Address": one that represents the business object concept, and one that represents an Address in the UI layer.

I prefer this approach, even though it appears to be more work at first examination. Let's start with the business object for an Address. It's always valid, and it always must exist. Any code using this address can assume the address exists, and is valid. That makes it much simpler for client code. It could provide one public method that allows client code to set all fields or properties at once, ensuring that it is still valid. The Address type could throw an exception when client code tried to set an invalid address.

The other Address type, used by the UI, would have much looser validation. Its visibility would be limited to the UI editor, and it would be only used by the UI. To perform the full validation, this EditingAddress type would rely on the Address type. Users would then be informed at save time that an object wasn't valid.

As a footnote, the same strategy, using two different types, would be appropriate for types that are loaded and saved using the XML Serializer. You can't rely on the order in which properties are set during the Deserialization process. Objects might not be valid during those transition points.

Published 22 July 2008 02:13 PM by wwagner
Filed under: , ,
Ads by Lake Quincy Media

Comments

# Peter Ritchie said on 24 July, 2008 09:48 AM

I agree, I prefer the second approach.  This approach can be encapsulated in the Data Transfer Object (DTO) pattern.  The process of editing fields that are part of the representation of an business object is a fundamental problem of binding your business objects directly to the UI.  DTOs allow you to decouple them and use the business object's standard behaviour while dealing with the data needed for the business object in states that would otherwise be invalid in the business object--much like a transaction.

Search

Go

Blog Group Links

Nascar style badges