Should i validate parameters in constructor?

2019-03-24 01:45发布

问题:

I am creating a web application following the MVC pattern.

In effective Java the author mentions to validate the parameters in the constructor of the class when creating a new object.

However i am not creating some API that will be used by third parties. My classes just accept parameters from input fields of a form which are validated before beeing submited to the server.

So in this case should i create my classes the way the author mentions in Effective java or it is useless?

回答1:

It is not as clear cut as reading a book and implementing what it says. You need to think and apply the knowledge to your specific situation.

It really depends on how you are initializing the variables in your class and using them right after object construction:

Some pointers:

  • If the variables are going to be used by some methods in the class or the object is going to be re-used right after constructions (which in most cases will), you should validate that the values that are required are not empty or null, to avoid getting nasty exceptions.

  • The second time to validate input parameters is when you expect the correct values to be set to specific internal variables. If you require that a parameter be constrained to a specific value range, then it is important that you validate.

Example:

Say we have a salary cap in the object:

int salary = 0;
int salaryCap = 1000;

During creation, you can validate the passed in salary amount:

public Employee(int salary) {
 if(salary >= this.salaryCap)
  this.salary = salary;
}
  • The class relationship also determines whether you want to validate the values or not. If the parameters will be passed up the inheritance chain for-example, I would take the time to validate them, especially if they will affect the state of other objects in the inheritance chain.

Example:

Whenever I have to call the super constructor, I am tempted to validated the input:

public Employee(int salary) {
 super(salary); //validate salary against known constraints
}
  • Where are the variables coming from? If you do not trust the source (like sql parameters etc), then you should validate them and possibly sanitize the input before executing further code. This prevents security attacks.

  • I am always weary to do validation and parameter checking in the constructor. I prefer to have getters and setters to validate input. That way, if something happens at object creation, at least I have the guarantee of semi-working object than a complete inconsistent object whose state cannot be readily determined. Of course this depends on your context, if you constraints are strict, you can stop the object creation and prompt the client (user, calling object etc) for valid input parameters.

The advantage that using getters/setters affords me is that the object is really constructed step by step by calling on the external interface the object gives, other than constraining the validation during creation, which when an exception occurs, renders the object unusable/unstable.

So instead of this:

public Employee(int salary) {
 if(salary >= this.salaryCap)
  this.salary = salary;
}

I prefer this:

public class Employee {
 public void setSalary(int salary) {
  if(salary >= this.salaryCap)
      this.salary = salary;
 }
}

The latter gives me the ability to cleanly exit with a valid exception to the caller, which will not affect object creation (I don't like throwing exceptions in the constructor).

In a nutshell, do your variable have constraints? If yes, validate those constraints before setting them to internal data properties.



回答2:

I would suggest validating the data in your domain and returning a (custom) exception when fields aren't filled in correctly. This way you'll be able to implement a different UI without having to do the entire validating process again, it's best to separate this as much as possible.



回答3:

At the first sight it is not necessary to validate the parameters since the validation was done before. But you should take into consideration that your class will be used in other circumstances, you cannot be sure that every time the input of your constructor is valid.



回答4:

It sounds like you are validating fields which have already been previously validated. In that case, it is just a waste of time (both writing it and in run-time). If your form (client-side javascript) have not validated the fields then it would make sense. Otherwise you can skip it.