2

I want my custom functions to modify / toggle a boolean variable. Let's say that I have code like

if (OK2continue) { findANDclick(new String[]{"id", "menuButton"});}
if (OK2continue) { findANDclick(new String[]{"src", ".*homeicon_calendar.*"}); }   
if (OK2continue) { findANDclick(new String[]{"src", ".*cycle_templates.*"});

I want to make sure that the flow of execution stops once any of the findANDclick functions toggles the variable OK2continue

I managed my functions to modify a String variable using StringBuilder.

Can I do the same for boolean type of variable?

Kevin
  • 4,618
  • 3
  • 38
  • 61
Radek
  • 13,813
  • 52
  • 161
  • 255
  • Possible duplicate: http://stackoverflow.com/questions/1385481/mutable-boolean-field-in-java – SteeveDroz Jul 01 '11 at 07:26
  • 3
    To toggle your boolean variable, you can do `myVar = !myVar`. But I probably don't understand your question. Can you explain it bit better? – Peter Štibraný Jul 01 '11 at 07:26
  • it's certainly a problem of variable passed by reference / value, if `myVar` is a `boolean` parameter, you may not be able to change its value in the caller context, in opposition to classic objects – Kevin Jul 01 '11 at 07:34
  • you can return {true/false} from your function and assign it to your boolean variable, a suggestion. – Asad Rasheed Jul 01 '11 at 07:42
  • @Asad: yes, but it will make the code bit harder to read.... – Radek Jul 01 '11 at 07:46
  • @Radek ... harder to read? Quite the opposite. I think it would be more clear. Also 'findAndClick' name doesn't suggest that method should toggle some boolean. – Peter Štibraný Jul 01 '11 at 08:11
  • @Peter: yes, in my eyes it would be harder. The line would change to `if (OK2continue) { OK2continue = findANDclick(new String[]{"id", "menuButton"});}` and I want to 'highlight' the parameters of findANDclick. They are the most important and now they are moving too right... – Radek Jul 01 '11 at 08:19
  • @Radek: Your code could then be changed to: `if (!findAndClick(...)) return; if (!findAndClick(...)) return;` (when extracted to different method). – Peter Štibraný Jul 01 '11 at 08:35
  • hmm, that looks good. I will try that. What does 'when extracted to different method' mean? – Radek Jul 01 '11 at 09:18
  • @Radek: since I added 'returns' to my code, that may change flow of your method, that's why I suggested extracting this code to different one. But it may not be needed. – Peter Štibraný Jul 01 '11 at 10:03

4 Answers4

5

I can't say it is equivalent. But using MutableBoolean offers you a mutable boolean wrapper, similar to the concept of StringBuilder a mutable sequence of characters. See this JavaDoc for details.

GordyD
  • 5,063
  • 25
  • 29
1

Well, the concept of StringBuilder is to create a mutable and extendable String wrapper (meaning the string can be extended via append and the like :) ). You'd still have to pass it as a parameter to the method in order to modify it (or use a static var - not recommended).

Since boolean can't be extended, the only similarity would be the parameter to be mutable. So you can use MutableBoolean as Gordon suggested, but you'd still have to pass it.

Another option would be to return a boolean from findANDclick(...) and use the boolean opperators like: findAndClick(...) || findAndClick(...) || findAndClick(...) which would only execute the next findAndClick(...) if the previous returned false.

Since that option is somewhat hard to maintain, especially since you might have side effects in findAndClick(...) as well as being quite static and hard to read if you have more calls in there, you might want to use a list of function objects:

class FindAndClickExecutor {
  public FindAndClickExecutor(String[] params) {...}
  public boolean findAndClick() {...}
}

List<FindAndClickExecutor> faces = ...; //initialize appropriately

for( FindAndClickExecutor face : faces ) {
  boolean ok2continue = face.findAndClick();
  if( !ok2continue  ) {
   break;
  }
}

Edit: since there seem to be other methods as well, you might use a more general list:

interface Executor {
  boolean execute();
}

class FindAndClickExecutor implements Executor {
   public boolean execute() {} // findAndClick code here, set parameters using constructor
}

class FindAndSelectOptionExecutor implements Executor {
  public boolean execute() {} // findAndSelectOption code here
}

List<Executor> testCase1Sequence = ...; //initialize test case 1
List<Executor> testCase2Sequence = ...; //initialize test case 2

for( Executor ex : testCase1Sequence ) {
  boolean ok2continue = ex.execute();
  if( !ok2continue) {
    break;
  }
}

This example could also be expanded on, e.g. by using a more complex return value containing the continue flag and maybe more data (use interface here as well).

Edit 2: you could also use some scripting to define and the builder pattern to generate the list of executors for each test case.

Thomas
  • 87,414
  • 12
  • 119
  • 157
  • Actually I love the `findAndClick(...) || findAndClick(...) || ` way but as you say it is not the best solution and for a reason that I might have some code in between findANDclic's ..... – Radek Jul 01 '11 at 08:26
  • Is there any chance you could explain bit more with an example what is the `list of function objects` about? I did not understand it... – Radek Jul 01 '11 at 08:27
  • @Radek the list of function objects means that you have a configurable object (or maybe subclasses) that execute the `findAndClick(...)` functionality. This let's you put them into a list and execute them in order until one returns false. If you have code in between you might use an interface and create other objects for that code which always return true (if appropriate). – Thomas Jul 01 '11 at 08:31
  • @Radek Can you provide an example of the code in between so I might extend my example? This might help you understand better. – Thomas Jul 01 '11 at 08:32
  • thank you...What I am doing here is testing web application. So I right now I can think of call other functions like findANDsetTextfield, findANDselectOption, etc etc. The sequence will depend on the test case scenario. I am trying to create my `bricks` so I can easily set up my test cases. – Radek Jul 01 '11 at 08:39
  • Well, you might then use something like a `Executor` interface and create implementations for all the methods you need. Then use a `List` for each test case and run the executors in sequence. – Thomas Jul 01 '11 at 08:53
  • This is far too complicated for me :-( – Radek Jul 01 '11 at 09:07
1

You need to clarify your reference to your usage of StringBuilder.

Assuming:

  1. You pass reference of the StringBuilder to your method. String is changed in method. If this the case, then see @Gordon Murray Dent's answer.

  2. Your boolean flag is visible in the method but is not passed. A simple Boolean will do.

package sof_6232851;

public class SideEffectingMethod {
    static Boolean flag = false;
    public static void main(String[] args) {

        flag = true;
        System.out.format ("flag is %b\n", flag);

        clickMe();
        System.out.format ("flag is %b\n", flag);
    }

    /** this method side-effects instance variable flag */
    public static void clickMe () {
        flag = !flag;
    }
}

[edit list item #2 to reply to OP comment]:

Note that #2 is not really recommended. You mention your desire for "readable" code. Side-effecting methods works against that goal.

public class ReturnValuesForFunAndProfit {
    public static void main(String[] args) {
        presentUI();
    }
    public static void presentUI() {
        if(!clickMe("woof")) return;
        if(!clickMe("meow")) return;
        if(!clickMe("hello")) return;
    }
    public static boolean clickMe (String blah) {
            // your logic here; this ex. always returns true
        return true;
    }
}
alphazero
  • 27,094
  • 3
  • 30
  • 26
  • can I modify `simple Boolean` inside my function if it is not passed? Modify so the change is visible outside my function? – Radek Jul 01 '11 at 08:24
  • That's option #2. Basically the reference needs to be accessible from both the call-site and inside the method body. See answer for example. – alphazero Jul 01 '11 at 08:41
  • Note the `static` key word plays no part here -- I just didn't bother making these instance vars and methods. They can be. – alphazero Jul 01 '11 at 08:42
  • hmmm, my `findANDclick` is inside SuperClass. It is not inside the same script like the caller. I am not sure if it matters. Looks like `MutableBoolean` is the way.... – Radek Jul 01 '11 at 08:49
  • 1
    That is correct: if reference is not visible, you must pass an object wrapping the `boolean` field that provides the mutator method. Keep in mind option #3 :) instantiate your SuperClass with a context object (once). Put the flag inside the context. – alphazero Jul 01 '11 at 08:56
  • I like #3. Do you meant to initiate it in `ublic abstract class MySuperClass extends ScriptSuperClass`? How can I use the flag inside the caller? – Radek Jul 01 '11 at 09:06
  • I am going with `if (!findANDclick(new String[]{"src", ".*cycle_templates.*"})) return getResult();` It works. Could you create another answer or updated the current one so I can accept it? I guess your answer was the closest one. Thank you. – Radek Jul 01 '11 at 09:27
1

Push this code into its own method, and use a return:

if (findANDclick(new String[]{"id", "menuButton"})) return;
if (findANDclick(new String[]{"src", ".*homeicon_calendar.*"})) return;
if (findANDclick(new String[]{"src", ".*cycle_templates.*"})) return;

Given that all your method calls are the same, you could also use a loop:

String[][] buttons = {
    {"id", "menuButton"},
    {"src", ".*homeicon_calendar.*"},
    {"src", ".*cycle_templates.*"},
};
for (String[] button: buttons) {
    if (findANDclick(button)) return;
}

You might or might not find that more readable.

Tom Anderson
  • 46,189
  • 17
  • 92
  • 133
  • I might need to use some code in between findANDclick's ... let's say findANDsetText or some kind of verification .... – Radek Jul 01 '11 at 08:30
  • Okay, then the loop is not very helpful for you. You could still use a separate method with multiple returns. I appreciate that this might interfere with the readability of your code, though. – Tom Anderson Jul 01 '11 at 09:24
  • I am going with `if (!findANDclick(new String[]{"src", ".*cycle_templates.*"})) return getResult();` where the `findANDclick returns true if everything was ok. Thank you for your help. – Radek Jul 01 '11 at 09:31