Monday, March 28, 2011

.NET: Like working at McDonald's?

So I noticed this blog entry on why Expensify doesn't hire .NET programmers, started to leave a comment, then ended up writing more than I had intended.

Here's what I've noticed after working in Java pretty much forever (1996-present) and being forced to work in .NET now (2010). When you compare Java language to C#, and the JVM to the CLR, I think it's basically a wash. Minor, albeit annoying, syntactical differences, different flavors of syntax sugar, etc. Not much to talk about there.

Next up is something that's a difference, but not huge: the standard libraries available on each platform. Java collections, IMHO, are superior to those in .NET. LINQ does offer something new to .NET and is nonexistent in pure Java, but with the advent of other programming languages for the JVM, like Groovy & Scala, those holes have been plugged, which brings me to my main point.

What really separates Java & .NET is the ecosystem of projects & languages available. Java, thanks to its low (free) cost of entry, has enjoyed tremendous innovation over the years. From JUnit to today's BDD frameworks, to the persistence frameworks like JDO & iBatis, to dependency injection, IoC and AOP, to the new NoSQL technologies, to build & dependency management tools like Ant, Ivy, Maven & Gradle, to OSGi, and to open source libraries too numerous to count that can do just about anything low level that you need done, Java's ecosystem simply can't be beat. The level of innovation on the Java platform is simply staggering.

Having said all that, Java is not without its warts. EJB 1 & 2 were terrible, especially entity beans. It wasn't until much later that all of enterprise Java took a lesson from the playbook of SpringSource, who revolutionized Java development. JDO provided a great, universal, lightweight persistence model that is still going strong today, but the JCP, due to its political nature, felt the need to reinvent the wheel (and do it worse) with exclusively-relational JPA. Logging in Java was being served fine by log4j, but then the JCP felt the need to change all that and ignore the de facto standard. The result was Apache's commons-logging, so that you could use either logging technology and continue coding. We'll see where modules and superpackages versus OSGi end up, and where closures are going. It wasn't looking good for a while, but now the JCP might be learning some lessons from the past.

Anyway, while Java is not perfect, it has stimulated just amazing work. The support of other languages on the platform make for a promising future, too. I've always walked away from an experience with Groovy & Grails saying "wow". I'm very interested in the promise of Scala, too. .NET is showing signs of innovation life in things like its dynamic type and Expando object (taken from Groovy, BTW), but it takes the whole community to really produce useful stuff. Codeplex is a start, but is absolutely dwarfed by the numerous pure Java or JVM-compliant projects out there in open source land.

Only time will tell if the .NET ecosystem can ever catch up with that of Java.

6 comments:

Ed Ropple said...

You know that quite literally everything you mentioned as being available in Java is available on .NET, right? Sometimes Java ports (NUnit 1 was basically a Java port, Spring.Net still is), sometimes entirely new tools (NUnit 2, Ninject, etc.), but it's all completely available and in high quality. Claims to the otherwise are counterfactual.

Yeah, there are a lot more Java and JVM projects out there. Who cares? What matters is useful projects, and eight billion bits of crapware don't make the one (or two, or ten) valuable projects available in both ecosystems any more valuable by virtue of the crapware's existence.

This is the future. This is 2011. Stop throwing feces about your preferred platform. It does nobody any favors.

(And, FWIW, about half of my .NET code ends up running on top of Mono on Unix machines. It's not like it's even remotely Windows-only.)

Matthew Adams said...

@Ed, I beg to differ. You claim that "quite literally everything" I mentioned is available on .NET. Please point me to the .NET equivalent of AspectJ, which I mentioned. And please tell me where I can find Spock (or any BDD tool) for .NET. I would be very happy if they existed.

There is only now the beginning of a dependency management tool in .NET (NuGet), but it is far from Ivy or Maven.

I agree that some of the bits in Java have been ported to .NET, but there are two things to notice here: first, they originated in Java, and second, they still aren't as mature as they are in Java. You mention Spring.Net. Yes, it's a port (more spiritual than literal), but the latest version (1.3.1) is nowhere near the functionality of its Java counterpart.

My point was that the level of innovation in the Java ecosystem far exceeds that in .NET, and nothing that you've said changes my opinion. I'm very willing to change it, just show me the evidence, recalling that I'm focusing more on innovation on the platform than the actual availability of a particular tool.

I'm sure someone, somewhere along the line called JUnit "crapware". Thing is, you never know when today's crapware becomes tomorrow's savior.

I'm not throwing feces, either. I pointed out crap in the Java platform as well. I tried to be fair in my assessment of the topic.

Brownie said...

AOP on .NET
PostSharp
(Spring.NET also does AOP)
BDD on .NET
mSpec
nbehave

As mentioned everything you named as "missing" from the .NET eco system is in fact there. In fact a simple google search for those terms AOP .NET, BDD .NET would turn up those projects.

Arguing that sheer volume of open source projects somehow makes java "better" is a fallacy. That's like saying because there are more cockroaches on earth they're better than humans.

You're crowing about how many languages target the JVM...guess who they stole that from? C#, VB, F#, IronRuby, IronPython, Boo.

And you're honestly going to argue that non-generic collections are better than generic collections? I know java has "generic" syntax but under the cover it's still boxing and unboxing going on. And LINQ goes beyond just collection operations, it provides a statically compiled query language for any datasource that has an IQueryProvider implementation including Databases, Quickbooks, Twitter, Facebook, and Salesforce. (many of those LINQ providers are in fact open source)

Saying that .NET stole Expando Objects from Groovy is naive. IExpando has been around in .NET since 1.1 released the same time that Strachan first started talking about Groovy.

I wish you people would stop spewing the same baseless, unresearched arguments as if they were gospel and bother to even pretend to verify your claims.

Brownie said...

BTW, outside of this specific post, there is a lot of insight on your blog. I also am a huge fan of Coad's Color-Based Modelling concepts, Streamlined Object Modeling, and DDD. I'm actually giving a talk on the topic at DevLink later this year. If you happen to go, make sure to hunt me down. We can discuss more over a coffee

Matthew Adams said...

@Brownie, Now that I have a second, I'll try to respond to your comments.

On AOP:

First off, my bad for not finding PostSharp. Ever since I got married, my ability to search has been gone. :) I was very happy to see this product. I took an (admittedly small) amount of time to look at PostSharp, and, while it's a step in the right direction, it's got a ways to go. Here are some things that I noticed.
* Only attribute-based AOP is supported. No syntactical means of pointcut expressions. That might be understandable, given that the .NET explicitly supports multiple languages, and to base interception on a particular language's syntax would not necessarily be portable. However, this means that you cannot weave existing binaries.
* Only method execution interception is supported; PostSharp does not appear to differentiate between "call", where the interception is performed outside the intercepted method when code calls an intercepted method, and "execution", where interception occurs inside the called method.
* It looks like intertype definitions (ITDs) aren't fully supported. You cannot introduce arbitrary fields, methods, constructors, etc to classes. You can introduce interface implementations, though, which is nice.
* I don't see any support for any "declare error" or "declare warning" behavior, where if a pointcut or other expression is matched, a compile-time error or warning, respectively, is emitted.
* It looks like PostSharp only supports issingleton & perthis aspects. There is no support for pertarget, percflow & percflowbelow.
* It is payware. While I feel that purchasers would realize a return on their investment, this will hinder adoption. I would recommend an open-source business model based on dual licensing, commercial & GPLv3, and support subscriptions. That way, PostSharp is free to use, increasing adoption potential, and the community can contribute patches & enhancements, benefitting the committers. Further, under the GPLv3, intellectual property is protected. The sustainable revenue comes from commercial support subscriptions. The astute observer will note that this is very much like SpringSource's business model.

After making these observations of PostSharp, I will say that it's a step in the right direction. It might be worth the time for SharpCrafters to have a look at AspectJ and see if they could port to .NET, which would be a substantial undertaking, but might be worth it.

NB: Blogger only supports a max of 4k per comment. This comment is continued on the next.

Matthew Adams said...

NB: This is continued from my prior comment due to the 4k limit on comments.

On BDD:
Sorry, I haven't had time to look at mSpec or nbehave and compare them to something like Spock. I'll get to that when I can.

On volume of projects:
I agree that more isn't necessarily better. However, it has been my experience that there are more worthwhile projects in the Java ecosystem right now than there are in .NET. The first thing that I looked for when returning to .NET was its answer to Ivy or Maven, in particular, transitive dependency management and standard builds. Now, don't get me wrong -- Maven has its difficulties when it comes to some things -- but on the whole, it's a good idea. Gradle is attempting to take the best of Maven, Ivy, and Ant to produce something much more usable. Anyway, there was nothing nearly as mature in .NET; I found NuGet, but I feel that it's still in its infancy.

An analogue to OSGi for .NET analogue is also missing. OSGi solves a problem in Java (that also exists in .NET) that was previously unsolvable. To make a long story short, OSGi is a solution at the level of the class loader that lets two components share a dependency on differing and incompatible versions of another component. This problem was unsolvable in Java prior to OSGi, and is still, AFAIK, unsolvable in .NET.

On number of languages:
I beg to differ that the idea of multiple languages targeting the JVM was stolen from .NET. Before there was .NET, there were languages other than Java targeting the JVM, in particular, languages like Eiffel. There were a few others, but I don't recall off of the top of my head. .NET, since it had to support both VB and what was to become C#, had to support multiple languages out of the gate, so they leveraged what the industry had learned from the JVM and baked in multiple language support.

On collections:
I never argued that what you term "non-generic" collections, which is called "type erasure" in Java, are better. In fact, I never even discussed generics at all. My point was that I felt that the Java collections library, with its Collection & Map hierarchies, is a great design, and I have found myself disappointed in .NET's collection library. I agree that type erasure can bite you in the ass, but it's there for backward compatibility. Boxing & unboxing also have nothing to do with collections; they have to do with converting between primitives and reference types that wrap the primitives, due to a Java design decision to support primitives. .NET solved that problem with value types and type aliases ("string" & "System.String").

I agree that LINQ is interesting, but with closures (known as "lambda expressions" in .NET), the same capabilities are present in the Java world. Note that I say "world" there, because it's not Java per se that supports closures yet -- it's other languages like Groovy that do, which are in the Java world. I'd like to see more LINQ-like capabilities in Java, but it needs closure support first, which, however slowly, is coming.

On IExpando:
I didn't know that .NET has had IExpando since 1.1. Interesting. Its inspiration from Groovy, I concede, is questionable.

On gospel:
I wasn't trying to preach. I was trying to say that Java ecosystem is more vibrant than .NET's, and has produced more quality projects, not just projects.

On Coad/SOM/DDD:
I'm glad to hear that you're into that stuff, too. It changed the way I look at pretty much everything. I've wanted to build a Spring Roo addin that supports all of the SOM & DDD concepts, but I haven't had the opportunity yet. Maybe someday. :)

Sorry, but I won't be at DevLink this year. For better or worse, I don't get out much to shows anymore...