March 20, 2008
Dynamic Method Invocation in Delphi (Part 2)
My post yesterday on dynamic methods invocation in Delphi has raised a few doubts about the rationale behind sch an "unnatural" way of writing Delphi code. I should have posted the rationale behind dynamic method invocation before starting showing code... but at least I'm doing it before delving into the actual tech details, a post I originally wanted to do today, but I'm delaying.
So do you want to invoke a method that doesn't exists at compile-time? There isn't a single answer, but I have used similar coding in real projects and have seen trends (mostly in other languages) going in this direction. So here is a short list of reasons:
- It is trendy. I know, this is not a technical reason. But with people who keep complaining Delphi is always behind every other language, I think it is worth pointing out Delphi has features that other popular languages (Java, C#) are thinking of adding now. And why are they adding this features? Mostly because they are trendy, and they have become trendy because Ruby on Rails is heavily based on them. Again, does it make any sense for Delphi to clone Ruby features? Certainly not, but claiming "hey we can do it as well" is certainly legitimate.
- Dynamic invocation is a common features of dynamic languages, from Ruby to JavaScript, which are not compiled in a strict sense. As Delphi developers you probably share with me some aversion for slow, late-bound, non compile-checked language features. I won't certainly use them as a standard coding practice. However there are situations in which we end up doing the same, in an even worse way. have you even accessed a property by name with RTTI? Have you ever passed a database field name (the string, I mean) as parameter? Every time you use a string to "parameterize" the meaning of a function call you are delaying the resolution of a symbol at runtime. With dynamic invocation you are doing exactly the same, only you are using the language base syntax rather than a convoluted string based one. How comes is setting a dynamic property with a variant is much worse than calling SetPropValue? The former can be more readable.
- Although I'm a string supporter of strongly typing and related features, I appreciate a lot when flexibility is build into a program in a way I don't have to recompile it when I could only reconfigure it. From DFM files to configuration files, to applications that change depending on database metadata, there are many cases in which you want flexibility into your programs.
- I've used this technique while toying with Domain Specific Languages. An internal DSL is like a sub-language hosted by your language and written according to its syntax, but meant almost for non programmers, easy to read and understand, not too bound to the language syntax. This is the situation in which calling date.am7 could be better that data.at (7, 'am'), the former is easier to write and read, especially for a non-programmer. You might not like the entire DSL movement, but I find it quite interesting.
- Coding against partially undefined (at compile time) or flexible data structures is quite neat. Won't it be nice to say table1.usename when the latter is a field of the table rather than writing table1.fieldbyname('username')? Sure, Delphi can generate the field definitions for you with the fields editor, but when you hit a table with a slightly different structure you are stuck. I ended using a similar solution to the one outlined here for XML DOM navigation. In my code (well, I wrote it with others) you could write data.user.name to get the name node under the user node of the document. Of course, the document needed to have those specific nodes or you'd have a runtime error. But the XML document could have different formats provided those nodes where present, something you don't get if you import the data structure at compile time and let Delphi define interfaces for you.
I might not have convinced you, I know, but here are some reasons I find interesting for using dynamic method invocation when it is needed. I will never give up strong type-checking as a general compiler rule, but I appreciate exceptions. The trouble, though, is that writing this code in Delphi is much more difficult than I'd like... but that something for another post (which might take a few day, due to Easter holidays. For now, if you have other reasons for using (or not using) dynamic methods invocation feel free to comment here (or in yuor blog, posting a link here, as you prefer).
To summarize, Delphi is more powerful and flexible than most of its user think. Let's use that power when needed...
7 Comments
Dynamic Method Invocation in Delphi Part 2
> Although I'm a string supporter of strongly typing I know this isn't what you meant, but I thought it was highly appropriate. 8:-) Brad.Comment by Brad White on March 20, 22:41
Dynamic Method Invocation in Delphi Part 2
It's a great method to integrate a script engine to Delphi application. Someone writes a routine using application built-in script language and this procedure can be called in a usual way: ScriptEngine.MyProcedure(EvenWithParameters) Implementation of the routine can be modified dynamically!Comment by George [http://casteng.com] on March 21, 13:13
In arguing FOR, you inadvertently made an excellent case AGAINST!
"Won't it be nice to say table1.usename when the
latter is a field of the table rather than writing
table1.fieldbyname('username')?"
Interesting. Now what if table1 dynamically supports
a "UseName" property.
What you really want in the case of such mis-typed
example is for your table1 object to complain (at
run/test time) that '"usename" is not a valid field
name', since that it was you meant to refer to.
What you will (potentially) get in this case is simply
some strange behaviour when the valid dynamic
"usename" invocation is called on to do something you
didn't intend and don't expect.
You ask what is the difference between (in this case)
being able to write:
table1.usename
and
table1.FieldByName('usename')
The difference is actually very obvious.
In the former case you (and table1) have no idea that
you INTENDED to refer to a *field* called "useRname",
so any errors you might get as a result of making a
careless mistake are going to be far less helpful in
identifying your mistake (assuming that you even get
an error).
Comment by Jolyon Smith
[http://www.deltics.co.nz]
on March 23, 00:19
Dynamic Method Invocation in Delphi Part 2
So when do we get part 3?Comment by Jim McKeeth [http://www.DavinciUnltd.com] on March 25, 23:09
Dynamic Method Invocation in Delphi Part 2
Roddy yes that is possible! Various,, Whenever your code is dynamic and not checked at compile time you can incur in errors. Passing the wrong field name as a string or a "dynamic" property is the same kind of error, so I don't understand why the former is commonly done and the latter (which reads so much better) sees to much opposition. Jim, part 3 will come later this week. I'd really want to change my code a little, before posting it... and I'm incredibly busy right now.Comment by Marco Cantù [http://www.marcocantu.com] on March 25, 23:24
Dynamic Method Invocation in Delphi Part 2
"Passing the wrong field name as a string or a "dynamic" property is the same kind of error" No, it isn't. In the former case you have made an error in identifying the field name you wish to refer to. In the latter case you have made an error but it's not actually possibly to determine what you intended, and it may be that your mistake is able to be accomodated in a way that you did not intend and do not expect. "I don't understand why the former is commonly done and the latter (which reads so much better) sees to much opposition." I don't understand why the modern trend towards "expressing intent" in code is seen by some as meaning we should try as far as possible to *hide* intent. Usually the idea that "intent is more clearly expressed and not hidden in mechanical noise" is used as an argument when in fact what is meant is "this saves me some typing" (but actually obfuscates the actual intent, implying that the intent is obvious - when it likely isn't).Comment by Jolyon Smith [http://www.deltics.co.nz] on April 1, 00:46
Post Your Comment
Click here for posting your feedback to this blog.
There are currently 0 pending (unapproved) messages.

Dynamic Method Invocation in Delphi Part 2
Comment by Roddy on March 20, 17:28