As software evolves, data types have to be extended, possibly with new data variants
or new operations. Object-oriented design is well-known to support data extensions
well. In fact, most popular books showcase data extensions to illustrate how objects adequately
support software evolution. Conversely, operation extensions are typically better
supported by a functional design. A large body of programming language research has been
devoted to the challenge of properly supporting both kinds of extensions. While this challenge
is well-known from a language design standpoint, it has not been studied empirically.
We perform such a study on a large sample of Smalltalk projects (over half a billion lines of
code) and their evolution over more than 130,000 committed changes. Our study of extensions
during software evolution finds that extensions are indeed prevalent evolution tasks,
and that both kinds of extensions are equally common in object-oriented software. We also
discuss findings about: the evolution of the kinds of extensions over time; the viability of the
Visitor pattern as an object-oriented solution to operation extensions; the change-proneness
of extensions; and the prevalence of extensions by third parties. This study suggests that
object-oriented design alone is not sufficient, and that practical support for both kinds of
program decomposition approaches are in fact needed, either by the programming language
or by the development environment.