Abstraction Abstracted Russ Abbott Department of Computer Science California State University Los Angeles, Ca 01-310-202-8035 [email protected] ABSTRACT Abstraction generally takes the form of the extraction and reification of a parameterized common core from some area of interest. In software, abstraction often goes under the name of refactoring. Refactoring gives software the elegance prized by software developers. Refactoring requires constructs (such as procedures, classes, etc.) that can be used to build abstractions. Often these are provided by a programming language. Sometimes they are provided by design patterns. We can teach students how to understand and use these abstraction-building constructs, and we can teach students how to recognize some of the situations in which these constructs are applicable. But refactoring is a skill that we have not (yet) learned how to automate. Like any other skill, some people will be better at it than others. When abstraction—i.e., the thought process often referred to as analysis—is applied to domains outside software the result is typically an intellectual or conceptual model. When we as software developers implement such a conceptual model in software we are externalizing our thoughts as software. Confusingly, the conceptual model that some software implements is often referred to as an abstraction of the software. (It’s also referred to as a specification.) The sense of this usage is that the conceptual model captures the essence of the software without describing the implementation details. This is a somewhat misleading use of the term abstraction. A conceptual model abstracts and parameterizes its subject domain. That abstraction may then be externalized and implemented in software. When abstraction (as domain analysis) is applied to the domain of software itself, it results in conceptual models, which when externalized and implemented (in software) result in constructs, tools, and frameworks that provide most of the abstractionbuilding constructs used in refactoring. Confident and definitive as the preceding sounds, we are just beginning to understand abstraction. This essay is intended to be exploratory, tentative, and speculative. It raises as many questions as it answers. Keywords Abstraction, refactoring. 1. INTRODUCTION Liskov and Guttag [Liskov] describe what they claim are two kinds of abstraction: abstraction by parameterization and abstraction by specification. Abstraction by parameterization covers the traditional forms of software abstraction such as procedural abstraction (procedures, functions, methods, etc.), data abstraction (data types, classes, etc.), iteration abstraction, and polymorphic abstraction. Abstraction by parameterization extracts an essential core of some computational element, usually a process or structure, and reifies that core as a computational element of its own. A while-loop construct, for example, extracts iteration as a computational element and by providing slots into which a boolean expression and a procedural code segment may be inserted makes iteration available in a generic form. I will argue that abstraction by parameterization is the essence of abstraction in general and that refactoring is how we do abstraction as parameterization in software. In order to do abstraction as parameterization constructs must be available for expressing extracted essences. Programming languages provide many of those constructs. Software frameworks and libraries provide others. Programming languages, frameworks, and libraries are considered useful to the extent that they provide mechanisms that software developers can use to build abstractions. These notions are explored further in sections xxx. According to Liskov and Guttag, “Abstraction by specification abstracts from the implementation details (how the module is implemented) to the behavior users can depend on (what the module does).” The implication of this definition is that one finds a piece of code, figures out what it does, and then expresses that understanding as an abstraction. For some code this may actually happen, but in most cases, the abstraction process goes in the opposite direction. One knows the behavior one wants before the code is written; one then writes code that implements that behavior.1 How does one know what one wants? There is no single answer to that. But however one develops the idea about what one wants—e.g., by systems analysis, by fantasizing about a software system, etc.—what one wants exists as an idea in one’s mind before it is externalized as software.2 Section yyy discusses the process whereby one develops an idea about what one wants and then implements it in software. An idea certainly is an abstraction. The process of creating in one’s mind the idea that one wants to have implemented and then implementing it is an important aspect of software development. So abstraction has two important and distinct roles to play in software engineering. Abstraction allows software developers to write better, i.e., more concise and more elegant software. 1 Of course that description is grossly simplified. Most of the time, one starts with an idea, codes a version of it, works with the written code, discovers that it’s not exactly what one wants, changes one’s idea about what one wants, etc. 2 For a discussion of software as externalized thought, see [Abbott08]. Abstraction also connects ideas in one’s mind with software that embodies them. 2. SOFTWARE ELEGANCE I would guess that most of the participants in this workshop think of themselves—undoubtedly with justification—as top-notch abstraction practitioners.3 We are among those whom Kramer [x] singled out as being able to produce clear, elegant designs and programs, while others cannot. Abstraction is suggested as the source for this phenomenon. Some software is simply far more elegant and conceptually inviting than other software; software development is an art. At least many of the most accomplished practitioners of software development think so. This sentiment is not new. Knuth’s 1974 Turing Award lecture [Knuth] was entitled “Computer Programming as an Art” and his still incomplete 7 volume work on software is called The Art of Computer Programming. In his Turing Award lecture Knuth described his feelings about software. [W]hen we prepare a program, it can be like composing poetry or music … The possibility of writing beautiful programs, even in assembly language, is what got me hooked on programming in the first place. … Some programs are elegant, some are exquisite, some are sparkling. My claim is that it is possible to write grand programs, noble programs, truly magnificent ones! As a programmer4 I have my own sense of what I mean by abstraction and elegance in software. I often use the analogy of climbing a mountain. To realize that there is an abstraction that incorporates a number of previously disparate elements as special cases is like reaching a spot from which one can look out over the valley below. One now has a better perspective of how things that were once familiar in detail are related to each other more abstractly. One also sees that one is not at the top, that there is another lookout area above. After climbing to that next overview one has an even clearer perspective. But once one has understood 3 Other than to think itself, I have been unable to find an English word that refers to the act of creating and manipulating abstractions—she abstracts very well—or to someone who abstracts expertly—he’s a superior abstractor. 4 My Ph.D. is in Computer Science, and I am a professor of Computer Science. But at heart I’m really a programmer. I fantasize that if I ever retire, I’d adopt an open source system and spend my time coding—and writing papers about software and computational thinking. The position of programmer as a job title is commonly denigrated as referring to a low level task. I think that’s a mistake. One of the most important attributes of software is that it is executable. That’s what keeps software developers at all levels honest. But creating executable software is at its heart programming a computer. Consequently, in the remainder of this paper, I use the word programmer in the broadest sense as encompassing software engineer, software developer, software designer, software architect, etc. the view from that perspective one sees that with a bit more reorganization, one can reach a higher level view yet. It seems never to end. At each level one catches glimpses of yet higher peaks with better views. No matter how God-like one’s view of the code, there seems to be an even more elegant and more abstract way of understanding it. On the other hand, I also find myself getting closer and closer to the code I write. The analogy I use in describing that experience is to someone who loves woodworking. After building an initial serviceable version of an artifact her next step is to make it more finished by going over it with fine sandpaper. She lovingly takes time with it until the wood is soft and smooth. As she works the material, smoothing it, polishing it, and shining it, it begins to glow with an inner light. One cannot resist running one’s hands over its subtle surfaces. With software one takes both journeys simultaneously. As the code becomes more abstract it also becomes more clarified and its surface more limpid and elegant. The farther the software allows you to see as a vehicle for generality and abstraction, the more one appreciates its detailed beauty, the ingenious simplicity of each element, the mind-satisfying shape of each line of code, the clarity of thought revealed by each construct. One of the earliest proposed “methodologies” for software development was called “stepwise refinement.” [Wirth x] Refinement in Wirth’s sense meant decomposition from higher level constructs into lower level details. That sort of refinement is not what I find myself doing when I develop software. But if one understands refinement in its other sense—to polish, to improve, and to perfect—then for those who appreciate it, software development is indeed successive (if not necessarily “stepwise”) refinement. 3. REFACTORING: THE ROYAL ROAD TO ABSTRACTION Refactoring is commonly understood as “the process of changing a software system in such a way that it does not alter the external behaviour of the code, yet improves its internal structure.” [Fowler] Why would anyone ever want to do that? If refactored software behaves no differently from unfactored software, why bother? The standard answer appeals to pragmatic benefits: when one later wants to modify the software the refactored code with its “improved internal structure” will be easier to understand and less expensive to fix or extend. I doubt, however, that most expert programmers would agree that the ultimate measure of software quality is how easy it is to maintain. Software quality is more than just ease of maintenance. Most expert programmers are fanatical about refactoring. Why? In my view, expert programmers refactor to reveal and express abstractions—in particular the abstractions that identify and reflect the essential structure of the software. Plato spoke of “carving Nature at its joints” (Phaedrus 265d266a). When we refactor software, we don’t so much as carve the software at its joints as sharpen our understanding of it. What had seemed somewhat amorphous comes to have bones and other essential skeletal structures. In other words, abstraction is the identification or creation of underlying structure. Here’s an example. In writing an expression evaluator in Prolog one could write the following.5 eval(A + B, C) :eval(A, AVal), eval(B, BVal), C is AVal + BVal. eval(A - B, C) :eval(A, AVal), eval(B, BVal), C is AVal - BVal. eval(A * B, C) :eval(A, AVal), eval(B, BVal), C is AVal * BVal. … But one could also write the following.6 eval(Expr, Result) :Expr =.. [Op | Args], isArithmeticOp(Op), map(eval, Args, ArgsVals), Expr1 =.. [Op | ArgsVals], Result is Expr1. Why is this better? It’s certainly simpler; there is far less code. More importantly, it is more powerful—because it is explicit about what one does to evaluate an arithmetic expression. One extracts the arguments, evaluates them, reconstitutes the expression using the argument values in place of the arguments, and then performs the expression’s operator on the result. In being explicit about how to evaluate an arithmetic expression this refactored version of the code is more powerful. Once one has an explicit representation of the process required to evaluate an arithmetic expression, one can apply that process to any arithmetic expression. Of course this is not new; it is procedural abstraction, the sort of abstraction represented by any software subprogram. This example may seem more elegant because it manipulates symbolic expressions rather than numbers. But it’s really no different. The conversion of the first version of the program to the second is a prototypical example of refactoring. The general process of evaluating arithmetic expressions has been made explicit and reified by factoring it out of the original code and expressing it separately.7 By extracting and reifying the essence of the expression evaluation process one has gained leverage: a unit of knowledge has been created and made available for further use. This is not a minor issue. As discussed below, virtually every word is an abstraction. When we as human beings create a word for a concept we have captured and tamed that concept (tamed in the sense of breaking a horse) at least to the extent that we can refer to it whenever we choose. So when one factors out and thereby reifies an aspect of a computation, one not only creates a concept but also “breaks it to the saddle” so that one can put it to work elsewhere. 4. CLIMBING THE ABSTRACTION MOUNTAIN The example in this section offers a simple illustration of how one abstraction leads to another. Figures 1 and 2 show standard versions of depth-first and bread-first search. The idea is that these searches are methods in a Goal class. A goal (instance of Goal) is passed the root Node of a tree, which is searched for a node that satisfies it. The test that determines whether a particular node satisfies this goal is the following. this.isSatisfiedBy(node). The method dfSearch uses recursion to perform a depth-first search. The method bfSearch uses a frontier list (of Nodes) to keep track of the nodes at the current and next level to be examined. Although it may appear that dfSearch does not keep a list of nodes to be searched, in fact it does. Its call stack is essentially such a list. The primary difference between the lists kept by bfSearch and dfSearch is that the list implicitly embodied in the call stack is (naturally) treated as a stack whereas the frontier list maintained explicitly by bfSearch is treated as a queue. If the implicit list embodied by the depth-first search call stack is made explicit, the two search approaches can be combined. The reasoning is as follows. Both searches keep a list of nodes to be examined. Breadth-first search calls that list a frontier. In depthfirst search the list is implicit. But let’s call it a frontier in any case. In both searches, nodes are removed from the front of the frontier. The difference is that in breadth-first search the frontier is treated as a queue (the list of children is appended to the frontier) whereas in depth-first search the frontier is treated as a 7 5 6 Prolog programs manipulate tree structures. Thus A + B is the tree structure with root + and children A and B. The Prolog is operator evaluates its right hand argument (as long as it is an arithmetic expression) and unifies the result with its left hand argument. Thus the first clause (the first four lines) says that to evaluate the expression A + B one should evaluate the arguments and then apply the + operator to the results. The Prolog operator =.. converts between its left hand argument, which is a tree, and its right hand argument, which is a list whose first element is the root of the tree, and whose remainder is the list of children of the root. The Prolog notation for a list is [Head | Tail]. It is appropriate that the term abstraction should be used for a process that extracts the essence from something. The Online Etymological Dictionary [Etymological] offers this entry for abstract. 1387, from the Latin abstractus “drawn away,” past participle of abstrahere, from ab(s)- “away” + trahere “draw.” Meaning “withdrawn or separated from material objects or practical matters” is from 1557. The original late fourteenth century sense of abstract was to draw away from. One still finds that sense in current dictionaries: to abstract is to extract. By the mid sixteenth century, a sense evolved that the act of drawing away separated the essence of something from its material realization. stack (the list of children is prepended to the frontier). This realization can be expressed as the code in Figure 3. various ways. Naturally also the product of abstracting is an abstraction. One may justifiable argue that combing breadth-first and depthfirst search in this way does no honor to abstraction. After all, these two searches have very different qualities. Most notably depth-first is not complete where as breadth-first is. But Figure 3 makes the two seem like twins, which they aren’t. Nonetheless, Figure 3 does illustrate two features of refactoring. (a) An implicit element (the depth-first search list of yet-to-be-examined nodes) is made explicit. (b) An underlying essential procedural similarity is highlighted and parameterized. The conceptualization of abstracting as refactoring into a framework plus parameters is somewhat different from the standard understanding—as expressed, for example, in [Kramer]. In that article (and others) abstraction is said to be concerned “removing detail and [identifying] generalisations or common features.” More interesting is the next step. Figure 3 suggests that the key to search types is how the children of a node are added to the frontier. Best-first search is different from both breadth-first and depth-first children in that it maintains the frontier sorted by a measure of goodness. So to add best-first search to Figure 3 one would merge (in sort order) the children into the frontier. But why not abstract out the entire question of how to combine the children and the frontier? Figure 4 illustrates how that can be done: pass as a parameter to the search method an object that represents the search type and let that object decide how to combine the children and the frontier. This refactoring reifies the search type itself. Both steps in this sequence of refactorings show how reifying as a first class computational element a previously implicit element of a computation (first a list and then a code segment) often yields a useful abstraction. This sequence also illustrates how taking an initial abstraction step sets the stage for more steps as one climbs the mountain of abstraction. 5. DEFINING ABSTRACTION The standard understanding of a (formal) parameter in mathematics and computer science is “a variable that can be varied or changed.”8 In the following I will extend that notion and use the term parameter to refer to any “slot” within any structure that may be filled in multiple ways. I’ll refer to structures that have such slots as parameterized structures. It’s striking that there seems to be no standard English word that refers to the slots in parameterized structures—other than “slot” itself. Nor does there appear to be a standard English word that refers to the process of building such structures. Words that come to mind include structure, pattern and framework. But I know of no standard English verb that means to create such a thing. Recently Jeanette Wing [Wing] wrote about what she called “computational thinking” and argued that computer science has developed ways of thinking that are valuable beyond their direct application to computing. This seems to be a good example. We can and should export the notion of building parameterized structures. Before exporting the notion we should name the process first. Naturally I propose “to abstract:” to identify and characterize (a) the fundamental organization or structure of an area of interest along with (b) the slots within that structure that may be filled in 8 This definition is from Eric Weisstein's World of Mathematics (http://mathworld.wolfram.com/Parameter.html), accessed January 13, 2008. I’d like to explain why I don’t think that adequately conveys the notion of abstraction as we do it in software development. In doing so, I hope to elaborate my sense of what it means to abstract. Abstraction is not the removal of detail. I would argue that abstraction is not the removal of detail but its parameterization. This becomes clearer when one thinks about abstraction from the perspective of refactoring. A refactored program is not the same program with detail removed. It is a reorganization of the program so that essential structures are made visible—as in an X-ray in which one sees inside an object and understands its internal structure, perhaps for the first time. To make essential structures visible, one highlights them and brings them to the foreground while putting the non-essential elements in the background. But the non-essential elements are not discarded. When one refactors, the connections between the essential structures and non-essential elements are retained. Typically those relationships are reflected as a parameterization of the non-essential elements within the essential structures. Consider, as a non-software example, the category of human beings. There are many details—height, blood type, eye color, a genetic code, etc.—about any particular person whose specific values are not essential to characterizing her as a human being. But it makes no sense to talk of human beings who don’t have a height or a blood type or a genetic code. Those non-essential values may differ from one human being to another, but they exist in all human beings. They are parameters in the “human being” abstraction and not discarded elements. This becomes clear when we conceptualize abstraction as refactoring. Abstraction is not generalization. A standard example of generalization in software engineering is the relationship between a class and its super-class: a super-class is a generalization of its sub-classes. I would argue that it’s not reasonable to say that a super-class is an abstraction of its subclasses. Abstraction and generalization are two different concepts. It’s often the case that a generalization has the same essential structures is its more specific cases. And generalization may be a good way to see those essential structures more clearly. But generalization and abstraction seem (at least to me) to be two different concepts. Again, refactoring makes this clear. Refactoring is often used to create super-classes. When one performs such a refactoring the step from one or more individual classes to a super-class— along with the newly declared subclass or subclasses—qualifies as abstraction because the refactoring has identified an essential structure that is separated out from the subclass or subclasses. But again, the subclasses are not discarded. They are (implicitly) parameterized when the super-class is defined. In virtually every object-oriented language, every class is capable of having subclasses created from it. Thus every class, simply by virtue of its being a class, has (perhaps virtual) “slots” predefined as available for subclasses. When a superclass is created from an existing class or classes, one is demonstrating one or more ways in which the new super-class’s subclass slot(s) may be instantiated. To say that every class has “slots” for subclasses is not very different from saying that every class has “slots” for instance variables or that every subprogram has a “slot” for procedural code. The class structure by definition has defined within it the possibility of having subclasses defined. Thus the refactoring step of creating a super-class from one or more existing classes is equivalent to the refactoring step of creating a procedure from one or more code segments. In both cases one is factoring out an essential structure and identifying how the defined slots may be filled in a particular case. New constructs such as a new class or a new procedure are powerful because they explicitly identify and reify a (presumably) important structure—along with that structure’s parameters. Abstraction is not the identification of common features. The fact that the sky and the ink in my pen in my pocket are both blue doesn’t make the category of blue things an abstraction. It is sometimes useful to focus on particular attributes. But I would argue that it’s not reasonable to say that “blue thing” is an abstraction of either the sky or the ink in my pen. Grouping elements together just because they have features in common does not produce abstractions. Abstraction is not formal methods. Compare and contrast with http://www.stsc.hill.af.mil/crosstalk/2008/01/0801DewarSchon berg.html. According to Liskov and Guttag, abstraction by specification “abstracts from the implementation details to the behavior users can depend on. It isolates modules from one another’s implementations; we require only that a module’s implementation supports the behavior being relied on.” A “worrysome trend” [Dewar], 1. Mathematics requirements in CS programs are shrinking. 2. The development of programming skills in several languages is giving way to cookbook approaches using large libraries and special-purpose packages. “The irresistible beauty of programming consists in the reduction of complex formal processes to a very small set of primitive operations. Java, instead of exposing this beauty, encourages the programmer to approach problem-solving like a plumber in a hardware store: by rummaging through a multitude of drawers (i.e. packages) we will end up finding some gadget (i.e. class) that does roughly what we want. How it does it is not interesting!” The opposite of creative abstraction. This is an attempt to reduce everything to fundamental physics. See [Abbott] Emergence. 6. IS EVERY CONCEPT AN ABSTRACTION? Or does it? When we group elements together because they have some feature in common why isn’t that an abstraction? Thought is all about abstractions. Is there a concept that is not an abstraction? In [Abbott if a tree] I claim that computation is exactly the externalization of thought—but I don’t attempt to define what I mean by thought, leaving that as a primitive. I don’t claim to have a philosophy of thought that I could explain were there more room in this article. I don’t. (For a review and discussion of concept see [Margolis].) I would like to assume that we are similar enough in our subjective experience of thinking that we have (or can agree to) a mutually consistent sense of what we mean by a concept. Given that assumption, we can take the notion of a concept as a starting point. Is every concept an abstraction? Certainly every concept is a intentional, i.e., it is about something—real or not real. It’s not clear to me whether it’s possible to have a thought that is about itself. (Perhaps that can be a Zen koan: can one think a selfreferential thought? What about the simple case of thought or concept itself? These seem to be self-referential, but not in a paradoxical way. What would seem more difficult would be a thought that referred to nothing other than itself. Concept and thought refer to the entire class of concepts and thoughts and not to the thing itself.) But other than that possibility, concepts are about something other than the concept itself. Does that make them abstractions? It may make them abstractions in the sense that a concept typically includes essential (to the thinker) elements of the concept’s referent—and leaves other aspects open for later binding. This is true when the concept is both a category (house) and an individual (my house). This is consistent with the notion of abstraction discussed above. Human beings have done quite well as a result of our ability to conceptualize. Are we talking about abstraction in thinking or in computing? Are they different? Fables are abstraction in thinking, but not computing. To what extent is the ability to do abstraction comparable to the general “g” measure of intelligence? That is, we can measure individual intelligences, and we can find a correlation, which we refer to as “g.” We can probably measure programming ability in multiple languages and frameworks. There is also probably a correlation. It’s unlikely that we can teach that. 7. BUILDING ABSTRACTIONS REQUIRES STRUCTURING MECHANISMS It’s also harder (in some sense) for CS in that if one doesn’t remember the notation, it starts to look foreign after a while. For example, here’s a lazy evaluation approach to computing the primes. primes = (sieve [2 .. ]) where sieve (p:xs) = p : sieve [x | x <- xs, (x `mod` p) /= 0] Uses list comprehension, list construction (:) and lazy evaluation besides the built-in functions take, mod (used as an operator), and /=. It also makes use of the ability to define a function on the fly using where. fib = 1 : 2 : zipWith (+) fib (tail fib) Uses zipWith, lazy evaluation, functions a first-class objects (+), tail, list notation (where : associates to the right), and infinite lists. 8. WE CAN TEACH STRUCTING MECHANISMS BUT WE CAN’T TEACH THEIR CREATIVE USE Can we build development environments that are able to suggest refactorings? If so, then we can certainly teach abstraction—at least at that level since we can teach it to computers. But if we can’t, then why should be assume that we can teach abstraction to people? Can that be taught any more than painting or piano playing? Probably one can teach about abstractions: does it offer conceptual convenience. It might be useful to attempt to develop a theory of abstraction qualities similar to a theory of aesthetic qualities in music, painting, writing. Those can certainly be taught. Can’t teach musical genius. Can one even teach a good pianist to be a good violinist? Or a good jazz pianist to be a good classical pianist? Or a poet to be an essayist? Is that different from being good with the abstractions in different languages or frameworks? To what extent is there are general abstraction skill? And can it be taught? 9. DESIGN PATTERNS ARE ABSTRACTIONS We certainly can “teach” computers to “do” the abstractions that are built into frameworks, languages, tools, etc. But that doesn’t mean we can “teach” computers to use them to develop programs. So even if we can teach people to understand those abstractions, that doesn’t mean we can teach people how to write elegant code using them. What about history? Does that teach modeling? 10. ALL SOFTWARE DEVELOPMENT IS ABSTRACTION: EVERY CONCEPTUAL MODEL IS AN ABSTRACTION Model building is both. Especially when the model is built explicitly. That's the abstraction. But isn't that just thinking? Isn't that what most academic disciplines teach in one way or another? Not the art disciplines. Some of them refine the senses. As a computer scientist it's hard for me to think of teaching anything else. 11. PROGRESS IN SOFTWARE (ALONG ONE AXIS) IS THE IDENTIFICATION AND IMPLEMENTATION OF INCREASINGLY POWERFUL ABSTRACTINOS Do search examples. How are elegance and abstraction related? From the website: Teaching Aesthetics to Artists. Most contemporary art forms already have a body of theory which for most artists constitutes the intellectual dimension of their field. This theory is often created by artists themselves, or by critics working closely with them, and it is ultimately visionary rather than analytical in nature. It is to be found in the manifestos, the avant-garde magazines, the interviews with artists, the reverential accounts by their disciples, that define the many artistic movements that have dominated our century. For the most part, this theory is prescriptive; it is concerned with defining art only in order to advocate a particular kind of art, and its discussions of aesthetic value, of the social effects of art, and of such classic issues in aesthetics as the nature of artistic meaning or the purpose of art, are all loaded to show that the work of a particular school or artist embodies the highest or latest development in the art form in question. Of course this kind of writing can be wonderfully creative and inspiring, and it naturally excites many artists. But the fact that “theory” for most student artists means this kind of artistic advocacy makes it harder to convince them of the value of aesthetics as most of us understand it—an attempt to analyze what is actually happening in the creation and appreciation of art, not to provide a rationalization for the work of a particular group of artists. The plodding work of analysis cannot compete with the glamour of “theory” as the term is used in most contemporary art forms. Sounds a lot like programming framework and language manifestos, which also are abstractions. Also like the proponents of patterns, object-oriented programming, etc.—also abstractions. All of software development is abstraction. What is abstraction? Is it a dimension of intelligence? Gardner’s dimensions of intelligence. Doesn’t mention, for example, olfactory intelligence or sensory intelligence. How are skills distinguished from intelligences? What sort of brain components do we have. (I don’t think we know.) Even if we did know, there are other integrating functions that also matter, which we also don’t know about. Is every word an abstraction? If every word is (approximately) an abstraction, that’s not what we’re looking for. Even proper nouns (and definite descriptions) are abstractions since they refer to individuals/entities who are different (literally and figuratively) from time to time. So a proper noun is an abstraction for an individual. But what we want in software is the ability to create new abstractions that reflect not coding efficiency but conceptual economy and efficiency: refactoring and reuse. As computers become able to deal with more and more domains, more abstractions will become important in SW-Engr. For example, what about image abstractions, which I don’t understand. For example, what about the image transformations that image manipulation programs perform, such as add what Picasa calls fill light or increase shadows and highlights in Picasa and layers in Photoshop. What about removing red-eye or “intelligent scissors?” Not a deep abstraction but certainly useful. These are probably not abstractions done elegantly at the software level but very useful at the user level. And transparency, which wasn’t available as an abstraction until someone figured out how to implement it by averaging pixel values. These abstractions are important because they do a good job of matching our intuitions and provide good ways of dealing with things in the world. But are they abstractions in the sense intended by this workshop? Is any library of concepts abstractions in that sense? Java generics are an abstraction of specifically typed data structures. But that’s an example of refactoring. They also don’t always reduce algorithmic complexity in the sense of making programs smaller. In fact, one doesn’t have to use them. Their use—like the use of types in general—tend to make programs better. But programming with bits (i.e., in assembly language) and without types will work. But it puts the burden of understanding the program on the programmer. It doesn’t externalize all the information in the mind of the programmer. We in computer science are always looking for abstractions—and we have done a very good job of finding lots of powerful ones. Sometimes abstraction is taken to mean the distinction between a specification and implementation. The specification is the abstraction. (Don’t agree.) Every time a biological organism (or some other device) is capable of making a distinction it has created an abstraction. Actually, I don’t think so. Making a distinction—say that changes behavior—is not the same as an abstraction in that an abstraction (a concept) implies an idea in the head. So if the thing that makes the distinction doesn’t have a conscious idea that goes along with the distinction it isn’t creating an abstraction—or at least not an explicit abstraction. But that sort of abstraction is a matter of category rather than a matter of combining things and categories, which is what the workshop sense of abstraction is about. What’s the real difference other than how you got there? Is abstraction more conceptual? Does it necessarily imply a category that can’t be reached directly but must be reached by abstracting away from some existing categories or things? So teaching frameworks, tools, languages does help in teaching abstraction since students will use the tools and are forced to think in terms of the abstractions they embody. This doesn’t teach people how to be creative in generating abstractions any more than learning aesthetics or a new style teaches artists how to be creative in terms of the aesthetic concepts or style they learn. Is abstraction for software like beauty in art? Not quite since it is more functional. Still, recursion is a powerful programming technique. But the recursive aspects of it can be factored out into what is known as a visitor pattern. A visitor pattern is a software structure that accepts as one of its two inputs a tree and as the other a chunk of software. The visitor pattern traverses the tree and applies the processing software to each node. In this way the recursiveness has been factored out of the processing software — which now need not worry about anything but the processing steps — and encoded separately in the visitor pattern. Even more generally a visitor pattern can be applied to any data structure. It need not be a tree. Tree search. (See appendix.) Is this a good abstraction? I don’t know. Depth-first and breadth-first have very different properties. Spaceintensive vs. not. Complete vs. not. So is it a good idea to combine them in a single elegant piece of code. The code illustrates what’s common about them. It doesn’t illustrate the significant ways they differ. 12. SOFTWARE IS EXTERNALIZED THOUGHT, I.E., EXTERNALIZED MODELS. SO WE SHOULD TEACH STUDENTS HOW TO CREATE CONCEPTUAL MODELS AND HOW TO EXTERNALIZE THEM This position also argues for teaching computer science students as many (mental) modeling techniques as we know — including mathematical techniques. As noted earlier, the point is not to teach mathematics as mathematics but to teach mathematics as a language for expressing models. It would be useful to computer science students to teach them mathematics in this way, i.e., as a way to model problem domains. In most mathematics courses, the use of the mathematical tools for modeling purposes tends to be taught as an afterthought or as an exercise. It would be much more useful (at least to computer science students and to most nonmathematics students) to teach the subject as modeling tools rather than as formal mathematics. It would be even better if the modeling aspect were taught separately from the solving of the equations. There are many systems available that can solve equations once they are generated. It would be useful to teach mathematics to nonmathematicians by using those systems. The goal of the course would be to teach students how to use a mathematical modeling language as a way to characterize a problem. Once a problem were characterized, the tool would use the equations to help one understand the problem from various perspectives. This would mean, for example, teaching a course in system dynamics to computer science students rather than teaching a course in partial differential equations. System dynamics could be taught much earlier and with far fewer mathematical prerequisites than today's courses in partial differential equations. Of course, those students who wanted to know how the system solved the equations or how to build a system dynamics modeling system would have to learn the necessary mathematics. But for most computer science students, it would be quite valuable to learn how to express relationships in terms of partial differential equations even if they relied on software to solve or simulate the effects of those equations. This is analogous to the way we teach programming languages. We teach all students how to write in a programming language. Only some students learn how to write compilers. I think that if mathematics were taught that way it would in fact help computer science students learn how to think more abstractly. Each such mathematical modeling framework would be another tool they could use to understand a situation from one or another abstract perspective. The same argument could be made about many other disciplines. Most disciplines develop models of their domains. It would be useful for computer science students to learn as many ways as possible to conceptualize the world. The challenge then would be to find ways to make models developed in other disciplines expressible in an executable form, i.e., as software. Of course most software does not attempt to model something that exists in the world prior to the software. Most software is the development of something new. But consider how our intellectual abilities work. We evolved the ability to conceptualize the world presumably because it was a useful survival capability. But once we developed that ability, we used it to invent new worlds — to write fiction — as well as to conceptualize the world as it is. The same is true for software. Most of the software we write involves developing models of things that don't exist elsewhere. But the ability to build software that models anything is grounded on the ability to write software that implements models in general — of both existing and imaginary elements. So it makes sense to argue that computer science is the study of building models and that anything that helps develop that ability will contribute to one's ability to write better software. Abstraction, then is the factoring out common elements in model building and understanding those common elements as conceptualizations on their own. My department is in the School of Engineering, Computer Science, and Technology. We recently had a school-wide open house in which we wore T-shirts that said "Turning dreams into reality." Although I don't for the most part think of Computer Science as an engineering discipline, I agree that we have that in common. We are both creative disciplines in which we create visions, which we then transform into something that exists in the material world. (Even software and the cyberspaces that it creates exist in the material world.) Engineering is said to be the application of science to practical ends. If one thinks of engineering as transforming dreams to reality, it is far more than that. But science is what underlies engineering. It provides the understanding that allows the engineer to transform a dream into reality. Perhaps in the same way, modeling serves as the "science" of computer science. It's the understanding of models and how models work that allows software developers to transform their dreams into software reality. But is the step of going from the intuitive notion of the size of a collection to the mathematical notion of number mathematics, or is mathematics the step of formalizing this new notion of number and proving theorems about it? In my experience, mathematics has always been about the latter, i.e., proving theorems about existing abstractions. The actual process of coming up with the abstraction about which theorems should be proved is considered somehow pre-mathematics. Computer science has been called applied philosophy. It's the only discipline that has created languages that can both (a) represent ideas in one's head and (b) produce results in the physical world. Software is the externalization of thought in a symbolic and executable form. No other discipline can claim anything like that. Definition of analysis and model and abstraction. Interestingly enough, Dictionary.com again comes up with a relevant definition of analysis. Analysis: a method of studying the nature of something or of determining its essential features and their relations: the grammatical analysis of a sentence. Model: a simplified representation of a system or phenomenon, as in the sciences or economics, with any hypotheses required to describe the system or explain the phenomenon, often mathematically. (Dictionary.com) Absraction: philosophy conceptualization: the philosophical process by which people develop concepts either from experience or from other concepts. (Encarta.com) Abstraction: the process of formulating general concepts by abstracting common properties of instances (Wordnet.edu) 13. REFERENCES All Internet accesses are as of January 24, 2007. [2] Abbott, Russ, “If a tree casts a shadow is it telling the time?” Journal of Unconventional Computation, to appear. [1] Robert B.K. Dewar and Edmond Schonberg, “Computer Science Education: Where Are the Software Engineers of Tomorrow?” Crosstalk: the Journal of Defense Software Engineering, January 2008. http://www.stsc.hill.af.mil/crosstalk/2008/01/0801DewarSch onberg.html. [2] Fowler, M., Refactoring: Improving the Design of Existing Programs, Addison-Wesley, 1999. Harper, Douglas (ed), Online Etymological Dictionary, http://www.etymonline.com/index.php [1] Knuth, Donald E. “Computer programming as an art,.” Commun. ACM 17:667-73, 1974. http://fresh.homeunix.net/~luke/misc/knuth-turingaward.pdf. [2] Kramer, Jeff and Orit Hazzan, “The Role of Abstraction in Software Engineering,” in Proceeding of the 28th international conference on software engineering, ACM, 2006, pp 1017 – 1018. [5] Liskov, Barbara and Guttag, John. Program development in Java. Addison-Wesley, 2000. [2] Margolis, Eric and Stephen Laurence, "Concepts", The Stanford Encyclopedia of Philosophy (Winter 2007 Edition), Edward N. Zalta (ed.), URL = http://plato.stanford.edu/archives/win2007/entries/concepts/. [2] Wing, Jeanette, “Computational Thinking,” Communications of the ACM, March 2006, (49, 3) 33-35. http://www.cs.cmu.edu/afs/cs/usr/wing/www/publications/Wi ng06.pdf. [6] Wirth, Niklaus, “Program Development by Stepwise Refinement,” Communications of the ACM, Vol. 14, No. 4, April 1971, pp. 221-227. http://www.cs.unca.edu/~brownsmi/0408_Fall/csci431/resou rces/generalReference/PgmDvmtByIterative.htm. Figures public Node dfSearch(Node node) { if (this.isSatisfiedBy(node)) return node; for (Node child : node.children) { Node solution = this.dfSearch(child); if (solution != null) return solution; } return null; } Figure 1. Depth-first search. public Node bfSearch(List< Node > frontier) { while (!frontier.isEmpty()) { Node node = frontier.remove(0); if (this.isSatisfiedBy(node)) return node; frontier = append(frontier, node.children); } return null; } Figure 2. Breadth-first search. public Node parameterizedSearch(List< Node > frontier, boolean breadthFirst) { while (!frontier.isEmpty()) { Node node = frontier.remove(0); if (this.isSatisfiedBy(node)) return node; // For breadth-first search put the children at the end of the frontier as usual. // For depth-first search put the children at the front of the frontier, simulating a stack. frontier = breadthFirst ? append(frontier, node.children) : prepend((node.children, frontier); } return null; } Figure 3. The search type has been parameterized: breadth-first or depth-first. public Node abstractedSearch(List< Node > frontier, SearchType searchType) { while (!frontier.isEmpty()) { Node node = frontier.remove(0); if (this.isSatisfiedBy(node)) return node; // searchType.merge(node.children, frontier) merges node.children // into frontier. Depending on the SearchType, the merge may produce // a breadth-first, depth-first, best-first, A* or some other search strategy. frontier = searchType.merge(frontier, node.children); } return null; } Figure 4. The search type has been abstracted.
© Copyright 2025 Paperzz