Public vs. Private Methods Generally Reduce Cascading Changes
This question might be a better fit on Software Engineering, but the most general use case is to keep the public interface of the class small and simple, hiding the internals of the implementation from callers and collaborator objects. Data hiding, separating public interfaces from internal implementation details, and drawing a distinction between public and private interfaces are basic principles of object-oriented programming.
This certainly matters more in languages that don't allow you to easily bypass protected and private method definitions, which is pretty trivial to do in Ruby with Object#send. Still, marking a method as private in Ruby at least communicates intent, and creates a demarcation between the public interface and any internals or data hiding that shouldn't be visible to, relied upon, or otherwise directly manipulated by collaborators.
As an admittedly contrived example, consider the following class that implements a public #calculate_value method and a private #calculate_value! method that is invoked by the public method.
class Foo
# Declare a public interface; the collaborator doesn't
# need to know how the value is calculated. If the way
# the calculation is performed changes, the inner
# details are not exposed in the public method so the
# caller shouldn't care as long as the result returned
# is what's needed or expected.
#
# @param x [Integer]
# @param y [Integer]
# @return [Integer] value calculated from _x_ and _y_
def calcuate_value x, y
calculate_value! x, y
end
private
# This method is private, so it doesn't need to expose
# how it works. The method could be modified, refactored,
# redesigned, or call 27 other methods to do its work,
# but those details should be a "don't care" when calling
# the public method #calculate_value.
#
# @param x [Integer]
# @param y [Integer]
# @return [Integer] a complex set of calculations using
# the _x_ and _y_ values passed to the public interface
def calculate_value! x, y
embiggen x, y
ensmallen x
triplicate y
[x, y, y].sum
end
end
In other words, #calculate_value is defined as part of the public interface for instances of the class, and should rarely change. Meanwhile, the implementation of the public method is really being handled by the private method #calculate_value! and declaring it private means (pragmatically speaking) that programmers and collaborator objects should generally interact with the public method and leave the private method alone.
This allows the public interface to stay the same even if the private implementation changes. Whether or not changing the implementation should change the behavior of the class or the value of the calculation is the difference between refactoring (where the implementation changes but the behavior remains the same) and where changes to the behavior are desirable. In either case, the public interface remains the same, which generally reduces the need to change code in the caller every time some detail of the underlying implementation is modified.