简体   繁体   English

如何简化验证检查代码?

[英]How can I simplify my validation check code?

I have code for validation: 我有验证代码:

public IDictionary<string, string> ValidateForDeletion(Account ac)
        {
            var account = _accountRepository.GetPkRk(ac.PartitionKey, ac.RowKey);
            if (account == null)
            {
                _errors.Add("", "Account does not exist");
                return _errors;
            }
            if (_productRepository.GetPk("0000" + ac.RowKey).Count() != 0)
            {
                _errors.Add("", "Account contains products");
                return _errors;
            }
            return _errors;
        }

All I see there are many many "return _errors" lines. 我所看到的有很多“ return_errors”行。 Is there any way that I could tidy up the code and keep the functionality? 有什么办法可以整理代码并保留功能? I saw one example using yield but not sure if I could use that for this method. 我看到了一个使用yield的示例,但不确定是否可以将其用于此方法。

public IDictionary<string, string> ValidateForDeletion(Account ac)
{
    var account = _accountRepository.GetPkRk(ac.PartitionKey, ac.RowKey);
    if (account == null)
    {
        _errors.Add("", "Account does not exist");
    }
    else if (_productRepository.GetPk("0000" + ac.RowKey).Count() != 0)
    {
        _errors.Add("", "Account contains products");
    }
    return _errors;
}

This will get rid of your multiple return statements 这将摆脱您的多个return语句

Well you can always pull the extra cruft into its own method: 好吧,您总是可以将多余的杂项放入自己的方法中:

public IDictionary<string, string> ValidateForDeletion(Account ac)
{
  var account = _accountRepository.GetPkRk(ac.PartitionKey, ac.RowKey);
  return BuildErrorsList(account);
}

private IDictionary<string, string> BuildErrorsList(Account account)
{
  if (account == null)
     _errors.Add("", "Account does not exist");
  if (_productRepository.GetPk("0000" + ac.RowKey).Count() != 0)
      _errors.Add("", "Account contains products");
  return _errors;
}

As good guideline is that each method should work on one level of abstraction, otherwise you probably want pull the "lower level" stuff into its own method. 好的指导原则是,每个方法都应在一个抽象级别上工作,否则您可能希望将“较低级别”的内容放入其自己的方法中。

public IEnumerable<ValidationResult> ValidateForDeletion(Account ac)
{
    var account = _accountRepository.GetPkRk(ac.PartitionKey, ac.RowKey);
    if (account == null)
    {
        yield return new ValidationResult("Account does not exist");
    }
    if (_productRepository.GetPk("0000" + ac.RowKey).Count() != 0)
    {
        yield return new ValidationResult("Account contains products");
    }
}
  1. It's not ideal that your method is changing state (the _errors field) whilst also returning the field — this makes it a bit confused. 您的方法既要更改状态( _errors字段)又要返回该字段,这是不理想的,这会使它有些混乱。 Normally you would either have a method that changes the state (change _errors ) or have a function that returns a result. 通常,您要么具有更改状态的方法(change _errors ), 要么具有返回结果的函数。

  2. The ValidateForDeletion method returns after the first failure rather than add all errors to the dictionary. ValidateForDeletion方法在第一次失败后返回,而不是将所有错误添加到字典中。 Are you sure that is correct behaviour? 您确定这是正确的行为吗?

If were refactoring this, I would probably get rid of ValidateForDeletion 's side-effects (changes to fields) and have it return IEnumerable<string> . 如果要对此进行重构,我可能会摆脱ValidateForDeletion的副作用(更改字段),并使它返回IEnumerable<string> I would also make it perform the complete set of validations. 我还将使其执行完整的验证集。 Obviously this will have ramifications on the calling code so you will have to make sure you do not break anything. 显然,这将对调用代码产生影响,因此您必须确保不破坏任何内容。

public IEnumerable<string> ValidateForDeletion(Account ac)
{
    var account = _accountRepository.GetPkRk(ac.PartitionKey, ac.RowKey);
    if (account == null)
    {
        yield return "Account does not exist";
    }

    if (_productRepository.GetPk("0000" + ac.RowKey).Count() != 0)
    {
        yield return "Account contains products";
    }

    return;
}

You could do something similar to yield. 您可以执行类似于yield的操作。 If you think about passing by reference, you can have validation code within your objects or repositories. 如果您考虑通过引用传递,则可以在对象或存储库中包含验证代码。

For example, I am validating to see if an account can be deleted, I can use an IValidateDelete interface on Account that has this method: 例如,我正在验证是否可以删除帐户,可以在具有以下方法的Account上使用IValidateDelete接口:

bool account.IsValidForDeletion(ref ValidationErrors validationErrors);

Then I can call it and pass in my empty validation errors method. 然后,我可以调用它并传递我的空验证错误方法。 If the result is true, you're good to go. 如果结果为真,那么您就很好了。 If it's false, it will have appended the validation error to the internal list in the ValidationErrors object. 如果为假,它将验证错误附加到ValidationErrors对象的内部列表中。

public bool IsValidForDeletion(ref Validationerrors validationErrors)
{
//
if (something is valid)
{
  return true;
}

validationErrors.AddError("Something is wrong, this cannot be deleted");

return false;
}

Now you can run through all your methods like this: 现在,您可以运行所有这样的方法:

public ValidationErrors ValidateABunchOfStuff()
{
   ValidationErrors errors = new ValidationErrors();

   account.IsValidForDeletion(errors);
   product.IsValidForDeletion(errors);
   cake.IsValidForDeletion(errors);

   return errors;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM