Uncategorized

Driving causes oil rigs

Monday, June 14th, 2010 | Uncategorized | No Comments

Sorry, this isn’t a technical post. I have to say something about the oil spill instead.

If we don’t have the technology to stop a spill at this depth, why are we drilling there?

Well, the government told the oil companies they weren’t allowed to drill near land after the gusher off California, so they needed another place. So we gave it to them, cause hey, we gotta have the 100M barrels a day needed to make America run the way it does.

The hard question, really hard for Americans to face is: what if America shouldn’t run the way it does? What if we just can’t have the oil forever?

I hope you guys are paying attention to Obama right now. Tomorrow in his first oval office address, I think he’s going to basically break the news to us: it’s true. We can’t operate this way, climate change is real, and to fix it, we have to change. His ambition is back, like early in Health Care. And this time, he’s learned some things. He’s not going to compromise away the barn. And he’s going to drive, and quickly. David Cameron asked him to stop, but he just pushes harder – diverting dividends isn’t enough anymore to let BP off the hook, and he’s made them disclose their actual, detailed plan for what they plan to do. The environment is on the top agenda.

Why has BP has prevented independent reporters from accessing the disaster sites, by telling the Sheriff to block them unless they’ve been approved? Why are they blocking reports from the mainstream media, until they’re reports of tourists on the beach getting slicked? BP has been treating this as a PR nightmare, which it is, but not also as a bona fide disaster, as in, stop drilling at all your other wells, and put everything you’ve got on this. Bring in tankers, rigs, drill more relief wells, everything.

Thankfully, BP didn’t disperse all of it into the water like they hoped, although many people are now hurting from the presence of oil on land like aquatic animals are hurting from it in the sea. But that means the East Coast is going to get it next, and a lot more of us will realize how bad this is. Big Oil, for their part, is in fighting spirit. John Hofmeister even went on Tavis Smiley to fight Obama’s new agenda. They are producing youtube videos.We have to fight too.

What’s our compelling argument, though??

Obama said the country’s continuing dependence on fossil fuels “will jeopardize our national security, it will smother our planet and will continue to put our economy and our environment at risk.”  Tomorrow he’s going to point blame at BP, sure, and demand a pound of flesh – but he’s also going to turn to us, like Jimmy Carter did. And not just say “please wear a sweater and turn down the thermostat.” I hope, at least, he’s going to offer us a new lease on an old way of life, one that worked great.

Because for millions of years, the genus Hominidae Homo has lived here, and lived a good life.

A great life, actually. We were once the “Original affluent society“, says Marshall Sahlins, author of Stone Age Economics. We were the best adapted species on the planet. We didn’t live like animals, we lived like kings of the animals. We got to eat almost any tasty thing that grew. We sweat and breathe independently from our stride, and have an incredibly evolved arch in our foot which let us outrun the other animals, in a long enough race. Really, there’s a race in the US where people race against horses. We then get to ride such animals, to take us to the tasty food, which just grew anywhere. Remember, we didn’t invent broccoli and squash and beans and corn and cucumbers and delicious cherries and peaches straight off the tree. We found them.

As the dominant species, we had it good. We had nutrient-rich diets which kept us healthy. We learned from our elders, even when they couldn’t operate a BlackBerry at all. Why do we now think we know better, and what went wrong? We ate from the tree of the knowledge of good and evil, and began the relatively quick, merely 200-generation process of learning the hard way that our judgement isn’t as clear as we think. We are animals, but we think it’s evil to live that way. The story of Genesis tells us all about it, as it’s the story of modern, agricultural man rising from the hunter-gatherer.

You didn’t think Genesis was actually about the first Homo Sapiens, right? We know that’s not it. There were lots of native people around for a couple million years before that. It’s an allegory of when Cain killed his brother Abel because Abel was using so much land for his goats and Cain wanted it to plant crops. Just like European Americans mostly pushed the Native Americans out of the way.

The reason to change

We should give up oil because we will be happier.

We think, the only thing worse than high gas prices would be no gas at all! We’d have to walk or ride bikes or use electric cars! We’d have a lot of trouble in finding tomatoes in the winter, and would be forced to eat roasted squash and preserves and such healthy things. We’d be forced to visit with our friends and relatives in far-off places nearly for free with video chat, instead of enduring the airport to spend a few rushed days with them a year. We’d have to spend time to teach our kids how to cope with a vegetable garden, reducing trash, and have fewer things.

Wait, modern (albeit short-distance transportation), healthier food, better communication with family, spending time with our children, more flavorful, fresh veggies, and less junk piling up? That’s really not so bad. But yeah, it’s different, so get ready to deal with that, and then, to enjoy it.

Making the case for unit tests to live in the code they test

Sunday, November 15th, 2009 | Uncategorized | 2 Comments

This is perhaps the most controversial idea in Noop. I had an interesting discussion that included Cédric Beust, in which I defended this idea from a lot of doubts, mostly around why it would be needed, and the challenges with tools that expect a conventional code layout. So, I went to spec out exactly how it could work. And I’m happy to report that I think it totally works.

First, what’s wrong with writing unit tests the conventional way?

  • Create a separate src-test or src/test source root, which is to contain just tests, so that we can compile the production code independently and enforce that prod code doesn’t have deps on tests.
  • Create a new source file in that source root, in a package/namespace mirroring the location of the prod file you want to test.
  • Name the new class with a convention like “*Test” so our team understands where to find the unit tests for a file.
  • In the test fixture, create an instance of the class-under-test, supplying fakes or mocks for some of the constructor/setter dependencies as needed.
  • Start calling methods in the class and sensing whether they did the right thing. Modify the code under test to make some fields or methods package-protected or friendly to the test class so it can white-box test where you need to.
  • Optionally mark that change with a comment or annotation like @VisibleForTesting so your team can understand why this field or method isn’t private as they’d expect.
  • Get the tests green, and send off your code review. The reviewer needs to flip between the test file and the production file, so they can use the test-as-documentation to understand what you intend the code to do, and help you find corner cases you missed in your test.

Here’s what’s wrong.

  • You want to change code in the prod class with the corresponding unit test visible. Maybe you have an IDE plugin like TestDox that can navigate between the two classes based on the naming convention. If not, you have to navigate manually, and maybe change your window layout to show the two side-by-side.
  • Even when you can see both prod and test code, you have to scroll around the two files to see the tests that cover the method you’re working on.
  • You refactor the prod class, changing the name or package, and the test class now is misnamed or in the wrong place. Maybe the package-protected access breaks so the compiler tells you, or maybe your code reviewer notices. But your refactoring tool probably doesn’t help you, and it’s easy to check in this mistake.
  • You changed the production code just to expose some fields for testing. You really want the test to have special access into the class internals that wouldn’t be allowed at production runtime, but the language doesn’t distinguish these two runtimes.
  • As the code grows, you refactor the class by extracting some methods and pulling out some responsibilities into their own classes. You have to read through all the tests to understand what behavior should be extracted into a new test. Some tests are no longer unit tests, since they test behavior that’s now an interaction between the original class and the new class, so you might move those tests to a third location.
  • It’s really annoying in the code review to correlate the test and prod changes, especially if your code review tool has a high latency when navigating between files.
  • The test needs to be written as a class with methods, even though you should never create an instance of that class yourself, nor call any of the methods yourself.
  • The test provides fantastic documentation, because it’s executable. The test always tells you the truth, even when comments get outdated. Sadly, that documentation is not found in your generated docs, because your doc tool doesn’t know where to find the tests. Some BDD frameworks have a separate tool to create the “spec” for the class, but it still doesn’t appear in places where the class API appears.

Sucky! Ok, so what are we going to do about it? Here’s what I propose in Noop:

Unit tests are a special entity, declared with a unittest keyword. The keyword is followed by a string literal, which allows you to write your intent in a normal sentence rather than “escaped” as a camel-case method name. They may appear either in a file dedicated to testing, or better, in the class being tested.

class TestThis() {
  String printHello(String name) {
    return "Hello %s!" % name;
  }
 
  unittest "It should print hello" {
    printHello("Fred") should equal("Hello Fred!");
  }
}

The unittest is a member of the class, just like a field or a method, so it naturally has intimate access to any fields or methods. And the test fixture is naturally provided as the “this” reference in the test, allowing you to simply call methods in the class.

Let’s deal with the objections now.

“Um, where does the ‘this’ instance come from?” -> I’m assuming here that the language has built-in dependency injection, so it’s normal to expect instances to be created for you. In the example above, it’s obvious how to make an instance of TestThis, so why should you have to make one yourself?

“Ok, but what about a less trivial constructor? What if the constructor needs some service that we want to mock?” -> Again, dependency injection to the rescue. You need a way to add “bindings” to the DI runtime, so that it understands how to provide instances of whatever objects you need in the constructor. These bindings need be declared in the unittest declaration, before the block that contains the logic and assertions, so that the ‘this’ reference is available in the first line of the block.

“I like having the tests in their own source root, like it’s been since the old days!” -> I think this is just an artifact of language tools that don’t understand tests, so the easiest way to compile the right set of sources, search for tests, and deal with dependencies was to create a separate source root. Starting with a fresh slate today, I don’t see why it’s necessary to continue to appease language tools at the cost of maintaining a separate package hierarchy and all the rest.

“But the production code shouldn’t depend on the tests, and the tests have extra dependencies that the production code doesn’t!” -> the first half is solved because the unittests aren’t methods, so there is no way to reference them in production code. The second half might require that there’s a way to make an import statement that only imports something for use by the tests. Maybe “test import junit.Asserts”? And the language tools need to provide a different set of dependency libraries in the classpath when running the tests vs. running production code

“But you don’t want to ship those tests to production!” -> well, I’m not sure why that’s a big deal, as there’s no way to call into that code without a test runner. But sure, the compiler or other language tools can support a “test” mode, just as many compilers have a “debug” mode to dictate whether the full symbol table is emitted.

“But this mixes testing and development!” -> You should really start doing Test-Driven Development. Testing is part of developing. They should be mixed.

I’m very keen on your comments on this one. Don’t leave me hanging!

Code style: too many choices

Tuesday, November 10th, 2009 | Uncategorized | 1 Comment

Q. Should a method parameter list continue on the next line aligned with the open paren, or 4 spaces from the left?

Every time I deal with code style, it annoys me. That’s because I have to do some annoying busy work to make my pretty text file serialization of the program conform to the group consensus in my team.

Don’t get me wrong, I think having a common code style is important and I’m glad all my teams do it. I just want to have it taken care of for me, I’d rather think in terms of editing the AST rather than pushing around ascii art in a bunch of files.

So why don’t we have the perfect code formatter? There are too many options. Look at this dialog for my Scala plugin in IDEA:

Scala code formatter preferences

And that’s just the “Spaces” tab. If I have the tool in my IDE, along with a command line tool to tidy up pre-submit, there’s no way I’ll get all of those settings right for the N projects I work on using M machines.

So if I’m right, the only way to stop spending this annoying time is either to stop editing text files (Jesse Wilson Jesse Wilson is starting to convince me of that), or just pick one global style so there’s no need to configure my tools. Sun proposed a style for Java, but somehow every Java shop I work in has a slightly different guideline, so that didn’t work.

The funny thing is, unless you’re a zealot about your personal preferences, you agree that it’s an arbitrary choice. The method parameters can continue onto the next line in any reasonable way. We just want to make a consensus so we can stop talking about style. In Noop, I’m going to push that we provide a non-configurable lint tool with the language, and bake it into the tooling in some way so it’s the natural choice.

What code reviews ought to be

Tuesday, August 25th, 2009 | Uncategorized | No Comments

Google is the first place I’ve worked where code reviews are a formal part of every change. And I’m really sold on them. I will always make code reviews a part of committing code from now on, because it guarantees that someone else understands my code. Sure, it’s also handy if the reviewer notices a bug, or suggests a nicer API I could have used, or has some good refactoring ideas. But the most important result for me is “shared code stewardship” – code I write isn’t “my” code, it’s part of the team’s product and it’s going to need maintenance by other people. The code review is often the first chance for someone else on the team to really read through the code and understand my changes.

But, I think it sucks that no one read the code earlier. Code reviews are like a less effective form of pair programming.

The more you pair program, the more often you find that the code review is already done. Your pair can be your reviewer, they have already signed off on the implementation, and they’re a great co-steward of the code for the future. Or, as one team I’ve worked with does, you can send the review to a third person, just to have some extra familiarity with the changes that the pair has made.

By pairing on the change as you make it, the pair may have some input near the beginning of the coding session. As soon as you start to create a new class, and you give it a name, they might say, “hey, I think there’s this other pattern we might use for this,” and you change course immediately. Contrast that with a typical code review – you’ve got to have some pretty serious objections to someone’s code before you tell them to go back to the beginning and use a different design. You’ll never do it if the improvement is minor – it’s not worth changing it at that point.

So code reviews end up being more about style, minor nits, and reminders to fill in the documentation. That’s great, but it’s a poor substitute for having that person onboard sooner. Here’s another reason: if you want to suggest a design change in a code review, you’ve got to explain it in your comments. If you want to make a small nit like changing the order of import/require/include statements, you add a comment and make work for the author to make your change. In both cases, it would be better to just grab the keyboard and make the change, explaining your reasoning as you go. There’s no separate prose you need to write in a comment explaining the change.

So, here’s my proposal for an awesome code review tool:

  • Pick the reviewer before you start making changes. They’re like your pair, but don’t have to be in your timezone.
  • You commit to a throw-away branch as you work on your change. The branch is automatically set up for your review, and allows commits by the reviewer(s).
  • When you commit on your branch, the reviewer gets notified, and can browse your code, in a read/write mode. Ideally it should be easy for the reviewer to load an IDE project from your review branch.
  • The reviewer can add inline comments in the code, which don’t appear in the source file, but in some extra metadata file. They can also change the code directly. They commit their changes, with a commit comment, and the author is notified.
  • The author considers the suggested changes, and can accept them or roll them back, with further comments if desired.
  • Bonus: the tool facilitates easy screen sharing, so if you IM with the reviewer and don’t agree or understand, you just remotely pair on the spot.
  • When there is some consensus and the change is done, the author does a merge back to the dev branch or trunk, and the review tool archives the review branch.

My top 8 reasons to use IDEA over Eclipse

Monday, August 17th, 2009 | Uncategorized | 2 Comments

I use IntelliJ IDEA as my primary IDE, although I’ve used Eclipse on and off in the past. The last time I switched back to Eclipse was to maintain the Eclipse plugin for Testability Explorer, and I was reminded of some things that I really missed. Here are my killer features:

Diff editor is full-featured

You’ve finished making some changes to a codebase you care about, so before you commit, you take care to look through the delta you’re about to commit and make sure it includes the right stuff, and to double-check your work. Often, I notice little things while I’m doing this – like missing documentation, some statements that could be refactored to a shorter form, or such. So, I begin editing the right side of the diff, and I need to have my real code editor there, so I can get completion in my {@link} javadocs, code completion, and so on.

I’ve seen people using Eclipse who get to this step and have to go back to the normal IDE window and then go find the file they were reading in the diff view. Too much context switching for me.

Completion shows compatible types

You start coding:

Widget w = new |

At the cursor, you’d like to get a completion list that shows the Widget class and any subtypes. This is especially important for some APIs that you don’t know well or don’t use often.

java.io.Writer w = new |

Man, I love getting suggestions like FileWriter there. I think Eclipse can only attempt to sort the list of completions in order of some heuristic of how likely you are to pick it.

Apple-arrow mapped to line home/end

It’s a minor thing on the face of it: on Mac, the home and end keys take you to the beginning and end of the document. Since Eclipse is on SWT, it’s not surprising that you get the native Mac behavior. In IDEA, maybe because it’s Swing, I get beginning and end of line instead. Whenever I use Eclipse, this majorly screws me up, because I forget to re-map my brain and lose my place in my editor.

I’ve tried to fix this in the OS, but it was too painful.

Understands prod/test code

I often feel like IDEA is made for people who write code, and Eclipse is made for people to write Eclipse plugins. This is an example of IDEA understanding how coding works – you always have a prod folder and a test folder. Instead of labelling these folders as just Source folders as in Eclipse, you tell IDEA whether they contain prod or test resources (or get it from an external model like a Maven POM). Now, when you do a search, you can search just prod code or just test code. When you make a new Test with the testdox plugin, it knows which source folder the new class belongs in.

Save on blur

We always work from a version control system. So, in my mind, the “buffer” I’m editing is my working copy. If I want to revert my changes, I use the VCS to do it. So, I hate the notion of “saving.” I don’t see how it’s ever useful to have different contents in the in-memory editor than you have on the disk. When I make changes to a file, I want the changes to get flushed out to disk. IDEA can do it when the IDE loses focus, which is a nice time. That way, my shell always sees what I typed. When I use Eclipse, I run something and it seems like my changes didn’t take effect. Then I realize there’s an editor tab with a star on it. The star makes me really frustrated, because it’s just the IDE telling me that it *knows* my disk has stale content, and asking me to do the busy work for it.

Diff annotations in gutter

Since we’re always coding against version control, our job is often to craft incremental changes to the codebase. I want to see that delta at all times, especially in the editor. That delta is my actual work product and it’s annoying to have to invoke another view to see what I’ve done so far, and revert changes or copy the previous content.

I’ve noticed that I’m more exploratory in my coding with this feature – if I don’t like the path I’m going down, it’s trivial to remove the last few changes and start a different change. I think there’s an Eclipse plugin for this, I guess that would work if it’s truly universal on all editor views and consistent with the VCS plugin, but I really don’t install many plugins.

SVN support built-in

It kills me to watch Eclipse users install a Subversion client plugin. It’s not easy to do, since you have to choose between JNI and pure Java, and the JNI version seems to have problems locating the native libraries in my experience. Maybe the install has gotten better, but still, this is another example where Eclipse should really support what I do out of the box. I think Subversion is popular enough that I should be able to check out a project with a freshly installed IDE.

Understands multi-changelists

I have more than one change happening in the same working copy a lot of the time. I like moving files into different lists, so when it’s time to commit some work, I have the right set of changes already grouped together. In Eclipse, I would usually toggle the checkboxes on the commit dialog to choose the files to include in the commit, and it was really hard to remember which classes belonged in the change. And I made a lot of mistakes.

Java – final variable to constructor parameter

The quickest way to type code is not to type, instead, let the IDE fix things as you go. Setting up the dependencies of a class is a common place where there’s a lot of typing, at least in a language with no properties like Java. I like to create my fields first, and if I make them final, IDEA will offer to add them as constructor parameters. Eclipse doesn’t – you must go the other way around, creating the constructor and adding parameters, then using the auto-fixer to create the fields.

$SwitchMap$

Wednesday, April 15th, 2009 | Uncategorized, nil | No Comments

I recently became the maintainer of the Testability Explorer project. It’s a library that inspects Java bytecode, assessing how difficult the code will be to unit test. Check out the author’s blog: Misko Hevery. For more info about the project, see http://testability-explorer.googlecode.com.

Testability explorer looks for a few things in your code. One of them is some mutable object that’s globally accessible. For example, the Evil Singleton makes it hard to unit test anything that uses it, but a public static final String is fine, since String is immutable.

So I was investigating a strange issue where a large mutable global cost was assigned to some classes, due to an anonymous inner class. It seemed that there was some globally mutable state hidden in SomethingOrOther$1, whenever SomethingOrOther has a switch statement with a variable of type Enum as the argument. That doesn’t make your code hard to test, so what’s going on?

Try it at home! Compile this with javac:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class HasStaticCost {
  public int compare() {
    Fruit fruit = Fruit.APPLE;
    switch(fruit) {
      case APPLE:
        return 1;
      case ORANGE:
        return -1;
      default:
        return 0;
    }
  }
  public enum Fruit {
    APPLE, ORANGE
  }
}

And run javac HasStaticCost. The outputs are:

  • HasStaticCost$1.class
  • HasStaticCost$Fruit.class
  • HasStaticCost.class

Three classes? What’s in that first one?? We’ll have to look at the bytecode:

class com.google.test.metric.collection.HasStaticCost$1 extends java.lang.Object {
static final int[] $SwitchMap$com$google$test$metric$collection$HasStaticCost$Fruit;
static {};
Code:
0:    invokestatic    #1; //Method com/google/test/metric/collection/HasStaticCost$Fruit.values:()[Lcom/google/test/metric/collection/HasStaticCost$Fruit;
3:    arraylength
4:    newarray int
6:    putstatic    #2; //Field $SwitchMap$com$google$test$metric$collection$HasStaticCost$Fruit:[I
9:    getstatic    #2; //Field $SwitchMap$com$google$test$metric$collection$HasStaticCost$Fruit:[I
12:    getstatic    #3; //Field com/google/test/metric/collection/HasStaticCost$Fruit.APPLE:Lcom/google/test/metric/collection/HasStaticCost$Fruit;
15:    invokevirtual    #4; //Method com/google/test/metric/collection/HasStaticCost$Fruit.ordinal:()I
18:    iconst_1
19:    iastore
20:    goto    24
23:    astore_0
// same for Fruit.ORANGE
39:    return
}

This is pretty crazy. The ordinal values of the Fruit enum are stored into a static array, named $SwitchMap$<enumname-encoded-with-dollars>, and stored in this synthesized inner class, and accessible to other classes in the same package. And that synthesized class isn’t stored with the enum, instead, each class that switches on the enum gets blessed with some ugly global state. Why? There was a release of the JVM in Java 1.5, along with the new language features, so you’d think the switch statement would understand an enum type. But this bytecode looks like a complete hack to make the switch statement think it’s operating on an int instead. Here’s how the switch is implemented:

0:    getstatic    #2; //Field com/google/test/metric/collection/HasStaticCost$Fruit.APPLE:Lcom/google/test/metric/collection/HasStaticCost$Fruit;
3:    astore_1
4:    getstatic    #3; //Field com/google/test/metric/collection/HasStaticCost$1.$SwitchMap$com$google$test$metric$collection$HasStaticCost$Fruit:[I
7:    aload_1
8:    invokevirtual    #4; //Method com/google/test/metric/collection/HasStaticCost$Fruit.ordinal:()I
11:    iaload
12:    lookupswitch{ //2
1: 40;
2: 42;
default: 44 }

At instruction 12, I would think the value 1 would naturally refer to the first ordinal value of the enum without needing to load the constant from the static array as it does.

It turns out this was just bad decision making by the Java 1.5 committee. They intended to implement Java 1.5 language features in a way that would execute on the 1.4 JVM, I bet because they knew that BigCorp wasn’t going to upgrade their production environments and the language features would sit on the shelf for a few years unless they could be deployed with little risk. So we got stuck with big things like generic type erasure, and small things like this hack for the switch statement… but hey, at least adoption would be easy.

I fixed testability explorer by whitelisting field names matching /\$SwitchMap\$.*/. Gross. Although that’s straightened out, it still leaves that bad taste in my mouth. Because it turned out that there was some feature added later on in Java 1.5 that did require a change to the VM, and so all these hacks are in there for no good reason. And, of course, BigCorp stayed on 1.4 for years.

Structuring Java code that assembles a UI

Saturday, November 1st, 2008 | Uncategorized | 1 Comment

I’m dong some GWT coding today, which is a lot like writing Swing. It’s very procedural. Create a new UI element, then call methods on it to set up the state. Even when you do the right thing and split your UI into many Composite classes, you get something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
StackPanel stackPanel = new StackPanel();
stackPanel.add(new Label("Recently Eaten"));
stackPanel.add(new Label("Manual Entry"));
stackPanel.add(new Label("Search the database"));
 
DockPanel panel = new DockPanel();
panel.add(stackPanel, DockPanel.CENTER);
 
FlowPanel buttonsPanel = new FlowPanel();
buttonsPanel.add(new Button("Done"));
buttonsPanel.add(new Button("Next"));
 
panel.add(buttonsPanel, DockPanel.SOUTH);

This is really annoying. The order of assembly is important, but it’s also very arbitrary. I’m creating my DockPanel before my FlowPanel, but you should always declare variables in the narrowest scope possible (item 45 in Effective Java). On the other hand, maybe I want to finish referring to my StackPanel, adding it to the parent, before I create my FlowPanel. Also, it’s easy to make a mistake here. I might accidentally add something to the wrong parent container, if the variable names are similar, and there isn’t a good way to test this code aside from inspecting the UI visually.

Maybe Java is just not a good language to express this UI layout, but for now I considered an under-used construct, inline instance initialization blocks:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
final StackPanel stackPanel = new StackPanel() {{
  add(new RecentlyEatenPanel(), "Recently Eaten");
  add(new ManualEntryPanel(), "Manual Entry");
  add(new DatabaseSearchPanel(), "Search the database");
}};
 
final FlowPanel buttonsPanel = new FlowPanel() {{
  add(nextButton);
  add(doneButton);
}};
 
DockPanel panel = new DockPanel() {{
  add(stackPanel, DockPanel.CENTER);
  add(buttonsPanel, DockPanel.SOUTH);
}};

This is kind of cool – the structure is certainly more evident in this code. The extra braces define an initializer that is copied into each constructor – see the Sun tutorial. I assume that the code in the initializer block executes after the constructor has finished its work, so we can depend on the add() method having a place to do its work.

The limitations: this creates a subclass, so you can’t use it to initialize fields in a final class. Also, as you see, any variables must be declared final to be used in the initializer block, just like with any anonymous inner class.

Links:

Here’s a clever DSL to build the GUI in a “fluent” way: http://www.pathf.com/blogs/2007/09/expressing-rich/

And a project to use Flex-style XML to configure the layout: http://code.google.com/p/gwt-ui/

Chrome, the first mainstream Site-Specific Browser

Wednesday, October 8th, 2008 | Uncategorized | No Comments

In a previous post, I got into my passion about the misuse of web browsers. They’re intended for browsing content on the web, and not really intended for running applications like we do so much of today.

The problems with normal browsers can be summed up:

  • The back button. In general, the browser’s controls only make sense in a browsing context.
  • Apps running inside the browser don’t show up in Alt-Tab/Cmd-Tab, they’re hidden in a browser tab.
  • Webapps can’t interact with the desktop in the usual ways, such as drag-and-drop, system tray/menubar integration, and running processes in the background like notifications.
  • Dialogs and pop-ups lose the association with the application that originated them.
  • One misbehaving webapp can take down the browser, along with other non-related apps.
  • Offline storage is not generally available, other than what can fit in cookies.
  • Security is a lot harder when state like your current session is expoitable by a site in another tab.
And the solution to these problems is the Site-Specific Browser. I like to think of an SSB as a platform in the style of Adobe AIR that provides a web-based delivery and update mechanism for apps that otherwise seem to have desktop characteristics — and the developer may be glad that the app is coded in HTML and Javascript and CSS but the user shouldn’t see a difference with their desktop applications.
I tried Fluid but I had a lot of problems with my GMail SSB. When I clicked a link, it got confused about whether it should open in the SSB or in another window, and would actually open a second GMail instance in my normal browser while redirecting to the real page.
Enter Chrome. This was a big surprise to me, since I was in the car driving to my first day as a Google engineer, ready to fix this SSB void in my 20% time, when the new browser was announced on NPR! They read my mind.
How it works: on any page, there’s a menu item to “Create application shortcuts”, which isn’t obviously named but it does create an SSB for the site you’re on. There’s no window chrome in the SSB view – no URL bar, nav buttons, history, etc. The SSB appears in the Alt-Tab/Cmd-Tabber, using the favicon.ico from the site. Of course, a well-known innovation in Chrome is that each site runs within its own process, so there’s no way one site will take down an unrelated app.
If you are in an SSB and hit the new Tab shortcut, you do get a new tab, but in a non-SSB browser window. Same with pop-up links like anything you click in GMail. This keeps your SSB window from turning into a web browser. Offline storage is provided by Gears, which is also available for other browsers. We’ll have to wait for apps to start using Gears, but it’s hard to see how that can happen until there’s a substantial install base of Gears already on consumers computers, as the site will have to degrade gracefully if it isn’t available.
Not all my demands have been met though. One problem is dialogs that pop out from an application – they go off into another process and aren’t grouped as an application window with the originating SSB. Only DHTML/AJAX modal dialogs appear within the application as they should. Another problem is that while processes are sandboxed from other apps and the computer, the client-state sandbox isn’t there. If an SSB has an open session to an application, the session is good in all other browser windows too, which allows them to hit a deep link on that other site and do something as your user.
The remaining challenge, integrating with the desktop, will have to be solved by client-side code like greasemonkey or plugins. It turns out that Chrome does let you drag and drop a file into a file upload box, like as an attachment in GMail – but you have to have the file selector open and drop onto it. I don’t know what other stuff can be done now to integrate a webapp with the desktop through Chrome, but I bet there will be lots more added in future releases!
Mac version, grumble grumble. Thank goodness for VMWare.

Work smarter, not harder… and faster!

Thursday, August 30th, 2007 | Uncategorized | No Comments

Maybe it’s obvious. When you try to do things really fast, it can actually be slower.

I always thought “A stitch in time saves nine” meant that you should stitch as fast as possible. I think I just assumed that, which I need to be careful of, because when you ASSUME, you make an ASS out of U and ME.

It’s certainly true with programming. When it comes down to it, if you look at a finished application, it’s conceivable you could just type the code for it in an afternoon, especially if you have good tools that let you express your intent quickly. Of course, you don’t know exactly what the code will look like until you start to create it, but let’s ignore that for a sec.

So… taking my time and thinking for a second to save time. I was too frantic for the last couple years, and wrote a lot of Log object instantiations.

public static final Log log = LogFactory.getLog(NiceObject.class);

I wrote that a lot, and got a Das Keyboard so I could type it even faster. I knew that Eclipse could do this for me, but there’s that nagging startup cost, where the first time I set it up, it would take longer, and I might go looking around for more of the same (or blog about it), making it much longer than typing it out.

Well, lo and behold, I am happy I took the 30 seconds to:

Correction!

Friday, August 24th, 2007 | Uncategorized | No Comments

Well, I learned that what I said yesterday isn’t quite true. It IS true that the geocoder.us site does a bad job geocoding on this street. You can see their map here:
http://geocoder.us/demo.cgi?address=4050+BEN+LOMOND+DR+PALO+ALTO%2C+CA+94306

BUT, if you zoom in, you see the shape of the street is right, they just have the pin in the wrong place. The maps come from the TIGER/Line data as well as the geocoding. The problem is that the Perl module, Geo::Coder::US, doesn’t use one of the data files in the TIGER set – the RT2 “type 2″ data. This file is Complete Chain Shape Coordinates which means it has midpoints for some street segments. I found the two midpoints for the street I showed yesterday, and put some pushpins at those spots – and behold, the curvy street problem would go away!

Now, too bad I can’t find any libraries (in any language!) that do the same thing as the Perl library, but use the RT2 data…

About Me

I'm Alex Eagle. I live in Sunnyvale, CA and I'm a code monkey.

eag...@captcha.me
LinkedIn.com/in/AlexEagle
Twitter.com/jakeherringbone

Add to Google Reader or Homepage

 Subscribe in a reader

Tweets

  • @LaChilangringa thank you, he will be called Walter and might like trains or frogs. You were at the rally? What did your sign say? in reply to LaChilangringa 2010-11-06
  • It says I'm not eligible to get a payout in the Buzz settlement. I'll have to settle for juggling with the Buzz developers. :) 2010-11-03
  • It's Movember and you can sponsor my mustache. http://goo.gl/Z1O4 I miss the beard; It's very drafty on my face today. 2010-11-02
  • Can 4 guys make themselves look enough like Mount Rushmore to fool Google Goggles image search? Love the demo slam. http://demoslam.com 2010-10-20
  • Saw Dalai Lama on Thurs, running last 6mi of SF women's marathon with Peggy today. Too many crazy crowds this week! 2010-10-17
  • Attn: people of the future. We wanted to avoid all that litter! It was our 2nd priority, right after annoying noises. http://bit.ly/cJzkGT 2010-10-09
  • Headed to Hardly Strictly bluegrass in GG park. Elvis Costello free! 2010-10-03
  • I vote that @TCooganPlants is having a rough week and deserves nachos. Who's with me? 2010-09-29
  • More updates...

Powered by Twitter Tools