Questions and Answers

"Make everything as simple as possible, but not simpler."
- most recently attributed to Albert Einstein, but variants date back as far as Occam, Aquinas, and Aristotle

This page documents the rationale behind many of the decisions about JIFFEE, rationale that would otherwise be hidden or forgotten. Most of it will probably be of interest only to people really interested in framework and library development, but at least this records the information so it doesn't get lost.

General:

Web Site: Packaging and Distribution: Development Process: Design Issues: Modules:

General:

Why is this called a "Q-and-A" instead of a "FAQ"?

Precise communication requires precise language, so I choose my words very carefully (sometimes even to the extent that I annoy my friends). Most of the questions here are unlikely to be asked "frequently" so the term "FAQ" would not be accurate.

How do you expect to make any money on this?

I don't. Like virtually every IF author, I'm doing it as a labor of love and because I want to give something back to the community.

Wouldn't your time be better spent improving an existing IF authoring system?"

That's a valid question, because it's a waste of effort to develop multiple systems that all do basically the same thing. However I believe that systems like TADS, Inform7, and JIFFEE are each exploring different aspects of the design space, so — to stretch an analogy a bit — rather than reinventing the wheel each of them is experimenting with new ways of using wheels. In addition, the purpose of JIFFEE is not to "poach" existing users of other authoring systems; I don't expect anyone who is happy with a system like Inform to switch to JIFFEE, nor do I want them to. My goal is to appeal to people who have never written any IF before, and thus to make the pie bigger rather than than redistributing the existing pie.

Why doesn't JIFFEE include my favorite feature?

I've tried to keep in mind a rule of thumb from John Gall's Systemantics: How Systems Really Work and How They Fail:

"A complex system that works is invariably found to have evolved from a simple system that worked. The inverse proposition also appears to be true: A complex system designed from scratch never works and cannot be made to work. You have to start over, beginning with a working simple system."
JIFFEE started very simple and is still relatively early in its evolution, so it's quite possible that there simply hasn't yet been time to add a particular feature.

I've also tried to follow a general principle that it is better to provide a few powerful features and many specific recipes, rather than many specialized features. Thus there are many features that I will deliberately never implement because it would add unnecessary complexity to the system, but instead there will be a recipe in the documentation that explains how to achieve the effect that you want.

Finally, the extension mechanism is a better way to add features that are useful but only to a limited number of authors. Because you have access to all the code and a full programming language, this is a very powerful mechanism.

Why didn't you solicit feedback from r.a.i.f. sooner?

An idea, like a baby, is fragile and vulnerable when first born. It needs time, often a lot of time, to find itself and grow strong enough to benefit from criticism. During the first 3 years of development, the flaws and shortcomings in JIFFEE were so obvious even to me that I really didn't need any help finding them. :-) Those early implementations were so rough that they would not have convincingly communicated or demonstrated the ideas I was trying to wrap my head around — I wasn't even satisfied with those implementations myself. Once the system began to mature a bit, then it was (will be) solid enough for constructive criticism to improve it. One good indicator was when I started ripping code out instead of just adding more, since that usually means you're starting to understand the problem.

A second reason for waiting until JIFFEE was reasonably complete and functional is that you only get one chance to make a good first impression.

Is "JIFFEE" really the best name you could think of?

The current name has the following nice properties:

Being a pretty open-minded and flexible sort of guy, as long as JIFFEE is still in Beta I'm actually open to concrete suggestions of the form "I think name X would be better because Y". However, any new name would have to be clearly superior to justify the effort of changing all the code, documentation, build automation, domain name registrations, etc.

Web Site:

What do the squiggly lines in the left margin signify?

I wanted a logo for jiffeegames.com that would provide a gentle cue that you're still on the same web site without being visually intrusive. If you put your logo at the top of the page in the conventional way it disappears as soon as the user scrolls, so I decided to put a tall skinny logo off to one side where it doesn't demand attention but is always visible. (Putting it in the left margin also helps if you want to print out hard copies of the web pages, since it allows you to punch them for a 3-ring binder without losing anything important.)

The final design is my homage to the original Adventure game: You're in a maze of twisty little passages, all different ... Each circle represents a room, and under the constraints I chose for determining which paths are legal, there are 81 unique ways to connect two consecutive rooms in the sequence. In keeping with the spirit of "all different," the logo includes each of the 81 ways exactly once before the whole logo repeats. This ensures that on any but the very largest displays, the paths visible at any given time within a single window will indeed be all different.

The same theme is echoed in the favicon, where there is only enough space for two rooms and their connected passages, but that's just sufficient to form the shape of a "J" for "JIFFEE."

How come one of your web pages was "last updated" tomorrow?

Because I use UTC. You must have been in the Americas, where it was still yesterday.

Have you ever considered putting ads on the web site?

Yes, but I prefer a lean web design that doesn't distract you from the content. Besides, it really doesn't cost much to run such a small web site, so there's no need for it to pay for itself.

Is HTML validation of the home page really worth the effort?

It's worth the effort for every page. Much of the hard work you put into creating a web site is wasted if some of your potential viewers can't see it properly. Of course it's important to test on as many browsers as you can, but with so many different browsers in use the single most effective way to increase accessibility is to formally validate your HTML (and your CSS). As you can see from the Web Site Validation page, for a site of modest size it's surprisingly easy to do and it will pay dividends in maximizing your audience.

Of course, if you really want to come across as a pro, check for dead links and run a spell-checker while you're at it. Your web site is your only chance to make a good first impression, so make the most of it.

Packaging and Distribution:

Why tell authors to put everything in one big file?

"Everybody" knows that it's better to split up your files — if you control all the files and if you expect people to load many pages that share files.

In this case, no single person controls all the files: you control your game code, and I control the JIFFEE library code. I don't want the correct and predictable functioning of your game to be at the mercy of changes in JIFFEE, and I in turn want to be able to improve and update JIFFEE (even in incompatible ways) without worrying about breaking your game. Putting the whole library into your HTML file is the equivalent of static linking and protects you from changes.[1]

Of course you could just make local copies and link to those, but that would make game distribution more awkward (you'd need to distribute a whole directory instead of a single file), and there's little to be gained. Unless someone is going to play multiple JIFFEE-based games, all from the same site, one after another, there's nothing to be gained at all.

On the other hand, if your heart is set on breaking things into multiple files and you know enough JavaScript to do it, be my guest. The examples I provide are intended as suggestions to help you get started, not as commandments that stifle experimentation.

Isn't the source code of the framework too easy to modify?

With the entire JIFFEE source code incorporated into every game, aren't I afraid people will start tweaking it for individual games? Not at all; if anything I'm afraid they won't. I'm sufficiently realistic to know that most authors will have little desire to mess with low-level code, but I'll be a bit disappointed if nobody tries to modify it. JIFFEE is designed to be malleable to encourage experimentation and innovation, and when someone implements an idea that works out well, it should be easy to incorporate that back into the main system.

Isn't the source code of games too easy to see?

It's trivial for a player to select "View Source" in their browser, and then even if they don't know any JavaScript they can see all the strings like "That was amazing! Those sneakers gave you the ability to leap the entire Grand Canyon." Doesn't this make it easy to cheat? Yes it does, but it's just as trivial to flip to the back page of an Agatha Christie mystery to see who really dunnit and that doesn't seem to dampen readers' enthusiasm for her work. If somebody wants to enjoy playing they'll play fair, and if they don't that's their own problem.

There is also a "string obfuscation" feature planned which will make casual cheating much less tempting.

Why isn't there a way to turn off all that expensive error checking once your game is done?

The extensive error checking is an attempt to compensate for not having control of the language parser (since JIFFEE is not a language). There is a modest cost (increased execution time) but I feel that price is well worth paying in exchange for helpful error diagnostics. As for turning them off, the proper time to do that is after you've found the last bug — and we all know that in practice you'll grow very old waiting for that to happen.

Since this is open source JavaScript it actually is possible to turn off a fair amount of the checking, but if you don't know enough JavaScript to figure out how to do that without my help, then you aren't ready to be playing with that particular type of fire.

Development Process:

Why do you use a version control system for a single-author system?

At first I didn't, although I was pretty religious about backing up my hard drive. As a system gets bigger, though, the changes and refactorings get bigger, and the odds go up that someday you're going to change hundreds of lines of code and then realize "Oh no, that was a terrible idea. I wish I hadn't done that." Subversion gives me a clean way to back out mistakes, even big ones. It also provides a history, in case anyone ever cares - and sometimes you actually do want to go back and review the details of some dimly remembered change from six months ago. You still have to back up your hard drive, though.

Case in point: Three weeks after I started to use subversion, a shell script I was updating ran amok and destroyed the contents of almost every one of my web pages. Although the previous day's version was safe on the web hosting server, I was very glad I had done an "svn commit" on my development system only a few minutes previously, so that I didn't lose all the other work I had done that morning.

Why isn't JIFFEE Open Source?

Someday it probably will be, but as a prototype it's still too squishy and changes too often for that to make sense. You can already read every line of source code and even play around with the code yourself, but until the design stabilizes I'm afraid that allowing redistribution could lead to multiple incompatible versions proliferating and that wouldn't be good for anyone. I'm keeping the "all rights reserved" in the copyright notice so that when I do decide to open the source, I will be free to choose the best license without being hamstrung by any previous loose copyrights.

I think JIFFEE should have an IDE, don't you agree?

Yes I do agree, and thank you so much for offering to implement it. :-) But seriously, developing a decent IDE for anything is an enormous effort that I simply don't have the time to take on. Creating a nice development environment would be a worthy and productive task, but I've chosen to focus my limited resources on different aspects of IF authoring.

Besides, three of the major advantages of an IDE are already at least partially available in the current JIFFEE system:

Last but by no means least, people are currently developing Eclipse plug-ins for JavaScript, and those will probably provide much of the benefit of a JIFFEE IDE without any effort at all on my part.

Isn't it a waste of time to test on so many obsolete platforms?

In any effort there is a point of diminishing returns, and for normal browser-based software you can assume that most of your users are running a relatively recent version of a popular browser. Testing on a lot of older systems would affect only a very small percentage of your potential users, and thus would be a poor use of effort that you could more productively invest in adding features, improving documentation, and so forth.

JIFFEE faces somewhat different trade-offs. It is intended to be especially useful in schools, and schools are often woefully underfunded and thus forced to get by with outdated and obsolete software and hardware. This isn't true of all schools, but students in the districts sufficiently well-funded to have good computer labs are going to get a good education anyway. I'd like JIFFEE to make a contribution to the students who need help the most, i.e. the ones in struggling schools.

I could volunteer to help a couple of my local schools upgrade their labs, but that doesn't scale to the other 90,000+ public schools in my own country, let alone private schools and the rest of the world. I can reach far more students and have much greater impact by developing JIFFEE and making sure it works properly on the systems those schools are using right now. There is still a point where compatibility isn't worth the effort (e.g. really old browsers that don't support JavaScript), but for JIFFEE that point is at systems around 10 years old instead of 3-4 years old.

Isn't it unreasonable to expect game authors to do as much compatibility testing as you do?

Absolutely, because the extent of my cross-browser compatibility testing far exceeds normal standards. Fortunately, that kind of testing is unnecessary for game authors, for the following reasons:

Of course none of this guarantees that you'll never see a compatibility bug, but I think the combination of factors is sufficient that compatibility issues will generally not be a major problem for authors.

Design Issues:

Why are you such a fan of JavaScript?

I'm not. My design goal was to use an established, well-documented language, without any particular bias about which one to pick. On its own merits I actually like Python better, but JavaScript was the only choice that allowed me to meet the one-click-to-play goal. In theory one could meet that goal by compiling Python into JavaScript, but creating such a compiler would be way more work than I'm ready to take on. A good Java-to-JavaScript compiler already exists (GWT), but Java seemed a bit heavyweight for IF authoring, and it would make the edit-save-run cycle more complex. Looking at the whole picture, JavaScript just seems like the best compromise choice.

Doesn't it defeat the whole purpose of an IF authoring system if you have to learn JavaScript to use it?

To use any IF authoring system, you have to learn a little bit of something. That something may be a formal language (even if it looks a lot like English but really isn't) or a system of GUI menus and dialogs, but one way or another you have to learn something. An important goal of virtually every authoring system is to make that something as simple and easy as possible.

If you want to write simple games in JIFFEE, the subset of JavaScript that you have to learn is very, very small and consistent. I believe it is small enough to be similar in difficulty to what you'd have to learn to get a comparably simple game running in TADS or INFORM7 (but of course that's a matter of personal opinion so you're free to differ).

If you want to write very sophisticated games in any IF authoring system, you're going to have to learn a lot more, and as the game itself becomes more complicated the implementation must inevitably become more complicated as well. The question then becomes whether you have a powerful, consistent language in which to express that complexity. JavaScript is inherently a more mature language than any IF system will ever be, not only in terms of the language itself but also with regards to the support available for it (web sites, documentation, tutorials, etc.)

So to answer the original question, no it does not defeat the purpose. You don't have to learn much to get started, that little bit is no harder than any other system, and the growth path as you become more ambitious is actually smoother.

Why is it such a big deal to avoid the usual download-and-install?

There are two issues here. The first is making IF games easy to play. One of the goals of JIFFEE is to reach out to people who until now have never played an Interactive Fiction game, i.e. almost everybody on the web. These folks are used to just clicking on things, so if you ask them to download something and install it on their system just to try out your game, most of them won't. Some of them may just be lazy and impatient, but many are such novices that they simply don't know how to install software or are intimidated by the prospect, and the savvy ones are — with some justification — very wary of installing anything on their computers that doesn't come from a well-known and trusted company. If we didn't eliminate the step of installing a Z-code interpreter, we'd lose most of these potential users. (And yes, this is also why Parchment is such a great idea.)

The second issue is making the authoring system accessible. JIFFEE is intended to be useful in education, which means it must be easy for teachers to bring into the classroom. One problem is that some teachers are still learning about computers themselves so simpler is always better, but a bigger problem is that in many school systems the computers are "locked down" so teachers cannot install random software on them. Only the official IT staff is allowed to change the configuration, in order to maintain some semblance of consistency and make support manageable. (In a small school the IT staff may well consist of of one math teacher staying late on Friday, and in a large system it might be 10 full-time techs supporting 10,000 machines spread across 100 buildings, but either way you can safely predict that they're understaffed.) You and I could have a long and interesting discussion about the pros and cons of such a policy, but the bottom line is that we have zero influence over it. If we want to play on their playground we have to play by their rules, and those rules often say "web-only."

Why is almost everything in JIFFEE done with function calls?

There are two main reasons:
  1. To make the initial learning curve easier for complete beginners, I needed to severely limit the JavaScript syntax that was used. My experience is that even novices accept and have no trouble with the module.method("arg1", "arg2", ...) syntax, so long as it is used consistently. Making all the basic stuff be function calls achieves this goal in the simplest way I could find, and it minimizes the number of distinct native JavaScript error messages that beginners have to deal with.

  2. I could have used some other consistent syntax, like noun.trait = "value", but if I'd done that the error messages would stink. Good diagnostics are one of the toughest nuts to crack when not inventing your own language, so it's really important that I do the best possible job with whatever tools are available. Making everything be a function call allows me to intercept everything the game author does and inject a lot of consistency checking on all the arguments, especially on the names of things like nouns and traits, so I can produce far more helpful diagnostics when the author misspells something or tries to assign an illegal value.

Why did you work so hard to get complete separation of the parser from the rest of the system?

Because I had no choice. Multilingual support is one of the biggest design goals for JIFFEE, and if a game is going to work in multiple languages the handling of language-specific strings had better be very, very clearly separated from the processing logic. Creating such a really clean division between syntax and semantics is hard, but any fuzziness here will lead to real nastiness in the code so the effort is well worth making.

Isn't it overkill to use SHA fingerprints in the cookies?

Not really. Brian Turek's open-source implementation makes it very easy to incorporate them, and JIFFEE relies heavily on the uniqueness of its fingerprints to make sure we don't get collisions between two games. (If such a collision occurred, each game would attempt to use the other game's stored state, and that would really confuse the poor user.) Writing a good hash function is surprisingly hard, and because of the Birthday Paradox it is surprisingly easy to get collisions, so I let others do the heavy lifting by simply choosing the latest family of the SHA functions published by NIST (SHA-2). Since we're not dealing with bank accounts or nuclear launch codes here, we don't have to be absolutely totally perfect, so I picked the version (SHA-224) with the smallest key to minimize the space used in the cookie. This is the simplest most reliable way I could find to ensure that each game gets a unique fingerprint and so is assured of getting its own cookie.

Using this standard hash algorithm allows JIFFEE to provide strong protection against accidental collisions, but if you want to create a collision deliberately, no fingerprints will stop you. Since the game source code is readable, a malicious author can simply mimic the names of nouns and traits of the game with which he wants to collide. Although other members of the SHA-2 family are technically more secure than SHA-224, they have bigger fingerprints, and there is no point in consuming extra bits in the cookie to prevent incredibly rare accidental collisions when deliberate subterfuge is far more likely. (If some low-life does try to do this, all you need to do is ban him from the archive. The cookies can only collide when both games are hosted on the same domain.)

Why doesn't the parser accept more forms of natural language input?

The purpose of JIFFEE is to help you write games, not to advance computational linguistics research. Since the games are playable now, the very significant work required to extend the input parser would not have a big payoff. You can even make an argument that since accepting all or most forms of input is infeasible, keeping the acceptable input syntax relatively limited helps the player remember what is legal. Of course, that doesn't mean that the parser can't be improved, but the end goal is usability not theoretical completeness.

What about XSS attacks?

Any JavaScript that displays user-generated content (in this case, the user's commands that are echoed back to the screen) is potentially vulnerable to Cross Site Scripting (XSS) attack. JIFFEE includes built-in protection (that's what the sanitize() function is for), but I'm no expert on security so if you find an exploit please do let me know.

Can JIFFEE be embedded in other programs?

JIFFEE is just a collection of JavaScript functions with a small, simple interface so it should be trivial to embed it into any JavaScript program.

A more interesting question is whether it can be embedded into programs written in other languages, and the answer is: probably. I haven't played with it myself, but I expect that by using Rhino you could fairly easily embed JIFFEE into an arbitrary Java program. If you try it let me know how it works out.

Why isn't JIFFEE more rule-based like some other authoring systems?

Any designer must choose between a traditional programming model and a rule-based model, or some mixture of the two. Both approaches are workable and each has advantages and disadvantages, so there is no clear-cut right or wrong choice.

At first glance, writing rules may seem more intuitive, but for simple situations both ways yield acceptably simple results so you really need to look at the complex cases to appreciate the differences. The key observation is that both approaches are formal specifications of behavior that, when sufficiently complex, can yield unexpected and surprising results that manifest themselves as program bugs.

I have some limited exposure to a large, purely rule-based programming system, and it was not a happy experience. Once you have thousands of lines of code, I personally found writing and debugging with such a system to be no easier than working with a large traditional program, and if anything it's harder because the relevant code can be spread out among a large and hard-to-identify set of rules instead of being localized in procedures or functions that can be traced in a more straightforward way.

An additional consideration is that most IF authors won't have a lot of mentors available who have experience with any rule-based system, so if an IF authoring system is understandable by traditional programmers it will be much easier for an author to find someone who can help him or her track down the inevitable obscure bugs.

Considering all these trade-offs in the design of JIFFEE, I opted to incorporate just enough of the rule-based approach to take advantage of its strong points, but I made that part very constrained and stylized with clear ordering rules to make it easier to understand. Then I kept the rest of the system structured in a more traditional way to make JIFFEE games simpler for the average programmer to debug.

You say you were determined not to invent a new language, but aren't the forms of string-actions and verb-selection clauses actually a small language?

Yes they are, and I did agonize over that decision. However, engineering is the art of balancing conflicting goals, and the practical benefit of that minor cheat seemed greater than the cost of slightly reduced design purity. That small language is there primarily to ease the learning curve for beginners, so advanced game authors who are offended by such a compromise can write their games using addRule() and JavaScript functions directly and thereby avoid sullying themselves. :-)

Modules:

Why is everything an extension module, even the core functionality of the system?

It's good programming practice to have clean separation of modules and to use consistent designs. Even more importantly, relying on the extension mechanism throughout the system is the best way to make sure that your mechanism really works correctly and is comfortable to use. (And in fact the design of the extension mechanism has already benefited enormously from being exercised by the core system.) Looking ahead to a day when JIFFEE will likely be Open Source, this also makes it easier for people to hack the core system if they want to experiment with modifying parts of it.

Why do you force module dependencies to be a DAG?

This was a personal choice. There is no law that prohibits mutual or other circular dependencies, but I find that the discipline of removing those leads to simpler, clearer designs. In addition to doing the dependency injection, the module interconnection mechanism also allows you to do module initialization and system phase change (from initializing to running) in the same simple, clearly-defined order. So far nearly everything in JIFFEE has fit fairly well into that pattern.

What is the rationale for the module interconnection mechanism?

There are two standard ways of "wiring together" a bunch of modules which call each other's methods, both of which are simply different ways of injecting dependencies. Both have problems:

I definitely wanted to keep the idea of dependency injection because it makes testing much easier, and I wanted to keep all the dependencies explicit to keep the system understandable. To achieve these goals while also avoiding code smells and churn, I designed a third mechanism: This keeps everything explicit, but it also removes any need to keep re-jiggering the arguments to and order of constructor calls as the dependency graph changes — which actually happens a lot as development proceeds.

Implicit in all this is the assumption that modules are objects, not namespaces or global libraries. This is what allows you to do nice unit testing, so it's an important property I wanted to preserve.

Why doesn't Check use the same module interconnection scheme as all the other modules?

I wish it could, but there is a chicken-and-egg problem here: If a constructor or an init routine is called incorrectly, I want to produce an intelligible error message. The routines that do that are non-trivial and are in the Checks module, so they would not be available when needed if the service locator was used to find them.

I wasn't willing to give up good diagnostics in the name of abstract purity, and I didn't care to replicate the message-formatting code in each module, so the necessary compromise was to treat Checks as a global library instead of a normal module object. This isn't too bad because Checks is completely stateless, and it's so simple and basic that you're unlikely to want to stub or mock it out.

Why are all of a module's methods (except for init) defined inside the init function?

This makes each method a closure, which has access to the local variables of the enclosing function invocation. Since "init()" has a local variable that points to each module that is used, it makes it easy to say things like "traits.set(blah blah blah)" without needing any extra qualifiers or look-ups.


[1] In the Windows world, these changes can lead to a phenomenon colloquially known as DLL Hell. Including the whole JIFFEE library in your HTML file protects you from that sort of thing.