Parameter Validation Best Practices

后端 未结 5 2758
一生所求
一生所求 2021-02-20 09:05

Imagine you have an application which is some kind of front-end to all your business logic. This front-end has a lot of DLLs upon which it depends, and the methods in t

5条回答
  •  长情又很酷
    2021-02-20 09:46

    Unless the validation of the parameter is going to be expensive, I would go with #1. Fail-fast behavior lets you catch bugs in a fraction of the time, which will save you a lot more time than it takes to write a few guard statements at the beginning of each method.

    One technology you may be interested to help with this is .NET's Code Contracts, which allow you to create quasi-compile-time checks to ensure that nobody calls a method without ensuring that the inputs match the expected patterns.

    I personally tried using Code Contracts, and found that there was a little too much overhead for my needs. However, I appreciated the syntax, so I made a class to help with these guard statements, but which only works at run-time. It works like this:

    public void ChangeUserName(int userId, string name)
    {
        Require.ThatArgument(userId > 0);
        Require.ThatArgument(!string.IsNullOrWhitespace(name,
            () => "Usernames must be non-empty strings");
        var user = GetUser(userId);
        Require.That(user != null, 
            () => new UserDoesNotExistException("No user exists with ID " + userId));
        user.Name = name;
        ...
    }
    

    And one final technology that helps a lot for these checks is Resharper's Annotations. For example, consider the following method:

    [CanBeNull]
    public User GetUser(int userId)
    {
        var user =  ... // Get the user from the db
        return user;
    }
    

    By telling Resharper that the method might return a null value, it will know to warn you if you haven't done a null check on user before trying to access user.Name. Another annotation is available to tell Resharper that Require.That(user != null) constitutes a null check. You could also re-write your method like this:

    [NotNull]
    public User GetUser(int userId)
    {
        Require.ThatArgument(userId > 0);
        var user =  ... // Get the user from the db
        Require.That(user != null)
        return user;
    }
    

    By marking this method as NotNull, Resharper can automatically tell you that user != null will always resolve to true so you don't have to check for it. There are all kinds of fun stuff you can do to make validation easier.

提交回复
热议问题