Here is an example of a local branch:
void foo() { if (someCondition) { doSomething(); } else { doSomethingElse(); } }
Branching is pretty advanced, right? The reason for this simplicity is that all branching logic is defined inside foo . Locally, so to speak. This means that the condition is checked and its path is taken depending on someCondition , but the branch does not exit foo . By looking only at this method, you know what the code stream looks like.
Now think about this less readable implementation:
void foo() { if(bar()) { // branch is handled by bar } else { doSomethingElse(); } } boolean bar() { if(somethingWrong) { return false; } doSomething(); }
This is less readable. But why? If you call the bar method from foo , the control flow is processed by bar . bar may, however, do something unexpected and still rely on foo to deal with this unexpected condition. This is not good practice, since you are distributing related logic between foo and bar , where a change in one place can cause abnormal behavior in another place. These are some exceptions if they are processed too far from the stack. You can even expand the complexity of the above example by adding additional intermediate methods. Therefore, the book proposes to keep branching locally, since it is often more readable and traceable, which I would equally suggest as a good idea. Take a look at this implementation based on the exception of the above code to visualize this more:
void foo() { try { bar() } catch(SomeException e) { doSomethingElse(); } } boolean bar() { if(somethingWrong) { throw new SomeException(); } doSomething(); }
Obviously, this distributed branch is more error prone than the if - else .
source share