在API中对参数验证抛出异常被认为是一种很好的做法



在函数参数验证时抛出异常是否被认为是一种好的做法,就像我对TryPassNameValidation函数所做的那样,如果:

  1. 代码没有直接面向UI。它是API的一部分
  2. 至关重要的是,执行不能以错误的论点继续下去
  3. 我想要良好的可读性和流畅性

我也考虑过返回一个验证对象,就像这个答案中描述的那样,但这种编程风格让我想起了GoLang函数处理错误的方式。我认为发明例外是为了防止我们不得不这么做。

    public void AddChildStructureLevel(Structure childStructureLevel)
    {
        try
        {
            TryPassNameValidation(childStructureLevel.Name); // throws if something is wrong
            Children.Add(childStructureLevel);
        }
        catch (ArgumentException ae)
        {
            throw new ArgumentException($"Provided structure name {childStructureLevel.Name} is invalid.", ae);
        }
        Trace.WriteLine($"Added new child structure level to parent structure children.");
    }
    private void TryPassNameValidation(string structureName)
    {
        TryPassingStructureNameMinMaxLength(structureName); 
        TryPassingStructureNameUnique(structureName);
    }
    private void TryPassingStructureNameMinMaxLength(string structureName)
    {
        bool nameIsTooLong  = structureName.Length >= maxLengthStructureName;
        bool nameIsTooShort = structureName.Length <= minLengthStructureName;
        if (nameIsTooLong) throw new ArgumentException($"Structure name is too long. Max {maxLengthStructureName} characters.");
        if (nameIsTooShort) throw new ArgumentException($"Structure name is too short. Min {minLengthStructureName} characters.");
    }
    private void TryPassingStructureNameUnique(string childName)
    {
        foreach (Structure child in Children) //TODO: recurse over children.children
            if (child.Name == childName) throw new ArgumentException($"Structure level name {childName} already exists.");
    }

我发现这段代码很难理解,这与您的目标背道而驰。验证是通过嵌套调用和不明显的控制流(异常)来完成的。我发现每种方法开头的常见if ... throw;序列更容易理解。部分原因是几乎所有的验证代码都是这样的。

应该使用Any来编写TryPassingStructureNameUnique。之后,它适合一行,可以用于上述if ... throw;验证模式。

bool nameIsTooLong的内容非常冗长。这些条件微不足道。他们应该只使用if ... throw;模式。

此外,我认为这个设计是一个有效的选择。这不是一个容易的选择。如果我能帮忙的话,我不会那样做的

如果有效性是这样一个核心概念,那么考虑将每个Structure包装在ValidatedStructure包装类中。施工时进行验证。这样,您就可以从视觉检查中知道给定的Structure是否已经验证。

这取决于API的含义。

如果你指的是一个业务逻辑,你可以预测一个无效的输入,比如空用户名,那么我不会抛出任何异常。

然而,如果你指的是一个框架(团队共享的库),因为API无法使用无效参数,所以你想向用户指示其无效使用,那么我会抛出一个异常。

相关内容

最新更新