Seeking advice on doing validation within setters

I had a function called createAccount that I was planning to have as a friend of my Account class so that it could easily change Account's private members such as firstName, lastName etc. and I was calling a validation function called validateNoSpacesAndNotEmpty from within createAccount. Then someone on here gave me the advice that I should not make them friends and instead use the setters and have the validation within the setters because the point of using setters is to make sure that the members of the object are never invalid

I'm not really sure how that would work though... Right now I have a typical setter.

1
2
3
4
void Account::setFirstName(string f)
{	
	firstName = f;
}	



But if I call my validation function from within the setter, the setter will be both getting input from the user and setting firstName to the value of it.

This is the validation function I want to use.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//<input> The input to validate
//<prompt> This should be something like "First Name: "
 string validateNoSpacesAndNotEmpty(string input, string prompt)
 {     
	cout << "\t" << prompt;
    while(!(getline(cin, input)) || (inputHasSpace(input)) )
     {
		 //display an error
         cout << "\tError: This field must not be blank or contain any spaces. \n";

		 //display the prompt again
		 cout << prompt;
              cin.clear();
         	  cin.ignore(100, '\n');
     }
     return input;
 }


It uses this
1
2
3
4
5
6
7
8
9
10
11
12
//<input> what the user entered
bool inputHasSpace(string input)
 {
     for (unsigned i=0; i < input.length(); i++)
     {
         if (input[i] == ' ')
         {
             return true;
         }
     }
     return false;
 }



I'm guessing if I want to do validation in the setter, I'll might have to change the way the validation works entirely, and maybe also pass a bool to the setter that specifies whether or not I want the validation to occur. After all I also use this setter to set firstName to be something I read from a file and I wouldn't want this prompt to ever pop up in that case.

I have never done any validation that isn't similar to the code above. Can anyone give me an idea as to how validation like this would usually be done in a mutator?
Last edited on
Validation should return true or false to indicate whether or not the supplied value passed the validation test. It should not prompt for re-input attempts by the user; what if that value was not even supplied by the user in the first place, but still needs to be validated (e.g., from a configuration file)?

The setter should just validate the input, and if it passed then perform the set. Otherwise it should not. You will probably want to also return a boolean from this function to indicate whether or not the setting occurred.

In the part of your program where you actually get input is where you should call the setter on the user input; by checking the return value, you can decide whether you need to re-prompt for proper input.
I probably won't be validating things read from a file because I don't think my instructor requires it but I do need to prompt for re-input attempts to make the program user friendly. I suppose I should do the re-prompting loops in createAccount then? It would be a lot of code to type, since I'd have to make a re-prompting loop for firstName, lastName, and password... well maybe it wouldn't be so much. I guess I'll just have to code it out and see. Thanks.
Last edited on
The file bit was just an example of why validation shouldn't be asking for input. The main reason is because it should be doing validation and validation only, not user input management.

As for the amount of code, you're going to need to ask for input again somewhere, so I don't see how doing it where you are doing the input already is any worse than in the validation code except for my above point that the validation could shouldn't be doing things other than validation.

It is actually possible to factor out the common code in reading the string here, but the way that comes to mind for me would involve passing the validation function as an argument so you could decide how to validate each time you call the function to read input. I'm not certain if you want to go into that much detail (I can only guess you haven't covered function pointers yet) but if you like, I can give you an example.
Yeah I was thinking I may need to pass functions as arguments but that does sound pretty advanced so I'll just do things the simple repetitive way since I need to get this thing done fast. Thanks again.
Topic archived. No new replies allowed.