CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 4 1234 LastLast
Results 1 to 15 of 53
  1. #1
    Join Date
    Nov 2008
    Location
    United States
    Posts
    81

    Object Validation

    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

    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.
    Three5Eight
    Using: MS C# 08 EE, MS SQL 05 EE, C++ .Net 08 EE, Vista Home Premium, XP Home

  2. #2
    Join Date
    Jun 2008
    Posts
    2,477

    Re: Object Validation

    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.

  3. #3
    Join Date
    Mar 2002
    Location
    St. Petersburg, Florida, USA
    Posts
    12,125

    Re: Object Validation

    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.
    TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
    2008, 2009,2010
    In theory, there is no difference between theory and practice; in practice there is.

    * Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
    * How NOT to post a question here
    * Of course you read this carefully before you posted
    * Need homework help? Read this first

  4. #4
    Join Date
    Nov 2008
    Location
    United States
    Posts
    81

    Re: Object Validation

    OK, I make a quick example (I started this before you replied)
    Code:
    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;
            }
        }
    }
    Quote Originally Posted by BigEd781 View Post
    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.
    Code:
    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?
    Last edited by Three5Eight; December 8th, 2008 at 07:48 PM.
    Three5Eight
    Using: MS C# 08 EE, MS SQL 05 EE, C++ .Net 08 EE, Vista Home Premium, XP Home

  5. #5
    Join Date
    Jun 2008
    Posts
    2,477

    Re: Object Validation

    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.

  6. #6
    Join Date
    Mar 2002
    Location
    St. Petersburg, Florida, USA
    Posts
    12,125

    Re: Object Validation

    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
    Code:
         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...
    Code:
    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......
    TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
    2008, 2009,2010
    In theory, there is no difference between theory and practice; in practice there is.

    * Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
    * How NOT to post a question here
    * Of course you read this carefully before you posted
    * Need homework help? Read this first

  7. #7
    Join Date
    Nov 2008
    Location
    United States
    Posts
    81

    Re: Object Validation

    Quote Originally Posted by TheCPUWizard View Post
    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
    Using: MS C# 08 EE, MS SQL 05 EE, C++ .Net 08 EE, Vista Home Premium, XP Home

  8. #8
    Join Date
    Nov 2008
    Location
    United States
    Posts
    81

    Re: Object Validation

    Nah, I have no idea what that code is supposed to do, sorry.
    Three5Eight
    Using: MS C# 08 EE, MS SQL 05 EE, C++ .Net 08 EE, Vista Home Premium, XP Home

  9. #9
    Join Date
    Jun 2008
    Posts
    2,477

    Re: Object Validation

    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.

  10. #10
    Join Date
    Nov 2008
    Location
    United States
    Posts
    81

    Re: Object Validation

    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".
    Three5Eight
    Using: MS C# 08 EE, MS SQL 05 EE, C++ .Net 08 EE, Vista Home Premium, XP Home

  11. #11
    Join Date
    Mar 2002
    Location
    St. Petersburg, Florida, USA
    Posts
    12,125

    Re: Object Validation

    Quote Originally Posted by Three5Eight View Post
    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.
    TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
    2008, 2009,2010
    In theory, there is no difference between theory and practice; in practice there is.

    * Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
    * How NOT to post a question here
    * Of course you read this carefully before you posted
    * Need homework help? Read this first

  12. #12
    Join Date
    Nov 2008
    Location
    United States
    Posts
    81

    Re: Object Validation

    Quote Originally Posted by BigEd781 View Post
    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.
    Three5Eight
    Using: MS C# 08 EE, MS SQL 05 EE, C++ .Net 08 EE, Vista Home Premium, XP Home

  13. #13
    Join Date
    Mar 2002
    Location
    St. Petersburg, Florida, USA
    Posts
    12,125

    Re: Object Validation

    Quote Originally Posted by Three5Eight View Post
    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:
    Code:
    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
    Code:
    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.
    Code:
    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

    Code:
    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:
    Code:
    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.
    TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
    2008, 2009,2010
    In theory, there is no difference between theory and practice; in practice there is.

    * Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
    * How NOT to post a question here
    * Of course you read this carefully before you posted
    * Need homework help? Read this first

  14. #14
    Join Date
    Nov 2008
    Location
    United States
    Posts
    81

    Re: Object Validation

    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?

    Code:
    public class Person
    {
        private string m_firstName;
        private string m_lastName;
    
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
    Code:
    public class PersonProvider
    {
        public void Save(Person p)
        {
            // Save
        }
    }
    Code:
    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.
    Last edited by Three5Eight; December 9th, 2008 at 12:14 PM.
    Three5Eight
    Using: MS C# 08 EE, MS SQL 05 EE, C++ .Net 08 EE, Vista Home Premium, XP Home

  15. #15
    Join Date
    Mar 2002
    Location
    St. Petersburg, Florida, USA
    Posts
    12,125

    Re: Object Validation

    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.
    TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
    2008, 2009,2010
    In theory, there is no difference between theory and practice; in practice there is.

    * Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
    * How NOT to post a question here
    * Of course you read this carefully before you posted
    * Need homework help? Read this first

Page 1 of 4 1234 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured