Using the source as documentation

31 July 2008

A common issue we get dinged on is that our official documentation (by "official" I mean, in essence, our help files) is not complete, and that sometimes topics, how-tos and other things are missing. My response to this is: be specific and I can do something about it and get it fixed, but be general and there's nothing I can do but make reassuring noises. (It's like saying the roads in Colorado are awful, well, sure some are, here's the ones I know, but by no means can I extend the specific anecdotes to a general rule.)

Sometimes I point out that our documentation also encompasses the knowledgebase and the support center and the forums. In an ideal world we'd merge all this data into the help so you wouldn't have to use these online services, but there's always more things to document and so this project gets pushed back. Personally I prefer to use a browser and Google to search for information on our own products (the help is completely online and hence indexed by the search engines). Google has changed permanently what it means to search and the rest of the world is still catching up.

Another source of documentation -- and it can be said to be the ultimate source, since it can never be wrong --- is the source code itself.

So here's a specific case that came up this morning on a phone call I had with a customer. He was having an issue with, wait for it, DXValidationProvider. Yeah, I know, you WinForms pros have got this particular component nailed and are nodding your heads sagely, but for me and the customer we were having some issues understanding how it worked.

If you drop a DXValidationProvider onto the form, you can modify how it validates the values of various controls on the form. There's a smart tag for the component and one of the options is to customize the validation rules. Click it and up comes the following dialog.


The customer wanted to use the Conditional Validation option. So we clicked it:


All very well, but what are Value1, Value2, and Values, and what are they used for? The customer was using "Contains" as the ConditionOperator. He wasn't sure what it really meant but was assuming "is contained in the Values collection" was close and had set up the Values collection accordingly. However he was finding that it wasn't working. Go to the help, is what I said. So we did:

"To create validation rules at design time and associate them with editors, use the 'Customize Validation Rules' editor"

And that, unfortunately, was that, as regards the help. I did ascertain that ConditionValidationRule was the class I should be interested in, but I couldn't find out very much about it in the help.

At which point I went to the source. I pulled up DXValidationProvider.cs and browsed. I found the ConditionValidationRule class and it's Validate method looked like this:

public override bool Validate(Control control, object value) {
return ValidationHelper.Validate(value, ConditionOperator,
Value1, Value2, Values, CaseSensitive);

OK, let's take a look at ValidationHelper. It's in the same file. Its main Validate() method (there were a few overloads) was most informative. I won't repeat it here since the lines are long enough to throw off the blog display, but suffice it to say that it consists of a large switch statement on the ConditionOperator value passed in.

Most of the code in each case block  makes calls to another set of methods (EvaluateIsBlankOperator is an example). Nevertheless we don't need to look any further than this to get some helpful information about the ConditionOperator, Value1, Value2, and Values, and in fact to answer the customer's actual problem.

  • Equals: checks the control's value against Value1 to be equal
  • NotEquals: the negation of Equals
  • Between: checks the control's value to be between Value1 and Value2
  • NotBetween: the negation of Between
  • Less, Greater, GreaterOrEqual, LessOrEqual: checks the control's value to be less, greater, etc, than Value1
  • BeginsWith: checks whether the control's value begins with Value1. Both are assumed to be strings. Value1 cannot contain a percent sign.
  • EndsWith: checks whether the control's value ends with Value1. Both are assumed to be strings. Value1 cannot contain a percent sign.
  • Contains: checks whether the control's value contains Value1. Both are assumed to be strings. Value1 cannot contain a percent sign.
  • NotContains: the negation of Contains.
  • Like: checks whether the control's value is "like" Value1, that is, Value1 is assumed to contain a text pattern, and the control's value is matched (or not) against that pattern. Metacharacters are '%' for zero or more characters, '_' for a single character. (Note, to find the metacharacters took more time than I took finding the switch statement.)
  • NotLike: the negation of Like.
  • IsBlank: checks whether the control's value as a string is null or empty.
  • IsNotBlank: the negation of IsBlank.
  • AnyOf: checks whether the control's value is one of the values in the Values collection. If the collection is null or empty, the control's value is assumed valid (this seems wrong to me, so I'll ask).
  • NotAnyOf: checks whether the control's value is not one of the values in the Values collection. If the collection is null or empty, the control's value is assumed valid.

So the basic solution to the customer's issue was to use AnyOf instead of Contains.

Now, let me lay down some thoughts on this small episode. First of all, I agree that this information should be in the help. No arguments from me on that score.

The customer could have pinged our support team with this problem and obtained the same answer, albeit a day later.

And, by the way, I'm certainly not advocating that we don't bother with providing help at all and just ask our support team to always respond with "use the source, Luke".

Nevertheless, with only a short time browsing the source code (less time than it's taken me to write this blog post), I came up with the answer. I hasten to add that I am not very familiar with the source -- it's not like I read a DevExpress source file every night before switching off the light -- but even so, I was able to unblock someone relatively quickly.

So, all I'm saying is, if you're stuck on something, maybe browsing the source is one way to find out the answer. I know it's worked for me with .NET in general; so much so, that Reflector is one of my primary tools.

[General preemptive note: if you find that the help is missing something or is confusing, don't get mad, get even. File a bug report and track it. Don't post it as a comment here: it'll get overlooked or lost. Throw it at the support team, and they'll in turn push it onto the documentation team. Most importantly of all, it'll get registered in our support database and someone will have to do something about it. I won't accept "Accepted - Release TBD" either. Documentation is not code.]

[Another preemptive note: behave if you want to comment, or I will turn off comments on this post faster than a hot knife through butter. This post has all the hallmarks of attracting anonymous ranters.]

Free DevExpress Products - Get Your Copy Today

The following free DevExpress product offers remain available. Should you have any questions about the free offers below, please submit a ticket via the DevExpress Support Center at your convenience. We'll be happy to follow-up.
No Comments

Please login or register to post comments.