Transcript of Kyle Cordes's Java Scripting Talk

http://kylecordes.com/2006/11/10/java-scripting/

Kyle Cordes: I did something very unusual and bold for my presentation; I did not use PowerPoint at all. Instead, I took words and I put them together into sentences and I put the sentences together into paragraphs. I made them very short sentences and short paragraphs and I put them on a piece of paper to hand you! You can look at the piece of paper. It's like having notes without having to take them.

If anyone does not like the point size, I have a small handful of them at a larger point size. I have more if that's not enough. I printed 30 and we have 18 people here. Does anybody want the large print edition? Raise your hand if you want large print. Would you hand him a large print? There's three or four in there, not the whole thing, just one copy.

I picked up that idea of putting words on paper instead of using PowerPoint from Edward Tufte. If you've heard of him, go to one of his classes. If you haven't heard of him, go Google him and then go to one of his classes.

I'm Kyle Cordes. I run a little company here calls Oasis Digital Solutions. We do a lot of stuff that includes Java stuff. I put my website on there so I don't have to show it to you. I'm going to talk about scripting your Java application. There's about 50 ways you can script your Java application, so I just picked a few of them that seemed most relevant and I'm going to demo those few that seemed most relevant.

The history of scripting: to go back to when people first started doing much with Java, there was this thing called the Beans Scripting Framework, and it's currently part of the Apache project. It started out as just some guy who started writing it, then IBM and a couple of other big players adopted it, and recently it's been handed over to Apache. So, somewhere around 1997 or 1998, real early on, there was this mechanism for binding a few scripting languages into Java. It was primarily oriented towards JSPs, so if you wanted to do JSPs, for whatever reason, you didn't want to type Java code in your JSPs, you wanted to type TCL code; you could type that instead of using this Beans Scripting Framework.

I probably wouldn't pick it up and start using it now on a project with today's technology, but a lot of us are stuck with the year before last year's technology because it's really a big deal to upgrade your Java and so on. BSF actually works very well, so it's not a bad idea to have it in your toolbox if you wanted to add some scripting. If your project is stuffed in JDK 1.4, it's going to work just fine.

So, let's see how it works. I choose JavaScript for my scripting language whenever I have the choice just for simplicity. I've tried to show here, basically, to give you a feel for the minimum amount of code it takes to get anything to work with the BSF. These lines are simply because I was too lazy to do the research to find out the magic BSF incantation to not have this line in here. This line is a language specific line. If this was not here, then the only thing in here that knew that this was JavaScript would be this little.js on the end of the file name.

So, this is a bit of junk just because these versions were in flux, and I couldn't figure out what the right little bit of API was in my version to get rid of that. The important stuff is in here; you can go to this BSF manager and say, "Based on the file name, figure out what kind of script I have." Then you can get one of these managers and say, "Give me a scripting engine for that language." In this case it's JS, so this code figures out that this is a JavaScript file. This loads the right scripting engine for that. The nice thing about this Beans Scripting Framework, it's a scripting framework and is it doesn't care what language you're using, so you could have just as easily said.tcl, I wouldn't have to change any of the Java code, aside from that thing in the engine.

This command is just a class I wrote to have something to call things in, and that is right here. The idea here is that I wanted to expose some commands that my script could call, and I made up a whopping one command that just prints out whatever you call it with.

This declare bean is the syntax for telling the scripting engine about an instance. So this instance, I'm saying, "Take this instance and put it in there with this name," this is what that will be known as inside the script. The interesting thing about this is that the Java -- this is a Java object -- could be any real class in your application, and you can expose it to the scripting with this line. This loads in the script, and this basically reads the script and processes it, and this calls some functions that are inside it. Let's see what that script looks like.

Here's the script; it's very simple. This declares one function. You call it and it calls the right method on something called commands. The neat thing about this is that you could make this look however you wanted for your application. If you were writing an application -- what's your application do?
Audience member: Insurance.
Kyle: If you needed to expose an insurance policy, you could make an insurance policy object and you could use this line of code right here to tell the scripting mechanism about the insurance policy object. Then over in there, you could say something like "Policy." and call methods on it.

How many people know JavaScript or know a little bit about JavaScript? How many people have never seen JavaScript before? So, there are a few that are in neither category. I chose JavaScript because it's pretty close to Java. In a deep way, it's nothing like Java, but in terms of just understanding what a few lines of code mean, if you know Java, you can pretty much guess what these lines of code mean.

Let me run this thing and let's see what pops up. I guess I had to unmaximize. There we go. So, there was this line of code in the script, it ran and resulted in something being printed. There you see a round trip of some data in and out of scripting.

That's a short tour of what the Beans Scripting Framework does. Next, I wanted to talk about BeanShell. BeanShell has got a neat history; I mentioned it in here. A guy named Pat Niemeyer, here in St. Louis, wrote BeanShell. Somebody said he used to come to these meetings, like five years ago.
Audience member: He presented at these meetings three times, I think.
Kyle: Yes.
Audience member: He comes once in awhile.
Kyle: Once in awhile?
Audience member: He used to come quite regularly when this started.
Kyle: Right. I remember when the group just started and they met over at Novell, and it was an amazing crowd of people. I think one time I estimated it was well over 100. [audience talking] You miss the popcorn? They had a nice facility over there.

OK. BeanShell does a lot of interesting things. It's a superset of a Java language syntax, so any valid Java is valid BeanShell, but there's other stuff you can type in BeanShell that's not valid Java. Well, the reason why BeanShell's interesting to me is because of that first property. So I'm going to show you how that works.

Let's say we had an application. And notice this is even shorter. It takes just astoundingly little work to get your application to connect to BeanShell. You make an interpreter. This is a BeanShell object, this interpreter. Here, let me make it more obvious, what we're looking at. You make an interpreter. That method here, this is the BeanShell syntax for this thing in the Beans Scripting Framework. So you can tell the Beans Scripting Framework folks kind of like complexity, and Pat really likes simplicity. I really like this code here; this is nice. Source means hold in the contents of this and run it. So that's it. These three lines, this one and these two, are the only thing in here that was needed to connect to BeanShell. We published one Java instance, frame, into BeanShell, and let's go see what's in that BeanShell code.

So that should look an awful lot like Java. Notice anything different from Java? Anybody notice anything, how this is not Java? [audience response] Yeah, we didn't have to clear those buttons - they just worked. Notice anything else different from Java? [audience responses] That's right. Anything else different from Java? Actually, I'll point one out. This just says south center, instead of having to have the type set for it. So there are some shortcut stuff in there that wires things up, so that that works. So now we have a program here, a pretty simple program, which is written half in Java and half in BeanShell, and it works. Pretty simple.

Now the reason I chose BeanShell to be one of the few that made the cut here to be worth demo-ing is because of this, I think this is a really important property I'm about to show you here. BeanShell is very close to Java, so I can take something that I got running with some configurable BeanShell mechanism, and I can then shove it right in the Java code. Now it's not quite right because I will have to bring it back so it's really Java. Call this button 2. OK. So now I'm going to disable the BeanShell part. And look - it still works.

To make the point more forcefully, I could take - here, let me put that back. Here's our scenario: We have a working Java application where we have a bunch of stuff hard-coded, and we're in a really big hurry. We need to make it seek and dynamically tweak something about this program, and we don't have time to think about all the different complex ways we should make it dynamically configurable. Let me show you the ultimate shortcut cheat to make it configurable. You take the Java code that shows your configuration, which is just hard-coded. You put in a few lines to wire up BeanShell, and you take that code out of that and put it in to the BeanShell instead. And now we took something that used to be statically compiled and it should just work. I going to stop for a second. Does anybody have any questions about what I just did there and why it's interesting? Because it was actually so few steps that it's hard to see what's important there. Anybody want to volunteer anything? Comments? Nothing.

The next one we're going to talk about is Groovy. I'm not going to say much about Groovy. I'm not really a fan of Groovy. Groovy has really one key point, which is that it's a scripting language but it's not a very dynamic scripting language, so it's particularly amenable to being compiled into Java. And so it's likely that it'll run faster and be a little bit more native Java feeling. But there's going to be a Java talk next month, you say? Next month? So, Groovy. Yeah, I'm sorry, Groovy. So I won't talk much more about Groovy. [audience response] It's much more of a scripting language. It's dynamic and all the sort of things you'd like it to be and duct-type and all that. So, I mean it's not Java, but it's more like Java than any of the other common scripting languages.

Now I'm intentionally showing you how this stuff works before I talk about what a scripting language is, so you'll have a little bit of frame of reference when I talk about it. OK. So now the big one. The JSR 223. It's been floating around for about two years, I believe. And that's an effort that someone started - I don't remember where. I read where but I don't remember. [audience response] Sun and Zend started it. OK. They figured out that a lot of people were doing a lot of scripting stuff with Java, and that it would be awfully nice if there was something in the Java box. So they came up with a JSR, where I believe the goal from the beginning, if I understand the history right, was to get something that could end up in the JDK. And that actually has happened. So this new JDK which is shipping December 7th, which is about a month away, will have Java script in it.

So I'm going to give you a demo of the technology that's going to go in it. But if I was giving this demo next month, or if I had the beta JDK on here, I could actually give you this next demo without having any jars. You see here, I have various jars in this project? I wouldn't need any of these with this new JSR 223 stuff. So JSR 223 is a more modern API that does the same thing as Beans Scripting Framework, but it's a little more polished, little easier to get things going, and it ships with one implementation already in it. The one it ships with is an engine called Rhino, which is just a funky name over at the Mozilla project for a Java script interpreter written in Java. But that one is about to be elevated to a very premiere place in the scripting world by nature of being in the Java box, in the JDK that you download in the JRE that you install.

So I have a quote on here you might enjoy reading. I won't bore you by reading it to you, but the essence of it is that you won't be fired for using the scripting that's in the Java box. It's not some funky thing. The guy talks about if you pick up Joe Bubba's scripting language and start using it and it breaks, that could be something people get really unhappy with you about. But if picked up the scripting language that came from Sun as part of the JDK, it's a highly defensible thing to do. It's not really important to me, but in some environments it's strongly encouraged to use things in the box if you can.

So to demonstrate this one, I took some demo code that I wrote for another talk here last year and I added a little scripting code to it. So, was anybody here last year for my talk about Java Swing stuff? You were here. Anybody else? So very little group overlap. So you make one tiny change to put this back. So what I'll run in a moment here is exactly what I ran last year. This is a thing that stimulates the situation where you want users to rearrange the order of some things, and it lets you drag and drop their order. And it does this kind of timing stuff in the background to get this smooth animated reordering. So you can say, "Oh, I want to grab this guy, bring him up into this position. This one brings him down to this position. This one brings it up to this position and so on."

It took about, I think about, twenty-five minutes to go through the code of how all that works so I am not going to do that now, but if we have time at the end and somebody wants a shorter tour of how this Groovy code works I can maybe give the ten minute version. The important thing about it is that this is just some demo code. This is all random made up data for the purpose of being able to demo and it's all hard coded into this demo code. What I wanted to do was show, let's say you had a working program that did something interesting and you wanted to add a dynamic hook to it. You wanted to be able to add run time without re-compiling and without deploying a new version. Put in some kind of business rule and I will talk later about business rule scripting. I just wanted to show some business rule scripting. So I created one extra class which I called a scriptable ordering widget and I will show you the code in that in just a moment.

To demonstrate the Rhino API, so this is calling Rhino, which is the Mozilla Java script engine that is going to be in the box in the next Java. But, I am calling it with its API. I am not calling it with the JSR 223 API because; I did not feel like putting the 1.6 data JDK on here for one demo. I apologize for if anybody really wishes they could see that. You can go to the site who's URL I put on the paper if you want to see what the difference is in the URL, but it's very similar. It's essentially similar to this but things are named different things. OK, so something you will notice about this is that even in a big font in a low resolution screen, it all fits on one screen. The point that I want to make as many times as I can is that adding scripting support to.

An application is usually much easier than it seems like it is going to be. We make a context, we make a scope these are details of Rhino. We have a name for the file where our business rule is in this Java script run time scripting file. Then I added this hook.

Now, if we have time at the end I will show you what this hook is called in terms of the Groovy, but what its purpose is, is to ask the question, "Can I drag this work order panel?" So when I ran the thing each one of these things you see this thing here is the work order panel and before the Groovy lets me drag it; it calls this to ask if this panel can be dragged. So, again I went through sort of the minimal motions to ask the run time loadable script if it can be dragged. I read in the script to a file to save it. I went and got the work order out of that panel. The interesting thing about the work order is that the here is the work order. This has nothing special about it, there is nothing script about this. This is like the plainest Java class you can stumble across. It's just that and so on. It has get urgency; it has a get address, that sort of thing. So I get one of those, I make that incantation to stick that right here into the context. I put that where the script can see it. This line basically ran the code that I ran. So, I run the code that has the script text in it. I shove in the objects that I want it to be able to see. So I say, "I kind of give you the hook." Here I am giving the script a hook into my program and then I call a can drag method in the script and then I decided that I wanted the calling convention for this demo to be that the script function would return a string. If referring to the string OK then it's OK to drag the thing. So now there is some way that I could have... It has the feature of being able to like convert a Java script or a pickled script into a Java script but I wanted to point out that its very common when building a scriptable system to have some kind of adaptation between what kind of API you expose to the script which in this case is a string based API verses a what your application uses internally. Those do not need to be the same. Here they are different. I put in the demo code exception handling, try not to do this in your real apps.

So let's look at that script. The function can drag; check to see it the order's urgency is one. Now this is not a Java code because, this is a Java bean. The bean will say "got urgency" on it and Rhino knows how to map between Java script and Java enough to say, "Oh, got urgency I am going to call get urgency to get that value." So that the urgency is one it's going to be OK otherwise its going to be no. So let's run it with that scrip in place. I will take one of these that are a four and I will try and drag it. It's not un-clicking here because you can't hear and it won't let me drag it. I got to a one and it will let me drag it. So I now have a run time's scriptable way of saying that one's are dragable and others are not. And just to demonstrate that its run time I am going to change is so that two's are scriptable, so two's are dragable. See my one won't drag anymore and now my two will drag. So without restarting the app., without restarting the applications surfer cluster, that is the thing. We have just an immediate run time straightforward way of making a change. Depending on how the time goes on at the end, I might explore this a little bit more after I have talked about some of the background behind it.

So here is where I wanted to talk about our experiences. The reason I picked this approach to show, like what is the most interesting demo, is that this is what we are using at my firm. We are using this Rhino engine. We are using Rhino's API, which is what I showed here, so we have lines of code very much like theses this context thing, this standard object thing. It's running, it's in production and it works great. Our experience is almost entirely positive. The only slightly negative part of our experience which you can probably guess is that there are a few people on the project who have never been exposed to Java script before so they find it a little bit jarring to have that other language in there. They find they are trying to de-bide some behavior or something and they find out "Oh that behavior is actually in the Java script scripting. I don't know Java script yet." And that is just kind of the general purpose caveat whenever you have a multi language project. We have had that same issue with Java in sequel. You can have a developer who is up to speed on Java, knows it really well, his the problems with the problems with the sequel, same issue "Oh I have got to stop and learn the sequel before I can work on this", that sort of thing. But, other than that it has been just a very positive experience having this script ability. OK, so three little demos and now I have a little bit more to bore you with talking.

Let's go back to the little light. OK, so what is the scripting language? I dug around what exactly a scripting language is and it seems to be that its one of those things where people say they don't know what it is, but they know it when they see it. There are six pages on here of what a scripting language is and it says there is really no clear definition of what a scripting language is. So what it means to me is that it's a dynamic language, meaning that you don't have to do this manifest typing thing. It's a language where you can just load up some text and run it. For example: In Java you can't do this right. You can't just load some Java from a file and then say, "OK, run that now." In the scripting language you can do that. Yeah, go ahead:
Audience member: And in terms of part of the difficulty of defining it is that I think I heard somewhere that in Java 6, which includes scripting, they make Java itself available as scripting language. Which automatically calls it compiling.
Kyle: If you have the compiler present you can to that.
Audience member: Right, which many production systems don't.
Kyle: Actually that is a good segue to mention, I mentioned something on the sheet here. When I showed you the BeanShell, you can just take Java code and run it in BeanShell. We have not done this yet on a real project. We did it on a little play project. For the especially large project, for a project beyond a certain number of classes or lines of code, you'll have a smaller download if you download the source code and run it with BeanShell than if you compile it. Because the Java compiler, the class file for it, is really, really bloated. I mean it's big. In most languages, certainly in my experience with C, C++, and so on, when you compile and you get files that are smaller than the files you started with. That's how compilation is typically done for most of the history of computer science. But with Java the class files are often noticeably larger that the source code you started with. So if your compile results are bigger than the source code, beyond a certain size, shipping the source code with an interpreter is smaller than shipping the compiled code. I'm not sure that I would recommend that in too many situations, but it is certainly an interesting thought experiment. It has some advantages -- think about eliminating the compilation step, just take your source and run it.

So, what is a scripting language? I said, "Interpreted execution." It's a common answer. I listed some common answers on here. But that's not really required. There are scripting engines which do this Just In Time compilation just like Java does. I think Rhino is just an interpreter at this point. Do you know? Is there any JIT in Rhino at all or is it purely an interpreter?
Audience member: No, it's a pure interpreter.
Kyle: A couple of the other scripting languages like what you're talking about actually do a JIT, so they are scripting, you can take some text and run it, but the thing you run compiles it, like in the Java class files which your JVM JIT compiles into machine code, so you have some text and now you are in machine code a half second later.
Audience: And most interpreters parse the code, make it a syntax stream, and then evaluate that, interpret that, which should remind you of the original Java.
Kyle: Which is how Java ran. So like early in a scripting language's adoption, it's likely to be purely interpreted. If it gets popular, and people start throwing money at making it fast, eventually it will probably wind up JIT compiled, just like Java and the.NET languages and so on.

So, why would you want to script? We asked ourselves that many times when we were scripting because we were a little bit afraid to add another language and add this complex powerful mechanism that people might use it to make really hard to understand programs. Some of the reasons we came up with are these that I discuss here.

One is that -- and I'd like to hear if anybody else that shares this experience: no matter what kind of configuration mechanism you build, you always find that the configuration people actually want doesn't work very well in that configuration mechanism. So you find that either it doesn't have a way of expressing a certain kind of data, or let's say you build a configuration mechanism where you build main value pairs, like A=2, that kind of thing, or like a list of values, two columns, X and Y. But then the user comes up and wants to enter a whole range, and the only way to express that in your configuration mechanism is to go into Excel, do some manipulation, and put 25,000 rows in your config file, that kind of thing, that happens to me a lot, things of that general nature.

Well, with scripting, you can say, well, rather than supply the configuration, you can say, supply a little bit of script which creates the configuration. So if you want to do something like use a loop in a config file. Has anyone wanted to use a loop in a config file? Let's see, a couple of headshakes. Well, if you use scripting for your configuration, you can use a loop in your config file.

A real good trigger that if you ought to think about that, is if you find yourself creating programming constructs in your configuration file. So lets say you have an XML configuration file for something and you find yourself putting a "for" tag or a "while" tag or some kind of a loop tag, that is screaming at you to go pick up scripting instead. It'll be a lot easier; you won't have to write it. A rule to live by is: don't program in XML. XML is a really bad syntax for any programming language.

Another part of why script -- I'm going to take a poll. Raise your hand if you work on in-house systems at a company? Raise your hand if you work on commercial systems that ship to many customers? So, for the purposes of my audio recording here, it was 18 to zero.

But, if you work on commercial systems -- I work on commercial systems -- and if you work on commercial systems, what you find is that you're never done. Because each customer of a commercial system asks for customizations of all kinds of behavior. But what you can use scripting to do is: you can use it to be done. You can divide your system to some core functionality, and then some add-on functionality. You can define the add-on functionality using the scripting mechanism, so then you can get your core program to be completely done. You fix bugs, but you don't customize it per customer. If a customer comes up with some funky rule where they want to make a certain field required only if another field is greater than seven, you don't go editing your source code. If your systems look like If Customer_ID = Emerson, then... You know, that kind of thing. Instead, you put that in script.

I mention that mainly as the in-house commercial divider, if you are in an in-house situation where you are deploying the same in-house system to 27 different factories around the country and they each have little custom rules, you can get to where scripting to provide installation instance specific rules makes sense.

Actually, I'm going to take another poll. How many people work on software where the instance or instances of it are all installed at one physical location? How many people work on software that is the other way, where work on software in your group that is deployed to many physical locations? That was more like 50/50. So if those physical locations are like different business units that have radically different rules or even somewhat different business rules, that sort of thing, you might find that scripting is a good way to accommodate that.
Audience member: You allow the customers to control the scripting?
Kyle: I addressed it here, mainly from what you could do. Practically speaking, when you start out and you go from no scripting to scripting, it's probably going to be your dev team that does the scripting. But the goal, especially with commercial software, is to get to where you can document how to script it. So when you go to document it, what you want to do -- here's what you don't want to do when you go to document it -- you don't want to say, first learn the programming language that we invented here for this project. You do not want that to be on chapter one of your documentation. What you want is, go learn Javascript or go learn Tickle, or go learn Joe's off-the-shelf language that you can go down to Borders and buy books about. And then, once you've learned that...

Javascript is great there, because so many companies already have people that know Javascript because they use it in their web stuff. Now you have a language, and you know how to use that language, now here is our Object Model. If you do web development you're familiar with the do Domain Object Model -- domain, is that right? No, Document Object Model. Well, you make your own Object Model. And I have an Object Model to show you here. Here is my Object Model for this demo project. It's one class that has a few methods on it.

But, you could define, let's say you're in insurance, you could have 10 or 20 or 30 classes which are your Object Model, and you can implement Java code to make those things talk to each other and make them talk to your database, and then you can write a few lines of code like this one to publish instances of those to the script that your customers or your customers programmers are writing. And you can ship a document that says inside your script here are the things that are available to you. Here are the methods, here are some test script code which show you how it works, that kind of thing. And if your Object Model is not too complicated, it's not too hard to do what I just said. The Document Object Model that browsers use is really complicated. It's unlikely that you're going to have for your typical business app something anywhere near as complex as that, that is really complicated. I think there is a book this thick, just on the Document Object Model.

OK, the next kind of scripting I wanted to talk about is... I did a talk last year about an application architecture which is called Alternate Hard and Soft Layers. Instead of building your application as one big piece, you build a layer in some low-level language you create pieces. hen you use a high level language, a "soft" layer, to wire it together. Well that soft layer it typically a scripting language kind of thing, so you would use this code and these things I talk about to implement that architecture.

I don't want to go into that in depth here because I already talked about it last year. It's going to be out of scope, but if you ever thought to yourself, "I wish we could just build some pieces and then reuse them for different purposes, and just wire them up differently," you're real close to this hard and soft layer idea, and you would implement that using scripting. If your hard layer was in Java, then you'd use one of these APIs to make your soft layer be in one of these scripting languages.

I threw in a single line comment here, which I think might be the most important point that I have to say, which is that in the process of designing your application to be scriptable, to have some kind of an API that it publishes to mod to scripts, you can't help but make your application more modular and more testable than it was before.

Modularity has been known since 1960-something as being an absolutely critical factor in application architecture, and testability has gotten real popular in the last five years. Those are really valuable things, and you might find yourself just stumbling into them by making your stuff scriptable, by making it possible to write dynamic pieces that pick up parts of your application and make it do things.

The other thing I wanted to point out, and this goes back to that question of who writes the scripts. Do you let just anybody write the scripts? The answer is if you sell a commercial piece of software to someone and it has scriptability, then you don't decide who writes the script. Your customer they decide which of their employees they are going to designate as the writer of the scripts.

There are some large-scale experiments out there. I call them experiments, I mean businesses. Second Life has anybody every played Second Life? I looked at it for five minutes and I decided my first life was so busy I don't have time to do Second Life, but nonetheless it's very interesting. The interesting thing about it from a scripting point of view is that they violated one of my earlier rules. They made up their own scripting language. They had hopefully good reasons why they didn't like any existing one.

Their language is, as custom-made languages tend to be, a little bit ugly, a little bit rough, not quite as well thought out as it might have been. And it's used by just people out there who come to their website and sign up. It is amazing what members of the somewhat programming-aware public have been able to do.

Sometimes it is amazing what people do with the most primitive of tools. I have a story about a client from about ten years ago where we made up our own really simple, really painful-to-type, impossible to read language. And they went and used it to create something amazing. They even coded huge amounts of domain knowledge that runs their entire company in this ugly language that we created, handed to them, and said, "Can you do something with this." I'm humbled at how much they were able to do with such a limited tool.

If you think about the things carefully that I said you should think about carefully, you'll probably be even more amazed. When I look at how much they did with an amazingly primitive tool, I think, "What if I had given them a real language that they could have gone and bought a book for?" They had to figure out how this worked from having a few phone calls with me. Imagine if they had been able to go over to Borders and buy a book about how to use the language that I embedded in their program. They probably would have done even more amazing things than they did: the sort of things like you are seeing happen with user-generated content on Second Life and four or five other things of that general ilk.

The last major topic is what kind of API should I have between my application and my scripting? This is an example of such an API. It's really simple. It's one class of which one instance is passed into the script and it has four methods on it. When I say API, don't imagine that means you have to go learn some new tool for creating APIs. No, the API is just what Java classes you choose to expose to your script.

I talk about four kinds of scripting and they each have different guidelines of how the API ought to work. The first is rule scripting, and that's the one I did here. Rule scripting is the simplest, most common kind of scripting you see. Things like "I want users to be able to type in arbitrarily complex if-then things to figure out how much to charge somebody on a bill."

Has anybody ever built a billing system? Ever worked on a billing system? I'm amazed how few people worked on a billing system. I just got maybe four. I thought everybody had to do that once in their life. If you write a billing system you find out that you never, ever get to where the rate-setting mechanism is good enough for the people who want to set rates. They are perpetually coming up with new ways of doing tiered rates and discounts and all kinds of crazy stuff.

A rules scripting mechanism says, well here's a rate table. I'll give you a rate table that you can type some rates into, or you can just go into one of the cells of the rate table and type in a script there. That's a pretty big piece of power to hand somebody. It might take them a while to figure out, but you can get from a place where, when business people come up with a new kind of billing rate rule, you do Java development. They describe it and you write a little bit of JavaScript (I'm using JavaScript, but you can write a little bit of Tickle, whatever kind of scripting language you like) and you email it back to them and say, "I think this works. Why don't you tweak the numbers in it and paste it into the billing rules system that's already on your desk, that's already working." That's a lot happier story if that's happening all the time.

We have a project that's moving from the first situation to this situation where right now they send us descriptions of what they want. Sometimes we modify our core software, but sometimes we just have to edit a script for them. We're going to get to a point where we only have to ever edit a script for them. Then we're going to document what that script API looks like, and then we're going to say, "Here, you can write scripts."

The key thing about this rules-type scripting is you want a simple shaped API. Here's the API for this one. You have to have to have a function called canDrag() and you have to return a string, and if that string is OK the guy can drag it. That, and then the methods you can call in order, that is the API in this case. It's very constrained. There are just a few things you can do. I could write arbitrary JavaScript code here, but the shape is, in a sense, dictated by that's the entry point for dragging.

The next kind of scripting is what I call plug-in scripting. Plug-in scripting is that you want people to be able to add features to your application in a more end-to-end way. Has anybody ever said to you, "Hey, for this kind of product we need to collect these two new fields of data from the user and those two new pieces of data need to go through the system and come out on the other end." Map that into your problem domain. That's the common kind of thing that will happen: an end-to-end situation. I want to add something at the beginning of the system, I want to do something with it in the middle, and I want it to come out at the end.

That's a very different kind of scripting than just supplying one little chunk of code to answer one question at one point, and that's what I call "plug in scripting" or even "end-to-end plug in scripting." For that, you have to do a very different shape of how your scripts talk to your program. It doesn't look much at all like this, I didn't do an example of it, because it would be, probably too big to fit in the hour I wanted to limit myself to, if someone asks a question about it I'll show you a little more of it. But, the idea is that you may even have a script that has more than one file. There might be a file that has to go under the client application, if they're like on a web server somewhere. There might be a file that ends in some back-end processing system. There might be another file that, You might have a script that has to define some customer SQL, the kind of script that says, run this script in a GUI, run this script to customize the SQL for this customer, run this script to add another field to the report, you know that sort of thing, end-to-end. That's a more powerful kind of scripting, and it's really also a lot more work.

The final kind of scripting, and I don't have Word or Excel on this machine or else I'd show it to you, is the big, successful commercial desktop aps, like all the Microsoft ones, and many of the competing ones, Autocad, even Emacs. It's common for sufficiently complex apps, for the app itself to be scriptable from an external point of view also. You can talk to Word as if it's a software component. You can invoke or instantiate a new MS Word and you can make calls on it, as if you were clicking on the API's. You can say, "Type this text in," "Do a file open," "Do a file print," "Do a format font style," that kind of thing. That is also scripting. It's a different kind of scripting than what I've shown here. It's also, if you're building an app that's useful as a component, that's worth doing.

One example, and I don't have code for it, because its in a different language and it's a decade ago. I built this little tiny app. Its sole purpose was to print a mailing label on a certain brand of label printer, and it was brand of label printer for which you couldn't get a Windows driver that was any good. So we had to have this little custom app that you could type text in. Well, we made a way of making it a COM object. Now if I was doing it now, it would probably be a Java project, with a Java API, but I was doing it then it was all Windows32, it was COM. But the idea is the same, that application, I wrote it as an application and most people used it as an application, they ran it they typed their text in, it printed out on this special label printer. Well, later we found a way to use it as a software component, so, that same application, some other application, which had a plug in scripting mechanism, (on your paper) called the external scripting mechanism of this label printer. So, between the different kinds of scripting, you can say "here are some applications, I throw some script in each one, and I wire them together and make them talk to each other" Its a style of Ad-Hoc programming. Which I don't personally find appealing, I like things that are a beautiful system, not, "I threw in some Word scripts and it worked." But, there are a lot of systems out there that somebody threw in some Word scripts and it worked. That's a legitimate and useful way to create systems of a certain kind in a certain context. If you can do this external scripting thing, where you expose or write your applications so that an outside program can get a handle on them and work with them as if they were a user, that can be a very useful capability.

So the last thing I want to point out, before I open for questions, show more details or anything, is to be really careful, about what you expose, to your scripts. So this has an important property, the only thing it exposes is, are gets of things like ints and strings. Lets say I had a work order, a customer, an order, an address, a whole rich set of domain objects and I expose those to my scripts, and just one of them had just one method that exposed some other classes, you could say like "get controller" and it gave you the web controller behind it, that kind of thing. Anybody ever written a domain class that sort of accidentally ended up with a "get" that would give you some like part of the application that wasn't really domain? Can anybody tell me you have never done that? Will anyone admit to it here? No one will admit to it here. I will admit to it here. I have done it, I suspect, some of you're teams have too, although surely no one in the room actually did it. If you do that, you can accidentally make your entire class structure, of your entire program, has now become the API for your script. So you think about what that means, Let's say this one had a "get web controller" method, and somebody, who didn't work for you, somebody from some customer side, some branch office, wrote some code, and they figured out, cause they were in a hurry and they were trying to meet their bosses needs and they had something like "order.webcontroller.su" and they did that. Well, you just accidentally made the particular structure of your application, BE the API of the scripts, so that when you re-write your application and you change something about this subcontroller, this method, you will break those scripts. So that's the caveat, is, be very careful what you expose to your scripting. That caveat, in the example here, all I had to do, was not mess it up in here, but, the way some of these scripting languages work, and I believe the way Rhino works, if you make a one line invocation to turn it on, maybe even without. You can write code in here, which I won't show you but it's in the docs, to go instantiate a Java instance. You know, the class name, so if you're not careful, even if you don't make a mistake in what you expose in your domain classes that you hand to your scripting mechanism, someone, who's like, in the heat of battle, trying to make their problem work, might go write some code, that instantiates some classes, which you had no intention of being part of any public API. And they start calling methods on them, and now, when you ship a new version of your app, you get in trouble because it broke their script.

Like, maybe they happen to know you use hibernate so they go instantiate some hibernate utility class, start making calls on it, and your entire system crashes because they thought they were doing a good thing. So, my advice is, build a firewall between how your app works and what you publish to your script. So you should actually find out how, go find out what the API is to call some sort of hibernate utility thing here, and go verify that that does not work, before you release the scripting mechanism for anyone to use. OK, so that's the end of what I wanted to talk about, I'd like to hear any kind of questions, or if anybody wants to see anymore details, about how any of this code works, including just the whiz-bang GUI thing, that has nothing to do with scripting. We had the short time, so we're actually done about fifteen minutes early so we have plenty of time.
Audience member: Just on that last section, where you were talking about different styles of using scripting languages, something that I've done, in a number of applications, is to just provide an expression evaluator, which many of these scripting agents offer, that is, rather than jumping out to a completely different script, you let the users type in a one line expression for something, like when they're putting in a course, they can describe the price for the course. Many courses will be, OK its five thousand dollars for you to have this course taught, and you can send ten people to it, and each person over ten is two hundred dollars. So you're just putting in an expression, rather than choosing pricing structure number 6. You let the users type in an expression, just like they would in Excel, and that's a very simple use of scripting that is very powerful.
Kyle: Yeah, and the code for that, if you wanted to do it, you can actually do that right in here. That is an expression. So, if I wanted to I could have omitted this. So, this is the line of code that when unloaded some file and got the system prepared and this is the line of code that actually invoked this call, this expression. I could have omitted this, loaded this out of my database and I would have achieved exactly what you just said, with this.

Next?
Audience member: It seems like this is pretty powerful but from what I've seen, with a lot of customers if you give them something that's powerful you are always going to at least have that one really well intentioned customer that learns just enough to get dangerous and they are constantly shooting themselves in the foot, bringing the whole system down, and making your life a nightmare.

Don't you open the door for that?
Kyle: You do open the door for it. Which is why I my caveat was so strongly stated. You need to keep your scripts in a sandbox. Now, even keeping them in a sandbox users will still find a way to make things bad but not anywhere near as bad as if they could get out of the sandbox.

So, to give you an example, if you keep them in that sandbox then in a sense the worst they can do is write a really, poorly implemented slow script for calculating the price so that, when they use their product with their gargantuan slow script, it takes longer to bill that kind of product. That's not nearly as bad and that's a lot easier to find and fix than if they get a hook to start making hibernate calls.
Audience member: Well, I can see that. but I can still see the customer that's always having a syntax error in their price method...
Kyle: Yep, Absolutely...
Audience member: And it never works and they are calling you and saying, "Yep, price is not working." So what would you do?
Kyle: That does happen. That's the trade off right? So, if you build a system that is very powerful, lets say programmable, now your users are programmers and they are going to be able to have programmer type problems. If you only give them a rate look up table they are never going to have that problem but they are only going to be able to do simple pricing structures in my ongoing billing example here.

Can you tell I work on a lot of billing systems? [laughter] All my examples are billing systems.

Anybody else? Yeah.
Audience member: I use scripting in kind of a different way to control a running system. So, I have a system that's using swing, has 200 some swing beads. I have exposed creative bindings for all of the swing beads so that I can use any of them that run my system. I have a filter that is exposed. Because it runs like that we often have to disable part of the application. Say, this has to be cut-off from this time to this time and we just use scripting to be able to control the application for a time and change behaviors, output them to this, remove it, shut-off access to this part of the system.
Kyle: That's more of an operations twist on what I call external scripting and it's a very, very good idea. The reason it's a good idea is that it's a lot less work on your part building the system. You can provide a much more useful interface than if you tried to do it without scripting. So, if you tried to invent your own way, from scratch, of exposing the ability to turn each kind of bead on and off. You would probably have to figure out how you have bugs in it and so on. If you just take a set of swing beads anyway you can flip a few switches and say let the script find the swing beads by name and you have the ability to write scripts, let it run time, call methods and turn things on and off. That's a fantastic thing to do.

Next?
Audience member: Can you take classes directly from the script or would you have to have some type of factory class.
Kyle: That's what I was saying. You can and I don't remember how the API of Rhino works. You might. It varies by language which things you have to specially turn something on to enable. There certainly is a syntax. In fact I think it might be this one. I think this might actually be the one that turns it on. There are some standard objects, which Rhino provides which are a Java script API to creating Java class instances would be what you just said.

But, I said for sandboxing you really want to hook into that and limit what the scriptwriter can do. But, on the other side, if you are doing the kind of operation things then you wouldn't want to limit them because it's not like it's some user writing scripts, its you writing scripts. So, there is a power versus risk trade-off.
Audience member: Can you only make it so you're accessing certain packages?
Kyle: I don't exactly remember what the API Rhino looks like. The answer is yes though because if you wanted to you could turn the whole thing off and provide a factory to the script that will only do the things you programmed it to do.
Audience member: I think ultimately the answer to that is you need to use Java security manager because some of these like Groovy and the other native Java scripting languages just inherently have all the access to all of Java. So if you want security you have to use Java security manager and using that you can completely control what classes you need hit, how and when. You have to manage it that way.
Kyle: That's one of the reasons I am not a big Groovy fan. I actually like more of the law between my system and my scripting whereas there are benefits the other way too and Groovy gives you the other benefits. Yeah, you can just type, just like in Java code. Just like in this bead code I showed you earlier. Yeah, I mean you can do what ever you want, right? [laugh] Hibernate, whatever. [laughter] So if you shove this bead shell thing in, yeah, people are going to be able to write code that just scrapes things up and does things with them.

I would be much more leery of exposing this kind of mechanism with bead shell where it's kind of "here's the power of Java" than I would be exposing the other thing where I said here is a limited keyhole API of what I want you to be able to call from these scripts.

Anybody else?

Anybody want the ten-minute version of how that GUI thing works? Show of hands, who wants it? How many say they want it? Who doesn't want it? Who wants to be done? It's hard to tell with three to zero. [laughter] I'll show it briefly then.

[noise] I am recording this on my little $80 voice recorder. Highly recommended purchase for 80 bucks. I am hoping to be able to slice a little podcast out of the middle of this somewhere. I don't think anybody would like to here the whole hour of the podcast but maybe it will be like a five minute segment or something that is worth posting.

You got to give me a minute to think about this one since I gave this talk a year ago. OK, if I remember how I did this I will start with some of the utility stuff; it's really easy to understand. This thing here just makes random data. You can tell it to make you a name or to make you an address. So, there is nothing in here that has to do with the cool GUI. This just makes some data so that the screen doesn't just say one, two, three on it, so it looks like real data.

That class we have already seen. It's just the data holder. It's a bead for work order stuff to hold the data about a work order, a very simple work order. This is a panel, which displays a work order. The interesting thing about it is that it has this highlight and unhighlight method. OK, so if this thing was running, this is not highlighted... oops, I got to find what I can drag [chuckle]. That's kind of funny. For the sake of being able to demo this thing without having our silly script thing getting in the way I will put this back to the non-scripted version.

OK, so that's not highlighted, now it's highlighted. It just turns the border yellow, basically. So, that is very straightforward swing code. makes a frame, makes a panel, sets up a border different ways and so on. The box layout, I think this was new in 1.4 or so, it makes it is easier to stack things up vertically; that's all it does.

What's the next piece? A palette, this is in the artist sense, a bunch of colors to choose from. Just made a place to store a set of colors that are decreasingly dire in their color. So, the one at index zero is red since it's really important, and so on. You can say, "get a color for a certain level of urgency," and it gives you the appropriate color.

So now, I've showed you several classes that are not -- essentially, there's nothing to learn from those in terms of how this silly GUI thing works.

What's left? We have a file util, all it does is load a string out of a file, so it doesn't have anything to do with the fancy GUI thing. We have main, widget and slots, so that's it.

Let's look at main. What's it do? You have to trust me; I don't feel like going through it line by line, this just builds the overall application. This doesn't have anything in it about the drag and drop other than that it takes this ordering widget, calls get component on it and puts that in the center of the layout. This is just boilerplate make a Java app run code. There's nothing worth pointing out here. This calls around a data thing.

The way we've all been taught, up until the last version or so, to instantiate a swing up page, is wrong. You really need to instantiate all this stuff from inside the swing event thread by doing this; this is the right way to do it. I think Sun has made it so that demo stuff always works even if you don't do it this way. But, you're really violating the rule about only manipulating your GUI stuff on the GUI thread, you really should. All this create stuff is often done in demo code, especially -- and actually in a lot of production code I've worked on -- in the main thread of the app, and you really need to be doing it in the GUI thread instead. Is that true? Is what I'm saying true Wichi?
Wichi: Yes. There are people who encountered problems by not doing it correctly.
Kyle: Right. It's exceptionally hard to debug.
Audience member: You're talking about the run later?
Kyle: Yes. This code just calls that random thing, and it makes a work order with some random data in it. It just makes this list of work orders and it tells this ordering widget thing to load those up. There's no code in here that has anything to do with that drag and drop GUI. That means there are only two classes to actually talk about that are not support classes that constitute that GUI, and those are the ordering widget and the slots.

The slots. This has a bunch of verbose code in it, but what it creates is basically this structure: the one, two, three, four, five. It creates a list of labels, it puts them in the right place and it creates a list of points where a work order can be located. The labels, this is index zero of the points. I'll give you a short tour of how that code works.

The stack size is how many are going to fit vertically, basically. When you call this set up slot code -- this gets called whenever the window gets resized -- it figures out if it needs to rearrange where the slots are, and if so, it keeps running. It loops over all of them, it figures out, by taking the modular thing, which row and then which column each slot goes into.

To find the X coordinate, you take what column it is, multiply it by the size of the column and add a left margin -- very straightforward. The max X and Y thing are what's the farthest point that the stuff can reach to. Here, for example, the max XY is somewhere right over here. The reason that is, even though the point is here, the width of this thing needs to be at least that wide to fit something in that column.

The reason it does that is so that by knowing that size, it can figure out whether the scroll bar needs to be there. Scroll bars are really easy to make work; you basically make the underlying component the right width, and the scroll bar just works. The code to make the underlying component the right width is right there.

This thing is looping through one through 50. I haven't configured these little 50 pieces of fake data. It makes a point for each one. At the points, it takes a label, calls a few things to get the label set up right and it adds the label to the layered pane.

The layered pane is worth talking about. A Java -- a J-layered pane, I think is what it's called -- lets these float a bunch of components on top of each other and specifies the order. You can tell it, "here's a bunch of stuff; I want some of them to be in the front and some to be in back," and you'll see, right here, label layer; the layer, which is just a number, we put the labels in layer five. If I drag stuff around, see how the labels are behind? The way they're numbered, higher numbers are farther back -- or are higher numbers forward? I think Wichi knows -- you look like you knew.

The point is there's a way of specifying. If you just put these on a J-panel without this layered pane, then you wouldn't have any programmatical control of what went behind what. I wanted to have that control, so I used the J layered pane, who's API is very simple. When you add something to a layered pane, you specify numerically what layer it goes in.

What this procedure does is it says given some point, which slot is that closest to. Where I'm pointing the mouse, the point I'm closest to is this 22. Basically, if I'm hovering this here, that's a way of saying if I'm here, I'm at point 22. That code is isolated from the rest, and it's kind of a bad algorithm. It doesn't do any kind of topological sorting or anything. It just loops through all of them and it says that one is closer than the one I had before, but now that's the closest one.

The thing worth pointing out is that I called distance squared here. That probably shouldn't care about this; I guess I don't have my source code installed. I called that instead of distance because the only thing I care about in these distances is which one is closer. It's computationally more expensive to calculate the distance than the distance squared -- the Pythagorean thing: A squared plus B squared is C squared. You have to take a square root to get the distance, but if all you care about is which distance is closer, you can skip taking the square root.

That probably doesn't matter. I probably couldn't even find a machine where that matters to this demo. If it can run Java, it can probably do square roots so fast, you'd never know the difference.

So, slots have nothing to do with these things flying around the screen; all this does is defines these points on the screen. That means that all the logic that has to do with stuff flying around is all in this, and that's good because that means that we only have 200 lines of code, roughly speaking, that actually do this neat thing. This is the one that I'll give a little more VOLOCK to. There's that layered pane; there's a scrolled pane that it lives in, so that you can scroll back and forth. We have a timer, which ticks every so often. We hook up some listeners to it. We put a border around it. There was some reason why this line of code was necessary.

There's some kind of a wrinkle in swing about your scroll panes don't work quite right if they don't have a border. I don't remember the details, but I remember it had to be there.

I turn on one of the scroll bars and off the other here. The way I chose to have this scroll is that it will put few enough columns that it never scrolls vertically, and it will scroll as far horizontally as it needs to to work. So I did that there. The usual little bit of glue to find out when it's been resized. When it's been resized, you'll notice when I resize it, it changes the number of items in the column? See how there are five per, now? It calls that code over in that slot class to rearrange the coordinates. This in essence controls the speed, every 25 milliseconds it gets called. Is anybody here familiar with EventHandler.Create already? Who writes Sling code? Does anybody write Sling code here at any extent, or is it all...? One. Who writes web app stuff? So it's almost all web here - very little Sling.

This EventHandler.Create - this is the syntax we have instead of Delegates. This is the way I'm telling Java that I didn't feel like typing something like this. I wanted to type less lines of code. So I said, "Make me a class, which implements the action listener interface so that I can successfully cast it the action listener and when any method gets called on this class, call the method drift position on this, this object." That's what that does. It's a little bit convoluted. Probably for the sake of demo code I should have done something like this instead so it would be simpler, but I wanted to show off Event Handler a little bit. This has been part of Sling since I think 1.3, I think they started shipping this in the box. So this basically is the hook. It calls some code every 25 milliseconds to move stuff. Up here, somewhere I added this thing here as a component, as a listener, there we go. So in this case I made this class be the listener, so I did implement these, which means I had to put in stubs for these events which I don't care about.

So I've showed off three different ways of Sling event handlers here. There's the anonymous inter-class, there is the event handler utility, and there is just implement the interfaces and put empty implementations in the ones you don't care about. Having done all of these, I didn't like any of them, so I didn't really feel that I should change all of them, so I left the three in there to serve as an example.

The mouse has been pressed. Now we're getting to the good stuff. With that layered pane you can say, "Give me the component that's at a certain point." So when I do this, I click, I pressed - the layered pane hadn't handed me back the component underneath where I clicked, in this line. We're only going to do this drag thing if it's a work order panel. So I put that in with it. Here's that hook I use later for the scriptability, so I cast it to the right kind of panel and I ask if that thing can be drug. Then here we go. Dragging is an instance variable that keeps track of the one we're dragging right now if we're dragging one right now. So I say, "This is the one we're dragging." I tell it to highlight itself. I say set layer, set layer 20, so higher numbers are closer to you. This way is up on the Z axis, and so the one that I'm dragging always stays on top of all the others. When I first did this, I didn't have that, and I noticed the one I was dragging was somehow sneaking behind some of the others. So one line of code and it comes up on top. These grab offsets - those keep track of how far from the upper-left corner I dragged it from. When I first did this, if I clicked down here, the thing immediately leapt two and half inches this way. And that was annoying. That didn't really feel natural. So I figured out that I had to keep track of where on it I dragged it, and then kind of use that offset the whole time. So here I am tracking that.

If I release the mouse, that only matters if you're dragging something. I take the one I'm dragging. I put it back down to 10, so I kind of put it back in my main layer, in my layer pane, so that it won't be on top of everything else anymore. I un-highlight it. I note that I'm not dragging it. I do this thing called start drifting. This turns on that timer to make that event get called every 25 milliseconds to move things where they need to be. Store order is an empty hook. I'll show you what store order does. It does nothing. This was to illustrate from my original talk that that's where you would put the code to tell the application, that this is embedded in, that the order has been changed - you need to store it back in your domain in some way.

I put this here to point out a little bit of an annoyance. It seems like double-clicking is an important-enough thing that it should have a method, some kind of named way of doing it. I'm kind of annoyed with the fact that you have to have a click count of two. It seems strange to me. I guess I'm used to Windows GUI frameworks that treat a double-click as a - that's a totally different thing than a single click So that's unimportant code.

OK. This is mouse drag. This gets called by Sling each time - if you're holding down the mouse button, each time your mouse moves, this gets called. And there is some limit of how often it gets called. I mean, it you go like this, it's not being called 10,000 times. It gets called every so often if you're dragging it quickly.

So if we don't have anything picked up, we don't have to do anything. So we eat at get point. This is a way of saying, "Where's the mouse now?" Translate is a way of saying, "Adjust that point." But what are we going to adjust it by? We are going to adjust it by the offset of where we dragged that panel. This calls that slot stuff I pointed out that loops through all the slots to find the closest one. So what this little three lines does is, while I am in the act of dragging, each time I move the mouse, it's figuring out which slot am I holding this closest to. So you can see - now, you'll see in a minute how the code works - but if notice what it's doing, it's opening a hole up at that slot. See that? So whatever I'm holding it closest to, it's opening up a hole there, as if I'm going to drop it, even though I haven't dropped it. Do a couple of checks just to make sure that I get a valid index.

Now this is an unusual piece of code. It's unclear what this does exactly. This is a list of all of these panels. It says, "The one that I'm dragging - take it out of wherever it is and then insert it at the index that corresponds to where I'm holding it. So pick it up out of whatever it is, so take it out of the list, and insert it into slot 4." So those two lines of code are what opens the gap at the right place. Then I take the one that I'm dragging and I set its location to what I calculated up here. So this is a mouse-dragged event. The Sling interpreter has no idea that I'm moving this panel underneath where the mouse goes. This code here is what tells it to move the panel relative to where the mouse is. I was hoping there would be something built in to do that. Sling has some drag an drop functions, but they have nothing whatsoever to do with this. Here's that resize code that calls the thing to re-setup the slots.

Here's where the action is - these next couple methods. So drift positions. Let's see where that's going to get called. Here we go. Start drifting turns on that timer. When that timer fires, which we saw up here, it calls drift positions. So that timer fires, here's the timer being passed from the action listener interface, so it calls whatever that method is called in the action listener interface, then this event handler makes that call drift positions. So drift positions is going to be called by the timer every 25 milliseconds, as long as the timer is on.

So, it's actually pretty simple. It loops over all the panels, if that panel is not the one we're dragging. So that's important. That means that the one that I'm dragging like this, is only being moved by me. And this is really important to create the illusion that you're physically manipulating something, is you want all kinds of neat logic to move other stuff around, but the one that the user has his hand on don't yank that around under the user's hand. Let the user hold on to that one. So, that concept is expressed right there.

This figures out where should this panel be. This is the panel, this is the index of the panel. The first panel should be in the first point. The one which is currently first in the list should be right here. That's what that means.

This is a way of saying, "Get me a coordinate closer than the current coordinate." So this is the current coordinate. This is where it should be. This is a closer coordinate. Let's see what that means.

When I gave this talk I had a much longer chunk of code here. Somebody in the talk helped me figure out it could be much shorter, and so here it is. Gap is how far the coordinate is from what it should be. Increment is how fast I'm going to move it. So look the speed I'm going to move is related to the gap. So the farther it is away from where I want it to be, the faster it's going to move.

Let's see that here. So if I do this, you notice that that one that has a long way to go, it goes real quick most of the way there and it slows down at the end. I experimented with three or four algorithms for doing that before I found that simple algorithm really produced the most smooth, nice feeling movement.

I love the ternary if operator. I'm sure some of you work in companies where it's like banned by your coding standard, but I really like it. So this converted five lines to three. This is just getting the sign right, basically. It's making sure if the actual coordinate is here, and if I recorded it here it goes this way, and vice versa it goes that way. That's what that line of code does.

Here's the code that called that. This checks to see if any of them are different. If either of them are different it moves the panel to that new location, keeps track of the fact that some are moved, and if none were moved we stop the timer.

I should probably simplify this demo code by taking that logic out, but I had already written it so I left it in. Calling the timer every 25 milliseconds if you're not using it, you' probably would never, ever detect an impact of that on your computer, but it seemed more polite to stop the timer when we don't need it. Once everything gets to its final destination, the timer turns off and you're back to a totally static app. It's not churning anything in the background.

This just puts them all on the screen. placeWidgets() just puts each one at the right layer, calls that slot sync to find out where it goes and put it there. So, this is just setup code. This puts everything at the right place in the first place, and that's it. The most interesting thing about this is if you're looking for the code that somehow manages all this stuff going on, it just doesn't exist. There isn't any code that understands or manages the totality of it.

What you're seeing is kind of an emergent behavior of that algorithm that is applied to each one separately. Every 25 milliseconds, each one of these is its own little program. Nobody is trying to figure out what should everybody should do for all time and make a plan to get there. No, each piece figures out what should I do right now. The emergent behavior is this whiz-bang demo. That's it.
Audience member: Just a thought on the turning off the timer. Something that some people have discovered is carelessly not doing that kind of stuff can interfere with hibernate mode on your laptop computers. So sometimes people go to websites and this AJAX thing goes on, and they close their laptop and find an hour later it's hot and its battery is dead because there is this AJAX stuff that has been trying for an hour to contact a disconnected website.
Kyle: I take it back. You should do the timer thing. That's it. Hope you enjoyed it.

[clapping]
Kyle: Oh yeah. Let's give away the books.
Audience member: OK, I need three random numbers in the range from one to 13.
Kyle: You want me to generate random numbers? Somebody make up a number.
Audience member: Somebody pick a number.
Audience member: Eight.
Audience member: Eight! Rob Widmer. Is that fair?
Kyle: I'm going to turn the lights on. Brace yourselves.

[Many audience members discussing picking numbers and distributing books]
Kyle: I'd love to hear some feedback on how anybody liked getting a piece of paper instead of PowerPoint. What was nice, what was bad, and stuff.
Audience member: It's nice because you show code up there and you don't have to jump back and forth between code and the PowerPoint slides.
Kyle: Was it distracting to have this in your hand?
Audience member: No, actually then you could look at it when you felt like it.
Kyle: Will you keep this or will you throw it away on your way out?
Audience member: I'll keep it for a while but I'll probably throw it away later. Actually, I'll probably set it on my desk and my wife will throw it away later.

[laughing]
Kyle: I'm trying to decide how much work it's worth carefully wording things on it, or whether it should just be an outline. I thought about making it be just purely an outline.
Audience member: It let me not take notes knowing that the chief point was there already.
Audience member: Especially the URLs.
Kyle: I hate it when people have to write down URLs during a talk. I'm always too lazy to go to the website to get the slides for something, but if I had this I might read it the next morning before I throw it away.
Audience member: Do you normally put the presentations or any information onto the website?
Kyle: Yeah, we have a website that contains all of the PowerPoint presentations, and one PDF file.

[laughing]
Audience member: Could you email it?
Kyle: Yeah, I'll send it. It will be one my site.

[many people talking]
Kyle: It would be hard to express that in less than an hour. If you go learn about that, he goes into how to present information well. He really, really doesn't like PowerPoint.

["he" here refers to Edward Tufte]

[many people talking]