Home
  Latest posts
  My Writings
  My Code
  My Gallery
  About me
 
  rssfeed Syndication
 
Bloggtoppen.se
 
 
Links
  Cornerstone
  SweNug
 
Post categories
  misc (48)
  Architecture (21)
  C# (19)
  Asp.Net (2)
  Vb.Net (2)
  Training (7)
  Data (19)
  Events (40)
  Platform (2)
  Orcas (4)
  Updates (3)
  Methods (10)
  Tools (6)
  Announcements (14)
  Languages (1)
  Patterns (6)
  Opinions (11)
  Fun (3)
  Ineta (1)
  Opinion (0)
  Practices (2)
  WCF (5)
 
 
 

Code smells are always code smells ...

Tuesday, October 21, 2008

... no matter what fancy technology you use.

A question that arise often is when and where to use anonymous methods (or lambdas) where a delegate is expected. Anonymous methods and lambdas is a really nice way to quickly pass in a piece of code where a function pointer is expected.

Quick but sometimes very, very dirty.

To avoid opacity you need to make sure that the anonymous method is clear in it's intent and is easy to understand and read. That's why they are great for one-liners (maybe two or three) but start to get messy when you add more. So a thumb of rule is, if the method intention isn't clear, apply "extract method" and name the method to clearly show intent instead.


To avoid needless repetition you apply the same refactoring. E.G if you discover that a piece of code is re-used over and over, just refactor it to a method with a name that's clear about it's intention.

Also, make sure it's forbidden to copy code and that if anyone want's to reuse some code that's already written they should extract it to a method. The "no copy paste" rule often makes it easier to not fall into "needless repetition" even for anonymous methods.

 

Comments
10/21/2008 3:31:00 PM   http://beza1e1.tuxen.de   -   beza1e1
 
Python kinda enforces this by only allowing expressions in lambdas. If you want to use a statement, you have to at least define a named, inner function.
 
10/21/2008 5:14:00 PM     -   bobo the sperm whale
 
Donald Knuth's literate programming is The One True Way.
 
10/21/2008 7:36:00 PM   http://zorander.net   -   Brian L.
 
There's no dirtiness here. First class/higher order functions are a staple of many programming styles and don't seem to cause organizational problems for their users. Closure capture is succinct, easy to read, and much less work (and maintenance) than the likely alternatives (option a: reference to state object passed to a callback method, for instance. option b: break reentrancy and add extra member variables to pass state indirectly, option c:...).

Hiding behavior inside anon methods also has an added benefit of enclosing implementation details of a certain behavior within a lexical scope. This improves locality for people reading the code and prevents other parts of that class from using a method really only meant to be a callback for another purpose.

Async callbacks (F#'s Aync<'t> syntax is much nicer than the normal IAsyncResult stuff, but the same arguments apply) also find nice representation in anon methods, since you can write readable, linear code across io waits without having to manage state explicitly (error prone) or create a dedicated thread (expensive).
 
10/21/2008 9:05:00 PM   https://lowendahl.net   -   Patrik Löwendahl
 
My argument is not that anonymous methods are evil, just that anonymous methods need to oblige to the same rules as all other code. It should be short, clear and not repeated across my system. You should be able to "read" all of the code without scratching your head to much.

When anonymous methods, or lambdas, do offer a clear intent. By all means use them, they will be the better option.
 
10/21/2008 9:22:00 PM   http://www.RogerAlsing.com   -   Roger Alsing
 
Also, one have to bear in mind that delegates may behave differently if you extract them into a method when the delegate references local variables.

bool wasCalled = false;

func< int > foo = () =>
{
wasCalled = true;
return 123;
};

Bar(foo);

if (wasCalled)
...

The above code will stop working if the delegate is refactored into its own method..

 
10/21/2008 9:23:00 PM   http://www.RogerAlsing.com   -   Roger Alsing
 
^ Maybe I should have added that I pretty much only use that kind of code in unit tests and very rarely in production code..
 
10/21/2008 10:22:00 PM   https://lowendahl.net   -   Patrik Löwendahl
 
Yes, you better :P
 
10/21/2008 10:50:00 PM     -   Joel F
 
Actually, Roger, what you're doing right there is a closure and wouldn't be refactored into its own method, but into a new class with a method and a bool field.


Comment
Title:
Your name:
Your url:
Text:
Please enter the text from the image: