This chapter begins a new section about methods. We start off talking about something that affects all of our methods, that is of checking the validity of the method parameters. This is a concern that affects all of our development. Invalid parameters, if not handled correctly can lead to various issues. From innocuous as delayed errors to something as serious as invalid data being persisted and corrupting all the valid data being processed.
So how can we mitigate this? It's usually fairly easy. As calls are made into our methods we check to see what if the parameters fit within our acceptable constraints. This may be something like running parameters through
Objects.requireNonNull or checking if an index is non-negative. Along with writing these checks in our code we also should update our Javadoc and other documentation to explain that these checks are happening and what parameters values are valid and which are not.
So what methods should we put these checks on. There are a few things to consider. Private and package-private methods you hold complete control over and thus should do the necessary checks before calling, in these methods we should not need to do the validity checks. Effective Java proposes using assertions in these cases instead of validity checks but I have never found that too useful. There are also cases where checking the validity could be expensive and/or will be performed in the regular business logic of the method.
All of this is solid advice and should be applied in places where this makes sense. It seems to me that much of Effective Java's guidance is largely applicable to library designers. While this is very useful, most developers don't find themselves writing reusable libraries with a wide distribution everyday.
The downside of these validity checks can be that the code gets much less clear. Validity checks, while often simple code, can be fairly lengthy. This is where things like the various
@NonNull annotations can come in as well as JSR-308. The beauty of these tools is that it allows you to add validation while not polluting your code.
Much of this section will be focussed on writing defensive code. Validating our parameters is a great step in that direction. As we do this we can bring errors earlier in the process, protect our business logic, and overall build a better system.
Top comments (2)
I like to use lombok to generate these checks. It is very useful. How do you suggest testing these checks? I have seen arguments against testing these things but I think for libraries it is very important to test the behavior of these checks.
Yeah Lombok is a great way to generate the nonnull checks. I actually don't find myself using it much but I like the idea. I'm not sure I know of other validity checks it can do for you other than nonnull but that check is definitely a common one.
As for testing I would say go ahead and test it. The test shows that it's important and elevates the verification logic to the same importance as other business logic. These validity checks are often very simple so messing up the implementation is not as likely but I do think it can protect against regressions where maybe a future developer imports one of the other Nonnull annotations that behaves different than we were expecting.