CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeremy D. Miller -- The Shade Tree Developer

Under the hood and working with .Net, TDD, Software Design, and Agile Stuff

C# 3 is like a Moped

When I was growing up I used to occasionally hear the saying "a Moped is just fast enough to get you into trouble, but not fast enough to get you out of trouble."  I have no idea where it came from, and never saw a single Moped until my twenties, but it's an ideal way to describe something I was feeling this week.  We're trying to do some language oriented programming in our new project with C# 3, and that generally means Fluent Interfaces.  We're getting some real benefits out of our approach, but the fluent interface code itself can become completely opaque when it devolves into "generics hell" like this:

 

public abstract class LayoutExpression<THIS, MODEL, ELEM, EXPR> where ELEM : IScreenElement

and

public class TextboxLayoutExpression<MODEL> : LayoutExpression<TextboxLayoutExpression<MODEL>, MODEL, TextboxElement, TextEditingElementExpression>

and

public abstract class ControlDefinition<T, ELEM> : IElementSource<ELEM> where T : Control, new() where ELEM : IScreenElement 

The API using this code is okay and generally pretty usable, but pain accrues when it's time to extend the Fluent Interface.

C# 3 is great, and I'm glad to have it, but the new language features apparently have their limitations.  You can drive out more code reuse with generics and lambda expressions, but the readability eventually collapses when you push it too hard.  We're backing up and writing more lines of explicit code instead of trying so hard with generics.

A couple years back there was a blog meme floating around called Is Ruby an Acceptable Lisp?  When C# 3 came out, there was some quiet discussion in ALT.NET circles that maybe the new language features (the "var" keyword, better type inference, lambdas) would be enough to satisfy us in regards to Language Oriented Programming and keep us from clamoring for Ruby.  The answer for me after three months of hands on C# 3 is that C# 3 is NOT an acceptable Ruby.  Simply having Duck Typing (or maybe the super type inference that OCaml and other exotic languages have) would have made what we were trying to do easier to code and easier to read.  Some of the Fluent Interface work helps to boil down code into a much smaller surface area, but there's still too many extraneous angle brackets, squiggley brackets, and semicolons floating around to make it really readable the same way that a Ruby or Python internal DSL can be.  Maybe my entire point here is that C# is simply not Ruby and we shouldn't try so hard to use C# like Ruby.

 

So, anybody know any new news on IronRuby? 



Comments

Jeremy D. Miller said:

@Edward:  

False dichotomy there a little bit.  You can have "duck" typing and compile time checking simultaneously, and some of the functional languages do this.  It's C#/Java style type systems that are giving me heartburn here.

Readability, Readability, and Readability.  It makes a bigger difference when you try to make internal DSL's and language oriented API's.

Let's see, what else:

* Easier code reuse

* Easier mocking in unit testing

* Less code to write

If you want to see the pro-duck typing arguments, you just need to go outside of the .Net mainstream and find Ruby or Python or Smalltalk blogs.

# March 14, 2008 10:44 AM

jdn said:

Have you ever tried this:

www.deftflux.net/.../Duck-Typing-Project.aspx

Any value in it?

# March 14, 2008 11:15 AM

Whatever said:

Have you tried just getting the job done, instead of constantly looking for the the coolest and latest toys? Just a thought....

# March 14, 2008 11:20 AM

Dan said:

@Whatever (fitting name)

I'm sure it depends on what you mean by "just getting the job done". I hope, I hope, I hope it's not the 'copy/paste' mentality (as your comment implies) 'cause that's definatley not what this blog or discussion is about.

# March 14, 2008 11:31 AM

Jeremy D. Miller said:

@Whatever,

I'm trying to find better and better ways of doing things with less effort.  "Just get 'r done" often equates to "work hard, not smart."  According to the Standish Chaos report, something like 75%-80% of all software projects fail, so I don't think we can say just "get 'r done" is really working for us.

# March 14, 2008 11:31 AM

Neil Mosafi said:

Hmm agreed, but i still don't think C# needs duck typing.  it just doesn't feel very C like and there are other languages out there which allow this.

Actually I've always wished that C# had a "typedef" operator, like in C++... it lets you alias any type with another name.  A simple example could be something like this:

namespace MyNamespace {

 typedef StringIntDictionary Dictionary<string, int>;

}

Then you could then just use StringIntDictionary everywhere that the namespace gets imported. It would essentially allow you to alias all the generic arguments so you only have to define them in one place.

# March 14, 2008 11:32 AM

Sergio Pereira said:

It's hard for me to adopt fluent interfaces in my C# code after having tasted how they are created and used in Ruby. I'm taking a pass on fluent C# APIs for the time being.

# March 14, 2008 11:34 AM

Rasmus Kromann-Larsen said:

Well you could always use Boo...

http://boo.codehaus.org/

Works like a charm for me.

# March 14, 2008 11:36 AM

Sergio Pereira said:

@Whatever

Mmm, I thought the name of this site was "Code Better"... Not "Code Again" ...

You may be reading a blog that is not aligned with your priorities, that's understandable, but a waste of your time when you should be getting the job done in the first place. Just a thought.

# March 14, 2008 11:38 AM

Mike Moore said:

@Edward For me, the difference between duck typing and static compile time checking boils down to this: Static languages (like C#/Java) implement polymorphism though inheritance, while dynamic languages implement polymorphism through composition. In one you have a strict hierarchy, while in the other you don't. Its as simple as that. Besides Jeremy's examples you should definitely look outside the .NET and Java world to see why this is so important.

@Jeremy Hurray! Glad to have you on the side of righteousness! I've been saying the same thing now for a while, although probably not as nicely as you just did. :)

One nit though. Language Oriented Programming, or using Domain Specific Languages (DSL), is alot more than building a library with a fluent interface. I don't consider a library with just a fluent interface to be a DSL.

IronRuby is progressing nicely. The code drop from Mix looks to be pretty good, but it is not a complete Ruby implementation yet. The DLR hosting API should be much more stable moving forward as well. I believe the plan is for a 1.0 release later this year.

# March 14, 2008 11:39 AM

Christopher Bennage said:

@Jeremym @Moore

What I'd like to read is a "language to task" analysis. By that I mean, what is C# good for? What is Ruby good for? What is Boo good for? Python, OCaml, etc.

If I'm to be a polyglot (and for inexplicable reasons I'm compelled to be), I need to know this.

I've heard things like, but they are still too vague for me:

OCaml is good for writing compilers.  Boo is good for crafting DSL's. C# is good for enterprisey things (whatever that means). F# is good for analysis (or the same things as OCaml). Ruby is just good.

I'm currently learning Ruby and Boo, but I don't know enough yet to answer these questions for myself. Maybe in a few months...

# March 14, 2008 11:54 AM

Mike Moore said:

@Christopher A language-to-task analysis is a great idea for a blog post. I'll add it to the pile of things I want to do but am behind on. :)

# March 14, 2008 12:13 PM

Justin Etheredge said:

@Jeremy Miller - John Lam said at Mix that they wanted to have a non-trivial Rails app running on IronRuby by RubyConf (which is pretty soon, so I have no idea of that is going to happen), but that they expected to hit 1.0 in about a year. It was actually pretty interesting to hear him talking about the challenges of developing the DLR version of a language that has no spec, and how much testing and prodding they are having to do in order to fish out the runtime behavior of performing certain tasks. Hopefully IronRuby will be something that Microsoft will pursue whole heartily, as there certainly are a lot of tasks that Ruby is much better suited for than C#, and vice versa.

# March 14, 2008 1:22 PM

wekempf said:

@Neil

C# does have that feature.

using StringIntDictionary = System.Collections.Generic.Dictionary<string, int>;

# March 14, 2008 2:09 PM

Neil Mosafi said:

Hey wekempf good point - I didn't know you write using aliases with generic types, that is quite useful, thanks.

It's not quite the same as with a typedef in C++, where you are actually exposing the type through the usage of your class/namespace to other classes which may use it.  still good

# March 14, 2008 2:20 PM

Edward J. Stembler said:

It seems C# is slowing evolving into a hybrid language.  However, I cannot help but to wonder:  At what point is it better to consider a different approach?

For instance, while it's true you can hack your way around many of C#'s language-imposed limitations (i.e. IoC, DI, Providers, plugins, duck typing et. al.).  Those types of solutions usually work against the gain of the original intent of the (C#) language.  They also add additional complexities and dependencies to your code base.  Whereas they are usually non-issues in dynamic languages such as Python or Ruby.  I'm not suggesting that dynamic languages are the end-all-be-all solution for everyone's needs.  However they are less prone to certain (static) design issues, and more conducive to flexibility.

In any case, I think a few years from now we'll see a convergance of sorts.  We'll be able to benefit from both worlds.  There won't be discussions about dynamic vs. static, or compiled vs. interperted...

# March 14, 2008 2:28 PM

Mike Moore said:

@Edward You raise an interesting point about C#'s evolution to a hybrid language. I agree we will see the lines blur between languages, but not in the ways we might always want. I actually had a somewhat viral blog conversation about this.

First, Chad Myers wrote an interesting article called "Dynamic-like Typing using Anonymous Delegates in C#"

chadmyers.com/.../dynamic-like-typing-using-anonymous-delegates-in-c.aspx

I commented on the article on his blog, and Chad followed up with "Moore on the Anonymous Delegate Approach"

chadmyers.com/.../moore-on-the-anonymous-delegate-approach.aspx

I replied on my blog with "The Rubification of C#"

blowmage.com/.../the-rubification-of-csharp

Bertrand Le Roy left a comment on my blog, which I replied to in "The Failure of Static Languages"

blowmage.com/.../static-languages-are-fail

So, you know, FYI. Apologies for the self-promotion. :)

# March 14, 2008 2:46 PM

Mike Moore said:

@Edward More to your point about language convergance: I think we won't see languages converge as much as we see different languages cooperate well together. This is the promise of putting the DLR on top of the CLR, and adding new languages to the JVM.

I think there _will_ continue to be discussions about dynamic vs. static, and compiled vs. interpreted, but those will be discussions about _which_ language to use to solve the problems in a particular "tier" of the application. This is the Polyglot Programming model.

# March 14, 2008 2:50 PM

Edward J. Stembler said:

@ Mike:  I agree, we'll likely see a polyglot phase before and on the way towards the ultimate convergance.

# March 14, 2008 3:00 PM

Jeremy D. Miller said:

@Edward,

I don't see convergence as a good idea.  Let's do polyglot programming and have languages that are simpler to do one thing very well instead of one size fits none languages.  Do you really think a language with both fullblown, compiler enforced Design By Contract *and* dynamic typing/open classes/metaprogramming is possible without collapsing under its own weight?  

# March 14, 2008 3:05 PM

Edward J. Stembler said:

@Jeremy:  I think convergance is simply the natural progression here.  Recently, we saw C# 3.0 gain some features traditionally found in dynamic languages.  The next version, 4.0, is gaining dynamic lookup.

It's not difficult to imagine a language/compiler combination, in the not too distant future, which could gracefully embrace both worlds.  Granted, this environment should be architected from from the ground-up.  Not something which is added on as an after thought to an existing system with existing limitations.

# March 14, 2008 3:22 PM

Ayende Rahien said:

Jeremy,

This is not the first time you stated that you are waiting for IronRuby.

Is there a reason for this?

Boo is here, stable, and has more language oriented features than Ruby.

And reason you are not exploring that?

# March 14, 2008 11:53 PM

lisp said:

Pingback from  lisp

# March 15, 2008 1:02 AM

Csaba said:

Hi,

You should look at  the Cobra language.

Best of Pyton with static and duck typing in .NET and more!!!!!

For an overview see: cobra-language.com/.../Cobra-Lang.NET-2008-Slides.pdf

For more info, see in cobra-language.com/.../why

Regards

Csaba

# March 15, 2008 6:54 AM

Jeremy D. Miller said:

@Ayende,

I knew you'd pop in here sooner or later.  I think that Ruby has a far richer existing ecosystem and a bigger community than Boo.  I know that you really like Boo, but it's basically Ayende on one side versus hundreds of other people for Ruby.  Boo is interesting, but I think I don't think it ever makes the mainstream if IronRuby really takes off.  Besides, I'm already using Ruby for little tasks and like the language.

And I think you're getting it backwards in terms of language oriented features, which is what I'm really wanting here.  From the examples and literature I've seen Boo is not as expressive as Ruby and doesn't have nearly the same metaprogramming abilities.  

# March 15, 2008 10:06 AM

Mark Brackett said:

@Neil Mosafi (re: typedef)

In C#, that's written as:

class StringIntDictionary : Dictionary<int, string> { }

Problem solved.

# March 15, 2008 9:40 PM

Dew Drop - March 15, 2008 | Alvin Ashcraft's Morning Dew said:

Pingback from  Dew Drop - March 15, 2008 | Alvin Ashcraft's Morning Dew

# March 15, 2008 11:08 PM

John Rusk said:

I've found it helpful to take a slightly different tack regarding fluent interfaces.  By leveraging a few C# features, the amount of method chaining can be reduced, which makes the API easier to construct.  Some details here: dotnet.agilekiwi.com/.../shorthand-interfaces.html

# March 17, 2008 1:57 AM

Joshua Flanagan said:

If you haven't yet, spend at least a weekend programming in Boo. For someone that has been "thinking C#" for a few years, I think it is much easier to jump into and be immediately productive with Boo as compared to Ruby.

# March 17, 2008 11:09 AM

Ayende Rahien said:

I can't argue that Ruby is more popular than Boo, but I can't think of something that I can do in Ruby that i can't in Boo, and I can certainly think about it the other way around.

Do you have any concrete example?

# March 18, 2008 12:21 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Jeremy D. Miller

Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy previously worked as a systems architect building mission critical supply chain software for a Fortune 100 company and learned agile development practices as a .Net consultant at ThoughtWorks, one of the pioneers of agile development. Jeremy is the author of the open source StructureMap (http://structuremap.sourceforge.net) tool for Dependency Injection with .Net and the forthcoming StoryTeller (http://storyteller.tigris.org) tool for supercharged FIT testing in .Net. Jeremy's thoughts on just about everything software related can be found on his weblog "The Shade Tree Developer" at http://codebetter.com/blogs/jeremy.miller, part of the popular CodeBetter site. Jeremy is a Microsoft MVP for C#. Check out Devlicio.us!

Our Sponsors

Free Tech Publications

This Blog

Syndication

News

All opinions expressed here constitute my (Jeremy D. Miller's) personal opinion, and do not necessarily represent the opinion of any other organization or person, including (but not limited to) my fellow employees, my employer, its clients or their agents.

About Me

"Best Of" Compendium

StructureMap (Dependency Injection for .Net)

StoryTeller (Supercharged Fit)

Build your own Cab

TestDriven

MVP