Friday, July 03, 2009

Generic types are not required for covariance

Java 5.0 introduced Generics. It also introduced covariant return types. Wikipedia does a fine job describing covariant return types.

Since they were released simultaneously, I consider them to be tightly coupled. For instance, here are simplified versions of an interface and implementation I recently wrote:

Note: I am having difficulty representing greater-than and less-than symbols in Blogger's editor, so you'll have to do with { and }.

Version 1: Java 5, Generics, Covariant return types
public interface Model{T extends Model{T}} {
  T read(InputStream in);
  T write(OutputStream out);
}
public class MyModel implements Model{MyModel} {
  public MyModel read(InputStream in) {
    ...
  }

  public MyModel write(OutputStream out) {
    ...
  }

 
public MyModel setName(String name) {
    ...
    return this;
  }
  public String getName() { ... }

}
Thanks to the covariance, I can write a method chain like this:
new MyModel()
   .read(in)
   .setName("foo")
   .setStopAtMain(false)
   ...
   .write(out);

With Java 1.4, the code would have to look like this

Version 2: Java 1.4
public interface Model {
  Model read(InputStream in);
  Model write(OutputStream out);
}

class MyModel implements Model {
  public Model read(InputStream in) { ... }
  public Model write(OutputStream out) { ... }
 
...
}
And the method chain would result in a syntax error:
public static void foo() {
  new MyModel()
      .read(in)
      .setName("foo")
     
^ The method setName(String) is undefined
        for the type Model.
      .write(out);
}
Which you could hack around with an ugly cast:
public static void foo() {
  ((MyModel) new MyModel()
      .read(in))
      .setName("foo")
     
.write(out);
 }
Back to the Java 5 example: My point is just this: covariant return types don't require generics. All that messy code in version 1 could look much simpler because covariant return types exist on their own without generics:

Version 3: Java 5, Covariant return types
public interface Model{T extends Model{T}} {
  T Model read(InputStream in);
  T Model write(OutputStream out);
}
public class MyModel implements Model{MyModel} {
  public MyModel read(InputStream in) {
    ...
  }

  public MyModel write(OutputStream out) {
    ...
  }

 
public MyModel setName(String name) {
    ...
    return this;
  }
  public String getName() { ... }

}
Lesson learned: I know generics fairly well, but there's a difference between knowing when it's useful and when it isn't. Said another way: when you have a Generic hammer everything looks like a generic nail.

Thanks to David Plass for pointing this out.

13 letters from camp

Last week my niece left for sleep-away camp for the first time! We're all wondering if she's doing okay, if she's enjoying herself and what kind of friends she's making and activities she's doing.
So you can imagine my excitement to see that she sent us a letter from camp!
 

What would she tell us? Did she have any adventures? Does she miss us? Does she sleep well in a bunk full of girls? I COULDN'T WAIT TO FIND OUT!!!!


"Hi im having fun."

Sunday, June 28, 2009

All contributions are Equal, some are more equal than others

This evening I read Cay Hortmann's article on upgrading to Galileo. (For those of you who do not know Cay, he writes the fantastic Core Java books. I learned Java from the 1.1 version, as well as both the 1.4 and 1.5 versions. He writes great stuff.)

In the article he makes this comment:
There is now an option to generate toString automatically. This is something I've wanted for a long time. Unfortunately, it is not very good. Core Java gives these simple rules for toString:
  • Use getClass().getName() to print the class name. Then your toString can be inherited.
  • When you redefine toString in a subclass, first call super.toString(), then add the subclass data.
The Eclipse formatter follows neither of these eminently sensible rules. Maybe in 3.6.
I've not yet seen the toString generator, but having written more than enough toString implementations, I've worried that such a code generator may be less than ideal. Similarly, I've seen the equals and hashCode generators at work, and I also tend to not want to use them.

Given that I work for a company that has so much Java code that "If code was ice cream, it would be a lot of ice cream," [Ref Java Posse 240, 9:15] in addition to having very helpful helper methods for hashCode and equals, I'd love more finely-tuned generators for such critical methods.

But I feel a bit constrained by one of the basic rules guiding Eclipse contributions, as defined by the book Eclipse: Principles, Patterns and Plug-ins:
As the Contribution Rule reminds us, “Everything is a contribution.” And with many contributions, the possibilities are endless.
OK, so let's say I write my own generators for toString, hashCode and equals. Then there are two toString generators in the IDE, one possibly better than the other. Why should the end user be forced to deal with two confusing UI contributions?

Sure, there's also the recent object of my affections, patch fragments, but the patch fragment is a back-door lover.

I want to remove the default contributions altogether, and replace them with something better suited to my environment. But that violates the Contribution Rule. Am I stuck with something less than ideal until Eclipse 3.6, or worse, forever?

What's the solution here?

PS: Has someone picked up on Cay's concerns and logged a bug?

Friday, June 26, 2009

Lies, Damned Lies, and Eclipse Upload Statistics

Update: Added 4th assumption, Saturday, June 27

As promised, 48 hours ago I downloaded several Eclipse products across all five published platforms using Bittorrent. Now that two days have passed, and my downloads have been made available for others to upload, I thought I'd consolidate upload bittorrent upload data for the sake of gauging popularity.

Some notes on my bittorrent process:
  • I downloaded the torrent files at about 10:30pm, two nights ago. I collected the data at about 11:30pm tonight. I'm calling it 48 hours. Anyone who cares enough, call the data police.
  • I did nothing to cap bandwidth for any of these Eclipse distributions.
I collected data on both megabytes uploaded from my bittorrent client, as well as ratio of upload to download. Since all copies of my products were fully downloaded, an upload ratio of 2.5 means that virtually 2.5 copies of that distribution were uploaded from my machine. Of course bittorrent doesn't ship data in full files, it's just pieces of the distrubutions, here and there.

These are my three primary, and therefore, potentially disputable, assumptions:
  • More popular products will be uploaded by more people.
  • Upload ratios are a better measurement of popularity than megabytes uploaded. If product X is 50% larger than the size of product Y, equal bandwidth dedicated X and Y do not denote equal popularity. I just think people using bittorrent aren't really worried about the size of their Eclipse.
    • Similarly, I consider negligible any difference in compression ratios between the win32 zip file format and other gzipped tar files.
  • 48 hours of data collection is more than enough time to collect data, and taking more than the first 48-hours of data will not yield significantly different results.
    • I presume that files that are not as well seeded as others will take more time to initially download, and as such, will not contribute much to the other uploads during the first part of this process, and so may exaggerate the results slightly. Given that, I suspect the correctness of the 48-hour window will be the most disputed assumption.
  • Update: fourth assumption: People don't care about how long it takes, if they're using bittorrent. I assume it's a "set and forget" type of tool.
In retrospect, this turned out some really cool data. I'm very sorry now that I did not download all distributions. This analysis suddenly suffers from its absence.

Let's start with downloads by product:


Here, the clear winner is the JEE distribution. Modeling, which is heavily discussed on the modeling blog and had a crazy number of talks at EclipseCon, has just under 25% the popularity of JEE. I haven't used WTP in a while but I hope, if it's this popular, that the developer docs reflect the popularity. (Please?)

Next we move to downloads by operating system:


Wow, Windows, huh? That's a surprise, and also, not really a surprise. I'd love to see how these numbers compare next year. Will we see an complete inversion of Linux 32 and Linux 64 in a year? Two years? I predict four years.

Let's look at all the download ratio data without grouping by products or operating system.


This chart really highlights both the JEE and Win32 popularity. I'm pleased to see the CDT platform is well used by the Linux32 community. I wonder why, on the Classic platform, OSX Carbon is uploaded slightly more than OSX Cocoa? Are variances on that scale negligible?

I hear the Linux community say "Rob, come on. We just shut down the spin machine from that ludicrous browser comparison. How about something that reflects reality?" Reality, whatever. You punks are lucky drawing charts is fun, so I'll do one more for ya. Here's the same data, with OSX and Linux products as single pieces of data.


Seriously, this does have something more interesting to say:
  • RCP is more popular among the OSX and Linux communities than Win32.
  • Without JEE, Win32 is not nearly as popular a platform.
  • CDT and modeling are not particularly popular among the OSX community.
  • CDT is loved by the Linux users.
I mentioned earlier that downloads by megabyte are not interesting to me. That doesn't stop me from graphing it. Here's a chart:


and heck, here's another:


Do these last two charts tell you anything different from the download ratio charts? I'll leave that up to someone else to discover. Add it in the comments.

Here's the last three pieces of data I want to share tonight:
Total Uploads: 145
Total MB uploaded: 18,781.1 MB
Upload average (assuming 48 hours): 111.295 kbps
You could say, then, that 145 people got their instance of Eclipse from my bittorrent client.

Thank you, Verizon FIOS. Thank you, Eclipse Foundation!

Tuesday, June 23, 2009

Downloading Eclipse via bittorrent == community

Hi all,

Tomorrow is the big day: the public release of Eclipse 3.5, a.k.a. Galileo.

Those of us that have become Friends of Eclipse are eligible to download it today, and that's pretty damn cool. In fact, I'm eligible to download it right now. If I weren't on a train, that's exactly what I'd do.

But here's the thing: I'd rather download it with bittorrent. Why?
  • Once I've finished the download, I can participate in someone else's download by making my file available to them.
  • This means the rest of the community will have access to it faster than using a standard download.
  • Any bandwidth you contribute so someone else can download Eclipse results in less bandwidth required by the Eclipse Foundation. In other words, you're saving money for the Eclipse Foundation
  • For extra credit, you can download multiple versions of Eclipse via bittorrent, even the ones you won't use. For instance, I no longer use Microsoft Windows, but because I downloaded Eclipse 3.4.2 / win32, anyone who wants that version will get parts of it from my torrent client. And let me tell you, by watching the bandwidth statistics, that's the most popular upload in my torrent client.
  • I can start my download here, on the train.
So, please, tommorrow, download via bittorrent. And, hey, while I've got your attention: would you please make a donation to become a Friend of Eclipse?

Monday, June 22, 2009

Patch Fragments, Redux

Sorry for those of you who have already read my patch fragment blog posts. I'm re-listing them in this post for the sake of the Planet Eclipse aggregator.

In short, an OSGi fragment is a bundle that attaches to a host bundle [1]. While patch fragments really aren't meant to be use to replace behavior in a host bundle [2], it's the most elegant hackish way to do just that.


The first blog post shows that I was able to make changes to all text editors using a patch fragment.
The second blog post hosts a screencast showing, step by step, how to build a patch fragment.
The third blog post shows the code required to create the effect from the first post.

So if you're coming here from Planet Eclipse, you may find these interesting.


[1] http://static.springframework.org/osgi/docs/1.1.0/reference/html/appendix-tips.html
[2] http://wiki.eclipse.org/FAQ_Can_fragments_be_used_to_patch_a_plug-in%3F