Marco published a little example of anonymous methods. I already commented about it on his blog, but to me this is the very proof of the uglyness of anonymous methods.
To me the beauty in object oriented languages is the ability to create easy readable code if you take care of your object design and naming conventions. If you have a sound object model and you choose the names of properties and methods wisely, your code will be very easy to read and to understand. If you keep you code logic simple and short (I very much favor methods and functions that have a very limited amount of code in them) no one will have trouble reading (and if necessary maintaining) your code.
Marco's example, to me, proofs that anonymous methods are terrible. One has to read his little piece of code a couple of times to see what's going on and still it would probably need a bit of documentation. Or, maybe it's me, and only I have to read his code a couple of times.
In my book the anonymous methods will remain very much what their name suggests: not very well known.
Bye,
Bart
Wednesday, September 24, 2008
Subscribe to:
Post Comments (Atom)
12 comments:
I certainly don't claim readability is a plus, but the alternative coding, with the need of deriving a class for each specialized behavior or attaching event handler, isn't really much cleaner...
Powerful features cannot always be powerful and simple at the very same time. There is always a trade-off, unfortunately. It’s inevitable, so we should either embrace new paradigms in programming, or to be at the tail-end of the industry.
Anonymous methods came from the world of functional programming where they are essential. So it’s quite natural that they look alien in the imperative languages like Pascal.
But if I were you, I’d better undertake a little investigation before making such bold statements (e.g., “terrible”, “ugly”, “unreadable”, etc.). In fact, anonymous methods are able to save a lot of lines of code thus making it more maintainable. So, it’s just a matter of habit/practice, I think.
@ Skywalker - I find this sort of comment depressing.
It's as if the lessons of the last 20 years of software development have not been learned.
"Maintainable code" is not code which is written in the shortest, tersest, least verbose form possible.
"Maintainable code" is code that is easily understood by someone seeing it possible for the very first time.
If you can understand something then you can perceive problems and if you can perceive problems you can fix them.
If you look at a piece of code and have to spend 15 minutes just figuring out what the heck is going on in the structure of the code before you can even begin to fathom how the code actually behaves, that is NOT maintainable code, even if it is expressed in only half as many lines of code as the alternative.
(and no, of course > quantity doesn't necessarily = increased maintainability. Unnecessarily verbose code is just as unmaintainable as the inscrutably terse).
If you want to do functional programming, use a language designed for it, don't drag it into a language never designed for it.
Such a self evidently powerful and flexible software paradigm must have plenty of successful commercially available implementations for you to choose from, no?
;)
It is a shame to see these knee- jerk reactions to a new language feature. Granted, it looks strange, and seems "unreadable", especially in the way that it was presented in Marco's example. But if he had put the anonymous methods into variables, and used the variables in the function call, it would have been much cleaner.
Anonymous methods provide a lot of new and interesting possibilities for coding. Of course they can be abused, and the Delphi community will be a while coming up with best practices for using them. But they are used to great advantage in other languages, and I for one am glad that the Delphi team is giving us language constructs and tools that open up new possibilities and paradigms.
@david novo: I'm not giving up on anonymous methods (yet), but I still haven't seen an example that convinces me. All the postings about anonymous methods come up with fabricated or hard to understand code. I am very much open for new language features and would embrace them if I can see the use for them. Maybe it will take a bit of time for the good examples to rise to surface, but the stuff out there right now, doesn't convince me at all.
But, if one day someone comes up with a good example for a problem that otherwise would be very hard to solve, I'll be the first to start the website wwww.iloveanonymousmethods.com.
I identify at least 2 different situations:
1) code should be "reusable" i.e. shared and easily maintained = anonymous methods won't make it.
2) interchangeable, though really simple and specific operations = anonymous methods here and there...
@Marco:
"...The need of deriving a class for each specialized behavior or attaching event handler..."
Patterns, patterns, patterns !!!
"Specialized" is just another word for "common behaviour + extended functionality" so OOP patterns should be used ... IMHO.
Anyhow:
Thank you Marco for the POC about the usage of anonymous methods.
2 Jolyon Smith:
Personally, I don’t find it exciting to write redundant lines code just to avoid using a certain language feature only because some find it to be “ugly.”
I don’t know the definition for the term “maintainable code”, though deeply believe that conciseness of the code is tightly correlated to its maintainability (and vice versa). It’s way more difficult to perceive a problem when code (which solves it) is scattered and smeared all around the unit. And I definitely hate digging in a medley of dummy code.
To be honest, one has to agree that syntactically the feature doesn’t look that great. Though I dare not say it is “ugly.” It’s unusual - yes, a little bit odd – of course. But only because we have not yet got into the way of using it. It’s a matter of time and practice. Why should we be afraid of using cool new language features?
In fact, what I am trying to say is that this particular feature is very useful in a limited number of occasions, but when it comes to it, anonymous methods look pretty sexy.
@ua.Skywalker:
I'm not saying that anonymous methods are ugly per se, I'm just saying that the examples that have been shown are ugly (in the sense of being hard to read). I appreciate that it's a matter of opinion (as well as the definition of readability and maintanable is), but I did put Marco's piece of code to a couple of programmers in my company and none them could tell me within a minute or two what it does.
My point is: I think code can and should be self explanatory and the things you need to document is the logic of it all. When I have to document single lines or even single statements to make it clear to other programmers what's up, I think the code is not good enough. It might do its job very well and maybe even better compared to other implementations, but if someone other than the author can't make sense of it, it's not going into my repository. But, that of course too, is just a matter of company policy...
2 Bart Roozendaal:
On the contrary, I believe “self-documenting” code concept is nothing but a myth. Code has to be clean, tidy and pretty. Comments are always welcome – at least for me they are like “anchors” which facilitate me reading and navigating through the code (especially when it is not-so-recent). So I tend to comment every single begin-end block. But I am a maniac :)
Concerning your employees -- give them time to get themselves accustomed to the feature :) In addition, Marco’s example was extreme (he himself acknowledged it). It seems, in most cases the problem can be fixed by proper code formatting.
I was going to write the long letter, but have read the message from David Novo, and I write only
+1
@Bart Roozendaal: "none them could tell me within a minute or two what it does..."
Probably, because Marco's example with the enclosed anonymous methods with a recursive call is an aerobatics of programming.
In practice I see possibility of wide use of closures instead of callback functions. They can really simplify a code and improve its perception.
Hi Bart,
Here is a simple example:
The current way:
for i=0 to length(colorArr)-1 do
colorArr[i]:=clNone;
Now, how do you split this across multiple cores. Do you create an abstract class that has:
.StartIdx
.EndIdx
and a virtual method .Execute.
Then, make a descendant that accepts a .ColorArr pointer and an Execute method that goes from .StartIdx to EndIdx and sets the array to ClNone. Then you can create multiple instances of the object, set the start and endIdx for each instance, and run them all in threads.
So, in order to do threading, you are creating an entire class structure to execute the code colorArray[i]:=clNone. Not to mention the lifetime management of the objects.
Wouldn't this be a little easier:
parallel_for(1,length(colorArr), procedure
begin
colorArray[i]:=clNone
end;)
Think of the analogy between records and classes. Now that records can have methods, visibility specifiers, properties etc. when would you use them instead of a class? You generally use them when it is simpler functionality that does not require subclassing and you don't want to worry about lifetime management issues. You can pass the records around all over the place, and not worry about freeing them.
Same with anonymous methods. There are times when object lifecycle issues are irrelevant to the problem you are trying to solve, and shoe-horning the code into objects is awkward. In that case, passing a snippet of code around and letting the compiler clean it up can be easy and clean. As was shown in some of the blogs, you can even create factories to generate the correct snippets of code.
Post a Comment