Is while(boolean method); a bad practice? (Example) - java

I really like the mechanism and style of this code, but Im kinda unaware if this coding style is appropriate or a bad practice.
public class Test
{
private static int counter;
private final static ArrayList<Object> _objects = new ArrayList<>();
public static void main(String[] args)
{
//iterate till you find a valid object randomly
while (!doStuffIfValid(_objects.get(Rnd.get(_objects.size()))));
}
public static boolean doStuffIfValid(Object obj)
{
if (++counter > 30)
return true; //dont try more than 30 times
// if condition
// {
// //do stuff then exit the caller loop
// return true;
// }
return false;
}
}

Well,
The answer to that lies within the boolean method. If that method is bloated, and resource heavy; then no.
Also, if you're randomly checking objects, it may be a better idea to instead: eliminate the objects you know aren't valid from a list, then randomly select from that list.
This way the pseudo-randomizer doesn't (by chance) select invalid objects to validate over, and over again; and waste time/resources.
Cheers.

There is nothing wrong with using a boolean method as a condition for a while-loop. However, stuffing loop functionality in the loop header is, generally, a bad practice. It leads to a code which is difficult to understand, debug (breakpoints become inconvenient) and maintain.

Related

How do I fix this stack overflow error in my code below?

I am trying to find the square of a number using the scanner method but keep getting a
stackflow error. I am new to programming will be glad if someone helps me out.
My code is as below
import java.util.Scanner;
interface Number {
int findSqr(int i); // Returns the square of n
}
//a class A which implements the interface Number.
class A implements Number {
public int findSqr(int i) {
return findSqr(i);
}
}
public class Question5_1{
public static void main (String[] args){
A a = new A(); // an object of class A
// Reading a number from the keyboard
Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
System.out.print(a.findSqr(i));
}
}
Fix the line which invokes the function recursively return findSqr(i) with return i * i as follows --
public int findSqr(int i) {
return i * i;
}
What you did there is an infinite recursion. The bit where it says
public int findScr(int i) {
return findSqr(i)
}
essentially calls the very same method an infinite number of times in the return statement.
What happens is, that you execute the method, and it tries to return an integer. What you wrote though is a return statement that "returns" another call of the same method, so it gets executed again. Then the whole thing starts over again, so you get a StackOverflow.
Since there is no other code present, I have no idea what you are actually trying to do, but the return findSqr(i) line is what causes the problem.
Initially, recursion may be a rather complicated subject to really wrap you head around, I suggest you either avoid it for now (although it enables you to solve many problems in a really elegant way) or try to understand it a bit better maybe. I'd suggest the Wikipedia article about recursion, although it gets complicated quite fast, or any other tutorial on it, just look it up on Google.

Elegant way to return variable before new variable assignment?

This might sound like a dumb question, because it might be no other way to do this. After designing my own list, this sort of "issue" came up in multiple occasions. To clarify, I have a problem with returning a cached variable after assigning new value to the original variable. Here's an example:
public T next() {
final Node<T> thisNode = posNode;
posNode = posNode.getNext();
return thisNode.getData();
}
This might seem like a non-issue, but occasionally multiple variables has to be cached before returning a valid value. I do not really like it, because personally I think it reduces the code's readability, especially when caching multiple variables.
Is there another way to write this code while maintaining its functionality? Basically a way to assign a new value to a variable after the return statement:
public T next() {
return posNode.getData();
posNode = posNode.getNext();
}
Thanks! :)
The second way is not possible as the code is not reachable after return. And your first way is the best way far you to achieve what you are looking for and it is not code smell. Often they refer as temp variables. Use them and better convey a message to the code reader by better naming convention. For ex tempPosNode
An elegant (but with some cognitive dissonance) option is a dummy method.
public static <T> T first(T first, Object... theRest) {
return first;
}
public T next() {
return first(posNode.getData(), posNode = posNode.getNext());
}
You can use a finally block to execute it, but it will execute even after exceptions:
public T next() {
try {
return posNode.getData();
} finally {
posNode = posNode.getNext();
}
}

Return in else branch of void function

Is it good or bad practice to have an else branch which only returns in a function that returns type void? Such as this code:
public void myFunc() {
if (<some condition>) {
//run some code
} else {
return;
}
}
Note that this topic is opinion based, you will probably see many different preferences from user to user.
For readability and maintainability you should try to reduce the complexity of your code. Therefore you want to also reduce the nesting. Thus my prefered variant would be:
public void myFunc() {
// Directly leave if condition does not hold
if (!condition) {
return;
}
// Now do the rest of the code
}
If you want to stick to your current variant then I would suggest to just drop the else part because it just aggravates the readability in my opinion, so:
public void myFunc() {
if (condition) {
// Do something
}
// You can always leave a comment if you think
// that helps a reader, so you can put "Do nothing
// if condition does not hold" here
}
However as said, I personally prefer the first variant because it reduces the nesting of the overall code.
No, this else statement is not required if you are not doing any operation.
The else statement is basically used to carry out an operation, if the condition of if do not met.The best practice is not to write the else statement, if you are not doing any operation.
public void myFunc() {
if (<some condition>) {
//call FunctionA();
} else {
//call FunctionB();
}
}
In the above case, the use of else is valid. But if you are not doing any operation, then the statement is useless. Please read Clean Code Book by Robert Cecil Martin. It will help you in writing clean code.
From the java.lang.Void class documentation:
The Void class is an uninstantiable placeholder class to hold a reference to the Class object representing the Java keyword void.
So any of the following would suffice:
Parameterizing with Object and returning new Object() or null.
Parameterizing with Void and returning null.
Parameterizing with a NullObject of yours.
You can't make this method void, and anything else returns something. Since that something is ignored, you can return anything.

Should exceptions be used to unwinding process back to main?

Now this is really quite difficult for me to explain so please bear with me.
I've been wondering as of late the best way to "unwind" every chained method back to a main method when certain circumstances are met. For example, say I make a call to a method from Main and from that method I call another one and so on. At some point I may want to cancel all further operations of every method that is chained and simply return to the Main method. What is the best way to do this?
I'll give a scenario:
In the following code there are 3 methods, however when Method1 calls Method2 with a null value it should unwind all the way back to Main without further operations in Method2 (EG the "Lots of other code" section).
public static void main(String[] args)
{
try
{
Method1();
}
catch( ReturnToMainException e )
{
// Handle return \\
}
}
public static void Method1() throws ReturnToMainException
{
String someString = null;
Method2( someString );
// Lots more code after here
}
public static boolean Method2( String someString )
{
if( someString == null )
throw new ReturnToMainException();
else if( someString.equals( "Correct" ))
return true;
else
return false;
}
In this example I use a throw which I've read should only be used in "Exceptional Circumstances". I often run into this issue and find myself simply doing If/Else statements to solve the issue, but when dealing with methods that can only return True/False I find I don't have enough options to return to decide on an action. I guess I could use Enumerators or classes but that seems somewhat cumbersome.
I use a throw which I've read should only be used in "Exceptional Circumstances". I often run into this issue and find myself simply doing If/Else statements to solve the issue
Exception throwing is relatively expensive so it should not be used without careful thought but I believe that your example is a ok example of proper usage.
In general, you should use exceptions only for "exceptional" behavior of the program. If someString can be null through some sort of user input, database values, or other normal mechanism then typically you should handle that case with normal return mechanisms if possible.
In your case, you could return a Boolean object (not a primitive) and return null if someString is null.
private static Boolean method2( String someString ) {
if (someString == null) {
return null;
}
...
}
Then you would handle the null appropriately in the caller maybe returning a boolean to main based on whether or not the method "worked".
private static boolean method1() {
...
Boolean result = method2(someString);
if (result == null) {
// the method didn't "work"
return false;
}
Then in main you can see if method1 "worked":
public static void main(String[] args) {
if (!method1()) {
// handle error
}
...
}
Notice that I downcased your method names and changed the permissions of your methods to private both which are good patterns.
Enumerators or classes but that seems somewhat cumbersome.
Yeah indeed. It depends a bit on how this code is used. If it is a API method that is called by others, you might want to return some sort of Result class which might provide feedback like a boolean that the argument was null. Or you might throw an IllegalArgumentException in that case. Instead, if this is an internal local private method, then I'd vote for a simpler way of handling argument errors. Either way I'd use javadocs to document the behavior so you don't trip up future you.
Hope this helps.

Non intrusive way to exit a method under a given condition?

Given this method:
public void walk( String path , ArrayList<String> files, String ext)
which collects all files into the ArrayList<> files starting at path and with given extension ext, I'm looking for a way to stop the search when a certain condition is met. For example, it should stop when files.size() becomes greater than a given number. How could I do this without modifying the method walk() ?
By not modifying the method, I mean not touching the source code in the editor. It's in a state that I like, and I don't want to touch it, because it's just for testing purpose.
Create your class extending ArrayList and override add method:
public class MyList extends ArrayList<String> {
#Override
public boolean add(String item) {
boolean added = super.add(item);
if (added && size() >= 10) {
throw MaxItemsReachedException();
}
}
}
When size is greater or equals to 10, for instance, you can throw an exception.
And call your method with an instance of MyList instead of ArrayList:
MyList list = new MyList();
walk("path", list, "extension");
DISCLAIMER: This is bad programming practice. Dont't do this. I only offer it because it solves the OP's problem.
Subclass ArrayList. Add some logic to the add methods that throw an exception if files.size is greater than some threshold.
It will look like this
public void add(E element){
if(size()<THRESHOLD){
super.add(element);
}else{
throw new RuntimeException("STOP HERE");
}
}
Try to throw an exception that walk does not catch and you should catch this exception in the method that calls walk.
Among other bad things this is using exceptions to manage flow control.

Categories