With apologies to those who have downloaded what I wrongly claimed was the “final” version a few days ago, I found an error in one of those last minute “improvements” I mentioned. I also took the opportunity to incorporate a couple of refinements that others suggested (thanks CR).
A new version is now available for download and contains the following fixes and changes:
1. Most importantly, I had realised that the CheckReferences() method would give false errors due to an error I introduced without testing – it was one of those: “this is so simple I can’t possibly have made a mistake” things.
Shame on me. 🙁
Now might not be the best time to mention that I plan on blogging about my testing framework at some point (I don’t call it a “Unit Testing” framework because it’s actually a bit more than that)
2. The Enabled read/write property is now read-only. To enable or disable an event use the newly added Enable/Disable methods, so where you would previously have written:
someEvent.Enabled := FALSE; try // Do something finally someEvent.Enabled := TRUE; end;
now use:
someEvent.Disable; try // Do something finally someEvent.Enable; end;
Originally I was aiming to keep the number of methods on a multicast event to a minimum, but I agreed with CR that this way of controlling the enabled state of an event was a bit “funky”.
3. I also agreed with CR that the two IOn_Destroy interfaces were something of a mess (I wouldn’t have gone so far as to call them a “hack” though! lol) and I realised that the problem that the separation into two interfaces had solved no longer applied in that no longer ever implement the interface directly; I always use the TOnDestroy class to add IOn_Destroy support to a class.
Accordingly I have now removed the IOn_Destroy_ interface and extended the IOn_Destroy interface to expose some additional methods of the encapsulated event (since the event itself is now not exposed directly).
Impact Analysis
With the possible exception of the change to the Enabled property, I don’t believe this should affect any code anyone may have written in the short time that the previous version was available.
And I would be very interested to here from anyone that has taken a look and is considering perhaps using the code in their projects, even if it’s just to say “Hi”. 🙂
The version containing these changes may be downloaded below.
[dm]7[/dm]
Meanwhile: Source Code Hosting
Whilst the downloads manager plugin that I’m using with my WordPress blog is very good, I am looking for a more practical solution to source code hosting.
I’ve looked at googlecode and sourceforge and one or two others, and they all seem to use SVN. I personally don’t like SVN. What do other people in my situation do? i.e. they want a source code hosting solution but the tools they use don’t fit with the popular offerings.
Do I just have to grit my teeth and learn to put up with SVN?
Which points in particular don’t you like about SVN?
Have you used other VCS tools that you enjoyed?
Actually now is the best time to mention the testing framework & why it should be used =)
I don’t agree that the Enabled property should be read only. Take for example the standard TDataSet, where you can do either
aDataSet.Open; //Or same as
aDataSet.Active := true;
I’ve used SVN for past project (the explorer integration of http://tortoisesvn.tigris.org/ is really nice), but I currently use git (http://git.or.cz/). You could host the project on https://github.com/. There are also plenty of tutorials to get you started: http://www.gitcasts.com/posts/git-on-windows — a basic screencast showing the essentials.
http://excess.org/article/2008/07/ogre-git-tutorial/ — a longer talk about how git works
http://kylecordes.com/2008/04/30/git-windows-go/ — basic instructions how to install git
Keep up the good work,
Ajasja
@Lars
I’ve used a few – VSS, PVCS, GlobalSource and others, most of which I couldn’t say I “enjoyed”. I even looked at TeamFoundation recently and was flabbergasted at how awkward some very basic operations were!
Of them all, the only one that I found a pleasure to use – easy to setup, easy to configure, easy to use, is Team Coherence.
I don’t really have any concrete reasons as to why I don’t like SVN other than something about it just “smells” to me.
My biggest concern is probably what most people consider it’s advantage – the way that a file system area becomes – or seems to – very tightly associated with a repository. I can see that most of the time this is fine, but those odd occasions when it is a problem, it could be a REAL pain (something that seems to be confirmed talking to colleagues who do use/have used it).
Being a bear of very little brain, I like to keep repository management a step removed from source code changes.
Bottom line I suppose is that I like what I’m already using – SVN seems to appeal most to people who are using alternatives that quite clearly suck.
🙂
@Ajasja
Thanks for the suggestion. I remember reading something about git but hadn’t looked into it. And yes I take your point about now being a good time to talk about the benefits of testing. 😉
I shall take a look at git, but as I indicated to Lars I think my biggest problem is not so much with SVN/git etc themselves so much as I already have something that I am using that I like, and SVN/git look to me like a bit of a step backwards from that (for me), although I can’t quite put my finger on precisely why.
This uncertainty whether to provide Enable/Disable methods or just Enabled property or both sounds similar. I usually start also with methods, i.e. Connect/Disconnet, etc. since they sound more natural language.
But, usually at some point there becomes a necessity to, for example, wrap the state or use a simple checkbox or just another Boolean property to control the status – in which case you need to write another wrapper like this:
SetChecked(Checked: Boolean)
if Checked then
Enable
else
Disable
and finally at this point I notice that for coding, the Boolean property is much more straight forward, so that should be there at least, to enable simply
SetChecked(Checked: Boolean)
Enabled := Checked
Now you can then decide to also have Enable/Disable, which are just shortcuts to ‘Enabled := True/False’ – just like in the TDataset example Ajasja showed.
BTW: I had missed your later entries to the blog although I subscribed to the RSS feed of Part 1 & 2 – and it was not that straight forward to find the complete series among your blog entries either. I would suggest you add comments to the previous blog entry when you add a new one, to help following.
Anyway, I find your implementation of the events very good. As I mentioned in Part 1 comments, I have a bit similar system, but it requires a “wrapper” object in the event listener part, to handle the “dirty details”. It makes the use a bit more complicated: although you also could not do without the “extra” interface for the destroy notification (which is more neat, anyway).
BTW: In your implementation, is there a simple way to identify the listening objects, if you would like to list them in the sender?
It seems my code examples lost their indentation. ‘SetChecked’ is supposed to be a procedure.
Thanks for the comments and suggestions Jouni – I’ll see what I can do to help find related articles in future.
There is no built-in mechanism for identifying the objects listening to an event, but adding that capability should not be difficult – the Data pointer in each handler TMethod is the TObject reference to the listener for that handler.
Rather than put this on the event class itself however, I think I’d rather provide a utility routine in the unit:
procedure GetEventListeners(const aEvent: TMultiCastEvent; const aList: TList);
Being implemented in the same unit, this routine will be able to enumerate the (protected) handler methods on the provided event and add the handler listener objects in the specified list).
What do you think?
Yes that sounds quite nice, although I am not sure I understand why you would not put it in the event class? I would think it is easier to notice that there is such, if it is in the class itself?
Anyway, I think it may turn out useful in some occasions!
As for RSS, I am still learning: I noticed that I can subscribe to your complete blog to get notices of new articles. And each article has a separate comment blog, which I need to subscribe as well – now I did not get a notice of your answer here 🙂
I was initially reluctant to incorporate it into the event itself because whilst it may be useful in some instances I don’t see that it will be that commonly used.
However, that would create a problem with IOn_Destroy so in retrospect, yes – providing it on the event itself is probably the way to go.
I’m hoping to get a CodePlex site – or something similar – up and running in the next week or two, and all code will be published through that in future.
As far as RSS feeds and the like go, frankly I’m a newbie myself! 🙂
I’m glad you figured it out though!
Feel free to email me direct in future if you want to be sure of a reply (jsmith@ this site).