2

I am writing a validation function, which checks a multitude of conditions and returns Success if none of the checks fail. I want to know, what would be the preferred way among two choices and why ?

private ResponseObj validationFunc1(ObjA objA, ObjB objB, ObjC objC){
ResponseObj responseObj = new ResponseObj();
if(condA){
   responseObj.setStatus("FAILURE");
   responseObj.setMessage("condA message");
   return responseObj;
} else if(condB){
   responseObj.setStatus("FAILURE");
   responseObj.setMessage("condB message");
   return responseObj;
} ....
...
}else if(condZ){
   responseObj.setStatus("FAILURE");
   responseObj.setMessage("condZ message");
   return responseObj;
}
responseObj.setStatus("SUCCESS");
responseObj.setMessage("Valid");
return responseObj;
}


private ResponseObj validationFunc2(ObjA objA, ObjB objB, ObjC objC){
if(condA){
   return new ResponseObj("FAILURE","condA message");
} else if(condB){
   return new ResponseObj("FAILURE","condB message");
} ....
...
}else if(condZ){
   return new ResponseObj("FAILURE","condZ message");
}
return new ResponseObj("SUCCESS","Valid");
}

Which of the above 2 functions would be preferred in production code ? If so, does one method has a performance gain over another ? Or, Am I just mistaken and the compiled code for both the functions will be same ?

Thanks in advance for your answers. If I have asked the same question again, I am very sorry. I did try my best to search for this.

cyphx
  • 130
  • 8
  • 1
    Good code is more than just performance. It should be readable/ expandable as well. If you compare both approached I'd say 2nd once however even 2nd can be improved. Also I would suggest you to check ellipsis in java. https://stackoverflow.com/questions/2367398/what-is-the-ellipsis-for-in-this-method-signature – Yoshikage Kira Aug 29 '19 at 18:03
  • @Goion, How would I use ellipsis in the above case ? – cyphx Aug 29 '19 at 18:09
  • You can iterate over each object and validate it. – Yoshikage Kira Aug 29 '19 at 18:13
  • I think you have misunderstood my code. I wanted to show that they are all different types of objects. – cyphx Aug 29 '19 at 18:31
  • No. I haven't. Even if your objects are from different class you can still compare them via interface. Like @GhostCat mentioned. see this for example https://stackoverflow.com/questions/383947/what-does-it-mean-to-program-to-an-interface – Yoshikage Kira Aug 29 '19 at 18:50
  • Think about performance mainly when you're in the N.O.P.E. branch. I.e. when you're deep in the loop structure that the code is executing many/many times. – trilogy Aug 29 '19 at 18:59
  • @Trilogy, I am sorry, but I do not understand your comment. Could you please elaborate a little? – cyphx Aug 29 '19 at 19:12
  • @michalk Absolutely not. Please take a look at their [help center](https://codereview.stackexchange.com/help/on-topic) first. – Mast Aug 29 '19 at 19:17
  • @Mast `Application of best practices` and `Performance` ? – Michał Krzywański Aug 29 '19 at 19:19
  • @michalk This is about general best practices, the program provided is hypothetical. Please note how that's explicitly off-topic. There's also [the Don't Ask page](https://codereview.stackexchange.com/help/dont-ask). – Mast Aug 29 '19 at 20:01

5 Answers5

3

Which of the above 2 functions would be preferred in production code

Neither one.

Good code follows certain rules, especially for Java, nicely formulated in the "Clean Code" book by Robert Martin. Things that clean code strongly advocates against:

  • high number of parameters (and 2 is consider high already ;-)
  • doing multiple "things" within one method/class

So, at least for some people, (well written) production code would look much different.

What you could do for example: define an interface Validator, and then put each different validation into its own class implementing that interface. And then "multiple" checks turns into instantiating each of those classes, and putting the objects in some List<Validator> ... when you then iterate, and apply one after the other.

And note: performance doesn't matter here, too. The only thing that matters is how easy to read, understand, and maintain your code is. At least for me, the above ... isn't very good at that, for the reasons stated above.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • 1
    Would you happen to have some reference to the code you suggested. My use case is pretty small, so I think I can live without the complexity. But if it ever starts ballooning, I would love to have an alternative. – cyphx Aug 29 '19 at 18:07
  • @cyphx You mean the Validator approach? I am not aware of a book or tutorial, but when you do some search, you can find stuff like this: https://stackoverflow.com/questions/43226111/how-to-chain-checks-in-java – GhostCat Aug 29 '19 at 18:41
  • 2 parameters is high? What do they suggest instead, passing a list, enum, entire class or whatever? – Mast Aug 29 '19 at 19:19
  • @Mast That very much depends on context. The point of clean code is, as said: you minimize what a single method does. The more arguments you have, the more code you will have to write to deal with them. And: the more paths throw that code manifest, that need to be tested. – GhostCat Aug 29 '19 at 19:23
2

Performance should be the same. You're making the same amount of comparisons and object creations in both cases.

Approach 1 is generally easier to trace later, especially in complicated functions. At the same time, something like

if (condition) {
  // lots of code
  // that scrolls and scrolls
  // with its own fors and ifs and whiles
} else {
  // by the time you're here, you've no idea what the corresponding if() was
}

can often be replaced with

if (!condition) { 
  return "error";
}

// lots and lots of code

and become more readable in the process. To summarize, there is not really a right answer, use your judgement and pick the variant you feel is easier to understand

iluxa
  • 6,941
  • 18
  • 36
0

The second example probably performs better because it has less method calls. However, it is so negligible that you really need to stop caring about it.

More importantly, the second example is more readable and less prone to bugs. For the first example, you have to worry about where responseObj came from and how corrupted its state may already be before you even get to it.

arcadeblast77
  • 560
  • 2
  • 12
0

To review your sample.

  1. Always prefer immutability, so your second approach would be better.
  2. Returning early the code easy to follow so you don't have to scroll all the way down.
  3. Returning a new ResponseObj("SUCCESS","Valid") is not a good structure cause it would open the gate to be (incorrectly) create a new ResponseObj("SUCCESS","Failure"). I'd suggest replacing it by an enum with both fields, which would also make the check for success easier downstream.
  4. Keep it easy with the args as already pointed out
Tomas Fornara
  • 1,280
  • 8
  • 12
  • Thanks for your comments. Actually, my second argument is meant as a message field, but I do agree with your advice about the enums. It would actually limit the number of combinations of ResponseObj. – cyphx Aug 29 '19 at 19:10
0

2nd approach is better, because in 1st approach code is tightly coupled and have repeated lines.

1) For tightly coupled: If the class provider ResponseObj is third person if they renamed the data members and their respective setters and getters then you also have to change where ever you have implemented.

2) Repeated lines of code: responseObj.setStatus("FAILURE"); there are so much same lines of code which we can see in every condition, and we dont know how many goes with number of conditions.

Solution: I feel 2nd Apparoach is better, however every thread should create a new object and constructors can be create any numbers as per the required(Overloading) without impacting to existing implemented developers.

Saqt
  • 1
  • 1
  • I did not see that 1st point coming. In face of it, it is absolutely certain that second approach is better. In my project, this is just a notification object, but if ever in the future, this object is changed, the 2nd approach would save me a whole lot of mindless work. – cyphx Aug 29 '19 at 19:23
  • Solution i have given on your second approach only, not from my two point. The 2 points which i gave that is the drawbacks on your first approach. – Saqt Aug 29 '19 at 19:31