Parameter Validation Best Practices

后端 未结 5 2757
一生所求
一生所求 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:34

    Usually parameter checks are very cheap, even if called thousands of times. For example test if a value is null, a string or Collection is emtpy a number is in a given range.

    But beware that checks may be expensive, so think twice: Evaluating a regex on a large string, checking if a file exists, checking that all elements in a collection meets a certain criteria.

    I would also only recommend checking only in public or protected methods. Note that all public methods with unchecked parameters are potential risks!

    EDIT/another thought: If a method does not use the parameters but is just passing it to another method then you may also omit the checking. Only the method which is actually using these parameters for itself should do the checking.

    This is because if the requirements of the parameters change you need to change the validations in multiple places, risking inconsistency.

    0 讨论(0)
  • 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.

    0 讨论(0)
  • 2021-02-20 09:48

    You may get mixed opinions, but in my view..it is best to do validation in both the layers. In the front and the business logic (dlls as you call it)

    0 讨论(0)
  • 2021-02-20 09:49

    As an author of a library, you cannot assume that the consumers have done proper validation of inputs, so you as a library author would want to ensure the arguments are valid before going to work with them.

    As a consumer of a library, if you know what inputs are going to cause the library to fail, why would you pass those inputs to that library? Validate against them so that you can perhaps prompt your user for better inputs or otherwise cancel whatever process you are in.

    The fact that you might be the author of both the library and the consumer is not particularly relevant, in my opinion, as this relationship may very well change.

    0 讨论(0)
  • 2021-02-20 09:53

    Very interesting topic :)

    in general you should implement a "validation facade" lower than the user interface and at the lowest possible level commonly accessed by user interface and external services.

    you can check for null and validate input also in the UI just to avoid a useless round-trip to the server, client side validation is a good practice, still you cannot trust the caller to only pass you valid values.

    0 讨论(0)
提交回复
热议问题