2
\$\begingroup\$

I have a set of validation functions which return a response code along with an error message if the validation fails. Requests can be of three types, and each of them contains a different type of values to be validated. My question is what are the options to avoid the repetitive code, particularly in the message assignment?

const Validation = (function() {

  const isParameterOneLengthValid = (data) => {
    return data.length >= 5 && data.length <= 10;
  };

  const isParameterOneValid = (data) => {
    return !(/[^A-Za-z\-0-9\,\.]/.test(data));
  };

  const isParameterTwoLengthValid = (data) => {
    return data.length >= 1 && data.length <= 5;
  };

  const isParameterTwoValid = (data) => {
    return !(/[^0-9]/.test(data));
  };

  function Validation() {}

  Validation.prototype.validateFirstTypeRequest= (data) => {
      if (!isParameterOneLengthValid(data.parameterOne)) {
        data.code = 0;
        data.message = 'Length of the parameter one is invalid';
        return data;
      } else if (!isParameterOneValid(data.parameterOne)) {
        data.resStatus = 1;
        data.resMessage = 'Parameter one is invalid';
        return data;
      }

      if (!isParameterTwoLengthValid(data.parameterTwo)) {
        data.code = 3;
        data.message = 'Length of the parameter two is invalid';
        return data;
      } else if (!isParameterTwoValid(data.parameterTwo)) {
        data.resStatus = 4;
        data.resMessage = 'Parameter two is invalid';
        return data;
      }

      return data;
  };

  Validation.prototype.validateSecondTypeRequest= (data) => {
      if (!isParameterOneLengthValid(data.parameterOne)) {
        data.code = 0;
        data.message = 'Length of the parameter one is invalid';
        return data;
      } else if (!isParameterOneValid(data.parameterOne)) {
        data.resStatus = 1;
        data.resMessage = 'Parameter one is invalid';
        return data;
      }

      return data;
  };

  Validation.prototype.validateThirdTypeRequest= (data) => {
      if (!isParameterTwoLengthValid(data.parameterTwo)) {
        data.code = 3;
        data.message = 'Length of the parameter two is invalid';
        return data;
      } else if (!isParameterTwoValid(data.parameterTwo)) {
        data.resStatus = 4;
        data.resMessage = 'Parameter two is invalid';
        return data;
      }

      return data;
  };

  module.exports = new Validation();

  return Validation;
})();
\$\endgroup\$
4
  • 1
    \$\begingroup\$ Make it data driven. Make one body of code which you pass an array or object of parameters to. The code examines what you pass in runs the code based on that, returning results to you. For the input parameters, you include the data to be tested (or even the DOM elements to be queried and tested), error messages you want returned, which tests to run, bounds/limits to be tested, etc... You can make it so that applying this code to another set of fields is nothing more than defining a new data object and making one function call, not writing new code. \$\endgroup\$
    – jfriend00
    Commented Jun 3, 2016 at 21:35
  • \$\begingroup\$ This code looks weirdly unrealistic — did you sanitize it before posting? Can you post real (or at least realistic) code? Also, the title of the question is much too generic — see How to Ask. \$\endgroup\$ Commented Jun 3, 2016 at 21:38
  • \$\begingroup\$ @200_success yes I have sanitized the code, this is the structure I have in real code as well, point taken about the naming will edit it \$\endgroup\$ Commented Jun 3, 2016 at 21:41
  • \$\begingroup\$ I have edited the title of the question to conform to site policy — see How to Ask and the rationale. \$\endgroup\$ Commented Jun 5, 2016 at 1:07

2 Answers 2

1
\$\begingroup\$

Mutating State

I really don't like that your validation functions modify the data object that they are given. It seems like an unnecessary mutation that's mixing data with error codes. Do you have any particular reason for returning the data object? If it's passed into the function, then wouldn't the user already has a pointer to it? My reasoning is that you could instead return an failed validation response object instead of mutating the data object. Some problems with mutating the data object are immediately clear; now you can't have a property in data called code, message, resStatus, or resMessage.

Singe Exit Point

I'm not sure if this came from sanitizing the code, but the returns in the validateResponse functions are a bit redundant. One programming platitude is to strive to give functions one exit point. Currently, your validateSecondTypeRequest function has three exit points:

Validation.prototype.validateSecondTypeRequest= (data) => {
  if (!isParameterOneLengthValid(data.parameterOne)) {
    data.code = 0;
    data.message = 'Length of the parameter one is invalid';
    return data; // these returns could be merged
  } else if (!isParameterOneValid(data.parameterOne)) {
    data.resStatus = 1;
    data.resMessage = 'Parameter one is invalid';
    return data; // these returns could be merged
  }

  return data; // these returns could be merged
};

The returns in the if else block are unnecessary and could be easily eliminated to:

Validation.prototype.validateSecondTypeRequest= (data) => {
  if (!isParameterOneLengthValid(data.parameterOne)) {
    data.code = 0;
    data.message = 'Length of the parameter one is invalid';
  } else if (!isParameterOneValid(data.parameterOne)) {
    data.resStatus = 1;
    data.resMessage = 'Parameter one is invalid';
  }

  return data;
};

Eliminating Duplicate Code

Write a function for each parameter:

function validateParameterOne(value) {
  let result;

  if (value.length >= 5 && value.length <= 10) {
    result = {
      code: 0,
      message: 'Length of the parameter one is invalid'
    };
  };
  else if (!(/[^A-Za-z\-0-9\,\.]/.test(data))) {
    result = {
      resStatus: 1,
      resMessage: 'Parameter one is invalid'
    };
  }

  return result;
}

Not only do you get rid of the duplication, but now you have fewer functions; all your code for validating parameterOne is in contained in one spot. Also, now you can write your validateTypeRequest functions like so:

Validation.prototype.validateFirstTypeRequest= (data) => {
  let result;

  if (!result) {
    result = validateParameterOne(data.parameterOne);
  }

  if (!result) {
    result = validateParameterTwo(data.parameterTwo);
  }

  // If you HAVE to return and mutate data
  //if (result) {
  //  return Object.assign(data, result);
  //}

  return result;
}
\$\endgroup\$
0
\$\begingroup\$

You can use a validation code where the system takes in a parameter sorting whether it's validating form 1 or form 2. Then just plug it into the response. For what you're doing you need a real abstract, you can learn JSON more so if you need to and use it from another page. Then you can take this code out of each page. You'll just need to create a JSON API for your code. You can flatten it to one instance of Validation along that line. You could correct the resStatus as a single err number though, as well. It's a form error. If you want to call it, your parameter list will need to reflect it somehow that you intend to use that error number when you need it called upon; when validation fails.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.