«Creativity Support for Computational Literature By Daniel C. Howe A dissertation submitted in partial fulfillment of the requirements for the degree ...»
In surveying the available environments, only two options presented themselves that appeared to satisfy a majority of these criteria, both of which used somewhat extensively in digital arts and introductory programming courses; specifically Adobe's Flash and associated ActionScript language, and Processing by Casey Reas and Ben Fry, an API and simplified programming environment using Java. The various tradeoffs between these two web publishing environments have been the subject of much debate, but for our purposes, the fact that Flash programs could only be authored in the proprietary, relatively expensive, and somewhat opaque Flash environment simplified the decision.15 Further we found Java to be a good fit as a general purpose language for teaching programming, not least of which due to the fact that it is free, open-source, and in wide use across a range of contexts. Further, it supports powerful (if less than perfect) object-oriented capabilities and has a relatively transparent syntax, especially for those familiar with other C-based languages. Lastly, in addition to a large and active user community, there exist a vast number of libraries and frameworks (both internal and external) available to extend the core language in many imaginable directions.
This is not to say that this choice, and Java itself, does not present potentially significant drawbacks. A specific example of such a drawback is the separate compilation step required before one can run a Java program, a language “feature” in direct conflict with a number of the design criteria presented above. This problem, however, had already been addressed in two ways: first by the Processing environment itself, which combined “compile” and “run” into one action (with a simple “play” button widget), and second, by the Eclipse IDE which performs continual compilation, highlighting syntax and other errors as the programmer types. By the second iteration of the course, students were encouraged to use This situation has changed somewhat recently with Adobe’s announcement in 2008 that the Flex 3 SDK would be made available under the open-source Mozilla Public License.
Flash Player, the runtime on which Flex applications are viewed, and Flex Builder, the IDE used to build Flex applications, however, remain proprietary.
either or both of these tools, depending on their experience and comfort level with each. For those wishing to migrate from Processing to Eclipse, an online tutorial was created and an optional help-session, led by the teaching-assistant was scheduled.
A second drawback to using Java in the classroom was its lack of a rapid prototyping framework, as even the simplest Java programs require class definitions, typed functions, a main routine or html-page, and at least some understanding of “static” scoping for variables and methods, not to mention a host of potentially troublesome setup options including file and directory/package structures and classpath specification. Again however, most of these issues had already been addressed by the makers of Processing, who explicitly designed the environment to eliminate such considerations from the learning process. Running a simple Processing program—e.g., drawing a line to the screen—can be accomplished by writing a single line of code and pressing the “play” button (see Figure 1). Further, though Processing supports object-orientation (all of the Java language is in fact supported), its basic mode of operation is procedural, with simple function calls made via the Processing API. As new techniques were learned—e.g., user-defined functions, objects, classes, interfaces, polymorphism—students could integrate these into more complex programs while still using the Processing functions where desired (either within Processing or in a more advanced environment like Eclipse.) As one student commented16 in an end-of semester reflection, [R]apid prototyping is definitely the most important truth I will take away from this course and this semester in general. Due to the freedom of our digital medium it takes no time to come up with a random idea and layer it with level upon level of abstraction, but to know it’s a good idea you pretty much have to prototype it and the faster the prototyping the faster you can To protect student anonymity, names and dates have been omitted for student quotations.
Unless otherwise noted, all student quotations are from the ‘Programming for Digital Art & Literature’ course.
Figure 1: A one-line Processing sketch.
Of course there are still other aspects of Java, at least “out-of-the-box”, that are less than ideal for arts-based software practice, e.g., the lack of dynamic typing, first-class functions, an interpreted execution mode, and “live-coding” support (topics discussed elsewhere,) all of which are present in languages like Ruby and Python. Yet for the requirements we had decided upon, most specifically web-based graphical execution, it was clearly the best selection from the existing choices.
2.2.2 Design Criteria The constraints of technique, resources, and economics underdetermine design outcomes. To account fully for a technical design one must examine the technical culture, social values, aesthetic ethos, and political agendas of the designers. [Pfaffenberger 1992] Once a base environment in which to implement the toolkit had been selected, we identified several criteria which we felt would be important in design and implementation, generally following the methodologies laid out in earlier work on design methods [Friedman et al. 2002]. These criteria are listed below in their initial order of importance, though their relative priority changed throughout the design process. Likewise, we also attempted to decide what goals the toolkit would not attempt to accomplish and thus created a list of explicit anti-criteria, which the toolkit was not expected to satisfy [Bird and Loper 2002]. As discussed elsewhere17, we were cognizant of the possibility that specific implementation decisions could (and likely would) bring design criteria into conflict with one another, specific cases of which are discussed below.
220.127.116.11 Requirements Ease-of-Use. The primary purpose of the toolkit was to allow students to effectively • implement their own creative language works. The more time students spent learning
Consistency. The toolkit should use consistent naming, syntax, functions, and design • patterns. Therefore if one object was created via the traditional call to “new()”, another should not be created via a static or factory creation pattern.
See the discussion of “design conflicts” in Howe and Nissenbaum .
Extensibility. The toolkit should easily accommodate new component • implementations, whether for replication of existing functionality (in exercises or assignments), or for the addition of new (for the needs of specific projects.) Documentation. The toolkit, its components, and its implementation should be • carefully and thoroughly documented and updated. All naming conventions should be carefully chosen and consistently used.
Design-By-Interface. Even if not exposed in basic usage, all core objects should be • implementations of interfaces and typed internally as such, thus allowing students to build and easily test their own implementations in exercises or assignments. In the case of RiTa, this practice facilitated the development of multiple implementations of an object for different use-cases; e.g., a transformation-based tagger when speed and memory footprint were of primary concern, and a slower but more accurate maximum-entropy version for general use.
Small/Light. To enable download and execution in web browsers, the library should • be as efficient as possible with resources, most importantly browser memory. The most recent core version of RiTa (not including the WordNet database or the TTS voices] was ~2.5 MB.
Modularity. The interaction between different components of the toolkit should be • minimal, using simple, well-defined interfaces. In particular, it should be possible to complete individual projects using small parts of the toolkit without concern for how they interact with the rest. This allows students to learn the library incrementally over one or more semesters.
Share-ability. Students programs should be easily exportable as web applets • including generation of HTML pages and web-browsable source code. To facilitate this, the toolkit should be efficient enough, in terms of memory, to ensure that student programs can run in common web browsers.
Performance. Library functions should be fast enough that students can use the • toolkit for interactive projects with functions returning in 'perceptual' real-time.
Transparency. The library and its underlying support APIs (Java Processing, etc) • should all be freely available with easily browsable and well-documented source
Platform Agnosticism. The library should contain no operating system-specific code • or behavior, allowing it be used in all major browsers and on all common platforms.
18.104.22.168 Anti-Requirements Comprehensiveness. The toolkit is not intended to provide a comprehensive set of • tools for natural language processing or digital art. Instead, it should facilitate the addition of new functionality to either extend the toolkit itself or to integrate it with
High-Performance. The toolkit need not be highly optimized for maximum runtime • performance as long as the constraints mentioned above on memory and “perceptual”
Cleverness. Clear well-documented designs and implementations are generally • preferable to ingenious yet opaque ones, as advanced students (and practicing artists) should feel comfortable examining the source-code of the library itself.
Object-Orientation. Consistency and conformity to intuitive use-patterns (both within • the library and with the Processing environment) should come before best-practice rules and patterns for object-oriented design.
2.2.3 Design Tensions At various times in the development and deployment of RiTa we identified tensions between two or more of our design criteria. When such tensions were recognized, following our prior work on activist gaming strategies [Flanagan et al. 2005], they were added to an evolving list, each of which was assessed in subsequent design iterations, much in the way that regression testing was employed to validate continuous technical progress.
22.214.171.124 Strings and Features An example of a specific design tension that arose during implementation concerned RiTa's internal representation of character data. As discussed above, a flat String-based approach was eventually adopted, with each character string (potentially) linking to a map of key-value pairs (referred to as “features”). The potential augmentation of the Java String with such a map (the basic RiString object) allowed for data to be continually accumulated as an object was processed by different core components.
The notion of “features” originated in the Festival speech synthesis system18, in which a similar mechanism was used to avoid the disadvantages of both “string-rewriting” and “multi-level data structures”, common mechanisms in systems at the time [Taylor 1998].
Unlike Festival, RiTa does not maintain separate data-structures of “relations” between linguistic items, e.g., the words that constitute a phrase, or the phonemes that constitute a word. Rather, all such information is embedded in the feature data itself.
For example, one might begin with a RiString object containing the string “the white rabbit”. This RiString might then be passed to a RiAnalyzer object where word-boundaries would be determined and each word tagged with part-of-speech, stress, syllables, and See http://www.cstr.ed.ac.uk/projects/festival/.
phoneme features, then to a RiChunker object which would add a “chunk-type” feature, tagging the phrase as a “noun-phrase”. We might then tag the phrase with “custom” features specific to our application. As trivial examples we can use the URL (with key “sourceURL”), where the phrase was found, perhaps during a text-mining operation, and the number of letters in each word (with key “letters-per-word”). Thus our feature data would appear as in Table 1, with custom feature displayed in italics.
Table 1: Feature data for an example RiString phrase19.
Once we have a RiString for a phrase containing multiple words, as above, we can use RiString.split(), to split the phrase into three new RiString objects20, one for each word.
Thus, assuming the RiString above was named “phrase1”, the following lines of code:
Note that the word and syllable boundaries are, in this case, the tab and forward-slash characters respectively, though these can be programmatically specified by the user.
Note that each RiString is assigned a unique identifier on creation to enable easy crossreferencing via the feature-map. For example, a RiString containing a single word might have
would result in a reference to a new RiString representing the last word of the phrase, i.e., “rabbit”, the features of which are shown in Table 2.
Table 2: Feature data for an example RiString word.