Article Discussion
Delegates, Components, and Simplexity
Summary: Anders Hejlsberg, the lead C# architect, talks with Bruce Eckel and Bill Venners about delegates and C#'s first class treatment of component concepts.
13 posts on 1 page.      
« Previous 1 Next »
The ability to add new comments in this discussion is temporarily disabled.
Most recent reply: March 15, 2004 2:06 PM by Olivier
Bill
Posts: 409 / Nickname: bv / Registered: January 17, 2002 4:28 PM
Delegates, Components, and Simplexity
August 31, 2003 6:44 PM      
Anders Hejlsberg says, "When you take something incredibly complex and try to wrap it in something simpler, you often just shroud the complexity. You don't actually design a truly simple system. And in some ways you make it even more complex, because now the user has to understand what was omitted that they might sometimes need."

Read this Artima.com interview with C# creator Anders Hejlsberg:

http://www.artima.com/intv/simplexity.html

What do you think of Anders' comments?
Joost de
Posts: 15 / Nickname: yoozd / Registered: May 15, 2003 4:13 AM
Re: Delegates, Components, and Simplexity
September 2, 2003 0:58 AM      
This concept of simplexity reminds me of Joel Spolsky's term 'Leaky Abstractions' http://www.joelonsoftware.com/articles/LeakyAbstractions.html

I think we all have had the experience of using some framework or some generated code and having to guess what the framework is doing because the 'simple' abstraction it is offering is hiding things you need to know/influence. The framework aims to make things easier but in these cases things get much harder.

Maybe one solution to this would be to offer the 'simple' API plus an 'advanced' API that's easily substituted when more insight or control is needed by the client programmer.

Joost
tushar
Posts: 2 / Nickname: tusha0 / Registered: February 11, 2003 0:11 PM
Re: Delegates, Components, and Simplexity
September 2, 2003 6:08 AM      
I used to think that delegates were just pure evil until I discovered that...

    void makeUI() {
        ok = new JButton("OK");
        ok.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                okAction(e);        
            }
        }); 
    }
 
    void okAction(ActionEvent e) {
        // Handle ActionEvent for the OK button. 
    }


...is just the purity tax that I pay Java. I'd rather say less to do the same...

    void makeUI() {
        ok = new JButton("OK");
        ok.actionEventHandler += new ActionEventHandler(okAction);
    }
 
    void okAction(ActionEvent e) {
        // Handle ActionEvent for the OK button. 
    }


I'd rather just forget about Anonymous Inner Classes like a bad dream. They were really ugly and awkward when I first used them. They're still ugly and awkward - I'm just used to them now. It's about time a language got used to me instead :-)
Bill
Posts: 2 / Nickname: billburris / Registered: August 8, 2003 4:01 PM
Re: Delegates, Components, and Simplexity
September 3, 2003 11:35 AM      
How do I simulate Delegates in C++?

I created a WatchDog class. For another class to receive messages from WatchDog it must inherit IWatchDog.

class IWatchDog
{
public:
virtual void Timeout( int id ) = 0;
};

The problem is that I need 2 WatchDogs in one class. As you can see I added and id to accomplish this.

Bill
Joost de
Posts: 15 / Nickname: yoozd / Registered: May 15, 2003 4:13 AM
Delegates & Functional programming & Iterators
September 4, 2003 7:36 AM      
Until now I did not realize that delegates in C# make functional programming possible. Especially constructions as you see nowadays in Ruby and Python and before probably in Smalltalk:

['H','A','L'].collect() {|x| x.succ() }

(this is out of the Ruby book of Thomas Hunt)

Since iterating over collections to transform them is all over the place in most applications this would be a very valuable idiom I think.

I tried to implement something like that in the public review of the generics JSR using some Function class that varies over the argument(s) of the function and over the return type.
Along the lines of
Function<Argument,ReturnType>

But then you'd still have to use the anonymous inner class construction that's so unnecessarily convoluted as Tushar rightly remarks.

Unfortunately it's too late in Java for that to change: I innocently asked Gilad Bracha, the spec lead for generics, for the Ruby construction above to be made possible.

His answer amounted to the effect that he's been lobbying for that for years and that the consensus is that another construction to deal with collections would be too confusing. I got the impression that stance pertained to inner classes too.

By the way: does anybody know wether there's a name for this construction with methods that take a function as an argument?

It's getting tiring to have to always use these long descriptions to refer to this. :-)

Joost
Greg
Posts: 1 / Nickname: singleton / Registered: June 18, 2003 2:39 AM
Re: Delegates, Components, and Simplexity
September 4, 2003 11:16 AM      
Interesting reading about C#, CLR and other languages.
http://www.javalobby.org/members/jpr/clr.pdf
Richard
Posts: 5 / Nickname: richardd / Registered: April 30, 2003 3:23 AM
Re: Delegates, Components, and Simplexity
September 5, 2003 4:38 AM      
> Anders Hejlsberg says, "When you take something incredibly
> complex and try to wrap it in something simpler, you often
> just shroud the complexity. You don't actually design a
> truly simple system. And in some ways you make it even more
> complex, because now the user has to understand what was
> omitted that they might sometimes need."

Thinking about API design rather than language design, if I'm not sure whether something should be included or not, I'd prefer to leave it out initially. Ie I'd rather run the risk of simplexity than unnecessary complexity.

Fixing simplexity with an API could be as easy as making certain methods public. Fixing unnecessary complexity is messy at best.

Richard
Joe
Posts: 15 / Nickname: jcheng / Registered: October 16, 2002 8:08 AM
Re: Delegates & Functional programming & Iterators
September 5, 2003 7:51 AM      
Joost,

['H','A','L'].collect() {|x| x.succ() }

This kind of code is actually a little annoying to write in C# as it stands today, because the delegate you pass in to collect cannot be defined inline. So you actually end up writing more code, not less.

With the next version of C# (Whidbey), you will be able to declare delegates inline. These will actually be closer in semantics to real closures than to Java's anonymous classes; you truly inherit the variable bindings of the enclosing context.

So with Whidbey, you will be able to do this:

List<string> list = new List<string>();
list.Add("a");
list.Add("b");
list.Add("c");
list = list.collect(delegate(String e) { return e.ToUpper(); });


As you can see, it's still much more verbose than Ruby; but it's fast and typesafe. And according to Don Box, Whidbey collection classes will have builtin methods to exploit this style of programming, so we won't have to use our own RubyStyleList classes everywhere. :)

I've been blogging about this topic lately at http://www.joecheng.com/blog.

-joe
Daniel
Posts: 5 / Nickname: dyokomiso / Registered: September 17, 2002 2:50 PM
Re: Delegates & Functional programming & Iterators
September 5, 2003 8:45 AM      
> By the way: does anybody know wether there's a name for
> this construction with methods that take a function as an
> argument?

They're called Higher-Order Functions, see http://c2.com/cgi/wiki?HigherOrderFunction for a summary. The "usual" HOF's for collection processing (i.e. map, fold/reduce and filter) can do most of the common tasks people use explicits loops to, usually with shorter/clearer code.

BTW here's a comparison of different syntaxes (assuming a succ function/method):

Ruby
"HAL".collect() {|x| x.succ()}

Smalltalk
"HAL" collect: [:x| x succ]

Lisp
(mapcar #'succ "HAL")

Haskell
map succ "HAL"

You can see the code getting terser while the redundant information is filtered down. Both Ruby and Smalltalk treat blocks and methods differently, so we need to put a block around a method name. Haskell and Lisp expect functions and they treat anonymous functions (i.e. blocks in Ruby) as named functions, so no problems here.
A nice thing about this transparency (regarding functions) is that you can combine them without much though (Haskell-like syntax):


multipliers = map (*) [1..10]
products n = map (\f -> f n) multipliers


So we can define a list of functions that take a value and return it multiplied by some factor (1 to 10 in this case) and use it find all multiples (up to 10) of some number n. This example is simple but sometimes is very handy to have a list of things to do and be able to process them with some parameter (like copying some data to multiple destinations).
Johan
Posts: 1 / Nickname: e8johan / Registered: September 16, 2003 1:24 AM
Re: Delegates, Components, and Simplexity
September 16, 2003 5:31 AM      
I feel that the delegates provided today are too strict. Using Qt's (www.trolltech.com and doc.trolltech.com) signals and slots the profiles of the signal and the slot does not have to match 100%. Instead a signal foo( int bar ) can be connected not only to a( int b ), but also to c( void ). This makes it even easier to loosly connect components together.

Another thing to point out is that to achieve true loose coupling the reciever of a signal cannot know of what is in the other end. So, instead of relying on a sender-object (as .Net/Windows.Forms) does all information needs to be transfered as parameters. Otherwise the components aren't independantly exchangeable.
Johannes
Posts: 3 / Nickname: jhannes / Registered: June 29, 2003 7:10 AM
Re: Delegates, Components, and Simplexity
September 23, 2003 3:00 AM      
It's all well and good that delegates are simpler in the basic case of calling a function directly. However, I have been really pissed off about delegates when writing real code.

The problem is that delegates only support calling a single method. The only state you can attach to this is the "this" pointer for the method (thank God for small favors: compare this to C++).

When I am trying to write moderately generic code, I almost always end up needing local state in the delegator, and what is the C# way of doing this? To create a whole new class, copy the neccessary variables over to it, and give a member method of the little inner class as the argument to the delegator. This is real simplexity!

The lack of anonymous inner classes alone makes C# into a more painful language than Java. I like to say: If you think writing anonymous inner classes is a kludge, try doing the same with top level classes.

BTW: Anders, as soon as C# anonymous functions are released, all my criticism falls. It should've been there from day one, though.
Howard
Posts: 25 / Nickname: hlovatt / Registered: March 3, 2003 1:20 PM
Re: Delegates, Components, and Simplexity
November 12, 2003 8:42 PM      
Take a look at this site:

http://www.geocities.com/csharpfaq/

Particularly the delegates section. You might not be so pleased with delagates afterwards :(

> I used to think that delegates were just pure evil until I
> discovered that...
>
>
> void makeUI() {
> ok = new JButton("OK");
> ok.addActionListener(new ActionListener() {
> public void actionPerformed(ActionEvent e) {
> okAction(e);
> }
> });
> }
> 
> void okAction(ActionEvent e) {
> // Handle ActionEvent for the OK button.
> }
> 

>
> ...is just the purity tax that I pay Java. I'd rather say
> less to do the same...
>
>
> void makeUI() {
> ok = new JButton("OK");
> ok.actionEventHandler += new
> += new ActionEventHandler(okAction);
> }
> 
> void okAction(ActionEvent e) {
> // Handle ActionEvent for the OK button.
> }
> 

>
> I'd rather just forget about Anonymous Inner Classes like
> a bad dream. They were really ugly and awkward when I
> first used them. They're still ugly and awkward - I'm just
> used to them now. It's about time a language got used to
> me instead :-)
Olivier
Posts: 1 / Nickname: pizz / Registered: March 15, 2004 8:49 AM
Re: Delegates, Components, and Simplexity
March 15, 2004 2:06 PM      
Garbage collector is a typical example of simplexity: objects lifetime is always part of specifications and must be explicitly implemented. The only use for garbage collector should be when instances creation and deletion is not performed in the same thread (messages in a queue, tasks in a scheduler...). Integrating garbage collector inside the language is a regression, at least if the goal is to match the code to the specifications.
13 posts on 1 page.
« Previous 1 Next »