Potential Side Effects of Reliance on Argument Values

For a simple (but, in real-world programming, potentially serious) example of how relying on the modified values of arguments rather than on explicit return values can introduce undesirable dependencies on implementation details, see side_effects.rb. Here is a method called stringProcess that takes two string arguments, messes about with them, and returns the results:

side_effects.rb

def stringProcess( aStr, anotherStr )
    aStr.capitalize!
    anotherStr.reverse!.capitalize!
    aStr = aStr +  " " + anotherStr.reverse!
    return aStr
end

Let’s assume the object of the exercise is to take two lowercase strings and return a single string that combines these two strings, separated by a space and with the first and last letters capitalized. So, the two original strings might be “hello” and “world,” and the returned string is “Hello worlD.” This works fine:

str1 = "hello"
str2 = "world"
str3 = stringProcess( str1, str2 )
puts( "#{str3}" )    #=> Hello worlD

But now there is an impatient programmer who can’t be bothered with return values. He notices that the modifications made inside the method change the values of the ingoing arguments. So, heck! (he decides), he might as well use the arguments themselves! This is his version:

puts( "#{str1} #{str2}" ) #=> Hello worlD

By using the values of the input arguments, str1 and str2, he has obtained the same result as if he had used the returned value, str3. He then goes away and writes a fabulously complicated text-processing system with thousands of bits of code reliant on the changed values of those two arguments.

But now the programmer who originally wrote the stringProcess method decides that the original implementation was inefficient or inelegant and so rewrites the code confident in the knowledge that the return value is unchanged (if “hello” and “world” are sent as arguments, “Hello worlD” is returned just as it was by the previous version):

def stringProcess( aStr, anotherStr )
    myStr = aStr.capitalize!
    anotherStr.reverse!.capitalize!
    myStr = myStr + " " + anotherStr.reverse
    return myStr
end

str1 = "hello"
str2 = "world"
str3 = stringProcess( str1, str2 )

puts( "#{str3}" )             #=> Hello worlD
puts( "#{str1} #{str2}" )     #=> Hello Dlrow

Aha! But the new implementation causes the values of the input arguments to be changed inside the body of the method. So, the impatient programmer’s text-processing system, which relies on those arguments rather than on the return value, is now filled with bits of text saying “hello Dlrow” instead of the “Hello worlD” he was expecting (actually, it turns out that his program was processing the works of Shakespeare, so a generation of actors will end up declaiming, “To eb or ton to eb, that si the noitseuq...”). This is the kind of unexpected side effect that can easily be avoided by following the one-way-in, one-way-out principle.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.137.38