Protect function from illegal input value

Image for post
Image for post

Introduction

* you can read about 'def' method in my article at medium

But my teammate write such code:

And code execution output:

Exception in thread "main" java.lang.NullPointerException
at com.github.darrmirr.fp.contract.Main.lambda$main$0(Main.java:14)
at com.github.darrmirr.fp.contract.Main.main(Main.java:17)

Something goes wrong and NullPointerException (NPE) is thrown while main method is executing.

My function and I unexpect that someone pass `null` object as function input value. Hopefully, I have another function that could protect my `cubeVolume` one. Contract is function’s name.

Contract function is function that applied to input value before one is passed to target function. Where target function is function wrapped by Contract one. Target function is not invoked if contract evaluates false.

Teammate and I rewrite last code snippet using Contract function:

And now it works without any exception!

I am going to show step by step how to come up to Contract function at the next article’s part. You can feel free to move to Conclusion part in order to read Contract function implementation.

Move towards to Contract function

Output:

Exception in thread "main" java.lang.NullPointerException
at com.github.darrmirr.fp.contract.Main.lambda$main$0(Main.java:14)
at com.github.darrmirr.fp.contract.Main.main(Main.java:17)

How to deal with this problem? Often NullPointerException is replaced by user-defined exception:

Output:

Exception in thread "main" java.lang.IllegalArgumentException: input argument is null
at com.github.darrmirr.fp.contract.Main.lambda$main$0(Main.java:15)
at com.github.darrmirr.fp.contract.Main.main(Main.java:18)

Pros:
+ NullPointerException is not thrown
+ there is error description at exception message

Cons:
- runtime exception may be thrown
- documentation of function is required in order to warn that function may throw exception
- curly brackets are used at lambda body
- function’s single-responsibility is broken

I think main implementation disadvantage is using exception. How to get rid of exception? Here is my code:

Output:

result : -1

Pros:
+ NullPointerException and IllegalArgumentException is not thrown
+ curly brackets are not used

Cons:
- documentation of function is required in order to warn that function used special code that may be returned
- function’s single-responsibility is broken

Supporting documentation is time expensive. Also developers rarely watch docs before using functions. How to show to developer that function could return special code? Here is another code snippet:

Output:

result : Optional.empty

Pros:
+ NullPointerException and IllegalArgumentException is not thrown
+ curly brackets are not used at lambda body
+ cubeVolume type `Function<Integer, Optional<Integer>>` shows that return value could be optional (IDE prompt information about local variable type)

Cons:
- function’s single-responsibility is broken

Function’s body looks pretty enough. But I find out that there is issue with `cubeVolume` function. What does function return in case input value would be negative?

Output:

result : Optional[-27]

Cube volume could not be negative value. I fix it:

Output:

result : Optional.empty

Pros:
+ NullPointerException and IllegalArgumentException is not thrown
+ curly brackets are not used at lambda body
+ cubeVolume type `Function<Integer, Optional<Integer>>` shows that return value could be optional (IDE prompt information about local variable type)
+ negative input values are filtered

Cons:
- function’s single-responsibility is broken

Optional structure is very useful! But function perform a lot of work and it breaks function’s single-responsibility priciple. I try to move code with Optional out of lambda body. Here is code:

Output:

result : Optional.empty

Pros:
+ NullPointerException and IllegalArgumentException is not thrown
+ curly brackets are not used at lambda body
+ cubeVolume type `Function<Integer, Optional<Integer>>` shows that return value could be optional (IDE prompt information about local variable type)
+ negative input values are filtered
+ function have single responsibility

Cons:
- impossible to reuse protected code
- predicate function is hardcoded to filter method

First of all, I extract hardcoded function from filter method:

Execute code in order to check that’s all works properly:

result : Optional.empty

And second, I extract protected code to method:

Pros:
+ NullPointerException and IllegalArgumentException is not thrown
+ curly brackets are not used at lambda body
+ cubeVolume type `Function<Integer, Optional<Integer>>` shows that return value could be optional (IDE prompt information about local variable type)
+ negative input values are filtered
+ function have single responsibility
+ predicat function is not hardcoded to filter method
+ protected code could be reused

Cons:
- difficult to read code
- a lot of parameters at method `getResult`
- non-functional code

I change method `getResult` return object from Optional<Integer> to Function<Integer, Optional<Integer>> in order to exclude passing x parameter:

Also I change method name due to it became more common that before. It looks like method `obligate` have no common meaning with interface Main. Therefore, this method could be extract to separate class or interface:

I call interface Contract. The Main interface is also changed:

Personally, I believe code become more humanreadable. Lets look at invocation of method `obligate`. It looks like `isPositiveNumber` make sense to Contract word not to obligate one. And therefore, I think method `obligate` have redundant method argument. I rewtite interface Contract in order to remove Predicate argument from `obligate` method signature. Here is my code:

Now interface Contract extends Predicate instead of passing predicate function as method argument to method `obligate`. Lets look how Main interface is changed:

Pros:
+ NullPointerException and IllegalArgumentException is not thrown
+ curly brackets are not used at lambda body
+ cubeVolume type `Function<Integer, Optional<Integer>>` shows that return value could be optional (IDE prompt information about local variable type)
+ negative input values are filtered
+ function have single responsibility
+ predicat function is not hardcoded to filter method
+ protected code could be reused
+ code is more humanreadable than previous code snippet

Cons:
- local variable type is written explicitly

I add special method to Contract interface in order to deal with last cons.

Method `of` create instance of class or interface. Some of standard Java classes or interfaces have method with `of` name. For example, Stream and Optional have method with the same name. And I keep this convention at my Contract interface. Lets look how Main interface is changed:

I think this code looks clear and pretty. And now Contract function protect my `cubeVolume` one. I rewrite previous code snippet a little bit at my favorite way:

Conclusion

Finally, here is my implementation of Contract function:

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store