Click to See Complete Forum and Search --> : Object Validation


Three5Eight
December 8th, 2008, 06:17 PM
I need help learning to validate my objects. I know how to do the validation but I'm wondering where is the best place to put it? I have been told that objects need to validate themself, so should I put the validate inside the accessors?

I have a validation method in my class that forces the class to validate itself before any values are saved to the database, but that method doesn't run until the user tries to save. So there is a good chance that the data in RAM is invalid. I would like to validate earlier then this so that invalid data is not allowed in RAM at all.

I looked on MSDN and found an article. I'm not really sure what this is supposed to do, but I've tried using it in my program and I cannot locate the namespaces. I tried adding them as references but I can't find them anywhere on my computer.

Article (http://msdn.microsoft.com/en-us/library/cc511640.aspx)

Where should I put my validation to make sure my class is always valid? Even putting them in the accessors seems silly because I have to validate everything twice, once in the accessors and then once when the users try to save.

Thanks.

BigEd781
December 8th, 2008, 06:20 PM
If you validate in the accessors, you should not have to validate once again before they save because you know that the data is valid already.

TheCPUWizard
December 8th, 2008, 06:40 PM
It is generally necessary to divide singular value validation from combinatorial validation.

The former is contidions such as a number must be between 1 and 100. This can (and typically should) be done in the setter.

The latter is more dificult. Consider three simple numberic fields. The object is valid if Field3 = Field1+Field2. During any type of update this will be invalid for a period of time, and therefore cannot be done inside the setters directly.

Additionally some validations may requires significant time, and extra (redundant) calls should be eliminated.

So the end result (as with so many things) is that it requires a careful evaluation of the specific implementation.

Three5Eight
December 8th, 2008, 06:44 PM
OK, I make a quick example (I started this before you replied)

using System;
namespace ClassLibrary1
{
public class Person
{
private string firstName;
private string lastName;

private const int LAST_NAME_MIN_LENGTH = 0; // Last Name not required.
private const int LAST_NAME_MAX_LENGTH = 15;
private const int FIRST_NAME_MIN_LENGTH = 3;
private const int FIRST_NAME_MAX_LENGTH = 15;

public delegate void ValidationMessageHandler(string p_message);

public event ValidationMessageHandler ValidationMessage;

public void OnValidationMessage(string p_message)
{
if (ValidationMessage != null)
{
ValidationMessage(p_message);
}
}

public string FirstName
{
get { return this.firstName; }

set {
if ((value.Length < FIRST_NAME_MIN_LENGTH) || (value.Length > FIRST_NAME_MAX_LENGTH))
{
OnValidationMessage("Message to user");
return;
}
this.firstName = value;
}
}
public string LastName
{
get { return this.lastName; }

set
{
if ((value.Length < LAST_NAME_MIN_LENGTH) || (value.Length > LAST_NAME_MAX_LENGTH))
{
OnValidationMessage("Message to user");
return;
}
this.lastName = value;
}
}
public bool Save()
{
if (!ValidateMyself())
{
return false;
}
// Save Implementation
return true;
}
public void Load(Guid dbID)
{
Person p;
// Load Implementation
SaveToRAM(p);
}
private void SaveToRAM(Person p)
{
FirstName = p.FirstName;
LastName = p.LastName;
}
private bool ValidateMyself()
{
bool error = false;
if ((FirstName.Length < FIRST_NAME_MIN_LENGTH) || (FirstName.Length > FIRST_NAME_MAX_LENGTH))
{
OnValidationMessage("Message to user");
error = true;
}
if ((LastName.Length < LAST_NAME_MIN_LENGTH) || (LastName.Length > LAST_NAME_MAX_LENGTH))
{
OnValidationMessage("Message to user");
error = true;
}
return error;
}
}
}


If you validate in the accessors, you should not have to validate once again before they save because you know that the data is valid already.

I don't really agree with that. Let me show you why.

I should still need to validate in the Save() even if I validate in the accessors.

For Example:
Lets say that FirstName and LastName here are both required.

using System;
namespace ClassLibrary1
{
public class UsePerson
{
public UsePerson()
{
Person p = new Person();
p.FirstName = "Bob";
p.Save();
}
}
}


There is a major bug here, because I only validate in the accessors. Remember FirstName and LastName are required. But the user called Save() without supplying a LastName. Since I only validate in the accessors, I have no way of knowing this information is missing. If the database is expecting a NOT NULL value for LastName... my program just crashed.

This is the problem I'm running into. I'm not sure how to do flaw-proof validation here.

EDIT: Thanks for reply TheCPUWizard. I posted this as you were replying. I can see what you are saying I'm running into that alot. I'm pretty good at getting the validation down, but I was having a problem with where to put it sometimes. Just on my example code, is that how you would do it with that class?

BigEd781
December 8th, 2008, 06:49 PM
That is true, my answer was overly simplistic, but I did not know what you are doing. CPU is right; it really depends on your implementation.

TheCPUWizard
December 8th, 2008, 06:52 PM
FirstName / LastName combinatorial, as I showed in my previous reply.

More imporaantly you need to re-factor (heavily)...look at how much duplication you have..

I any real application you will end up with thousands of

if ((....))
{
OnValidationMessage("Message to user");
return;
}

type constructs.

Develop a good validation object model!!!!!

Other problems... You are tieing business logic (your classes) to UI presentation (Showing Messages). These should be separated by (typically) TWO layers.

A starting point...

class Verify<DATA_TYPE, HANDLER_TYPE>
{
public Verify(object owner) {}
public DATA_TYPE Value { get; set; }
}

class Person
{
public Person()
{
InstanceValidator(this);
}
public readonly Verify<string, Validator> FirstName(this);
public readonly Verify<string, Validator> LastNameName(this);
public ObjectValidator IsValid(this);
}

NOTE: Shortcust were taken, and this will NOT compile, it is for conceptual purposes only......

Three5Eight
December 8th, 2008, 07:03 PM
More imporaantly you need to re-factor (heavily)...look at how much duplication you have..

Woo, this is my point of making the thread. I don't want to type this over and over again. It's taking up too much time and it's making my code really messy.

Unfortionally, the example you provided just confused me even more. I'm not even sure how to read that code.

I'm going to dinner I will try to understand it again when I get back.

Three5Eight
December 8th, 2008, 07:42 PM
Nah, I have no idea what that code is supposed to do, sorry.

BigEd781
December 8th, 2008, 08:28 PM
he has created a class to deal with validation. This way, when (not if) the validation routine needs to change, you can change in a single spot instead of throughout various classes. Each class that needs validation owns an instance (or more) of the validate class and delegates validation work to it.

Three5Eight
December 8th, 2008, 08:33 PM
I'm trying to understand it. I tried to recreate it in IDE but I haven't had any luck. It looks like it using generics, but either way I get a compile error on the last three lines "this" it says "Type Expected".

TheCPUWizard
December 8th, 2008, 08:41 PM
I'm trying to understand it. I tried to recreate it in IDE but I haven't had any luck. It looks like it using generics, but either way I get a compile error on the last three lines "this" it says "Type Expected".

You did NOT pay attention to my "NOTE"...The code as posted is not even close to a real compilable sample. It is purely for illustration of

1) Using a Class to encapsulate to the verification of a field
2) Associating each validator with the instance of the object that contains the field
3) Aggregating the validity of the instance to include the validity of each field as well as some overall validation.

The "real" cloasses will be a few hundred lines of code. But remember once they are written and debugged, then they can be used thousands of times.

Three5Eight
December 8th, 2008, 10:34 PM
he has created a class to deal with validation. This way, when (not if) the validation routine needs to change, you can change in a single spot instead of throughout various classes. Each class that needs validation owns an instance (or more) of the validate class and delegates validation work to it.

That explination makes more sense to me but I don't see how the code shows that. I've made validation classes before but I was told that objects need to validate themself, not depend on another object for validation. Maybe that's not true, but I think the code is confusing me even more because I have no idea how to read it.

TheCPUWizard
December 8th, 2008, 10:52 PM
That explination makes more sense to me but I don't see how the code shows that. I've made validation classes before but I was told that objects need to validate themself, not depend on another object for validation. Maybe that's not true, but I think the code is confusing me even more because I have no idea how to read it.

You are confusing having an external validator such as the following:

class Validator
{
bool IsValid(MyBusinessClass object);
}


Where the USER of your class (ie any code that calls your class) must explicitly know about the validator.

This is completely different than factoring out the implementation of the validation, butr still having the object public properyies do the work

class MyBusinessClass
{
bool IsObjectValie() {...this MAY call other classes}
int SomeField
{
get { return m_SomeField; } }
set {
Validate(value); // throw exception if bad data.
m_SomeField = value;
}
}


Now we know there are certain types of validators, lest say UpperLimit and Range.

class abstract Validator
{
public abstract void Validate(int value);
}

public UpperLimitValidator : Validator
{
UpperLimitValidator(int upperLimit) { m_UpperLimit = upperlimit; }
public override Validate(int value)
{
if (value > m_UpperLimit)
throw new ArgumentException();
}
}

So now we have validaotrs we can use, but would still have get and set methods for each property, along with manual calls to set/retrieve the backingfield, and to call the validator...so lets eliminate that


class ValidatedInt
{
public ValidatedInt(Validator validator) { m_Validator = validator);
public int Value
{
get { return m_Value; }
set
{
m_Validator.Validate(value);
m_Value = value;
}
private Validator m_Validator;
private int m_Value;
}


Now our usage is simple:

class MyBusinessClass
{
public MYBusinessClass()
{
Quantity = new ValidatedInt(new UpperLimitValidator(100));
}

public readonly ValidatedInt Quantity;
}


MyBusinessClass test;
test.Quantity.Value = 1; // will work
test.Quantity.Value = 101; // will throw exceptino


Even this more detailed explaination is for reference. You do not want to have to write different validators for all of the different types, so generics will come into play.

Three5Eight
December 9th, 2008, 11:10 AM
I'm going to try to make a class using that example. I think its a little more clear. I think I was getting confused when I was told that an object needed to validate itself. I thought that it ment that the objects validation functions needed to be inside the object itself. After reading the last post I'm thinking that it meant the object needed to call the validation functions automatically, and not rely on the user to call the validation function before calling the save function.

So I can leave the object by itself?


public class Person
{
private string m_firstName;
private string m_lastName;

public string FirstName { get; set; }
public string LastName { get; set; }
}



public class PersonProvider
{
public void Save(Person p)
{
// Save
}
}



public class Form1
{

Button1_Click
{
Person p = new Person();
p.FirstName = "Bob";
p.LastName = "LOL";
PersonProvider pProvider = new PersonProvider();
pProvider.Save(p);
}
}



I know this doesn't have to do with validation but it helps me in the same way to understand how to organize the class.

Should Save() (and other functions) be put inside Person or should they be put inside PersonProvider? I have seen both examples where the Person class is ONLY the Person object, and the functions that maniuplate ther Person class are within another class called PersonProvider. I've also seen the maniuplation functions like Save(), Load(), CalculateSalesTax(), etc.. inside the Person class.

It makes more OO sense to me, to have them seperated, but by doing that I mess up my data security because I have to make all of the fields inside Person public so that PersonProvider can access them. Unless I derived PersonProvider from Person.. But I'm not sure that makes sense.

I'll post back my final code for the validation when I get it finished.

TheCPUWizard
December 9th, 2008, 11:26 AM
1) Your FirstName, LastName properties set accessors should automatically call any validation that is appropriate for the field in a stand alone condition

2) Your Person class should expose an IsValid property which makes sure that everything in the class is valid (this validation can be implemented as a class, and called from within the propery).

3) Validation failures in set accessors MUST throw exceptions, otherwise the calling code can "continue on its merry way".


Once you do this post back the Person class, you will see that it contains duplication of constructs...This is what we want to avoid.

Three5Eight
December 9th, 2008, 12:28 PM
Ok, I tried it again. I think it might still be wrong. :(

TheCPUWizard
December 9th, 2008, 12:57 PM
Starting to look better. Your setters now to inherent validation.

But lets look closer...

public string FirstName
{
get { return this.m_firstName; }
set
{
PersonValidator pval = new PersonValidator();
if (!pval.FirstNameValid(value))
{
throw new ArgumentException();
}
m_firstName = value;
}
}


The code (neglecting the silver/gray text) is being DUPLICATED, and remember the mantra that CODE DUPLICATION IS EVIL.

You want to factor this entire part so that it exists ONLY ONCE, no matter how many fields "Person" has, and no matter how many different business entities you create.

So you create a class:

class ValidatedString
{
public string Value
{
get { return this.m_Value; }
set
{
if (!m_Validator.Validate(value(value))
{
throw new ArgumentException();
}
m_Value= value;
}
}
public ValidatedString(Validator validator)
{
m_Validator = validator;
}}


Now you NEVER have to type in or paste that construct again. You can simply use it:

class Parson
{
public readonly ValidatedString FirstName;
public readonly ValidatedString LastName;

// Setup an Assign Validators in the Constructor
public Parson()
{
FirstName = new ValidateString(new FirstNameValidator());
LastName = new ValidateString(new LastNameValidator());
}


See how much smaller your class is??? NO Duplication, and Just 2 lines (as opposed to close to 20) for each field....

Three5Eight
December 9th, 2008, 01:50 PM
I think it's getting closer then, but its still not working. I think I'm starting to understand what you are doing but I'm having trouble getting the syntax correct. I think I need a Validator interface or something. Because this wont compile. I'll try to fix it.

Sorry this is taking so long, but I look at your profile and remember you have been programming computers longer then I've been alive, so it comes easier to you.


David V. Corbin was an original founding member of Dynamic Concepts in 1984.


Dang. I wasnt even boren in 1984. :ehh: No wonder the examples don't make sense to me.

TheCPUWizard
December 9th, 2008, 01:59 PM
1) All your "validators" should derive from Validator. every one of them should have a single method called void Validate(string)

2) You are missing a new when creating the fields.

That should get you to compile.

ps: Yes, I have ben doing this for over 36 years [since sept 1972]....

Three5Eight
December 9th, 2008, 02:44 PM
OK, it compiles now so I think I'm almost there. Except I know that PersonValidator.ValidateString won't work you can see why. I think this is what you talked about before in your first code example.

I know I need to pass some STRING_TYPE in there. I can add it in the param, "FIRST_NAME" but then that will break my code in ValidatedString.Value and I'll be having a bunch of duplicated code again if I do it the way I want.

I think you meant I can use generics to create my own string type which will hold the VALUE of the string and the TYPE (firstname, lastname, middlename) of the string.

I don't want people typing in my code though with data that can be corrupted:


MyStringType value<"Bob", "FIRST_NAME">;


So should I create an enum?


enum StringType
{
FirstName,
LastName,
MiddleName,
SomeOtherString
}

MyStringType value<"Bob", StringType.FirstName>



ValidateString(MyStringType value)
{
switch (value.StringType)
{
case StringType.FirstName:

// Validate
break;

case StringType.LastName:
// Validate
break;
}
}

Three5Eight
December 9th, 2008, 02:52 PM
What if I just added a m_valueType to the ValidatedString class. That might work instead. Then I would need to update my functions to take two arguments, and I would still need an Enum.

TheCPUWizard
December 9th, 2008, 02:58 PM
You are overcomplicating it....

class Validator
{
public virtual void Validate(string data) { }
}
class LengthValidator : Validator
{
public LengthValidator(int min, int max)
{
m_Min = min;
m_Max = max;
}

public virtual void Validate(string data)
{
if (String.IsNullOrEmpty(data); } throw new Exception();
if (data.Length < m_Min) throw new Exception();
if (data.Length > m_Max) throw new Exception();
}
}

FirstName = new ValidateString(new LengthValidator(1, 10));
LastName = new ValidateString(new LengthValidator(2, 15));

Three5Eight
December 9th, 2008, 03:16 PM
ooook,

I guess I don't need all that extra consts in the validation class then because the sizes go when the field was created.

I'm pretty sure I can figure it out now. Then I will test it and see if it works. The few lines that are confusing me I put below. I think they were causing me the most trouble understanding this.


public readonly ValidatedString FirstName;


You made this read only so when I test this I don't think I will be able to assign a first name at run time. Only in the constructor. This information might change from time to time so should I remove the readonly?


LastName = new ValidateString(new LengthValidator(2, 15));


This one I don't understand, I don't think. It looks like I'm making LastName into an instance of ValidateString... ohh **** nevermind. I got it, duh.

TheCPUWizard
December 9th, 2008, 03:19 PM
1) You only create the field once (From the constructor), that is why ist MUST be readonly.

2) When you are changing the Values, you use the Value Propery:

FirstName.Value="John";
LastName.Value="Smith";
Console.WriteLine(FirstName.Value);

Three5Eight
December 9th, 2008, 03:21 PM
I'm stupid.

TheCPUWizard
December 9th, 2008, 03:37 PM
I'm stupid.

If that from before my last post, or do you not understand my last post???? :confused::confused:

ps: I am going out for a few hours, it may be the monring (I am in NY USA) before I get back.

Three5Eight
December 9th, 2008, 03:40 PM
No. I figured it out. I am stupid because it took all day to figure it out and it was so simple.

Thanks for all the help. I think I will be able to get it working now. If I get another problem I will post back.

BigEd781
December 9th, 2008, 03:50 PM
You're not stupid, this happens all of the time when making software. The next time you try this you will already know how to do it, that's what learning is all about.

Three5Eight
December 9th, 2008, 04:30 PM
So is it OK to leave unimplemented functions?


public abstract class Validator
{
public virtual void ValidateString(string m_string)
{

}
}


This works fine now, but if I name ValidateString abstract, add abstract ValidateDateTime to the validator class then I get an error in my LengthValidator ("Does not implement inherited ValidateDateTime"). But only DateTimeValidator should implement that. So I used virtural and left no implementation. Its an abstract class so I think this will be ok and it will allow derived classes to implement only the functions they want to use and ignore the rest.


Second, since I throw exceptions in LengthValidator will this code fail? If ValidatedString throws an exception will the value still be written into m_value?


public string Value
{
get { return this.m_value; }
set
{
m_validator.ValidateString(value);
m_value = value;
}
}

Mutant_Fruit
December 9th, 2008, 05:32 PM
One nice trick which I was introduced to a while ago is for when you check public methods to ensure the parameters passed in are non-null. What you do is something like this:


static class Check
{
void DoCheck (object o, string name)
{
if (o == null)
throw new ArgumentNullException (name);
}

void Path (object path)
{
DoCheck (path, "path");
}

void Stream (object stream)
{
DoCheck (stream, "stream");
}
}


public void PublicMethod (string path, Stream stream)
{
Check.Stream (stream);
Check.Path (path);
}


This makes it easy to keep your null checks in sync with the names of the parameters. If you rename a parameter, you just call the corresponding Check method. While it isn't a huge saving in terms of LOC (1 line instead of 2), it is definitely more readable and can be easier to maintain.

Three5Eight
December 9th, 2008, 05:54 PM
Cool, that is similar to what I was thinking about doing. I wasn't sure if it was a good idea or not, but now I know its used by other people.

Was the last code example I posted ok? Is it normal to leave a function with no implementation like I have done?

Also, like CPUWizard said I want to keep my code from duplicating as much as possible. On a type like boolean, which doesn't need to be validated because its always either true or false guranteed. Should I be putting my get; set; accessors in the class itself, or should I be making another class similar to ValidatedString that will take care of the accessors? That would reduce duplication.

Three5Eight
December 9th, 2008, 07:02 PM
OK! Finally!

I got it done. I added some extra classes for data types that I will be using. Maybe I don't need to do this but it makes my code so much easier to read because its not loaded with get; set; anymore.

Here's what I did:


public class BooleanField
{
private bool m_value;

public bool Value
{
get { return m_value; }
set { m_value = value; }
}
}



public class GuidField
{
private Guid m_value;

public Guid Value
{
get { return m_value; }
set { m_value = value; }
}
}



public readonly BooleanField Deleted;
public readonly BooleanField Taxable;
public readonly GuidField InternalID;

// constructor
Deleted = new BooleanField();
Taxable = new BooleanField();
InternalID = new GuidField();


I put these extra classes in a namespace called "Helpers"/

Now I can access everything with Value. I have 15 booleans in one class for various settings and I don't have to type the accessors over 15 times, omg that saves me so much time!

In the future if I need to add validation to the Guid field I can simply modify the GuildField class. The entire program will update automatically.

TheCPUWizard
December 9th, 2008, 07:04 PM
[QUOTE=Three5Eight;1790619]

EVERY validator should have one method. Validate(...) DO NOT change the method name, just change the class name.

I should NOT have declared the base class abstract, it should in fact be a do nothing validator. This will actually result in faster code than having to check if a validator is installed.

Three5Eight
December 9th, 2008, 07:25 PM
But now I'm confused because the Validator base class can't have the same methods?


public abstract class Validator
{
public virtual void ValidateString(string m_string) { }
public virtual void ValidateInt(int m_int) { }
}


Are you saying the Validator class should just be an empty class?


Edit:

If this is correct then I need to modify the base-class:


public class Validator
{
public virtual void Validate(object o) { }
}

BigEd781
December 9th, 2008, 07:42 PM
You can override the Validate() method in your inherited classes so that it does the right thing for that class..

TheCPUWizard
December 9th, 2008, 07:50 PM
But now I'm confused because the Validator base class can't have the same methods?

Einstein once said, keep things as simply as possible, but no simpler...

In this case, my keeping generics out of the picture to keep things simple has actually caused the confusion.


If you are rady, try:

class Field<T>
{
public T Value
{
get { return this.m_Value; }
set
{
if (!m_Validator.Validate(value(value))
{
throw new ArgumentException();
}
m_Value= value;
}
}
public Field(Validator<T> validator)
{
m_Validator = validator;
}
private T m_Value;
private Validator<T> m_Validator;
}


class Validator<T>
{
public virtual void Validate(T data) {} // do nothing base...
}

class ValidatorNumRange : Validator<Int>
{
public virtual void Validate(Int data)
{
// do work here
}
}



Does that make sense???

Three5Eight
December 9th, 2008, 08:23 PM
Does that make sense???

Yes, however one part doesn't make sense to me.


public T Value
{
get { return this.m_Value; }
set
{
if (!m_Validator.Validate(value(value))
{
throw new ArgumentException();
}
m_Value= value;
}
}



I'm not sure what it means (value(value)). "value" is a keyword so I don't know if its getting the value or value .. doesn't make sense to me.

Also, that statement will never work because Validate does not return a value so ! is not making any sense to me.

Three5Eight
December 9th, 2008, 08:28 PM
If I modify Validate to return a bool so that statement will compile, then the class is incorrect because my override would also have to return a bool and it would not return anything because once that exception is thrown the function is done.


public override void Validate(int p_int)
{
if ((p_int < m_LBound) || (p_int > m_UBound))
{
throw new ArgumentOutOfRangeException();
return false; // never happen
}
}


I'll keep working on it.

New Version: But it looks wierd.


public class Validator<T>
{
public virtual bool Validate(T data) { return false; }
}



public override bool Validate(string p_string)
{
if (string.IsNullOrEmpty(p_string))
{
throw new ArgumentNullException(); // RETURN NOTHING
}

if ((p_string.Length < m_minLength) || (p_string.Length > m_maxLength))
{
throw new ArgumentOutOfRangeException(); // RETURN NOTHING
}
return true;
}

Ok, I believe I got it. Here is the final solution attached for people to use as long as CPUWizard thinks its correct this time.

The only thing I have left to do is figure out how to add an IsValid property to the Person class, that wont require me to write all the data validation functions over again. I'll work on that tomorrow.

TheCPUWizard
December 9th, 2008, 10:05 PM
The return value is in case you eventually need a condition where you will suppress the assignment silently. Until this need arises (which will come with some advanced validators!), you should just implement so that it either throws, or returns true.

Three5Eight
December 10th, 2008, 04:07 PM
OK,

I added one function to the Field<> class:


public bool IsValid()
{
if (m_validator != null)
{
if (!m_validator.Validate(m_value))
{
return false;
}
}
return true;
}


I also use that function with the IsValid() function of the Person class (in this case Department class):


public bool IsValid()
{
bool validationError = false;

if (!Description.IsValid()) { validationError = true; }
if (!ReportName.IsValid()) { validationError = true; }
if (!DisplayName.IsValid()) { validationError = true; }
if (!DepartmentID.IsValid()) { validationError = true; }

return !validationError;
}


I believe that was the final touch, everything should be working now.

Thanks for all the help on this matter!

TheCPUWizard
December 10th, 2008, 04:12 PM
Glad you have a workable solution.

I see you added a check to allow a field to NOT have a validator (the check for null). I believe this to be a bad decision.

1) It makes it easier to forget to install a valiadtor (remember to strive to make code HARD to use incorrectly). It is better that the coder must explicitly create the validator (which is why the base classes I gave were NOT abstract, so they could be used as explicit "do nothing".

2) It can reduce performance. As this pattern becomes more and more common in your designeds, you may find the "Field" code to be executing millions of times per seconds. Optimal performance is achieved by ELIMINATING branches which flush time compilers pipelines. It will actually be faster to call a "do nothing" than to check for null in many circumstances.

Three5Eight
December 10th, 2008, 04:59 PM
Well the reason I decided not to have a validator is because some fields cannot be validated. For example:


bool Taxable;


In my Department class to tell if the class is taxable or non-taxable. I don't know how to validate that, because its a boolean and it can never be invalid. It can't be assigned to null and it is guranteed to always be true or false. I don't see how that could be invalid.

So if I were to validate that field I would have to check if its either true or false and it will always be one of the two values.

Also, a GUID field I have no way to validate. I just make sure that its not Guid.Empty. But there is no way that a GUID can be invalid either because you would receive a cast exception as soon as you tried to assign it something that is not a real GUID...

So I guess you want me to create a BooleanValidator class and just have that class do nothing??

TheCPUWizard
December 10th, 2008, 05:06 PM
But then you make things "Harder to Use Correctly". Some of your objects "Fields" will have one syntax, others wil have a different one:


class Foo
{
public Field<Int> Item1;
public boo Item2;
}

Foo f;
f.Item1.Value = 3; // need to use value since this is a validated field.
f.Item2 = true;l // raw field, cant use value.

Also your object level validation will be more difficult (because you can not build up a simple collection of all of the fields and then do a for-each on the IsValid method).

Also if you ever need to change from a raw field to a validated field, then all of your client code will have to change.

Remember the goal (as Scott Meyers put so well about 13 years ago) is to "PRogram in the Future Tense". This means writing your code today, so that it can meet the (currently unknown) challenges of tomorrow.

So far we have simply been talking about some trivial "value" type validations. What happens if next year you need to validate a user (or better a role) for security to assign a valud to a field?

If you write all of your code today to use the new classes, then you can simply enhance your validators and NONE of your application level code will need to change (e.g Only a "Supervisor" can mark a item as non-Taxable in an inventory control system).

Three5Eight
December 10th, 2008, 05:13 PM
Ok, so I think you are saying instead of doing this:


public Field<bool> field1;


I just use the normal way?


public Field<string> description;
public bool taxable;


So when I am using a field that doesn't need to be validated then don't use the Field class?

If that's what you are saying I tried to do that but then I got into code duplication, because if I have 6 boolean fields in my class then I have to type 6 get; set; accessors, one for each field. So the reason I put them into Field and didn't assign a validator was so that I could use the get; set; included in Field, instead of typing them over and over again.

TheCPUWizard
December 10th, 2008, 05:19 PM
Ok, so I think you are saying instead of doing this:


public Field<bool> field1;


I just use the normal way?


public Field<string> description;
public bool taxable;




No...that leads directly to the "Negatives" I pointed out in my previous post.

what I am saying (at least for how I have been using this pattern for the past decade)

1) Alway use "public readonly Field<T> fieldname"

2) ALWAYS have a validator assigned.

3) DO NOT have an "if (validator==null)" in the setter within the field class.

Three5Eight
December 10th, 2008, 05:25 PM
Sorry, but I don't know how to create a validator for a boolean field if I always need to have a validator assigned.

I can't even assign it to Validator class and use the default "do nothing" field because that field had to change. Since the last example you gave me returned a boolean, the "do nothing" function had to be modified.

So now, it technically does something.


public class Validator<T>
{
public virtual bool Validate(T data) { return false; }
}

TheCPUWizard
December 10th, 2008, 05:32 PM
The default validator should return TRUE!

Three5Eight
December 10th, 2008, 05:43 PM
Ok, I'll make the changes then. I tried to stay away from returning true because no matter what is passed into the function will always be true even if it's not valid. I figured it was safer to return false and not assume the field was valid.

Now my IsValid() function will check all the field's Value property correctly. But I didn't know it was possible for a class to build a collection of all of the fields declared within it.

Right now I'm checking them all manually like I shown in my code example on Post # 40 (http://www.codeguru.com/forum/showpost.php?p=1791011&postcount=40)

TheCPUWizard
December 10th, 2008, 05:53 PM
If you remember,there was a time when the constructor for "Field" had a "this" parameter, but this broke things because we were using initializer lists....

Building the collection is done by implementing a set of calls. during construction (which is now taking place within the business objects constuuctor.

I dont have time tonight, but I will try to post an updated sample tomorrow morning.

Three5Eight
December 10th, 2008, 06:02 PM
Interesting, I'll look forward to your example. I think that would be usefull in many places. Not just validation. I guess you learn something new everyday. In the mean time I'll keep working on cleaning up my classes after all this.

TheCPUWizard
December 10th, 2008, 06:25 PM
Ironically this process is leading directly toward some material I am preparing for publication (that does handle alot more than validation). If the current implementation works for your immediate needs, it may be best to wait a week or so, so you can see the "real" design.

Three5Eight
December 10th, 2008, 06:39 PM
Well everything works except the IsValid() function right now. I have many more classes to design, and if I can get the IsValid() down first then I do not have to rewrite all those classes.

But, other then that everything seems to be working. However, I haven't tested it at run time yet to see if the code really does what its supposed to. I wanted to get this last piece worked out first so everything is working when I test it.

Three5Eight
December 11th, 2008, 12:48 PM
TheCPUWizard:

In reguard to your PM here is the new project you requested. I think this is what you needed.