patternjavaMinor
Validating Firstname and Lastname
Viewed 0 times
andfirstnamelastnamevalidating
Problem
I have written some code in Java that checks if the strings
Both these strings,
The below code works as expected:
```
/Returns false if both names are valid and true if they aren't/
public static boolean errcheck(String Firstname,String Lastname,int security)
{
while(true)
{
if(security>=2 && !checklen(Firstname,Lastname))break;
if(security>=3 && !checknum(Firstname,Lastname))break;
if(security>=4 && !checkvowel(Firstname,Lastname))break;
if(security>=5 && !checkcon(Firstname,Lastname))break;
return true;
}
return false;
}
/Checks if length of both strings are less than three/
public static boolean checklen(String Firstname,String Lastname)
{
if(Firstname.length()='a' && c='A' && c='a' && c='A' && c2 || numv>3) //Invalid name detected
return false;
break;
}
if(test=='\0')conv=0;
}else{numv=conv=0;break;} //New word. So reset counters
}
}
numv=conv=0;
for(i=0;i2 || numv>3)
return false;
break;
}
if(test!='\0')conv=0;
}else{numv=conv=0;break;}
}
}
Firstname and Lastname are valid names. These are inputted by the user. My code works as expected, but I would like to optimize and shorten the code such that it is readable and understandable.Both these strings,
Firstname and Lastname, will not be null or empty and might contain more than one word.Firstname and Lastname are valid if- The length of both
FirstnameandLastnameare more than two.
- There isn't any character which isn't an alphabet or space in them.
- There isn't more than three vowels in a word in
FirstnameorLastname, and there isn't more than two consecutive vowels in a word.
- There isn't more than four consecutive consonants in a word in
FirstnameorLastname, and there isn't more than two consecutive same consonant in a word.
The below code works as expected:
```
/Returns false if both names are valid and true if they aren't/
public static boolean errcheck(String Firstname,String Lastname,int security)
{
while(true)
{
if(security>=2 && !checklen(Firstname,Lastname))break;
if(security>=3 && !checknum(Firstname,Lastname))break;
if(security>=4 && !checkvowel(Firstname,Lastname))break;
if(security>=5 && !checkcon(Firstname,Lastname))break;
return true;
}
return false;
}
/Checks if length of both strings are less than three/
public static boolean checklen(String Firstname,String Lastname)
{
if(Firstname.length()='a' && c='A' && c='a' && c='A' && c2 || numv>3) //Invalid name detected
return false;
break;
}
if(test=='\0')conv=0;
}else{numv=conv=0;break;} //New word. So reset counters
}
}
numv=conv=0;
for(i=0;i2 || numv>3)
return false;
break;
}
if(test!='\0')conv=0;
}else{numv=conv=0;break;}
}
}
Solution
Requirements
The first thing that springs to mind is that the requirements seem a bit limited, are they intended to be used in a real world system or is this a programming exercise
Specific Points
- It really should be called something like
- Why is the
Is it really valid to say that sometimes we only care about the length, sometimes about the length and valid chars, sometimes about the length, vaild chars and vowel counts. It seems overkill/confusing to allow that level of customization.
How does the rest of the system deal with names that sometimes cannot have '-' chars in them [we tested them with security level 3] but sometimes can have them [we tested these will level 2]
Like
We should probably have separate tests for the valid first name and last name characters. It aids reusability - if we want to check the validity of a first name on its own we do not need to have a dummy last name. This may seem like a very picky point but why add a dependency between checking the first and last name when there is none.
Design
I can't say how it would work for performance but in terms of readability and extensibility, I would approach it as a set of tests that can be executed against the first, last or both names.
We have a
Each test has a level, a set of TestTypes (we can apply the same test to both first and last names) and an execute method. In this version we just get a simple pass/fail, in a production system I would return a
We can invoke validation on first and last names separately. The validator executes the appropriate tests by level on the input name (assumes some tests can be on both first and last name or else we might have separate lists of firstname and lastname tests)
I am a big fan of regular expressions for this sort or thing. Length and valid chars can be built into a single check e.g. [a-zA-Z]{3}, with separate tests for first and last name if they can have different characters in each.
Apologies on the code, it is generated from C#
The first thing that springs to mind is that the requirements seem a bit limited, are they intended to be used in a real world system or is this a programming exercise
- Ryan O'Neal wouldn't pass the second check, nor would Farrah Fawcett-Majors
- Abigail is not an uncommon name (depends on the location, I suppose) and it would fail the third check
- How would Lon Chaney Jr. or Trey Parker (Randolph Parker III) be handled by the system? Are the suffices considered part of the last name? If so, they fail checks 2 and 3 respectively.
Specific Points
errCheck() - It really should be called something like
validateName. - Why is the
security parameter here? I can see what it does but it isn't in the stated requirements. Is it really valid to say that sometimes we only care about the length, sometimes about the length and valid chars, sometimes about the length, vaild chars and vowel counts. It seems overkill/confusing to allow that level of customization.
How does the rest of the system deal with names that sometimes cannot have '-' chars in them [we tested them with security level 3] but sometimes can have them [we tested these will level 2]
checkNum() Like
errcheck, it doesn't match to what the function does. Also, the standard is for camel casing, so it should be called checkNum (if it checked the number of anything. checkValidChars ?We should probably have separate tests for the valid first name and last name characters. It aids reusability - if we want to check the validity of a first name on its own we do not need to have a dummy last name. This may seem like a very picky point but why add a dependency between checking the first and last name when there is none.
Design
I can't say how it would work for performance but in terms of readability and extensibility, I would approach it as a set of tests that can be executed against the first, last or both names.
We have a
NameValidator that takes a ITestProvider in the ctor. This allows us to add new tests without having to open up the NameValidator again. Enables easier use of dependency injection.Each test has a level, a set of TestTypes (we can apply the same test to both first and last names) and an execute method. In this version we just get a simple pass/fail, in a production system I would return a
TestResult with details of why it failed.We can invoke validation on first and last names separately. The validator executes the appropriate tests by level on the input name (assumes some tests can be on both first and last name or else we might have separate lists of firstname and lastname tests)
I am a big fan of regular expressions for this sort or thing. Length and valid chars can be built into a single check e.g. [a-zA-Z]{3}, with separate tests for first and last name if they can have different characters in each.
Apologies on the code, it is generated from C#
public enum TestType
{
None,
FirstName,
LastName
}
public interface ITest
{
Iterable getAppliesTo();
int getSecurityLevel();
boolean execute(String name);
}
public interface ITestProvider
{
Iterable getAllTests();
}
public interface INameValidator
{
boolean isValidFirstName(String name, int level);
boolean isValidLastName(String name, int level);
}
public class NameValidator implements INameValidator
{
private Iterable _tests;
public NameValidator(ITestProvider testProvider)
{
_tests = testProvider.GetAllTests().ToList();
}
public final boolean isValidFirstName(String name, int level)
{
return checkName(TestType.FirstName, name, level);
}
public final boolean isValidLastName(String name, int level)
{
return checkName(TestType.LastName, name, level);
}
private boolean checkName(TestType type, String input, int level)
{
// in C# I use all the tests of the correct type and security level and execute them on the input. If all pass, then we return true, it any fail, then return a false. Don't know enough java to quickly convert.
}
}
public class SimpleTestProvider implements ITestProvider
{
public final Iterable getAllTests()
{
return new java.util.ArrayList(java.util.Arrays.asList(new ITest[] {new FirstNameLengthAndChars()}));
}
}
public class FirstNameLengthAndChars implements ITest
{
// C# regex. don't know java equivalent
private final static Regex Regex = new Regex("[a-z]{3,}", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public final Iterable getAppliesTo()
{
return new java.util.ArrayList(java.util.Arrays.asList(new TestType[] {TestType.FirstName}));
}
public final int getSecurityLevel()
{
return 2;
}
public final boolean execute(String input)
{
return Regex.IsMatch(input);
}
}Code Snippets
public enum TestType
{
None,
FirstName,
LastName
}
public interface ITest
{
Iterable<TestType> getAppliesTo();
int getSecurityLevel();
boolean execute(String name);
}
public interface ITestProvider
{
Iterable<ITest> getAllTests();
}
public interface INameValidator
{
boolean isValidFirstName(String name, int level);
boolean isValidLastName(String name, int level);
}
public class NameValidator implements INameValidator
{
private Iterable<ITest> _tests;
public NameValidator(ITestProvider testProvider)
{
_tests = testProvider.GetAllTests().ToList();
}
public final boolean isValidFirstName(String name, int level)
{
return checkName(TestType.FirstName, name, level);
}
public final boolean isValidLastName(String name, int level)
{
return checkName(TestType.LastName, name, level);
}
private boolean checkName(TestType type, String input, int level)
{
// in C# I use all the tests of the correct type and security level and execute them on the input. If all pass, then we return true, it any fail, then return a false. Don't know enough java to quickly convert.
}
}
public class SimpleTestProvider implements ITestProvider
{
public final Iterable<ITest> getAllTests()
{
return new java.util.ArrayList<ITest>(java.util.Arrays.asList(new ITest[] {new FirstNameLengthAndChars()}));
}
}
public class FirstNameLengthAndChars implements ITest
{
// C# regex. don't know java equivalent
private final static Regex Regex = new Regex("[a-z]{3,}", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public final Iterable<TestType> getAppliesTo()
{
return new java.util.ArrayList<TestType>(java.util.Arrays.asList(new TestType[] {TestType.FirstName}));
}
public final int getSecurityLevel()
{
return 2;
}
public final boolean execute(String input)
{
return Regex.IsMatch(input);
}
}Context
StackExchange Code Review Q#86942, answer score: 5
Revisions (0)
No revisions yet.