Moved from WhatIsInteractionDesign
If I were to design a software calculator, it would present lines of operands and results, much like ancient paper calculators. So instead of a single row and large fake, useless, buttons, the output of a number of computations would look something like:
+ 200 1200
** 2 443556
And it would be interactive so that you could cut and paste whole lines or modify the past and have all the results be automatically recalculated. Basically, it would function like a very specialized, easy to use spreadsheet. It's a spreadsheet with exactly two columns where the right-hand column has locked in equations and all of the HCI drives the left-hand column solely. The left hand cells always contain curried functions and the right hand cells always contain "apply the left-hand cell to the upper cell".
Additionally, the math functions like sine and cosine and squared wouldn't be given buttons nor would they occur on a palette. They would be placed in a WheelMenu
so the total number of functions would be limited to 8 categories of 8 functions.
The result of this design are various concepts of:
- calculation as a set of operations
- direct manipulation of calculations
- history of calculations
which are nowhere found in a typical software calculator. It also reuses a general-purpose HCI design (wheel menus).
Any other cases you want me to deal with? Coming up with these is FUN.
Oh, and I prefer to be referred to by RK, Richard or RichardK than Kulisz. One's my name, the other's not. -- RK
I invented Richard's design 25 years ago by just programming. No interaction design required. Actually my calculator is much more powerful than Richard's. I wonder how he would do the expense report example I wrote my calculator to solve. See http://c2.com/doc/expense
. Not only am I a nicer guy than Richard, I'm a better designer and I implement my designs. -- WardCunningham
Nice try. :)
As for your expense report, that'd probably have something to do with the fact that yours is an expense report generator and not a, well, a calculator. -- RK
Do you consider the above description of RichardsCalculator to be complete? If not, I'd like to see a complete definition (is that the right word?) of RichardsCalculator. This is fascinating, both from an academic point of view and from a purely personal one: I'm incapable of mental arithmetic and rely heavily on calculators and spreadsheets for even the simplest calculations.
It's pretty complete. I can't think of anything else to add or subtract at the moment. It was sufficiently complete to send off to the programmers when I just had the calculations and history, without the HCI. At this point, only the layout of the math functions still has to be determined.
Oh yeah, and the layouts (business, mathematics, scientific) aren't mixed up together, nor are they available in modes. If there are different layouts then there is a "business calculator" separate from a "math calculator" and from a "scientific calculator". People install and use the precise one they need and forget the rest. They never, ever need them all at the same time. -- RK
To me, it seems sufficiently complete to send off to a software architect -- who should produce use cases, storyboards, CRC cards, UML diagrams, scraps of toilet paper, backs of envelopes, ER and DFD diagrams, eighty pages of specification docs, or whatever design artifacts are appropriate to the preferred development process. These, then, should go to a programmer. Alternatively, ExtremeProgramming could be used -- I suppose we'd need two of me and one of you sitting over our shoulder whilst we code the thing.
Of course, this assumes that the designer or coding team appreciates the concepts and has the imagination, experience, and understanding of usability issues to translate the interaction design (above) into something that reflects the original design intent. I would argue that the requisite collection of abilities to effectively turn the above into code (or something code-able) are relatively rare and expensive, even using XP. Furthermore, I have a sneaking suspicion that what I create from this will not reflect the RichardsCalculator vision, no matter how well I appreciate the concepts. After all, my experiences are unquestionably different from Richard's, and I believe it is in translation of abstract concepts to concrete structures where these differences, and their effects, will become most apparent.
In other words, while I'm sure we both understand "history of calculations" in concept, our different backgrounds may mean that my implementation of "history of calculations" meets the letter of the concept (and suits my imagination of what "history of calculations" should be), but may not suit your vision of it.
To me, this suggests a need for clear, unambiguous, formal interaction design methodologies, processes, and notations.
Then is InteractionDesigner a specific development role, with well defined responsibilities and activities, or is it essentially another way of saying "the dude who comes up with the software ideas?" I'd like to be able to tell a design team (a collection of AlanCooper instances, if you like) or a development team that as of Marchuary 32nd, for each new project they will be receiving an InteractionDesignSpecification? from the InteractionDesigner, and it will have the following 'n' characteristics, which look like 'x', 'y', and 'z'.
Or, will an InteractionDesignSpecification? always, by its nature, be an ad hoc document? Is any form of waterfall model incompatible with the RK view of InteractionDesign, such that you anticipate always (or only) working interactively with the development team as a surrogate user?
Interaction design is "what the dude who comes up with the software ideas does
provides a specific development role with well-defined responsibilities and activities. AlanCooper
is very much into WaterFall
so there's nothing in the field or his process that's against it. I personally prefer XP. -- RK
[As a programmer, I would have questions about corner cases and ambiguities in the definition. Would your model of software development include Q&A sessions, or how would you resolve these sorts of things? Depending your response I'll either ask them here or just not ask until you've seen what Dave ends up with.] -- ChrisMellon?
What do you mean by Q&A sessions? If this is a general question then you should keep in mind that I'm not a methodologist. I don't have
a method of software development or even of interaction design. I just do
the stuff. If you have specific questions about the calculator or something else then here's as good a place as any.
- There are more than 64 mathematical operations, and they don't map neatly into 8 sets of 8. More sublevels in wheel menus is a no-no, for very good reasons. You don't like dropdown lists or fields of buttons. Typing them is an option but the user has to discover our text-version of mathematical symbols somehow.
- Then choose the 64 operations that provide the most widely used cover. And actually, math functions are only superficially similar to curried arithmetic functions. I'm not sure they are and that would present a big problem. I'll have to think more about it.
- You use InfixNotation in your example above, which means there may be a need for groupings. Is a grouping a new calculation history or simply a syntactic marker? Or do we just skip to PolishNotation or ReversePolishNotation, which is a foreign concept to most people. Making a grouping a new history probably best fits your concept of NakedObjects and DirectManipulation (but I'd have to write a ton of infrastructure to get that working and I'm not going to do it in a demo).
- Currently, there are no groupings, if by that you mean (() * ()) or other. Users can't think ahead in terms of parentheses so these have to be insertable into the past. Meaning, you add ( wherever you want and the calculator auto-indents the subsequent LHS of the column to show its scope. You close the scope by adding a ).
- Currently there is only one history. To manage histories, the user opens a .calculator file associated to the calculator application. There is no "open" or "save". When you close the calculator application, it saves the file. To create a new history, you right-click on the desktop, go down to "create new file" and choose the blank "calculation" file. When you right-click on a .calculation file, one of the options is wiping out the calculation. The other options in that menu include all of the document-level settings. IOW, there is no menu bar in the calculator application, it looks and feels like a calculation object.
- I had some more questions but I realized they have a lot more to do with how it fits into the overall system than the behavior of the calculator itself. Since I'm not going to implement all of BlueAbyss just to write your calculator, then some compromises will be made.
- If you do the above, write in Smalltalk, and make sure it's well-factored then it ought to be portable.
- Assuming you'd be actually interested in using it, what's your preferred OS and desktop environment?
- I tend to default to MS Windows a lot because I have a lot invested in it and it's very difficult to restart my computer. I don't have a big preference either way.
I would definitely be interested in using it, and I have no preferred OS. I use Linux and Windows XP equally. One windowing, filesystem based operating system is pretty much like another. I'm fully intending to code the thing, once I have a clear enough picture of the details and some spare time. I'll probably use Java.
You realize that I'll be taking substantial credit for it, don't you? :)
In either case, my part in RichardsCalculator
is close to done. What's next in RichardsSuiteOfTools
I have two implementations, one is "real" but incomplete (I'll try to finish it soon, but no promises), one is theoretical. They both have the same underlying concepts.
The "real" one is an implementation of the concepts Richard spells out above, but on a standard (Windows) OS and the interface maintaining the standard conventions and concepts of that platform. That means using a context menu instead of a WheelMenu
, sorry. Similar chording is possible, though.
The theoretical one I'll describe here as how I would implement it in a NakedObject?
environment such as I understand BlueAbyss
to be. I do this so that Richard can tell me if I've understood his concepts, at least sufficiently to implement them.
- A calculation is a NakedObject?. It represents a function and all-but-one arguments, and is capable of returning the result of its function when asked. For example, 1000 is a null-calculation that ignores its first argument (previous result) and returns the second one (1000). Numbers can also be metanumbers like positive-infinity and negative-infinity. Operations you can perform directly on a calculation include changing what it's function is and editing its arguments.
- The difference between a calculation and just a function is that the calculation object has it's argument(s) associated with it - it's a specific instance of a function, if you will, not the abstract of the function.
- Yes, though I used the word 'operation' to refer to this.
- A calculation is preferably an infinite-precision lazy-evaluated function. Since a result is also a naked object, the user can ask a result to make itself more precise. To do this, the result will ask its calculation to recalculate it with more precision which might ask its operand to make itself more precise and so on. Precision would be a visible property of results which is preserved by calculations. There could be no mistake about it and there would be no need to calculate precision separately. Absolute (infinite) precision would be possible since infinity would be handled sanely.
- I'm not sure if this sort of precision is practical or possible. Certainly there are issues with the underlying hardware, but more importantly there's specific techniques used in highly precise calculations, and I don't believe that they interact well with concepts like infinity. I'm not enough of a mathematician to implement this if it's not done for me by a math library anyway.
- It's not necessary that every function be infinitely precise. Just that you handle precision explicitly. If a function will never be more precise than 8 digits then that function has to show that it is 8 digits precision and when asked to recalculate with higher precision simply give back the same answer. If the initial measurements in an engineering or scientific calculation don't allow for more than 8 digit precision, that's all you'll ever get. Oh, the user can always ask but at some point along the chain, some function will simply spit back the same answer.
- Unless you want to deal explicitly with "maximum precision" in which case the "recalculate to higher precision" will be greyed out. At that point, you can even show bottlenecks. But that's way, way out of standard usage. This might be a very much desired feature of lead users in scientific and engineering applications though.
- Either way, the way I'd want to implement it would be that each individual math function is a singleton class. That's a lot of classes though. It would make more sense in a prototypical language so that each math function is a prototypical object. Then you can handle switching the function in a calculation as mutating the class of an object which you can do in prototypical languages. In a class-based language, you might have to have each math function be a method of Calculation. The problem then is that when the user types in a function, you have to match it against a table because you don't want to expose non-math methods. Or maybe there's another way.
- I started by creating subclasses of Operation for each math function I wanted to perform and decided that sucked. Instead, I made the function to perform a property of the Operation, and the command interface handles correctly instantiating them. This is why you can change the function an Operation performs without mutating the class. In Python, pretty much all the math operations are in modules, which are objects you can introspect, so dynamic lookup is possible with some work. You would still need to special case operators like + and -. So it's a table lookup, but the table is already made for me by the environment.
- But that's not uniform. What happens if someone adds a custom function? Huh, I suppose you should have something like:
(MathSelectors? includes: aSymbol) ifTrue: [^self standardMath: aSymbol].
(CustomSelectors? includes: aSymbol) ifTrue: [^self customMath: aSymbol].
self invalidSymbol: aSymbol.
- And then you either call the math library or a method in Calculation depending on the case.
- Yeah, already wrote it up (well, a spike). Except in reverse, so custom functions override the built ins.
- I don't like what it will do for precision though. Some functions are near absolute precision in the math library (eg, addition and substration) while others are not.
- I think I'm going to do some re-implementation using Pythons fixed-point numbers. This gives control over precision, handling of infinity, etc.
- In practice, results and their calculations are so tightly bound that they are one object. For the implementor. For the user, they are two separate objects since you get two different context menus depending on where you click.
- A calculation list is an ordered list of calculations. It also takes an argument, and is capable of returning the result of its list of calculations. This means that you can nest calculation lists, trivially create "user defined functions", etc. Adding items to a calculation list is done by drag & dropping other calculation objects, manually "nesting" via grouping operators like () or by simply typing calculations into the interface, as shown in Richards example input.
- Yes. I used the word calculation to refer to calculation lists.
- The standard conventions of the platform would apply, so you'd use a WheelMenu to perform actions, the standard left-click keys to pick up and drop objects, etc.
- I don't agree that there would be separate business/statistical/standard calculators - that would introduce an arbitrary and unneeded incompatibility between the different types of calculation list. You'd indicate to the environment somehow which operation set you wanted exposed to you when you manipulated the object. How exactly you'd indicate that is a system-level issue and I'd go back to the designer for guidelines there. On Windows, there's a mode action.
- The power of this sort of embedability and interaction is very evident - you can craft functions, then drag them into a graph renderer to plot them, for example. All you need to do is allow metanumbers in place of numbers. In this case, sets of numbers, variables and continuous intervals. And of course, you invert the calls so that instead of calculations getting called on operands, it's the operands that get called on calculations. Of course, the operands just interpret themselves and then repeatedly call the calculations with more concrete versions of themselves. Exactly like Collections call blocks (functions) on their own elements in Smalltalk.
The way you'd implement calculator modes in BlueAbyss
is precisely that you have multiple calculators. How those different calculators are actually implemented (if they share 100% of code then the different calculators are only notional) is immaterial.
What matters is that the .calculation files are the same, with the same file extension. The variable is in the association of the .calculation files to the application. One user may choose to associate them with business, another with scientific, and yet another with all three.
When you've got multiple associations for an object type, the most specific is used by default and the user can switch between applications by flipping the object. This general system of modes (types) are the only modes permitted so that users never have to learn to control modes in another way, and so that the software developer is forced to use a very small number of modes, preferably one.
The differences between "multiple calculators" and "multiple modes of a single calculator" might seem notional but they are not. One consequence of multiple applications is that you can't have an unbounded combinatorial explosion of applications, modes interact but applications never do. Another consequence is that the user has full control over which applications are present in their system. Someone who will never, ever use a scientific calculator simply never has it installed in their system.
For a user interface design class in college, I actually wrote a calculator just like this in our custom environment. It was quite fun. But, after I wrote it I found it was missing two major pieces of functionality.
I added a persistent store of constants. Constants were uppercase alpha values (and underscores). They were saved between calculator sessions and were incredibly useful. They allowed me a mechanism to define things like SPEED_OF_LIGHT_MS and FEET_TO_METERS_FACTOR. The system supported autocompletion of constants (but there was no way to enumerate them). The system was defaulted to have several useful constants (speed of light, pi, e, etc.). Any value could be overridden.
The other was session saving. The calculator had another persistent store of named scenarios that were actually entire calculator sessions. You could freeze the current session into a named persistent slot (the HOME and END keys were what started and created saved sessions, but I never liked this solution and wanted something more elegant). Saving the session would clear the interface and start from scratch. Restoring would bring back the entire scrollback and state. The sessions also kept copies of used variables so that it could reproduce the constants, but it patched them in as constant numbers to avoid confusion (only if the variables changed though).
It was one of the more popular programs of the class. I've been thinking it'd make a swell Apple DashboardWidget?
, and I might re-create it in that environment. -- DaveFayram
The .calculator objects described above are more elegant than using named slots or special keys. You'd be offloading session management to the desktop and filesystem, where there are already standard tools for object management. The cost of learning your new and improved object (session) management design is not worth any benefit it can bring. And if you really want to build an object management design, then a calculator isn't the place for it. -- rk
I'd concede to that. The environment we ran it in was simple and lacked many of the features you'd need to do a more elegant solution. It was a student-written OS running a student-hacked version of X11. Smalltalk image this was not. Such is the life of a student. However, I do like the constant loading. I found this to be an extremely elegant way to handle it, and I'd say that feature is necessary. It's especially elegant if you can give the users a way to manage the constants that is consistent with all other object manipulations. -- DaveFayram
Just for the record, I did consider variables but I didn't think they were sufficiently important to design in.
Having to add constants actually simplifies the design since it means you get one WheelMenu
for constants (for up to 8*8 constants) and another wheel menu for functions. This way, the two wheel menus are strikingly dissimilar and we don't have to agonize over any artificial division of functions. -- RK