Java Reference
In-Depth Information
intended, the journey from X to Y has been destructively updated. Indeed, the firstJourney
variable is no longer a route from X to Y but one from X to Z! This will break code that depends
on firstJourney not being modified! Suppose firstJourney represented the early morning
London-Brussels train, which all subsequent users trying to get to Brussels will be surprised to
see as requiring an onward leg, perhaps to Cologne. We've all fought battles with such bugs
concerning how visible a change to a data structure should be.
The functional-style approach to this problem is to ban such side-effecting methods. If you need
a data structure to represent the result of a computation, you should make a new one and not
mutate an existing data structure as done previously. This is often best practice in standard
object-oriented programming too. A common objection to the functional approach is that it
causes excess copying and that the programmer says, “I'll just remember” or “I'll just document”
that it has side effects. But this leaves traps for maintenance programmers who later will have to
deal with your code. Thus the functional-style solution is as follows:
static TrainJourney append(TrainJourney a, TrainJourney b){
return a==null ? b : new TrainJourney(a.price, append(a.onward, b));
}
This code is clearly functional style (it uses no mutation at all, even locally) and doesn't modify
any existing data structures. Note, however, that the code does not create an entirely new
TrainJourney—if a is a sequence of n elements and b a sequence of m elements, then it returns a
sequence of n + m elements of which the first n elements are new nodes and the final m elements
share with the TrainJourney b. Note that users are also required not to mutate the result of
append because in doing so they may corrupt the trains passed as sequence b. Figures 14.2 and
14.3 illustrate the difference between the destructive append and the functional-style append.
 
Search WWH ::




Custom Search