void method refactoring with multiple checks - java

I have this method:
public void validate(param1, pararm2, param3 ...) {
if(check1)
add error
return
if check2
add error
return
getDbObject
check3
exception
return
There is another use case where along with the above checks, if check1 and check2 are passed then after check3 the db object should be returned.
What should be the best practice for implementing this?
Should I write a new method with the same checks and return the db object after check3, or add more parameters and simplify the existing method?
I read the best practice is to have a maximum of 5 parameters, so if we add more parameters eventually the first method call will have 8-9 parameters
and if we reduce the number of parameters then it will require more checks (if-statements) on every call which is also against OOPs basic principles.
So is there an alternate solution?

I would rewrite to use Exceptions, intentionally returning null isn't that helpful to the caller, perhaps like this:
public DbObjectType validate(param1, param2, ...) throws Check1FailedException, Check2FailedException, Check3FailedException {
check1();
check2();
check3();
return getDbObject();
}
private check1() throws Check1FailedException() {
//DoCheck and throw Exception if failed
}
private check2() throws Check2FailedException() {
//DoCheck and throw Exception if failed
}
private check3() throws Check3FailedException() {
//DoCheck and throw Exception if failed
}

I would simply rewrite the method with same amount of parameters and return value of DbObject's type.
Don't really understand what are those checks doing(they check if object's atributes are in range of parameters?..), but i would code something like this:
public DbObjectType validate(param1, param2, ...) {
// if one of the checks fail, validation failed
if (check1 || check2 || ...checkN) {
add error;
return null;
}
else {
DbObject obj = getDbObject();
if (lastCheck) {
exception
return null;
}
return obj;
}
}
You don't have to have every if on separate line, if the actions performed after if are the same for every if. Chaining them together makes the code more readable.
As the return value is DbObject, returning null will not break the program because object types can be null.

You could apply the Strategy Pattern.
Define a ValidationStrategy interface that expose the method public abstract void validate()
Define a class ConcreteValidationA that implements the method validate() with the behaviour of your validate(param1, pararm2, param3 ...)
Define a class ConcreteValidationB that implements the method validate() with the behaviour of the alternative method
In the Context class (i.e. the class where your method stays) add a reference to a ValidationStrategy and modify validate(param1, pararm2, param3 ...) to choose a validation strategy and calling the relative validate() method by forwarding.
Context example
class Context {
/*... your methods and members */
public Context(){
//...
strategy=new ConcreteStrategyA(); //defalut strategy
private ValidationStrategy strategy;
public void validate(int param1, int param2,int param3){
if(param1<param2 && param1<param3)
strategy=new ConcreteStrategyA();
else
strategy=new ConcreteStrategyB();
strategy.validate();
}
}

Related

Is there some sort of generic bound in Java?

I am defining a type Option<T> in Java that should behave as much as possible as Rust's equivalent.
It has a method, Option::flatten, that is only implemented if the inner T is some other Option<T>. I am thinking of something like this:
public class Option<T> {
/* fields, constructors, other methods */
#Bound(T=Option<U>)
public <U> Option<U> flatten() {
if (isNone()) return None();
else return this.unwrap();
}
}
But the syntax is of course completely fictional. Is there some way to make this work in Java? I know static methods are an option, but they can't be called like a normal method which is the only goal of this type.
This is not supposed to be a standalone thing, but rather a part of a larger Java implementation of Rust iterators I'm currently working on.
The problem with trying to come up with a non-static method such as flatten is that in Java one cannot conditionally add more methods to a class based on whether the type parameter of the class fulfills a certain constraint.
You can, however, make it a static method and constrain its arguments to whatever you need.
class Option<T> {
// ...
public static <U> Option<U> flatten(Option<Option<U>> option) {
if (option.isNone()) return None();
return option.unwrap();
}
}
Which would work for valid implementations of None, isNone and unwrap.
A more complete example follows.
public static class Option<T> {
private final T value;
private Option(T x) {
this.value = x;
}
public static <T> Option<T> of(T x) {
java.util.Objects.requireNonNull(x);
return new Option<>(x);
}
public static <T> Option<T> None() {
return new Option<>(null);
}
public T unwrap() {
java.util.Objects.requireNonNull(this.value);
return this.value;
}
public boolean isNone() {
return this.value == null;
}
public static <U> Option<U> flatten(Option<Option<U>> option) {
if (option.isNone()) return Option.None();
return option.unwrap();
}
#Override
public String toString() {
if (this.isNone()) {
return "None";
}
return "Some(" + this.value.toString() + ")";
}
}
Usage:
var myOption = Option.of(Option.of(5));
System.out.println("Option: " + myOption);
System.out.println("Flattened: " + Option.flatten(myOption));
Output:
Option: Some(Some(5))
Flattened: Some(5)
I think the way you want to handle this is not to actually have a flatten() method, but have different handling in your constructor. Upon being created, the constructor should check the type it was handed. If that type is Option, it should try and unwrap that option, and set its internal value to the same as the option it was handed.
Otherwise, there isn't really a way for an object to 'flatten' itself, because it would have to change the type it was bounded over in the base case. You could return a new object from a static method, but are otherwise stuck.
I want to point out some of the potential headaches and issues regarding this re-implementation of Optional<T>.
Here's how I would initially go about it:
public class Option<T> {
/* fields, constructors, other methods */
public <U> Option<U> flatten() {
if (isNone()) return None();
T unwrapped = this.unwrap();
if (unwrapped instanceof Option) {
return (Option<U>) unwrapped; //No type safety!
} else {
return (Option<U>) this;
}
}
}
However, this code is EVIL. Note the signature of <U> Option<U> flatten() means that the U is going to be type-inferenced into whatever it needs to be, not whatever a potential nested type is. So now, this is allowed:
Option<Option<Integer>> opt = /* some opt */;
Option<String> bad = opt.flatten();
Option<Option<?>> worse = opt.<Option<?>>flatten();
You will face a CCE upon using this for the other operations, but it allows a type of failure which I would say is dangerous at best. Note that any Optional<Optional<T>> can have #flatMap unwrap for you: someOpt.flatMap(Function.identity());, however this again begs the question of what caused you to arrive at a wrapped optional to begin with.
Another answer (by #NathanielFord) notes the constructor as an option, which seems viable as well, but will still face the runtime check upon construction (with it simply being moved to the constructor):
public class Option<T> {
/* fields, constructors, other methods */
public Option<T>(T someValue) { ... }
public Option<T>(Option<T> wrapped) {
this(wrapped.isNone() ? EMPTY_OBJECT : wrapped.unwrap());
}
public Option<T> flatten() {
return this; //we're always flattened!
}
}
Note as well, the re-creation of Optional<T> by
#E_net4thecommentflagger has the potential for a nasty future bug: Optional.ofNullable(null).isNone() would return true! This may not be what you want for some potential use-cases, and should #equals be implemented in a similar manner, you'd end up with Optional.ofNullable(null).equals(Optional.None()), which seems very counter-intuitive.
All of this to say, that while Rust may require you to deal with these nested optionals, you are writing code for Java, and many of the potential restrictions you faced before have changed.

possible to check cross fields constraint in the middle of method

We have a service class in Java 8 SpringBoot application that needs to check if a field of object A matches object B passed in as a method parameter. It would have worked beautifully using ConstraintValidator if all method signatures took Object A & Object B as parameters.
Method in service class:
#Override
#MyCheck
public String serviceDoLogic(Object B, Object A) {
......
}
Validator class:
#SupportedValidationTarget(ValidationTarget.PARAMETERS)
public class MyCheckValidator implements ConstraintValidator<MyCheck, Object[]> {
#Override
public boolean isValid(
Object[] value,
ConstraintValidatorContext context) {
if( value.length <2 ) {
return true;
}
if ( ! value[0].equals(value[1].myField()) {
return false;
}
return true;
}
}
Unfortunately, for some methods in the service class, it can only take a String identifier for Object A (as it is the only thing known at the time), and within the service, it needs to call DAO to get Object A. Thus the constraint cannot be triggered for them.
Any solution, other than having the check logic embedded in every method that needs it, to get it done in an elegant way? Hope I explain it well
Many thanks in advance

How to Avoid Constructor calling During Object Creation?

I want to avoid the constructor calling during object creation in java (either default constructor or user defined constructor) . Is it possible to avoid constructor calling during object creation???
Thanks in advance......
Simply extract the intialization logic that you want to avoid into another method called init. You can not avoid calling exactly one constructor.
No matter what pattern or strategy you use, at some point your will need to call a constructor if you want to create an object.
Actually, its possible under some circumstances by using classes from the JVM implementation (which do not belong to the JRE API and are implemenation specific).
One example here http://www.javaspecialists.eu/archive/Issue175.html
It should also be possible using sun.misc.Unsafe.allocateInstance() (Java7)
Also, the constructor is apparently bypassed when using the clone()-method to create a copy of an object (and the class doesn't override clone to implement it different from the Object.clone() method).
All of these possibilities come with strings attached and should be used carefully, if at all.
You can mock the constructors of a class. They will still be called, but not executed. For example, the following JUnit+JMockit test does that:
static class CodeUnderTest
{
private final SomeDependency someDep = new SomeDependency(123, "abc");
int doSomething(String s)
{
someDep.doSomethingElse(s);
return someDep.getValue();
}
}
static final class SomeDependency
{
SomeDependency(int i, String s) { throw new RuntimeException("won't run"); }
int getValue() { return -1; }
}
#Test
public void mockEntireClassIncludingItsConstructors()
{
new NonStrictExpectations() {
#Mocked SomeDependency mockDep;
{ mockDep.getValue(); result = 123; }
};
int result = new CodeUnderTest().doSomething("testing");
assertEquals(123, result);
}

how to send custom return messages from functions?

I am having a function that does a DB operation and sends a boolean value for success/failure. suppose it fails, i want to send the failure reason as a return value.
for now, i have defined return value as a string. if it is failure i return "failure: reason" and if it is success, i return "success". but this is not good practice.
On Failure you can throw a checked custom Exception.
public class DBException extends Exception{
public DBException(String exp){super(exp)}
...
}
This is what you use throw exception for. You can very well change your method signature and set the return value to be boolean. Then create a custom Exception class:
public class MyCustomException extends RuntimeException {
// define error code, error message etc.
// create getters & setters
}
After that, whenever you find a reason for failure, do this:
if (some_failure_reason == true) {
throw new MyCustomException(error_code) ;
}
In your controller (or service), catch the exception:
try {
// call the method in question
} catch (MyCustomException mce) {
if(mce.getErrorCode() == some_error_code) {
// do stuff
}
}
You can make the error messages static final Strings so other classes will be able to access them, example:
public static final String DB_FAILURE_REASON1 = "failure: reason1";
Otherwise create a subclass of Exception, and either store specific reasons as the Exception's msg or create further subclasses of your subclass for specific failure reasons:
public class MyDBFailure extends Exception
And add a throws to your method:
public String myDBMethood() throws MyDBFailure
Ideally you should throw Exceptions (you can customize them if you none of the existing ones suit your needs). Your approach is more C like.
If you really can't use Exceptions (which will provide who ever is using your code to decide what to do), you might resort to an Enumeration, listing some possible outcomes, if not all. Note though that such an approach can be quite cumbersome.
Write your own Result class with a string field containing return value and getter (or overload toString() method):
public class Result {
String message;
public Result(String message) {
this.message = message;
}
public String toString() {
return message;
}
}
Another option is to use enums.
You can throw an exception on failure and call the function in a try-catch statement.
You can create a global variable of type string and set that on failure and return false, and then you can get the error message out of the global variable.
You can return an array in which the first element is the return value and the second is the error message.
My personal favorite is the second option.
Use CustomException with return error codes codes. A better way of identifying error reasons is to define it inside enums so that whenever error condition occurs you can construct exception with Enums.
Also you can extend this paradigm to handle multiple error codes in single exception if required.
whenever error condition is detected create instance of CustomException and then throw it.
//Error Condition detected
if(input<10)
throw new CustomException("Invalid Input it should be greater
than 10 ", ErrorCode.ErrorCode1);
You can use Multiple error conditions like below.
if(intput>100 && input < 1000)//Just a sample case.
throw new CustomException("Invalid Input it should be not be greater
than 100 and less than 1000 ", EnumSet.of(ErrorCode.ErrorCode1,
ErrorCode.ErrorCode2));
Source for CustomException:
public class CustomException extends Exception {
private EnumSet<ErrorCode> errorCodes;// You can also maitain multiple
// error codes for same
// exception
public CustomException(String message, ErrorCode errorcode) {
super(message);
this.errorCodes = EnumSet.of(errorcode);
}
public CustomException(String message, EnumSet<ErrorCode> errorcode) {
super(message);
this.errorCodes = EnumSet.copyOf(errorcode);
}
}
public enum ErrorCode {
ErrorCode1(1, "First Error"), ErrorCode2(2, "Second Error");
int code;
String reason;
private ErrorCode(int code, String reason) {
this.code = code;
this.reason = reason;
}
}

Stubbing a method that takes Class<T> as parameter with Mockito

There is a generic method that takes a class as parameter and I have problems stubbing it with Mockito. The method looks like this:
public <U extends Enum<U> & Error, T extends ServiceResponse<U>> T validate(
Object target, Validator validator, Class<T> responseClass,
Class<U> errorEnum);
It's god awful, at least to me... I could imagine living without it, but the rest of the code base happily uses it...
I was going to, in my unit test, stub this method to return a new empty object. But how do I do this with mockito? I tried:
when(serviceValidatorStub.validate(
any(),
isA(UserCommentRequestValidator.class),
UserCommentResponse.class,
UserCommentError.class)
).thenReturn(new UserCommentResponse());
but since I am mixing and matching matchers and raw values, I get "org.mockito.exceptions.misusing.InvalidUseOfMatchersException: Invalid use of argument matchers!"
The problem is, you cannot mix argument matchers and real arguments in a mocked call. So, rather do this:
when(serviceValidatorStub.validate(
any(),
isA(UserCommentRequestValidator.class),
eq(UserCommentResponse.class),
eq(UserCommentError.class))
).thenReturn(new UserCommentResponse());
Notice the use of the eq() argument matcher for matching equality.
see: https://static.javadoc.io/org.mockito/mockito-core/1.10.19/org/mockito/Matchers.html#eq(T)
Also, you could use the same() argument matcher for Class<?> types - this matches same identity, like the == Java operator.
Just in order to complete on the same thread, if someone want to stubb a method that takes a Class as argument, but don't care of the type, or need many type to be stubbed the same way, here is another solution:
private class AnyClassMatcher extends ArgumentMatcher<Class<?>> {
#Override
public boolean matches(final Object argument) {
// We always return true, because we want to acknowledge all class types
return true;
}
}
private Class<?> anyClass() {
return Mockito.argThat(new AnyClassMatcher());
}
and then call
Mockito.when(mock.doIt(this.anyClass())).thenCallRealMethod();
Nice one #Ash. I used your generic class matcher to prepare below.
This can be used if we want to prepare mock of a specific Type.(not instance)
private Class<StreamSource> streamSourceClass() {
return Mockito.argThat(new ArgumentMatcher<Class<StreamSource>>() {
#Override
public boolean matches(Object argument) {
// TODO Auto-generated method stub
return false;
}
});
}
Usage:
Mockito.when(restTemplate.getForObject(Mockito.anyString(),
**streamSourceClass(),**
Mockito.anyObject));

Categories

Resources