record has yet to propagate). In another dimension, a richer conceptual view of a web service would recognize that, due to load balancing across servers, an update by one user might not be visible to another user, even aer the second user has submied a later update that was accepted. To understand this, you would need a concept of *web service* that incorporated the notion of eventual consistency.

Understanding the security properties of browsing the web is challenging because so many disparate components and systems are involved, and their functionality is oen very complicated. In contrast, application designers seek to present the user with a smaller world—an enclosed garden rather than a busy city—that can be understood in its entirety.

25. e limits of learnability. e designer has a responsibility not only to design good concepts, but also to *map* them: to represent them faithfully and compellingly in the user interface to maximize the chance that the user will create a matching mental model.

is is not easy. Some concepts are inherently complex, and some users are less able to infer even simple concepts. As Amy Ko has wisely noted, the standard goal of "learnability" in user interface design should be taken with a grain of salt [82]. Not all concepts can be "taught" through the user interface, and rather than learning through experimentation, most users learn through a social process of engagement with friends and colleagues who demonstrate and explain apps to each other. Most concepts, moreover, are not new but are familiar to users from previous apps, so no single app is solely responsible for teaching a concept.

Of course, apps designed for experts may include concepts whose power is obtained at the cost of some complexity, and in that case, expecting users to be trained is reasonable. e concepts of *channel*, *layer*, and *mask* in Adobe Photoshop, for example, present formidable complexity and confusion to novices, but can be mastered if approached systematically—by learning the concepts one at a time. Learning by trial and error, and watching endless online short video tutorials, is not very eective, despite being the most popular approach.

## *Chapter 3: How Concepts Help*

26. e power of paragraphs. As an example of how the *paragraph* concept in Word is stretched to encompass the kind of functionality you'd expect to be provided by additional concepts, consider the formaing of chapters. Rather than having a distinct chapter concept, Word allows you to dene a paragraph style—called *chapter heading*, say—using the *style* concept, which, in combination with the *format* concept, allows each paragraph that opens a chapter to be set in an appropriately large

font and given the formaing property *page break before* so that a new chapter always starts on a new page.

Word does in fact have a *section* concept, but it's not what you might imagine. Rather than being a subdivision of a chapter (a concept that does not exist in Word), it represents a contiguous sequence of pages with the same formaing.

- 27. Misunderstanding the trash concept. In one history of the trash, published in Slate, we're told that it was invented "[w]hen the team realized that users needed a way to delete les permanently." But permanent deletion is easy: the hard part was designing a way to get les back! (Cara Giaimo, Why Only Apple Users Can Trash eir Files, *Slate*, April 19, 2016[; hps://slate.com/human-interest/2016/04/the](https://slate.com/human-interest/2016/04/thehistory-of-the-apple-trash-icon-in-graphic-design-and-lawsuits.html)[history-of-the-apple-trash-icon-in-graphic-design-and-lawsuits.html\)](https://slate.com/human-interest/2016/04/thehistory-of-the-apple-trash-icon-in-graphic-design-and-lawsuits.html).
- 28. Apple's song concept. In his biography of Jobs [59], Walter Isaacson noted that, unlike Apple, Sony was not only a leader in consumer electronics but had its own music division—and yet it missed the opportunity to unify those capabilities with the concept of a *song* that could be sold directly to consumers. Even the granularity was new; prior to Apple's innovation, a song could be played but could not be bought: you had to buy a whole album. Although the sleek appearance of the iPod got all the aention when it was rst released in 2001, its success can be aributed as much to the *song* concept as to the new technology that made it possible (the FireWire connection that let you upload all your music in an hour, and the microdisk that stored it).
- 29. e frequent yer concept. e *frequent flyer* concept might even be described as a *dark concept* (by analogy to dark paerns in user interface design) on account of the array of tactics that airlines have developed to make it as unusable as possible. For example, many airlines cause miles to expire but go to great lengths to hide the expiry date from customers, excluding it, for example, in email updates; they make it hard to spend miles by ensuring that very few seats on a given ight are available for reward redemptions; they tempt customers to exchange their miles for low-value magazine subscriptions; and they introduce complex formulas so that discounted seats, and those sold through airline partners, result in fewer "miles." British Airways employed an even more devious tactic: by reducing the apparent cost of a fare and assigning the balance, a much larger portion than for other airlines, to surcharges and taxes, it was able to lower the value of miles (which on redemption covered only the fare itself). A class-action suit over this trick (in a New York federal court in 2018) resulted in a cash selement of \$27m.

- 30. Are Gmail labels cost-eective? According to a study reported by one of the lead designers of Gmail, only 29% of Gmail users had created *any* labels at all [91]. is is not necessarily a problem. It reects partly the power of Gmail's search mechanism, which obviates the need for manual organization. And it could be that dropping *label* would be a showstopper for some of the three in 10 customers who use it. But it does make one wonder whether the inclusion of *label* is a net win for Google, or whether a dierent concept might be more cost-eective.
- 31. Separation of concerns. e term was coined by the computer scientist Edsger W. Dijkstra in a 1974 piece [34], in which he quoted from a leer he'd wrien to a colleague, explaining how separation of concerns entails "study[ing] in depth an aspect of one's subject maer in isolation for the sake of its own consistency, all the time knowing that one is occupying oneself only with one of the aspects."

"Even if not perfectly possible," Dijkstra explained, separation of concerns "is yet the only available technique for eective ordering of one's thoughts that I know of." Separation of concerns is perhaps not only the most important strategy but also the most underappreciated. It seems so unglamorous, but it's so oen at the heart of eective problem solving, and can be the seed for a radical innovation.

Separation of concerns should not be confused with "divide-and-conquer," a much less powerful technique that comes from the structuring of recursive algorithms. To apply divide-and-conquer, you take a problem and divide it into two or more parts which, if solved, can then be recombined to solve the problem as a whole. Beyond algorithms, divide-and-conquer turns out to have few uses. It assumes that a problem can be neatly divided into parts, and the solutions to the parts easily recomposed—both of which are dodgy premises in most problem-solving contexts.

A related strategy is *top-down design*, in which a problem is broken into subproblems typically representing processing steps. In the early days of programming, it led to a style of structuring in which processing was broken down into reading the input, doing some computation, and then generating the output. Such a structure is usually poor, being both inexible (since input and output rarely occur in well-dened phases) and hard to maintain (since the assumptions that readers and writers share are not localized in the code). Separation of concerns, in contrast, would recognize input and output as a subject of interest in its own right, to be treated independently from computation.

Michael Jackson has noted that top-down development, in which a soware system is built by breaking the specication into smaller and smaller parts until eventually the parts are small enough to be implemented directly, usually fails be-

cause the initial (and most consequential) decomposition is made when the developer has the least understanding of what's being decomposed [68].

32. Reusing concept implementations. Today's libraries and frameworks have the wrong granularity for reusing whole concepts, but eorts are underway to develop new concept-based frameworks that allow programmers to incorporate concepts in their entirety, with both front-end and back-end components, and to congure them exibly to the problem at hand.

*Déjà Vu* is a concept reuse platform built by Santiago Perez De Rosso [119]. Concepts are full stack, including both GUIs and backend services, and are assembled in a variant of HTML, so that minimal programming is required. An end-user developer only needs to pin the existing concepts together (using action synchronization, explained in Chapter 6). In contrast, existing frameworks tend to oer components that are too small (such as the date pickers of GUI libraries) or too large and inexible (such as rating or commenting plug-ins for content-management systems such as Drupal).

33. Apple's underpowered synchronization concept. A cynical observer might suggest that Apple knowingly omits the ability to synchronize only some les in order to encourage users to upgrade their phones to new models with more storage. Apple's designers might also have ruled out selective synchronization because it threatens simplicity. In that case, however, they could have provided a restricted form, rather than supporting the feature in its full generality. For example, they could provide a mode in which only more recent photos are kept on the phone, and older ones are removed while remaining in cloud storage.

Similar synchronization problems arose with Apple's iTunes. Originally, iTunes was an application whose purpose was to transfer music from a laptop or desktop computer to an iPod music player. e developers of iTunes chose to regard the computer as the holder of master copies of the les, so synchronization was designed to be one way. New les appearing on the computer (bought through the iTunes music store, or ripped from a compact disc) would be transferred to the iPod. But les appearing only on the iPod would not be transferred to the computer, and in fact would be deleted.

Perhaps this made sense at the time, when an iPod cost less than a tenth of the cost of a computer, and had no means of obtaining les itself except through iTunes. But by 2019, the last year of iTunes' life, the most expensive iPhone had comparable storage and cost to Apple's least expensive laptop, and of course could obtain les through other means.

Confusingly, photos taken on an iPhone camera were propagated back to the computer. But music les were still regarded as owned by the computer and not the phone. e most egregious consequence of this design was that if your computer was damaged or lost, and you purchased a new computer, you would think that iTunes, when synchronizing with your old iPhone would allow you to transfer all your music les to the new computer. In fact, when you connected it, it would warn you that synchronizing would delete all the les on the phone to make it consistent with the new, empty computer!

- 34. Two-factor authentication aacks. e aacks on *two-factor authentication* that I mentioned are two of many that are known. e LinkedIn example is a combination of a social engineering aack (in sending unwary users to a spoof server) and a classic "man-in-the-middle" aack. It was described in 2018 by Kevin Mitnick, a famous hacker who was caught by the FBI in 1995 and spent ve years in prison, and later became a successful consultant.
- 35. Critical systems: safety and security. Our society relies increasingly on soware for its most vital functions. In the past, "critical systems" occupied a specialized niche, but now almost all soware is critical. Few businesses can function at all without working soware, and couplings between businesses mean that one failure can have massive repercussions.

Safety and security have traditionally been distinct concerns in soware development, applying to dierent kinds of systems. Safety-critical systems were the ones that posed risks to human life: medical devices, chemical plants, electrical grids and so on. Security-critical systems were those in which damage to data through corruption or leakage—was the primary risk, and nancial loss was the main concern.

is distinction was always tenuous, resting on the faulty premise that we could neatly divide systems into those that controlled physical devices (and were therefore a safety risk) and those that managed our data (and were a security risk). Back in 2005, two anesthesiologists described an incident in which the pharmacy database for a large, tertiary care hospital failed, leaving nurses unable to provide medication for thousands of patients [29]. Catastrophe was averted only because the nurses were able to laboriously reconstruct the pharmacy records from printed slips. And this was long before the era of ransomware aacks on hospitals.

Aention is now turning to security risks in devices. Kevin Fu, a leading security researcher, has founded a center that focuses on security in healthcare, has testi ed before Congress, and wrien many papers on the security risks of medical devices, including implantable devices such as pacemakers and debrillators.

36. Design aws in medical devices. Preventable medical errors account for almost half a million deaths per year in the United States, comparable to the deaths from cancer or heart disease. In a remarkable new book [142], Harold imbleby argues that many of these deaths could be avoided with beer design of medical devices.

e book is full of shocking examples of user interfaces with egregious aws at all levels—physical, linguistic and conceptual—and presents a compelling case for beer regulation, beer training of engineers, and more consistent application of the design principles we already know.

Concepts could play a major role in improving the design of medical devices, by embodying and codifying best practices. It seems that many accidents are associated with just a few areas of practice, and that formulating a shared handbook of concepts such as *dose*, *prescription*, and *adverse interaction* might make it easier to achieve consistent standards across device manufacturers.

37. Design principles for grounding design criticism. Principles of user interface design mostly address the physical and linguistic levels. Earlier (in Note 7) I surveyed the development of these principles. In addition to those appearing in Don Norman's *e Design of Everyday ings* [110], explicit lists of principles include Ben Shneiderman's "Eight Golden Rules of Interface Design" [134] (originating in 1985); Jakob Nielsen's "10 Usability Heuristics for User Interface Design" [108] (1994); and Bruce Tognazzini's "First Principles of Interaction Design" [143] (2014). ese collections have considerable overlap; the most common themes are the need for consistency, discoverability, visibility, and user control (especially for undoing errors).

Here is an example of some user interface design principles and their application. Don Norman's notion of *aordances* refers to how a physical control (or screen widget) signals to a user (with what Norman calls a "signier," a word taken from Saussure's theory of semiotics) the capabilities (or "aordances") it oers, and thus the appropriate actions for the user to perform. A door handle, for example, can be shaped to make it clear whether to pull or push, and a user interface button can convey to the user whether to click or slide.

e *Gestalt principles* of visual organization say that items of similar shape and color, and placed close together, will be regarded as oering similar functionality. And Fis's Law (mentioned in Note 21 and in Figure 2.6) says that the time to move a pointing device to a target is proportional to the distance to the target and inversely proportional to its size.

Together, these principles not only provide a language for critique but may even nudge us towards particular solutions. ey might tell us, for example, that an

emergency stop buon should be large, have a distinct visual appearance, and be close to (but clearly separated from) other buons.

Similar principles are common in other elds that employ "crits." Typographic designers, for example, talk about the "color" of type, referring not to literal color but to the visual impression of a block of type in terms of its rhythm, texture, and tone. Photographers talk about "balance" in an image (a quality that is hard to de ne and even harder to achieve, but easy to recognize). And programmers make extensive use of the "minimize coupling" principle, which has many ramications for avoiding bugs, and for reuse and maintainability (see Note 6).

38. Design critique vs. user testing. Design critique is not popular in soware design, or indeed in design thinking more generally. In design thinking books and articles, there are endless paeans to brainstorming, but rarely a mention of any kind of analysis or review—which is strange given the prominence of the "crit" in all traditional design elds.

In HCI circles, it seems almost to have become a dogma that user testing is the only appropriate way to evaluate a design. Rather than spending too much time thinking hard about the design (and possibly being misled by prejudices and preconceptions), you are encouraged just to try the design out. You might do this with a prototype, or by building a full product, or by experimenting with variants of the product (a common strategy in web applications).

is kind of evaluation is certainly valuable. Behavioral economics has taught us that human behavior is less governed by reason than we used to imagine, and we are less condent that we can predict how our designs will be received. Soware developers oen leave user testing too late, maybe even waiting until deployment to discover crippling aws that will require major revisions of the design. Moreover, the cheapest testing methods—paper prototypes or simple wireframes, and a "Wizard of Oz" seing in which a designer simulates responses to the user's actions—are oen the most cost-eective. e excellent online book by Amy Ko [83] gives an informative survey of design methods in general and evaluation techniques in particular.

And with the advent of tools for handling large data sets, and of machine learning as a technique for discovering latent trends in data, empirical evaluation at scale is now cheaper and more eective (although one has to wonder whether the availability of data isn't the cart leading the horse).

Empirical evaluation is also a useful countermeasure when design decisions risk being hijacked by the unsubstantiated opinions of inuential people, sometimes referred to as the HPPO (highest paid person's opinions) eect.

e value of user testing was evident in a small app that I built with some students during the pandemic of 2020. Our app aimed to reduce the feeling of isolation during a lockdown by pairing up members of a predened group, prompting them (by text messaging) to call each other. Early on, we tested a version of the app with some older users. Realizing that the text messages sent by our app might not be identiable, we had made sure to include in the rst message a clear explanation of whom the message was from ("this is the hand2hold service you subscribed to"). But we discovered that these older users, contrary to our expectations, deleted every text message as soon as it was read, so when later messages arrived, they didn't connect them to this initial message, and they dismissed them as spam. e remedy was to include the identication string in every text message.

Despite all this, I can't help thinking that empirical evaluation is overrated. As a means of obtaining feedback on deployed designs, it is obviously necessary. But as a means of creating and rening designs, it may be too crude and expensive a tool. It is infeasible to nd a design by exploring a space of options and testing each option empirically. It simply costs too much to implement more than one or two options. At best, we can create a parameterized design, in which some feature can be varied over some range of simple values. ese might be the textual content of a message, or the layout of widgets on the page, or the color of some element—all aspects of a design that might turn out to be important in practice, but are hardly fundamental.

e long established approach to evaluating designs involves expert *critique*. e designer—and perhaps others, either as members of a design team or as external reviewers—evaluates the proposed design on the basis of prior experience and deep knowledge of the domain. She anticipates the reaction of users based on the accumulated evidence of how similar users have responded to similar designs in the past. She predicts potential problems by mentally simulating the design, imagining its use in various scenarios, and subjecting the design to known corner cases. And most signicantly, the designer—whether consciously or not—applies principles that embody the experience of the community.

Our contemporary fondness for empirical evaluation seems to me to reect a loss of condence in the ability of designers to do this eectively. Douglas Bowman, the rst visual designer to work at Google, le the company in 2009 in frustration over its approach to data-driven design. In a blog post, he described Google's approach: "Remove all subjectivity and just look at the data. Data in your favor? Ok, launch it. Data shows negative eects? Back to the drawing board. And

that data eventually becomes a crutch for every decision, paralyzing the company and preventing it from making any daring design decisions." [14]

Design critique is indispensable, since it is the best way we have to evaluate our work during the process of design. By critiquing ideas as they arise, a skilled designer can navigate a path from a vague intuition to a concrete design proposal, rejecting bad ideas and rening good ones. is kind of work is hard and demanding, and it requires considerable education and experience. is is why, the Pentagram designer Natasha Jen suggests [74], it is downplayed in some design thinking circles, which may be more eager to promote the democratization of design than to recognize how challenging it is.

In summary, then, a constructive approach to design needs both critique and testing, but the balance needs to be redressed, with principled critique forming the centerpiece of the design activity. A designer can apply design principles in the ow of her work, and only when a design satises those principles does it make sense to expose it to user testing. is proposed ordering is local rather than global. It does not mean that all design renement should precede all user testing, but that the design can proceed in small increments—for example, one concept at a time—with user testing aer each increment.

39. An easter egg in Don Norman's book? Years ago, my brother, Tim Jackson, sharing my delight at discovering Don Norman's book [110], noted a aw in the design of the book itself which is so self-referential I'm tempted to wonder if it was planted by a designer as an intentional "easter egg."

In the very section explaining Norman's notion of mapping, there is a two-page spread of gures illustrating the application of the idea to the positioning of knobs on a cooktop. In one bad design, for example, the knobs are arranged in a straight line in front of four burners that occupy the four corners of a square; without labels it would be unclear which knob controlled which burner.

ere are four gures in the spread laid out not that dierently from these four burners. And yet the captions for the gures are placed in sequential order from top to boom—and, even worse, there are three captions for four gures!

# *Chapter 4: Concept Structure*

40. Purposes aren't goals. You might wonder: why isn't *deletion* a perfectly reasonable "purpose" for the *trash* concept? Aer all, isn't that what people use it for most of the time? (See Note 27.)

e power of purpose as a design notion would be weakened, however, if this were admied. Instead, I prefer to make the following distinction. A *goal* is some-

thing that a user may want to aain at one time or another, and which may be achieved with the help of a concept; a *purpose*, on the other hand, is a need that motivates a designer to include a particular concept. So goals for the *trash* concept might include deleting les, tracking information about previously deleted les, and even providing soothing ASMR (autonomous sensory meridian response) sounds by repeated emptying. Undoing deletion would be a goal too, but out of all these, it's the only purpose, because there are simpler (and in some cases more effective) ways to provide the other goals.

Or to put it another way, if the *trash* concept were not there, what opportunities would be missing? On the reasonable assumption that there would some way to delete things (since every prior operating system that could create les had an easy way to remove them), this suggests that the purpose of the *trash* is undoing deletion, since that's the key benet that it brings.

Adding a concept to a design generally increases the cost, both to the designers and developers who build the soware, and to the customer who must learn how to use it. e concept's purpose helps you decide whether the cost is justied by the benet, by articulating the precise advantage that this concept brings and thus the motivation for including it.

e same distinction between purposes and goals can be applied to the other two examples in this chapter. e purpose of the *style* concept is to enable consistent formaing of documents—in particular, allowing you to modify the format of a single style and have all the elements of that style updated in concert. Naive users of programs like Word oen think that styles are for *applying* formaing: that they just give you a quick way to apply a collection of predened formaing properties to an element (for example, making a section header bold and large). But as with the deletion goal of the *trash* concept, there are much simpler ways of achieving this goal without the *style* concept.

And likewise for the *reservation* concept: a user's goal may be simply to obtain a table at a restaurant. But if that were all the restaurant wanted to provide, and it was happy to have customers turning up and waiting for tables, it could use a simpler concept in which tables are just assigned on the y.

e trash is not a metaphor. Another common misconception about the trash is that it's aractive and intuitive to users because it's a *metaphor* for a physical trash can. Metaphors do play a role in many user interfaces: folders and les, for example, clearly benet from drawing an analogy to physical folders and the paper les they contain.

For understanding the *trash* concept, however, a physical trash can is a misleading metaphor. e purpose of a physical trash can is to *stage* the removal of trash: we have trash cans in our kitchens so we don't need to take each item of garbage outside to the larger bins that are collected weekly. e purpose of Apple's *trash* concept is, instead, to allow the *restoration* of items from the trash—a feature also supported by the kitchen trash but not one we generally like to take advantage of.

- 41. e importance of names in design. Names are essential in design, because they allow us to refer to known paerns without having to explain them. Just as an architect might say "let's have a cantilevered balcony" rather than "let's add a lile platform on the side of the building that people can walk out onto, and which doesn't have visible supports holding it up," so a soware designer might say "let's use the trash concept for handling message deletion" rather than "let's handle deletion of messages the way they do on the Mac desktop with that trash can icon that lets you restore les that you deleted."
- 42. State is memory. Another way to describe the state of a concept is that it captures what the concept must *remember* during execution. So if the items in the trash were to be shown sorted by time of deletion, we would need to remember when each item was deleted, and the association between items and their times would have to be included in the concept's state.

I nd that this simple idea is oen not clear to novices constructing data models. ey somehow come to think of a data model as if it were making truth statements about the world. is view is encouraged by using "has" terminology for relations (as in "a user has a name"), and it's not implausible when designing pure ontologies (for example, a data model intended to describe chemical compounds). But it's rarely a helpful perspective in soware design, where the data model is there only to support actions, so if no action requires a particular piece of information, it can be omied from the data model, and conversely, if an action relies on some information, it must be included.

Concepts make data modeling even more straightforward, because in place of a global data model, there are instead a collection of miniature data models, each de ned as the state of a single concept, and justied by that concept's actions.

43. e operational principle. e operational principle can also be viewed as a *theorem* about the behavior of the concept, asserting that the concept has some key property, or equivalently as a kind of generalized test case. But whereas theorems and test cases play a secondary role, being used to check the consistency of a program or specication, the operational principle is front and center in the design of

the concept: it's the very essence of the concept (and oen the most compelling way to explain it).

Imagine Isaac Newton—presumably a bright fellow—examining a toaster, and wondering what it does and what it's for. He sees a knob that's labeled as going from "light" to "dark," a lever you can press down, and a buon marked "cancel." How would you explain the toaster to him? You surely wouldn't start by describing the state (the dial seing that determines the cook time, the on/o state of the heating element, and the state of the timer, with the time remaining until ejection). Nor would you start with the actions: for example, that turning the dial adjusts the state component corresponding to the cook time.

You'd just tell him what the toaster is *for*, namely its purpose, which is toasting bread. en you'd demonstrate *how* to use it—its operational principle—by putting two slices of bread in the top, seing the knob halfway, say, and pushing the lever down. You might extend the operational principle to a second scenario by setting the knob too high, and pressing the cancel buon to eject the toast when it begins to burn.

So although the state and the actions dene the behavior fully, they don't provide the crucial missing parts that both designers and users need: the need for the concept (given by the purpose) and the demonstration of how that need is fullled (given by the operational principle).

e operational principle comes to me via Michael Jackson [72] from the work of the philosopher Michael Polanyi [125] who explains that the operational principle of a machine species how "its characteristic parts—its organs—fulll their special function in combining to an overall operation which achieves the purpose of the machine."

My toaster example is based on Polanyi's observation that the laws of physics are incapable of explaining a machine—a fundamental distinction between physics and engineering, for which a "logic of contriving" is required. In Polanyi's words: "Engineering and physics are two dierent sciences. Engineering includes the operational principles of machines and some knowledge of physics bearing on those principles. Physics and chemistry, on the other hand, include no knowledge of the operational principles of machines. Hence a complete physical and chemical topography of an object would not tell us whether it is a machine, and if so, how it works, and for what purpose. Physical and chemical investigations of a machine are meaningless, unless undertaken with a bearing on the previously established operational principles of the machine." [124, p. 39]

imbleby's partial theorems. Harold imbleby has noted that users infer behavioral theorems by observing their interactions with systems, and come to rely on them [140]. is is ne if theorems are either true (in which case they will often be helpful) or manifestly false (in which case users will quickly recognize their invalidity).

Trouble comes with what imbleby calls "partial theorems": theorems that are *almost* always true. Because a partial theorem holds most of the time, the user will come to believe that it holds universally, but one day will be misled and get a nasty surprise. For example, in an email application with folders, it is natural to assume that the "sent messages" folder (1) contains every message that was sent and (2) contains only messages that were sent. Both properties are in fact untrue: the rst (more obviously) because messages can be moved into other folders to organize them, and the second because you can (for no good reason) move a message that you received but did not send into that folder.

Here are some examples of partial theorems for the three concept examples of this chapter. Each of these theorems is true for the concept itself, but partial in some implementations. For the *trash* concept, the operational principle as I've stated it is actually a partial theorem for the Apple Macintosh implementation. As I explain later in Note 73, emptying the trash does not always permanently remove every le that is in the trash (although most users will never observe this case).

For the *style* concept, there is a common extension in which styles can be arranged in a hierarchy, with each style inheriting the formaing properties of its parent. In one of my rst papers [62] on automatic analysis of soware models, I used the *style* concept as my running example, and showed how a rather mundane theorem turns out to be partial. You might think that if you change the parent of a style, changing it back immediately will have the eect of an undo, and the styles will be unchanged. Surprisingly, this turned out not to be the case for common implementations. I won't spoil the surprise by telling you why in detail, but will just hint that it arises when a style and its parent set the same value for a given formatting property.

For the *reservation* concept, the obvious partial theorem is again the operational principle itself—and its partiality is understood by most restaurant customers. When you turn up at a restaurant with a reservation, there is a small chance that no table will actually be available. e reason is that the restaurant, in accepting reservations, must make an assumption of the maximum length of time that a party will remain at a table. Sometimes a party will overstay its welcome, and the restaurant may nd it lacks enough empty tables to honor reservations.

e operational principle vs. use cases and user stories. Scenarios are popular in many approaches to soware development. Ivar Jacobson [73] developed an approach to requirements that involved specifying "use cases," each a scenario in which the user interacts with the system and achieves some goal. "User stories" are similar but are usually expressed in a less structured way.

Both of these are unlike the operational principle. ey play a dierent role. Rather than explaining the essence of the design, they are intended to describe the functionality in its entirety. Moreover, use cases and user stories are applied at the system level, and not at the more granular level of individual concepts.

So a full requirements description might have dozens or hundreds of use cases, handling not only normal usage but abnormal cases too. In concept design, you give only the few scenarios that are needed to show how the concept fullls its purpose, and the details (including the abnormal cases) are handled by the action specications. In the *style* concept, for example, the operational principle need not include a scenario explaining what happens when a style is deleted. is is a tricky case, but it's hardly the essence of the design.

e essential quality of the operational principle, distinguishing it from regular scenarios, is the way in which it motivates the concept's design as a whole. Suppose you asked me how *style* worked, and instead I showed you that you can dene some styles, such as *body*, *quote* and *heading*, and then format a paragraph easily by selecting the relevant style and applying it. is is a perfectly valid scenario, and people do it all the time. But it's not the *motivating* scenario for the *style* concept. To support this simpler scenario, the app doesn't need to remember which styles are associated with which paragraphs. A less powerful concept would suce.

Use cases and user stories are commonly used as increments of programming work in agile development. is is an appealing idea, and consistent with the agile goal of incrementally delivering pieces of functionality with clear value to users. But focusing on just one or a handful of use cases may give too incomplete a picture, leading to an implementation that can't easily be extended to the next use case.

Suppose, for example, you were implementing the *style* concept, and you started with use cases in which you dene a style and apply it to some paragraphs. If these use cases don't involve *modifying* an existing style, your implementation wouldn't need a mapping from paragraphs to styles. When you apply a style to a paragraph, you could just take the format seings dened in the style and apply them directly to the paragraph. is is a plausible concept—just a dierent one. It goes by the name of "style" in Apple's TextEdit app, but by omiing the crucial association of

styles to paragraphs, it fails to be very useful. Only later when you get to implementing a use case in which a style is modied would you discover that your code cannot be easily extended. In fact, including in the use case a style that is modied won't be enough; it will have to be a style that is modied *aer* it has already been applied to a paragraph.

Of course this is a small example, and reworking the code might not be so hard in this case. But in the context of a large system, these kind of problems can become crippling, and suggest a reason for why teams that follow an agile approach oen program themselves into a corner and have to throw work away (a practice also known as refactoring).

Concepts oer a beer granularity for incremental development because they are self-contained and largely independent of one another. If you were implementing a word processor with concepts, you might start with the concept of *paragraph* and build the basic code for editing text (and dividing it into paragraphs); then you might implement the *format* concept that lets you change the size and typeface of the text, for example; and then you might implement the *style* concept that allows you to apply formats systematically to paragraphs through their styles.

44. Concept formalism. e concept descriptions in this book are given informally, in plain English, in order not to put o readers unfamiliar with code or logic. In practice, it's oen beer to use a formal notation that is precise and unambiguous, and can be potentially be analyzed automatically and compiled into running code. Many notations exist that would be suitable for specifying concepts; these include Alloy [66], Z [136], VDM [75] and B [1]. Alloy does make a cameo appearance in the concept descriptions in the declarations of the state components, and for the constraint (in Figure 4.4) that denes *format* in terms of the other components.

Concept semantics. For the benet of computer scientists and other readers wanting a more rigorous explanation of what a concept denition exactly denes, I am including here some notes on concept semantics. I'll focus on concept *behavior*; the purpose of a concept does not seem to be readily formalizable.

A concept's behavior can be viewed, in the simplest terms, as a state machine. Figure E.3 shows part of the state machine for the *trash* concept (Figure 4.2). In the initial state, no items are accessible or trashed, and the only possible action is to create an item. Executing the action *create(i0)* leads to a new state, in which the item *i0* is now accessible; *delete(i0)* takes us to a third state in which the item is trashed, and there are now two options: *restore(i0)*, which undoes the deletion, and *empty()*, which returns us to the initial state.

![](03.Resource(책임X,%20정보,학습)/30.%20Concept%20Garden%20Development/EssenceOfSoftware_Eng/concepts-211-240/_page_15_Figure_1.jpeg)

fig. E.3 *Part of the state machine for the trash concept.* 

is lile state machine only includes actions on a single item, *i0*. e concept itself allows *Item*, the set of possible items, to be unbounded, so the real machine is innite. Nevertheless, even if we can't draw it, we can dene it. You start with the initial state, and then consider each action in turn. If the action denition says it's allowed in that state, you add a transition to the state it prescribes, repeating this for each possible action. You then nd the outgoing actions for any new states that were produced, and continue in this fashion, expanding the machine for ever.

(A full concept denition language would include some syntax for dening the initial state. I haven't needed this in any of the examples, because the states have always comprised sets and relations which are assumed to start out empty.)

Transition relations, preconditions and deadlock. Mathematically, the meaning of an action is a *relation*. Given a concept with a set of states *S*, an action *A* with an argument drawn from the set *X* has an associated relation

$$trans(A) \subseteq S \times X \times S$$

containing all the transitions *(s, x, s')* of the action, where *s* is the state before, *x* is the argument, and *s'* is the state aer. To account for more than one argument, we just view *X* as a set of tuples.

e transition relation need not be total. e set of pairs *s, x* of prestates and arguments for which a poststate *s'* exists is called the *precondition* of the action. When the precondition does not hold, the action is not enabled and may not occur. (is is subtly dierent from the notion of a precondition of a function in programming. ere, with nothing to prevent a function from being called, the precondition represents only an obligation: if you call a function when it does not hold, the usual assumption is that anything can happen.)

In any given state, any number of actions may be enabled. It's possible to design a concept in which a state can be reached from which *no* action is enabled. is is called *deadlock*, and is undesirable because it means that the concept can never do anything else again.

Usually a concept embodies a collection of objects, each with its own lifetime. e lifetime of any individual object may well come to an end, but the behavior of the concept as a whole continues because the collection itself is not bounded. e *reservation* concept, for example, handles the lifetimes of individual resources—a dinnertime slot at a restaurant, for example—which come to an end when the resource is used. But a new resource can always be added, so the concept as a whole continues to execute, and there is no deadlock.

Formalizing actions. States and actions can be readily formalized in any of the languages mentioned above. For example, the *reserve* action that was dened informally in Figure 4.7 as:

```
reserve (u: User, r: Resource)
     when r in available
     associate u with r in reservations and remove r from available
can be wrien formally in Alloy like this:
   pred reserve (u: User, r: Resource) {
     r in available
     reservations' = reservations + u -> r
     available' = available - r
     }
```

e precondition is the same (because *in* is a keyword in Alloy already), but does not need the keyword (because preconditions are implicit in Alloy). e last two lines dene the new values of the two state components (denoted by priming their names) in terms of their old values. (e priming, by the way, is a shorthand introduced to Alloy by the Electrum [20] extension.)

If I were designing a new language for concepts (which I hope to do), I would prefer a more operational syntax in which relations can be updated on particular domain elements, writing something more like this:

```
reserve (u: User, r: Resource)
  when r in available
  u.reservations += r
  available -= r
```

with exactly the same intended meaning. Following the programming language CLU, this uses C-style shorthands in a generalized way, so a statement of the form

*e1 op= e2* stands for *e1' = e1 op e2*. e second line above is thus short for an update constraint along with an implicit frame condition:

```
u.reservations' = u.reservations + r
all p: User | p != u implies p.reservations' = p.reservations
```

Traces and state observations. e state machine formulation has a simple and mechanistic quality to it, but in practice a more abstract view is helpful. We can de ne the *traces* of the concept to be the set of all the nite histories of action instances that are possible. So for the *trash* concept, these include:

```
<>
<create(i0)>
<create(i0), delete(i0)>
<create(i0), delete(i0), empty()>
<create(i0), delete(i0), restore(i0)>
…
```

and so on. In addition to observing these traces, the user of a concept can observe the state at any point. at is, there's some function

```
state: Trace → State
```

that maps each trace to the state that it produces. e state produced by the empty trace, *state(<>)*, is of course just the initial state. e state aer a longer trace can be computed by applying each action in turn, following the rules given in the action denitions. So aer deleting an item we nd it in the trash:

```
state (<create(i0), delete(i0)>) = {accessible: {}, trashed: {i0}}
```

and aer emptying the trash, the item is permanently removed (and coincidentally we're back in the initial state):

```
state (<create(i0), delete(i0), empty()>) = {accessible: {}, trashed: {}}
```

System actions and determinism. Concepts are assumed to be *deterministic*. is means that the transition relation associated with each action is functional: given a particular state and set of argument values for which an action is enabled, at most *one* state can result from executing it.

is is what justies the denition of the state function: a trace always leads to exactly one state. Another consequence of determinism is that an action cannot be refused arbitrarily; whether it can occur is dened (by its precondition) in terms of the state in which it is invoked, so if you know the trace that has occurred up to some point in time, you can predict whether a given action can follow.

Not all actions need be performed by the user. In general, dierent categories of users will perform dierent subsets of actions. System actions, performed spontaneously without any user participation are possible too, and in a full concept nota-

tion might be marked with a special keyword. For example, in a ight reservation system, the *seat allocation* concept may have an action

```
system assign-seat (c: Customer, s: Seat, f: Flight)
```

that assigns to customer *c* the seat *s* on ight *f*. Since the system (and not the user) selects the seat, this allows us to describe the scenario in which a user, having bought a ticket, gets a seat assigned, apparently arbitrarily. In some sense this is a non-deterministic outcome of the user's request, but because the choice of seat is visible in the argument of the action that the system takes, the concept remains deterministic. And indeed, in practice—in a good design at least, even if not the design that many airlines choose—such an action would be synchronized with a notication leing the user know which seat had been assigned.

A logic of operational principles. Operational principles can also be readily formalized. Dierent kinds of temporal logic might be used; here I will illustrate how they might be expressed in *dynamic logic* [53] because it most closely matches the style of the informal denitions that I have shown.

e basic forms of dynamic logic are *[a]p*, which says that aer performing the action *a*, the predicate *p* always holds, and *<a>p*, which says that aer performing the action *a*, the predicate *p* may hold. For the operational principles we'll write, only the rst form is needed, and I'll drop the modal operator, writing *a{p}* instead of *[a]p*.

Actions can be combined into compound actions using *sequential composition*, with *a;b* denoting the *a* followed by *b*; *repetition*, with *a\** denoting zero or more occurrences of *a*; *choice*, with *a or b* denoting an occurrence of either *a* or *b*; and *negation*, with *not a* denoting any action that is not the action *a*. I'll also assume a special operator *can* that extracts the precondition of an action; thus *can a* holds in a state in which the action *a* can happen.

With these operators in hand, we can formalize the operational principles of this chapter. For the *trash* concept, the principle wrien informally as

```
after delete(x), can restore(x) and then x in accessible
```

becomes two separate formal assertions:

```
delete(x) {can restore(x)}
delete(x); restore(x) {x in accessible}
```

For the *style* concept, the informal principle

```
after define(s, f), assign (e1, s), assign (e2, s) and define (s, f'), e1 and e2 have format f'
becomes
```

```
define(s, f); assign (e1, s); assign (e2, s); define (s, f') {e1.format = e2.format = f'}
And for the reservation concept, the informal principle
```

```
after reserve(u, r) and not cancel(u,r), can use(u, r)
becomes
   reserve(u, r); (not cancel(u, r))* {can use(u, r)}
```

ere's some latitude in exactly how the operational principle is expressed, and formalizing it brings the various options to mind. For example, you might wonder why, given that the principle for *reservation* allowed for actions between reserving and using a resource (while stipulating that no cancellation occur), the same exibility wasn't expressed in the *trash* concept's principle. In the laer case, we might have wrien instead

```
delete(x); (not (restore(x) or empty()))* {can restore(x)}
```

saying that aer deleting an item, you can perform any other actions prior to restoring it except for restoring it (since you can't restore it twice) and emptying the trash.

My (admiedly imsy) justication for not expressing it this way was that the scenario expressed by my original principle for the *trash* is not rare: it's common to delete an item by mistake and restore it immediately. But for the *reservation* concept, a scenario in which a reservation leads to a use without any intervening reservations occurring is impractical and thus a poor exemplar.

A linear-temporal logic version. e operational principle might also be expressed in *linear temporal logic* (LTL) [123]. LTL and dynamic logic are not equivalent in their expressiveness, but both can express the general form of our operational principles—namely, that aer some possible sequences of actions, some condition holds. In the newest version of Alloy [20], which includes LTL operators, the operational principle for the *reservation* concept

```
after reserve(u, r) and not cancel(u,r), can use(u, r)
can be wrien
   all u : User, r : Resource |
     always reserve[u, r].then [can_use[u, r].while [not cancel[u, r]]]
     }
having dened the then and while operators as macros:
```

```
let then [a,b] {a implies after b}
let while [a,b] {not b releases a}
```

Although this formulation seems to me a bit less intuitive than the one in dynamic logic, it has the great advantage of being usable right now in Alloy, and can be executed and checked automatically. (ank you to Alcino Cunha for providing this example.)

Real actions in temporal logic. In fact, neither dynamic logic nor linear temporal logic exactly captures my intended meaning for operational principles, because both treat the occurrence of an action as equivalent to its state transition.

In the operational principle of the *reservation* concept (Figure 4.7), for example, the expression *cancel(u,r)* matches—in both logics—*any* transition resulting from an execution of the *cancel* action with arguments *u* and *r*. If the *retract* action were dened (dierently) to allow a resource to be retracted even if reserved, then, after the action *reserve(u,r)*, the actions *retract(r)* and *cancel(u,r)* would have exactly the same eect (namely undoing the reservation of resource *r* by user *u*). And yet we might want the mention of *cancel(u,r)* in the operational principle to apply only in a case in which a reservation by user *u* of resource *r* is dropped due to a cancellation and *not* a retraction. To make this distinction, a richer semantics is required in which the *names* of actions are signicant.

Incidentally, although its title might suggest otherwise, the Temporal Logic of Actions [85], an elegant logic devised by Leslie Lamport and supported by a powerful model checker, also doesn't represent actions explicitly, and, like Alloy's temporal logic, might be more accurately (if less catchily) described as a "logic of state transitions."

Classication of objects. I've talked about an action instance such as *create(i0)* happening, but I haven't explained what kind of thing the object *i0* is. Because identifying and organizing objects is such an important part of the design process, it's useful to classify objects into dierent kinds. I'll describe three dierent dimensions along which objects can be classied: by role, by mutability, and by interpretability.

Object roles. Objects play three dierent roles in a soware system. First, an object may play the role of an *asset*. An asset has inherent value, although the value may be dierent for dierent users at dierent times and for dierent purposes. Some assets—photos, audio tracks, blog posts, comments—correspond to familiar objects in the physical world; others, especially those associated with security—certicates, permissions, capabilities, passwords, etc.—are more abstract.

Second, an object may play the role of a *name*. Names are used to locate or identify other objects. Sometimes these named objects are physical: a social security number names a person; a serial number names a camera; a mailing address names a building. Sometimes they exist in the world but are not physical: a date names a day in the past or the future, and a product code names a product category (corresponding, for example, to all Roxbury russet apples). And sometimes they are virtual, and exist only inside a computer: an email address names an email account, a domain name names a server, a le system path names a le or folder.

A name is usually intended to be unambiguous, pointing to exactly one object, but its interpretation will oen depend on context. A small company, for example, may name its members using rst name/last name combinations (until the day a second John Smith comes along). A name for one object may be used as a proxy name for another; it's common, for example, to use phone numbers as names for people, since almost everyone now has a unique mobile phone number.

e third role of an object is as a simple *value*. Values, unlike assets and names, carry no meaning of their own; their meaning comes from their relationship to other objects. e number 80, for example, may be a person's age, or the temperature of water in a lake, or the number of hits a website has received in the last hour.

Figuring out what role an object plays is an essential part of design, and prompts some immediate design questions. For an asset: Who owns it? Is privacy a concern? How would you search for it? For a name: What context is it interpreted in? Is it indeed unique? How long is it valid for? For a value: What does it describe? Does it have units? Can two dierent values be usefully compared?

e same object can play dierent roles in dierent concepts. On the Hacker News website, users upvote and comment on posts that comprise no more than a link to a web page. For the *post* concept itself (and most other concepts of the site), a post is an *asset*; but to the *url* concept that provides the functionality of following links, a post is a *name*.

Object mutability. A mutable object is one that changes over time. For such a notion to make sense, we need to distinguish the *identity* of the object from its *value*. (I'm using "value" here as it's conventionally used in programming, and not with the specialized meaning of "simple value" in the role classication just discussed.) To "change" means that the value associated with a given identity at one point in time diers from the value associated with the same identity at another point in time.

Where exactly the identities lie, and which values are replaced, is usually a subtle question, and is determined more by choices of description than by any objective reality. Take, for example, an image in Photoshop that is comprised of some two-dimensional array of pixels. Suppose we apply an adjustment to the image that makes it appear darker. Did we change the value of the image itself, so that now it contains a dierent array of pixels? Did we keep the array but change which pixels it contains? Or did we keep both the array and its pixels, and change the values of the pixels themselves? An examination of the code might reveal which of these is correct from the perspective of the programmer. But for the user, it's hard to argue that one is more compelling than the other.

Identities, by the way, are not the same as names. e relationship between an object's identity and its value is more like that between a box and its contents. A name allows you to *refer* to an object, and oen also to *nd* it. An identity, in contrast, merely allows you to *distinguish* one object from another.

Since concepts communicate only by the synchronization of actions (as will be explained in Chapter 6), objects that are passed as arguments of actions are required to be immutable. If they were not, an action in one concept might mutate an object shared by another, leading to a hidden communication. is would open up the kinds of complications (such as aliasing) that plague programming languages and have led language designers to control if not eliminate mutability whenever possible.

Within a concept, the user is free to interpret the concept state in terms of mutable objects. Such an interpretation is no more valid, however, than one in which all objects are immutable and changes involve only the relations between them. In our description of the *reservation* concept (Figure 4.7), for example, there is no explicit "reservation" object; instead, a reservation is represented as a tuple in the relation *reservations* from users to resources.

Interpreted and uninterpreted types. e third and nal dimension along which objects can be classied is whether they are *interpreted* or not. Most of the objects involved in a concept are treated as if they were opaque. e concept behavior only recognizes equality: that is, whether an object held in one variable or state component is the same object as that held in another.

For example, the *cancel(u,r)* action of the *reservation* concept (Figure 4.7), which cancels user *u*'s reservation of resource *r* compares the objects named *u* and *r* with the objects it stores in the *reservations* relation. From the action's point of view, users and resources could be anything so long as one user or resource can be distinguished from another.

In contrast, consider a *rating* concept with an action *rate(i,n)* in which a user rates an item *i* with a number *n* (between 0 and 5, say). In this case, the item is uninterpreted, but the number *n* is interpreted as an integer, and contributes to the computation of the item's average rating.

Why does this distinction maer? If the same type ows from one concept to another—by synchronization, as explained in Chapter 6—the two concepts will need to treat the objects of that type in a consistent way. For uninterpreted types, it's trivial; they must simply agree on which references to an object denote the same object and which do not. But for interpreted types, it's more challenging, because the two concepts must give the same interpretation to each object. If the

shared object is a date in the form 050721, for example, the concepts would have to agree on whether this represents May 7 (following the typical American order of mm/dd) or July 5 (following the British order of dd/mm).

e distinction between interpreted and uninterpreted types can be formalized in terms of *permutation invariance*. Each type *T* that appears in a concept description has some set *Objs(T)* of objects associated with it, comprising the objects that variables of that type can hold. e permutations of *T* are all the one-to-one functions from the set *Objs(T)* to itself.

Applying a permutation *p* to an action instance *a (x <sup>0</sup> , x <sup>1</sup> , …)* in which argument *x 0* has type *T <sup>0</sup>* , *x <sup>1</sup>* has type *T <sup>1</sup>* , etc., gives the instance *a (y <sup>0</sup> , y <sup>1</sup> , …)* in which *yi* is *p(xi )* if *Ti = T* and *xi* otherwise. Permutations are lied over traces and states in the obvious way.

Now can we express the invariance property: a type *T* is uninterpreted in a concept *C* if, for every permutation *p* of *T*, and for every trace *t* of *C*, the permuted history *p(t)* is also a trace of *C*, and *state(p(t)) = p(state(t))*.

For example, given this trace of the *reservation* concept and its associated end state

```
<provide(r0), reserve(u0, r0), cancel(u0, r0)>
   available: {r0}, reservations: {}
applying the permutation that swaps resources r0 and r1 gives
   <provide(r1), reserve(u0, r1), cancel(u0, r1)>
   available: {r1}, reservations: {}
```

which is also a valid trace and end state. Since this invariance condition would hold for any permutation of *User* or *Resource* and for any trace, both types are uninterpreted.

is is hardly surprising, since these types are generic type variables, so by de nition the concept can assume nothing about their objects. But a regular, non-generic type can be uninterpreted too. e *Task* type in the *todo* concept (Figure 6.2) is uninterpreted, for example, because the concept includes no functionality such as searching for tasks with given content, or checking spelling, which would require looking "inside" a task.

To check whether a type is interpreted, one need only look at the operations performed on its objects in the state updates of the actions: if they include only the "logical" operations of sets and relations and equality comparisons, the type is uninterpreted. (Alfred Tarski, who invented the relational calculus that forms the basis of Alloy, characterized "logical notions" as being exactly those whose meaning is invariant over permutations of the universe [138].)

![](03.Resource(책임X,%20정보,학습)/30.%20Concept%20Garden%20Development/EssenceOfSoftware_Eng/concepts-211-240/_page_24_Figure_1.jpeg)

fig. E.4 *Data models for the style concept (le) and labels in Gmail (right).* 

### 45. e power of relations in data modeling. In dening a derived state component in the *style* concept (Figure 4.4), I wrote

*format = assigned.defined*

which says that the relation *format* is the relational composition or "join" of the relations *assigned* and *defined*. Such constraints can be given a nice diagrammatic interpretation (Figure E.4, le): the path comprising the arrow labeled *format* is equivalent to the path comprising the arrows labeled *assigned* and then *defined*.

Or in words, more laboriously: to get the *Format* associated with an *Element*, you can either follow the *format* relation in one step, or you can get the associated *Style* by following the *assigned* relation in a rst step (geing the style assigned to that element), and then follow the *defined* relation in a second step (geing the format de ned by that style). e diagram also makes clear, incidentally, how the design exploits indirection: see *Concepts have rich states* in Note 48.

inking of relations as arrows and paths in a graph is intuitive and helpful when you get the hang of it, and is reason alone to describe your data model in terms of relations (and to draw it as a diagram). Just looking at a data model diagram and considering how paths might be related is an easy way to discover possible constraints. Figure E.4 (right) shows a similar situation for labels in Gmail, in which a constraint of the same form applies (and turns out to be the source of some serious problems, as explained in Chapter 8).

is style of modeling is the essence of Alloy [66], and was inspired by Z [136], which pioneered it. Most other notations do not support this kind of navigational thinking. In rst-order logic, you'd need quantiers:

∀ *e: Element, f: Format | (format(e, f)* ⇔∃ *s: Style | style(e, s)* ∧ *defined(s, f))*

In an object-oriented style, you might think you could write something like this:

∀ *e: Element | e.format = e.assigned.defined*

but it would be ill-formed because of the cases in which *e.assigned* is undened. A solution to this problem is to treat such an expression as denoting a *set* of values

(which is empty when an element is not mapped), and to li navigations over sets. is is exactly what Alloy does, by treating the mappings as relations and the dot as relational join.

- 46. Near misses aren't necessarily bad. Calling a concept a near miss doesn't mean that it's necessarily a bad design. e *style* concept brings some real complexity in the structure that must be maintained. Apple's color picker oers a system-wide palee, so a document in a particular application would need somehow to name this external palee, introducing a dependence that has its own liabilities.
- 47. Bad conict detection: an airline reservation example. A common feature in variants of the *reservation* concept is *conict detection*, in which users are prevented from making reservations that inherently conict, in order to prevent them from gaming the system and making reservations they're likely to cancel.

Sometimes the conict rules get in the way of reasonable usage. My wife once wanted to y from Boston to Cincinnati on a Sunday morning for a wedding that aernoon, and to return home that night. A round-trip ticket wasn't available, but there were open ights in both directions. So she tried to make two reservations, one for the outgoing ight and one for the return ight. e airline's system wouldn't allow her to reserve both ights at once, and displayed a message saying that you couldn't take ights from two dierent cities on the same day!

48. Concept characteristics. Because the main text only hints at some of the essential qualities and characteristics of concepts, I thought it might be helpful to elaborate these for readers wanting more detail.

Concepts are inventive. When philosophers talk about concepts, they're usually referring to the way we categorize things that already exist in the world. us we use concepts like "dog" and "cat" to classify animals. In the early 18th century, Carl Linnaeus developed the taxonomy we still use today for classifying biological organisms, by dening concepts based on characteristics. Birds, for example, lay eggs, have feathers, have warm, dark blood, and "y in the air and sing."

(Linnaeus's contribution was more the idea of classication than the classication itself. e *Ornithological Dictionary; Or, Alphabetical Synopsis of British Birds* of 1831 complained that his classication wasn't entirely accurate, noting that "more than two-thirds of the known species of birds *never sing*; and that many birds, such as the cassowary, the ostrich, and the penguin, *cannot y* for want of sucient wings.")

In contrast, when we talk about the concepts of a soware app or service, we're referring to things that were themselves *invented*. ey might not have been invent-

ed by the designers of the app, but they were invented by somebody at some time. Your tax preparation app didn't originate the concept of *social security number*. at concept was not just "out there" in the world along with dogs and cats, however. It was invented, in 1936, to keep track of the earnings of American workers for administering their benets under the new Social Security program.

e *trash* concept was invented by Apple, and was a focus of its legal struggles with Microso and Hewle Packard. In the end, Apple lost its claim to ownership of the concept but retained the right to the name (which was why it was called the "recycle bin" in Windows).

e *style* concept was invented by Larry Tesler and Tim Mo at Xerox PARC in the early 1970s. Styles were introduced in Bravo, the rst WYSIWYG document preparation system, developed at Xerox PARC in the early 1970s by a team led by Butler Lampson and Charles Simonyi. PARC's Larry Tesler and Tim Mo had visited Ginn, a traditional printer in Boston, to learn about how text was marked up, and conceived the idea of styles, which Simonyi subsequently included in Bravo, and then took to Microso, where he led the development of Word.

e *reservation* concept appears to have been invented, at least for restaurants, in the 19th century, when big city restaurants began to oer advance bookings for both tables and private rooms. It's a fun game identifying concepts that are essential pieces of our social infrastructure and uncovering their origins. Alexis Madrigal, a writer for *e Atlantic*, researched the restaurant reservation, with help from historian Rebecca Spang. Why reservations took o only at the turn of the 20th century isn't clear, but seems to be related more to social changes that made restaurant dining more pervasive than to the advent of the telephone. (See: Alexis Madrigal, "Where restaurant reservations come from: A journey into the mysterious origins of the pre-arranged table." *e Atlantic*, July 23, 2014.)

Concepts evolve. As the benets and limitations of concepts become clear over time, their designs evolve. Small improvements may accrue over years or even decades. e *style* concept was quite primitive when it rst appeared in the Bravo text editor at Xerox PARC. ere was a xed collection of built-in styles, and although users could adjust the formaing properties of a style, they could not create new styles. (is is actually the situation in the Google Docs app today.) e same restriction carried over to the rst version of Microso Word, but eventually the concept expanded to include user-dened styles, as well as stylesheets for packaging collections of styles.

A nice example of a design improvement that took many years to come can be found in the *group* concept. Used in all drawing and layout programs, it allows the

user to bind multiple objects together so they can subsequently be treated (in many respects) as a single object. For many years, however, the design had an annoying aw. If you grouped some objects together, and later wanted to make a slight adjustment to one of the constituent objects, you had no choice but to ungroup the objects, select and modify the object in question, and then regroup them. is was especially burdensome if there were many objects in the group, and if the group object itself had its own assigned properties (such as animation order) that were lost when ungrouped.

About ten years ago, decades aer the introduction of the *group* concept, Apple designed a clever solution that has since become universal. A single click will select an object, and if the object belongs to a group, the entire group will be selected as a single object. A double click will select an object *within* a group, which can then be individually edited, essentially "opening" the group. A click on another object within the group will select that object; a click on an object outside the group, or on the background, will unselect the grouped object and "close" the group, leaving it in its previous state all but for the modications made to the constituent objects.

Some concepts evolve in a dierent way, with their behavior responding to a changing purpose. Consider Facebook's *post* concept, for example. Initially, posts were limited to 160 characters. e limit was progressively extended, to 420 characters in March 2008; to 5,000 in September 2011; and then beyond 60,000 in November 2011, only two months later. e *post* concept thus morphed from providing a short message to supporting publishing of long articles—a very dierent purpose. Indeed, in advertising the latest limits, Facebook noted that a typical novel of 500,000 characters could be shared in 9 posts.

is evolution of the *post* concept corresponded to a subtle but signicant change in Facebook's *profile* concept. When Facebook was rst deployed, the intent was that users would visit each other's prole pages, and look at the information and photos placed on them. Users notied each other of changes to their proles through *status update*s. ese status updates, which later came to be called posts, grew in size and signicance and became the content themselves. Now when you visit a Facebook user's prole, the main araction is no longer the *profile* but the *timeline*, which oers a chronological sequence of the user's posts.

Concepts are purposive. Concepts have purposes; that's why they were invented. e purpose of *trash* is to allow undoing of deletions; the purpose of *style* is to help maintain consistent formaing; the purpose of *reservation* is to achieve ecient use of resources.

If you can't identify a compelling purpose, you probably don't have a concept. is will mean that sometimes apparently central notions in a soware design turn out not to be concepts. e user of a system is not a concept; if there's data associated with users, it's probably there for concepts that have easily identiable purposes, such as *authentication* (identify users of a resource) and *account* (aggregate the transactions of a single user).

Novices oen assume that entities that are important in the real world context of a design must be concepts. If you're designing a soware system for a bank, you might imagine that *bank* itself should be a concept. But you'd almost certainly be wrong. In your data model (and in the code of the system), there may well be *bank* objects. But the structures associated with these objects will likely be in support of other concepts. Most banks have an FDIC certicate number; this is a key identi er for the concept of *fdic insurance*. Likewise, a bank's ABA number is not an inherent property of the bank akin to the number of legs of an animal or the vintage of a wine; it's an identier that's assigned for a particular role, namely to support the concept of *interbank transfer*.

Of course banks were invented for a purpose, but this purpose is not the reason for including the notion of a bank in the system. is is a rather subtle point. Just because something has a purpose in the world doesn't mean that it becomes a concept in a soware system that refers to it. Purposes become relevant only when they are also purposes in the soware design itself. So *reservation* is a concept in a restaurant reservation system not just because the concept has a purpose in the external world, but because the concept has the *same* purpose within the system.

To see this distinction more clearly, imagine a system used by banks for managing loans. Clearly such a system will have concepts such as *loan* and *collateral*. But suppose that to determine whether someone is creditworthy the bank collects information about the real estate, bank accounts, and stocks that they hold. Would these be concepts? Almost certainly not. In a stock trading system, *stock* will almost certainly be a concept. But in the loan management system, the purpose of the *stock* concept is not relevant; a borrower's stocks or other holdings are just *assets* that are used to evaluate them. e behavior of stocks in support of their purpose is of no interest in this system; all that maers is that the borrower holds some property whose value uctuates with time. And so while *stock* would likely not be a relevant concept, *asset* would be; its purpose is for evaluating loan risk (and maybe also to act as collateral).

e same object or collection of objects can thus be viewed as belonging to different concepts depending on the context. A stock holding may be an *equity* in a

trading system and an *asset* in a lending system; a book may be a *publication* in a desktop publishing system and a *holding* in a library system.

is is not a new idea. In the 1970s, the Turing Award winner Charles Bachman developed the *role model*, an extension to the network database model that augmented entities with "role segments." A role, according to Bachman, is a "behavior paern which may be assumed by entities of dierent kinds" [7]. Classifying things according to their *behavior* is likewise the essence of concepts. e idea of roles has appeared repeatedly in programming and soware development since then. It motivates the notion of cross-cuing types dened by their operations (such as Java's interfaces), and is the focus of an entire development method known as Object Oriented Role Analysis and Modeling (OOram) [128].

Concepts are behavioral. e concepts we've looked at have both static structure (in their state) and dynamic behavior (in their actions), but it's behavior that really denes a concept. To the user of the *trash* concept, the fact that the trash contains items is secondary to the more important fact that those items can be restored or permanently removed. To the user of the *style* concept, what maers is that if you change a style, all paragraphs that have been assigned that style are updated in concert; that the word processor must remember the style of each paragraph is just a prerequisite to this important behavior. And nally, the restaurant customer wants to be able to book a table, turn up and nd it available; that the restaurant chooses to use a reservation book is of no interest to the customer.

is quality of concepts leads to a simple rule of thumb: if there's no behavior, there's no concept. If you're designing a photo editing app, you might be tempted to identify *pixel* as a concept. It's certainly a concept in the informal sense of the word. But what behavior is associated with pixels? Asking this question moves you towards the real design concepts. Perhaps the behavior is that you can take a photo comprising an array of pixels and edit it by making all the pixels darker or lighter; in that case, the concept might be *adjustment*. Or perhaps the behavior is that you can split a pixel into its constituent red, blue and green components, and edit just one of those components for all the pixels in the image; in that case, the concept might be *channel*. Or the behavior is building up an image by combining pixels from multiple overlapping pixel arrays; then the concept might be *layer*.

Identifying behavior rst is useful from a design point of view because without behavior there's very lile to design. All the complexity of a soware app comes from its behavior. Suppose you're designing a photo library in which each photo has a collection of metadata elds that include camera seings, capture time, location, and so on. Storing and retrieving this metadata will obviously be import-