Abstract
The rhetorical significance of naming practices is widely understood, but it--and
many other rhetorical dimensions of language--are often overlooked in the domain of
software development, especially in regards to code languages and relevant practices
(as demonstrated in file names, functions, variables, and so on). While naming conventions
in code are typically recognized as inherently arbitrary, they are also tangled up
in numerous networks of community expectations, constraints, and mores, whether organizational
or interpersonally social in nature. Given Kenneth Burke's argument for the revealing
and concealing influences of terministic screens upon our engagement with the world
(by establishing ways of seeing and not seeing), naming conventions in code play an
important role in how meaningful invention occurs for human developers and readers
of code files. Despite the apparent triviality of such a component of software projects,
naming practices shine a light on the goals and values of a programmer in addition
to the functional intentions that they might have for the use of a given body of code.
There are only two hard things in Computer Science: cache invalidation and naming
things.
—commonly attributed to Phil Karlton [
Fowler 2009]
[T]he mere act of naming an object or situation decrees that it is to be singled out
as such-and-such rather than as something-other.
—Kenneth Burke [
Burke 1973, p. 4]
Introduction
Among the most seemingly trivial qualities of software code is
the set of names given to the components of a given program, including files,
functions, and variables. After all, other than file names, it is unlikely that the
majority of users will ever explore the source code of that program (assuming that
they are even provided access to it). However, it is hardly novel to assert that such
names are meaningful; after all, we frequently gain insight from names and naming
practices (whether in code or other forms of writing) by virtue of their potential
reflection of an author’s values, ideologies, or intended rhetorical action — most
notably in regard to the author’s relationships with various audiences. What has been
relatively unexplored, and what offers especially notable significance for the
rhetorical study of code, is how and why particular rhetorical strategies are enacted through practices of naming
in code texts.
There are numerous theoretical perspectives through which naming practices in code
might be examined rhetorically, and each contributes to a fuller understanding as
to
the purposes for which a programmer might use particular naming practices and the
kinds of effects that particular names might have on readers of a code text. While
this article cannot comprehensively explore the full range of perspectives available
through rhetoric, there are several that serve well to illustrate initial paths for
further exploration. In this article, I apply a critical framework that brings
together classical categorizations of forensic, deliberative, and epideictic rhetoric
with Steve Holmes’ (2017) notion of procedural habits. In conversation with one
another, the components of this framework allow me to demonstrate how different
naming practices in code facilitate particular kinds of
phronesis
— prudence or practical wisdom [
Sachs 2011, p. 209] — that emerge as habits
to enact certain rhetorical aims and action among authors and readers alike.
My demonstration involves several brief case studies, each of which serves as an
example of phronesis with a different sort of rhetorical aim
in mind. The brief declaration and throwing of an exception (named up) demonstrates
humor via the forensic nature of naming, meaning an effort to determine what happened
and why (in this case, why did the author name the exception up?). An epideictic
(praising or blaming) naming occurs in the explicitly named method
RichardIsAFuckingIdiotControl, whose author explains his code’s functionality through
names that criticize his colleague’s coding decisions. Naming practices’ deliberative
qualities — those that work toward a determination of what should
or should not be done — can be observed through a
metadiscursive and satirical guide to writing “unmaintainable code,” whether that
code is meant for others or even the initial author to maintain. Together, these
studies illustrate how different habits can promote a variety of rhetorical goals,
some less immediately apparent than others.
What’s In a Name?
Any examination of the rhetorical qualities of naming practices in code must
acknowledge the metaphorical basis of language. George Lakoff and Mark Johnson (1980)
argued that it is often easier for one to understand a potentially complex idea or
system when translated into metaphorical terms that contextualize that idea or system
into a more easily understood image (e.g., argument as war, time as money or other
resource, emotion as orientation). Concisely, they note that
“[h]ow we think
metaphorically matters” [
Lakoff and Johnson 1980, p. 243]. In other words, the metaphors we use
to describe and explain complicated ideas have the power to influence
how we understand those ideas — the metaphors are neither
ornamental nor arbitrary in serving to characterize our conceptualizations of those
subjects we discuss. This argument should resonate with rhetoricians, since it is
what we choose to communicate as rhetors that reveals to audiences the goals and
values that underlie the arguments we make.
Not surprisingly, this sentiment about language’s metaphorical nature is shared by
Kenneth Burke (1969), who identified
“the use of language as a symbolic means of
inducing cooperation in beings that by nature respond to symbols” [
Burke 1969, p. 43]. The construction of meaning through language relies on what that language
represents — not only to the author of a given statement or message but also to any
audiences who encounter it. This reliance is no different in the source code of
software than in any conventional form of discourse. Of course, each individual
encountering some language approaches it from a unique perspective, with a unique
set
of values, interests, and motives, and with a unique frame for interpretation of that
language. [
Burke 1966] referred to this concept as the
terministic
screen, an orientation toward one’s understanding of the world via their
experiences, beliefs, etc. that facilitates some interpretations and constrains
others. Burke has famously observed that
“a way of seeing is also a way of not
seeing” [
Burke 1965, p. 49], highlighting the boundaries and limitations, as well as
the strengths, of any given perspective. As such, any language use is meaningful in
ways that potentially extend beyond any individual reception or interpretation of
it.
Metaphors tend to perform this extension in some significant and engaging ways,
offering insight into the rhetorical contours of an argument through the ways that
metaphors ask audiences to consider particular ideas.
This idea of metaphor as rhetorically meaningful has persisted since classical
Greece, with Aristotle identifying metaphors as incredibly powerful pillars of
rhetorical invention that are employed through
examples and
enthymemes, incomplete syllogisms that audiences are
implicitly invited to complete [
Aristotle 1991, I.ii.8]. This long-standing
comprehension of the power of metaphor has informed the development of rhetoric and
its applications across speaking, writing, and myriad other forms of communication.
When used to serve particular ends — to perform various kinds of symbolic action —
strategic use of metaphor (and other devices) in language can augment or compromise
an argument and the kinds of support it might otherwise gain. Given code’s existence
as/through language, the metaphorical dimensions of names in code, as with other
rhetorical dimensions of such names, are incredibly significant — especially when
it
comes to the impact that names and name schemes might have in influencing subsequent
programming habits to realize or perpetuate values and ideologies with cascading
effects across continued development and potential use of a given program.
Names and Naming in Code
The naming practices of software development, like with any other context for
naming something, can be quite complicated and nuanced. Frequently, the metaphors
of names in code — such as, for variables, functions, files, etc. — often attempt
to reflect an understanding of multiple perspectives, motives, and goals: a) the
purpose(s) of the named code for members of the development team; b) relationships
between the named code and other bits of code; and c) the potential purpose(s) of
the named code for user and any other groups not involved in the code’s
development. Depending upon the nature of a given project (such as whether it is
developed by an open source, volunteer-based community or by a corporate or
proprietary organization), these nuances have the potential to provide confusing
or unintended messages to audiences where they intersect or when the development
membership changes at a different pace than the stylistic preferences for
contributions to that project.
Naming practices within a given project may or may not be dictated or constrained
by an explicit or implicit style guide meant to inform involved developers about
how they can or should understand naming descriptions and idiosyncrasies within
the scope of that project. There may or may not even be a shared sense of how
names should rhetorically operate (and there is rarely any express conversation
about the “rhetorical” dimensions of such names), which can lead to a wide variety
of naming practices by project developers and subsequent discussion about how
best, if at all, to address and resolve differences in interpretation of specific
naming practices that impact continued development of the project in some way.
Further, this variety is rarely neutral: Names and naming practices can suggest
ideological and value-based systems that might reflect the interests, beliefs, or
agendas of one or more authors, their organizations, or the cultural contexts in
which they live and operate in relation to which the authors, through their code
and the names in it, are performing particular identities and roles. As Safiya
Umoji Noble (2018) has demonstrated, technological systems like search algorithms
often reinforce and reify racist and sexist structures; as code-based components
of algorithmic systems, names in code have the potential to perform similarly at a
smaller but no less significant scale wherever relevant names appear (noble,
2018). Names, like any other components of code, perform and help realize
particular aims when engaged by human readers. Wendy Hui Kyong Chun (2011) notes,
“Code does not always or automatically do what it says, but it does so in a
crafty, speculative manner in which meaning and action are both created” [
Chun 2011, p. 24]. While this argument is primarily directed toward the execution of
code, it is just as applicable to code’s composition — especially in regard to how
names and naming schemes facilitate or obfuscate various readings of that code’s
functionality.
How, then, might we interpret and analyze names and naming practices in code from
the perspective of a rhetorician? What can we learn, and how might it help
illuminate existing practices as well as to inform future practices? By turning to
particular case examples of some common naming practices, we can begin to explore
how different purposes or aims might motivate and inform some naming decisions —
especially regarding the use of metaphor — as well as how different effects might
be achieved through those decisions.
Forensic, Deliberative, Epideictic
According to Aristotle, there are three general contextual aims of classical
rhetoric:
forensic, to determine what happened in the past;
deliberative, to determine what should or should not happen
in the future; and
epideictic, to celebrate or condemn a
subject [
Aristotle 1991, I.iii.3–4]. While these aims work well to describe common
oratory contexts, they are not necessarily exhaustive in covering all the potential
purposes for communicating today. Nonetheless, these classical aims can illustrate
initial steps toward a clearer understanding of the rhetorical power and potential
in
naming practices in code.
For example, code might be employed in an epideictic manner to excoriate a subject,
such as one’s employer, colleagues, users, or some relevant principle involved in
the
development of a given project. As will be examined later, numerous names in the
publicly available code snipped for the case of “Richard Is a Fucking Idiot” serves
to call attention to the implied failings of the code written by the author’s
coworker Richard, which was published initially not by the author but by another
colleague who wanted to celebrate the frankness of the code’s descriptive names.
Richard — whether real or not — need not be the anticipated reader of this code in
its original context, since anyone who might encounter the code (e.g., a future
maintainer of the program) is asked to pass judgment on Richard, with the expectation
that they will agree with the author’s condemnation of Richard’s abilities, both when
reading it and — if a collaborator on the project — when calling its functions as
part of continued program development in their own code.
Similarly, we might view many variable names as functioning in a deliberative sense,
as they are “meant” to describe the particular functional use(s) of those variables,
e.g., timeCounter as a container for measuring the passage of time in some way. While
this might seem purely descriptive, in that timeCounter has been named that because
it describes the counting of time recorded in the variable, it may have been named
timeCounter to be used for such a purpose. Its descriptive
nature is thus also a persuasive argument for deliberation, an enthymeme made to
developers working on that code so that they will (or feel obligated to) choose to
employ the variable primarily, if not solely, for the purpose of counting time, even
if the specific reason for counting time may be understood or implemented in
different ways by different developers. The phronesis in play
reflects a particular kind of habit, a means of prudently
supporting both a programming project and its development community through the
employment of naming practices that facilitate functionality-related readability and
relevant ease of implementing any variables, functions, methods, etc. that rely on
interpretations of names via that understood functionality.
Procedural Habits in Naming
The rhetorical decisions regarding names and naming in code are rarely unique and
thus tend to reflect common qualities — what might be understood as conventions of
code text genres (for more on rhetorical genres in code, see [
Brock and Mehlenbacher 2018]). These
common qualities might also be described as
procedural habits,
a term coined by Holmes (2017) to highlight
“the specific forms of rhetoric that
emerge from dynamic and locally situated repetitions of social, behavioral, and
material habits that give rise to meaning and communicative agency in the activities
of videogame design, play, and writing about play” [
Holmes 2017, p. 10]. While
Holmes’ definition is clearly focused on the context of videogames, the term can and
does also describe habits beyond those bounds — with software development as a
broader and overlapping context in which procedural habits persist. Holmes stresses
the need to understand
“habit” not only as mechanistic (that is, roughly, as
practices we do not consciously think about performing and, in turn, hopefully do
not
influence our thoughts or behaviors) but also as non-mechanistic:
Non-mechanistic approaches to habit do not allow thought to unmoor itself in
transcendence or the free play of signifiers. Rather, these approaches ask instead
how thought, rhetoric, and writing are possible at all without the ability of habit
to create duration, stability, and repetition in cultural practices, texts, and
communication patterns amid an otherwise anonymous flux of Becoming. [Holmes 2017, p. 15–16]
That is, procedural habits, when understood non-mechanistically, serve to facilitate
the
ethical nature of rhetorical activity by allowing habit to
inform how we think, act, and communicate rather than positioning it as a negative,
purely mechanical or rote execution of operations. Holmes frames this approach in
part through Aristotle’s notion of
hexis as
“state,
disposition, bodily comportment, our habituated ‘second nature’ that guides ethical
reasoning” [
Aristotle 1991, p. 15]. Viewing habits as non-mechanistic provides a
flexibility in analysis and application that allows us to advocate particular
habit-related practices of
phronesis, the application of
practical wisdom that might facilitate more effective rhetorical strategies in
particular circumstances, such as in terms of code developed as part of collaborative
effort compared to that written by an individual developer for their own unique needs
or interests.
What does Holmes’ definition suggest for an exploration of the rhetorical dimensions
and effects of names and naming practices in code? Beyond the obvious — that naming
practices can be, for many, a kind of procedural habit cultivated both unconsciously
and consciously by software developers — it is also that different hexein can inform different states and comportments toward names and how
engaging those names might, especially in combination with different orientations
toward phronesis, guide other relevant procedural habits of
software development and related communication. Further, habits reflect rhetors’
typical and recurrent behaviors, allowing us to understand their work rhetorically
as
simultaneously idiosyncratic and also representative of their cumulative education
and experience with writing and reading code.
For example, common practice tends to involve a proportional
decrease in the significance of variable (and, to a lesser extent, function or
method) names and their broad readability, with those variables more local in scope
often having a name whose meaning or purpose is less immediately clear. That is, a
variable or function likely to be used throughout a program (e.g.,
copyDataToClipboard(data) ) may need to be more descriptive or memorable when a
developer encounters it numerous times throughout the code comprising an entire
project, while a variable that exists in a limited scope (such as single-letter
variables popular as iterators in for loops) may not require longer-term memory of
its purpose.
Procedural habits of varying kinds and demonstrating metaphorical connotations that
support a range of rhetorical aims (forensic, deliberative, and epideictic), appear
across the following three brief case examples that illustrate important
considerations regarding rhetorical strategies used in code-related naming practices.
First, throw up calls attention humorously to the liminal qualities of naming
metaphors — specifically, how forensic rhetoric can emerge through physical metaphors
enacted through procedural events. Second, RichardIsAFuckingIdiotControl functions
epideictically to excoriate a colleague and their own work practices through a set
of
methods whose purpose is ostensibly to avoid the mistakes of “Richard’s” practices.
Third, the deliberative rhetoric involved in the writing of “unmaintainable” code is
explored through a series of sarcastic recommendations — a kind of worst practices guide (whether performed intentionally or not by those whose
examples populate the document) — for ensuring that one’s code is impossible for
anyone to maintain. Together, these case examples can teach us how the rhetorical
work that occurs in code-related naming practices has the potential to be employed
even more effectively toward desired or anticipated ends and to reach particular
audiences so as to induce productive action, whether for continued development of
a
program or for its use to effect some sort of change in the world.
Case Example 1: Throw Up
Hans-Erik Nissen (2002) has suggested that most software developers are interested
primarily in the functional quality of a specific block of code, its purpose or
utility to the program in which it is used. According to Nissen, "[s]oftware
practitioners are well aware of the denotational features and largely ignore the
connotational features of language. Concepts employed in software products must have
unambiguous interpretations in very limited contexts, such as computer programs,
database schemas, and so on" [
Nissen 2002, p. 86]. Such a position recognizes many
corporate development practices, to be sure, but to suggest that developers
ignore the connotational features of language — especially for
coding purposes — is inaccurate. Even when making use of "built-in" (non-customized)
functions and operations, coders are often painfully aware of the connotations of
their code, although they may not explicitly make note of those connotations either
in the moment of writing or during later navigation and implementation of that
code.
For example, the following two lines of Java code describe an explicit exception —
that is, an expected disruption of the normal interpretation and execution of code
for a given program. Arguably, every variable or function definition is a kind of
argument with varying degrees of forensic and deliberative effect, whether to
determine what that defined term has been constructed to do, which often appears in
code comments that reflect on relevant code, or to make a case in the code itself
for
its continued use throughout the project through the name itself.
This particular exception is defined by the
up variable as an
Exception event and by
the resulting action that should occur through the
throw statement, which removes
that exception from the process being executed — the
“throw” term loaded
metaphorically with a suggestion of forceful removal — usually by ending the program,
and the exception alerts developers (or, in some cases, a user) to the specific
origin point for that disruption. The
throw up exception is articulated and commented
on as follows [
スーパーファミコン 2009]:
Exception up = new Exception("Something is really wrong.");
throw up; // ha ha
The developer's comment,
// ha ha, makes clear the author's awareness of the multiple
connotations of the language being used as part of functional code, and the feelings
that might arise within a developer for catching an exception that, while
anticipated, are likely undesirable, are summed up concisely through the activity
(metaphor and computational operation)
throw up. If an exception generally indicates
a forceful removal via the
throw statement, then
throw up offers an even more
powerful metaphor of regurgitation and expulsion. The problem becomes an unwanted
entity to be rejected by the program, a source (and effect) of nausea. While not all
developers might approach this joke with a sense of revulsion for the exception being
thrown, there might nonetheless be some truth in the affective quality of the
metaphor. If developers were generally to ignore the multiple meanings of the
language they employ
daily through code, we would have to
assume they similarly do so in other contexts, i.e., in natural language use. Since
very few might ever make this argument, there is no reason to suggest that it occurs
within the realm of code.
Further, the most explicitly forensic component of the code is
the message that is communicated when the exception occurs: Something is really
wrong. There is no hint here of the vomit metaphor in which the message is coded to
appear, other than the most general sense of “something wrong” relating to or causing
the act of “throwing up” to occur. Even so, the author’s comment — // ha ha — also
performs forensically to draw attention to the polysemous nature of the exception’s
metaphor. While the output message may only specify that “something” is wrong, the
author knows the cause was the code “throwing up” this message. Similarly, those
familiar with writing exceptions and identifying their purpose as (either facetiously
or seriously) as a kind of vomit-like or vomit-inducing point of frustration as well
as problem-specifying event can use this sort of linguistic play to cultivate a sense
of community through such a naming practice.
Case Example 2: Richard Is a Fucking Idiot
Many programmers have made extensive use of the flexible possibilities of
customization in naming practices to help generate a narrative for themselves and
other developers as a means of justifying the purposes toward which they anticipate
their code working. Tom Ritter (2010) shared an excerpt of Java code written by
another developer who was clearly angry at a coworker during the time of the code's
composition. Quoted in part below, the naming practices used in this code pull
absolutely no punches in communicating the author's feelings towards the coworker,
renamed "Richard" to keep that worker's identity protected [
Ritter 2010]:
public RichardIsAFuckingIdiotControl() {
MakeSureNobodyAccidentallyGetsBittenByRichardsStupidity();
}
private void
MakeSureNobodyAccidentallyGetsBittenByRichardsStupidity() {
// Make sure nobody is actually using [the original] method
MethodInfo m = this.GetType().GetMethod("BindCompany",
BindingFlags.DeclaredOnly | BindingFlags.Instance |
BindingFlags.Public | BindingFlags.NonPublic);
[...]
}
[...]
protected override void OnLoad(EventArgs e) {
if (IsThisTheRightPageImNotSureBecauseRichardIsDumb()) {
Page.LoadComplete += new EventHandler(Page_LoadComplete);
Pager.RowCount = GetRowCountBecauseRichardIsDumb();
}
base.OnLoad(e);
}
These functions were authored by Dan McKinley (2009), who revealed his own identity
after the code quoted in part above was posted to the popular programming help
website
Stack Overflow [
Ritter 2010], and McKinley explained
the above excerpt was part of a larger method declaration named
RichardIsAFuckingIdiotControl. This class worked specifically to route data around
what McKinley felt was inefficient and resource-intensive code — a sentiment
expressed most clearly through his accusations toward the programming skills of
coworker "Richard" (a pseudonym, according to [
McKinley 2009]). For example, the
function
IsThisTheRightPageImNotSureBecauseRichardIsDumb(), whose code was called
(but not outlined) in the above excerpt, performs a confirmation check on a requested
URL before the URL is loaded in order to avoid performing a number of other,
potentially unnecessary operations relating to the load (which would then slow down
any continued use of the program). This check was added because "Richard" had
initially coded the software to execute those potentially unnecessary operations any
time a URL was requested. The function's name is clearly not a genuine inquiry but
rather a sarcastic evaluation of the preexisting code as being unable to do what
McKinley felt it needed to do. That is, McKinley's understanding of how the program's
code
should work has been complicated — with apparently
disastrous results — by Richard’s change to the program's expected functionality.
While one might argue that McKinley's naming scheme is certainly denotative, since his custom function names certainly describe the
functional intent of those functions, the scheme also attempts to communicate connotative meaning just as intensely to his audience in an
epideictic fashion: The author is not just fixing a problem but demanding that any
readers of the code understand — and likely agree with — the amount of anger or
frustration he may have felt at having to rework his colleague's efforts. (It should
also be noted that this may or may not be an objectively accurate reflection of
Richard’s code but rather of McKinley’s interpretation of Richard’s code.) Similarly,
McKinley’s naming practice attributes all potential failures
of the program here to be the fault of "Richard," at least within the scope of the
code: "Richard" is the only idiot identified as potentially being at fault for
whatever troubles might befall the user or other developers working on the project.
Specifically, McKinley’s naming practice suggests that he needed to
MakeSureNobodyAccidentallyGetsBittenByRichardsStupidity with the assumption that user
error would be anomalous given the problems that McKinley’s naming practice
associated with his coworker's code.
McKinley's adjustments assert a specific deliberative paradigm for how the
development organization and its employees should approach
their work, an argument for the cultivation of a particular kind of procedural habit
that reflects a kind of phronesis regarding the sorts of
change that one developer might be able to effect more easily than others when
encountering problematic functionality in a colleague’s code. The tone of those
adjustments similarly suggests a level of general and contextually-specific
programming knowledge that readers — beyond McKinley and Richard specifically — may
possess. In excoriating Richard, McKinley’s code might be
perceived to either purposely or inadvertently suppress potentially experimental or
innovative contributions to the program that could be written by his colleagues.
Whether they identify sympathetically with McKinley or with Richard is unknown, but
there is an unstated question: if another developer upsets McKinley (or anyone else
who might respond similarly), will their shortcomings also be condemned so explicitly
throughout a set of documents available to an unknown number of employees at their
organization? Or is McKinley’s code here demonstrating a cathartic habit available
only through hyperbole and pseudonym, since this sort of practice is — in the
contexts of many professional, and especially corporate, organizations — entirely
verboten, even if many might feel the sentiment is warranted.
In addition, Richard's name itself comes to serve as an example of synecdoche, a rhetorical device that refers to some concept or entity by way
of one of its parts (or, as in this case, the part by way of the whole). Here
Richard's code is the point of contention, and Richard's
nature as a "fucking idiot" is demonstrated only through the code to which McKinley
has alluded with his workarounds. Our exposure to Richard exists only through these
changes made to his code — we do not experience Richard's alleged “mistakes” in the
program source. Rhetorically, the audience is asked to consider Richard (the person)
indirectly through the lens of Richard's body of code and directly through the lens
of McKinley's body of code about Richard's body of code, with
all the value statements made about Richard’s code intertwined with the proposed
change in functionality that McKinley applied to it.
McKinley is able to direct his frustration with the code toward its author, and his
appeal is effective for those who might have experienced similar irritation with
coworkers or collaborators of questionable skill or knowledge (but, conversely, may
be less effective for those who may be less comfortable with their own programming
skills or knowledge of the organizational "flow" related to working with McKinley
or
with Richard). Whether or not this frustration or irritation is well-founded, of
course, varies from case to case — but that's not the point. Instead, the potential
for an author to communicate it at all is the important
detail; the developer's impetus is inscribed and preserved in the program for all
future contributors to witness.
Case Example 3: How to Write Unmaintainable Code
This following case “example” is not a single excerpt of source code but rather a
document about code, a satirical take on practices that
implement embarrassing or frustrating naming schemes in code. This metadiscursive
document reflects another sort of orientation toward the cultivation of emergent
procedural habits in software development and which may reflect a commonly recognized
sense of phronesis present in their execution. Roedy Green
(2017) provides, through this satirical guide, a relatively thorough examination of
the laughable decisions made by some programmers that, deliberately or otherwise,
“ensure” that their work is impossible to build on or otherwise maintain. While
Green's organization of their larger work, with “Naming” as a subsection, suggests
that naming practices make up only a small part of the means by which someone could
construct an unmaintainable program, the entire essay is pervaded with observations
that relate to the habits of naming practices in a variety of ways, from ambiguity
or
obfuscation that decreases readability to eschewing company standards and style
requirements in favor of personal preferences.
Much of Green's advice relates to considerations of names in code as representatives
of particular metaphorical structures or as subversions of those same structures.
For
example, Green jokes that it is important to prefix class instance names with some
sort of indicator that the developer recognizes it is an object, such as
“o_apple” or
“obj_apple”. This approach, Green notes,
“show[s] that you're thinking of the big,
polymorphic picture” [
Green 2017].That is, the attention paid to clarifying details
in this particular habit — which might normally require no clarification — suggests
not that an authoring programmer understands the purpose (the
“big, polymorphic
picture”) of a name as reflecting some sort of understood utility but rather that the
author perceives those clarified details as constituting the significant metaphorical
dimensions of a name, likely to the detriment of its future maintainers. What benefit
for the author and any other developers arises from such a name? The nomination of
each class instance as an object, such as with a prefix, does not guarantee that the
remainder of the name descriptively reflects, in any way, the suggested purpose of
that particular object, especially if it was instantiated with some specific goal
in
mind that might be more meaningful to other readers. Green elaborates on a similar
point elsewhere:
“Under no circumstances, succumb to demands to write a glossary with
the special purpose project vocabulary unambiguously defined” [
Green 2017]. The
statement hyperbolically lambasts the principle of clearly communicating to one’s
reader the scope and purpose of the naming scheme(s) used for a particular project,
as that would invite the reader to understand those schemes more fully and,
theoretically, to participate in the use and proliferation of those schemes in
further development of the project at hand.
Similarly, languages like Java provide developers with the opportunity to (or the
demand that) variable types are named twice, e.g.
String[] myString = new String[];
However, as Green notes, it is possible to complicate this approach by specifying
a
variable as a different data type than expected:
“Bubblegum b = new Bubblegom();”
(notice the spelling difference in g
om vs. g
um). This sort of naming can be even more obvious or pronounced, but for
Green it seems to be the subtle, hard-to-spot, change that has the most significant
effect in regard to creating work for a future developer. After all, clearly visible
differences stand out, and Green’s argument appears to be most interested in the
sorts of stylistic naming activities that elude easy recognition. As Green notes,
“Your code should not look hopelessly unmaintainable, just be that way. Otherwise it
stands the risk of being rewritten or refactored” [
Green 2017] [emphasis in
original]. That is, the more overt or recognizable the
“bad” practice, the easier it
is for an audience to address productively.
As a result, names as representatives of metaphor have the potential to derail those
metaphors — or force a drastic reconsideration of them — when multiple developers
approach a particular project with different metaphors in mind. This situation is
unavoidable; one can never ensure that any reader will ever engage a text in exactly
the same way as any other, sometimes even when there are closely aligned expectations
about the text; c.f. [
Fish 1982]. However, the freedom provided to every developer
to name the components of their code however they desire (regardless of those names'
helpfulness or clarity) supports a view of naming as extremely powerful practice,
since it imparts some indication of interpreted significance to a reader through the
names chosen by an author. In some cases, an author’s choices are constrained by the
authors of an overarching system, e.g. the labels used for particular data types
(such as
String vs.
Object vs.
var), specific operations (such as
“throw” in
“throw
up”), or semantic tags in markup (such as
<blockquote> or
<cite>) to
suggest particular kinds of tagged content; see [
Beck 2016] for a discussion of the
rhetorical differences between human and machine interpretative contexts. These
metaphorical practices are, of course, procedural habits formed over time by exposure
to the particular habits of others and imitated or rejected to varying degrees for
just as varied reasons. In Green's case, these habits can result in decisions that
appear infuriating or laughably painful to the reader, but they nonetheless all
demonstrate the developer-as-namer to be a crucial nexus in a network of meaningful
development-related communication.
The Rhetorical Nature of Development Practices
The broad range of possibilities for naming practices — such as those briefly
explored in the three case examples above — appropriately reflects the broad range
of
possibilities for communicating meaning in any mode or medium. Whether such practices
are viewed as being significant for the purposes of rhetorical study, the fact
remains that developers' values and perspectives on their code — as well as those
of
organizations, systems, and structures exerting varying degrees of overt and implicit
influence on those developers — are transmitted through the names they provide for
their work along with any goals they intend to suggest the code should achieve. In
addition, those same values inform the way(s) their code is
designed to function, both internally (with other functions, sometimes written by
other developers) and externally (through the expression of the overall program in
which that code operates). When a number of developers' individual practices converge
for the creation of a large-scale program, these rhetorical influences often override
the sets of standards and best practices to which the involved developers are
expected to adhere. As a result, the contextual and situated qualities of rhetorical
meaning-making underlying both the code and its expressive program become visible,
providing rhetoricians with an excellent opportunity to study the creation of that
software as well as the range of actions it facilitates through its use.
Among the most intriguing such programs are the open-source software projects
developed by volunteers from across the globe, since there is potentially a wide
range of sociocultural factors introduced to, and influencing, any number of
components of those projects' code. These factors can demonstrate both a diverse set
of interests and perspectives as well as any efforts to transform that diversity into
consistency (of code style, functional logic, and/or cultural expression); in both
respects, the developers' rhetorical awareness can have a significant impact on
future development and use of a given project. While there may be little explicit
discussion among programmers about the meaningful nature of the naming practices they
participate in, whether individually or collectively, there can be little doubt that
the names chosen reflect and influence how a particular code
project continues to be developed and applied. This is not to suggest that naming
practices are any less important in corporate or proprietary contexts, as
demonstrated by the “Richard Is a Fucking Idiot” case example above, as they are (by
their very nature) much less open, if open at all, to critical scrutiny from third
parties.
The procedural habits implicit in various naming practices in code are worthy of
further scrutiny, not only to understand more fully how they operate rhetorically
in
an immediate or obvious sense but also how they enact potentially prejudicial or
oppressive ideologies, whether those ideologies are recognizable to or intended by
any of the authors involved in a particular project’s naming practices or in naming
practices surrounding coding itself, e.g. the pejorative term
“code monkey”
frequently used to describe an unskilled programmer or low-status programming
position [
Easter 2020]. Similarly, offensive language was so prevalent in code
uploaded to the open-source repository GitHub during the early 2010s [
Romano 2013]
that the site’s administrators have since developed and enforced explicit policies
on
banning and preventing such language on the site [
GitHub 2022]. More recently, the
administrators for GitHub and a number of software projects have argued against the
conventional use of
“master” to describe the primary version or branch of a software
repository, seeking to replace the term with
“main” to reduce the use of racially
charged and historically loaded terms and to support the Black Lives Matter movement
[
Cimpanu 2020].
By attending more closely to how names and naming practices perform rhetorically in
a
range of significant ways, we — scholars, programmers, teachers, and citizens — can
work not only to communicate more effectively how code does and could operate but
also how that code contributes to the development of a more inclusive and considerate
world.
Acknowledgments
This article was originally developed for, but not published in, the short-lived
open-source journal experiment
Push: Research & Applied Theory
in Writing with Source. The author thanks
Push’s
founder Karl Stolley for that opportunity and is grateful to Chris Lindgren, Steve
Klabnik, and Ward Cunningham, who offered valuable feedback for the earliest
iterations of this article [
Brock et al. 2012].
Works Cited
Aristotle 1991 Aristotle. (1991) On
rhetoric: A theory of civic discourse (G. Kennedy, Trans.). New York: Oxford
University Press.
Brock and Mehlenbacher 2018 Brock, K. and Mehlenbacher, A. R.
(2018)
“Rhetorical genres in code”,
Journal of Technical Writing
and Communication, 48.4, pp. 383-411.
https://doi.org/10.1177/0047281617726278
Burke 1965 Burke, K. (1965) Permanence and
change. Berkeley and Los Angeles: University of California Press.
Burke 1966 Burke, K. (1966) Language as
symbolic action. Berkeley and Los Angeles: University of California
Press.
Burke 1969 Burke, K. (1969) A rhetoric of
motives. Berkeley and Los Angeles: University of California Press.
Burke 1973 Burke, K. (1973) Philosophy of
literary form. Berkeley and Los Angeles: University of California
Press.
Chun 2011 Chun, W. H. K. (2011) Programmed
visions: Software and memory. Cambridge: MIT Press.
Easter 2020 Easter, B. (2020) “Fully human, fully machine:
Rhetorics of digital disembodiment in programming”, Rhetoric
Review, 39.2, pp. 202-215.
Fish 1982 Fish, S. (1982) Is there a text
in this class?: The authority of interpretive communities. Cambridge, MA:
Harvard University Press.
Holmes 2017 Holmes, S. (2017) The rhetoric
of videogames as embodied practice: Procedural habits. New York:
Routledge.
Lakoff and Johnson 1980 Lakoff, G. and Johnson, M. (1980) Metaphors we live by. Chicago: University of Chicago
Press.
Nissen 2002 Nissen, H. E. (2002) “Challenging traditions of
inquiry in software practice”, in Dittrich, Y., Floyd, C., and Klischewski, R.
(eds.), Social thinking-software practice, Cambridge, MA: MIT
Press, pp. 69-90.
Noble 2018 Noble, S. U. (2018) Algorithms
of oppression: How search engines reinforce racism. New York: NYU
Press.
Sachs 2011 Sachs, J. (2011) “Glossary”, in Aristotle (J.
Sachs, trans.), Nicomachean ethics, Indianapolis and
Cambridge: Focus Publishing, pp. 201-212.