<?xml version="1.0" encoding="utf-8"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en">
<title>The Daily Dump</title>
<link rel="alternate" type="text/html" href="http://www.adamboddington.com/" />
<modified>2006-02-13T01:02:22Z</modified>
<tagline></tagline>
<id>tag:www.adamboddington.com,2006://1</id>
<generator url="http://www.movabletype.org/" version="3.16">Movable Type</generator>
<copyright>Copyright (c) 2005, Adam Boddington</copyright>
<entry>
<title>Apostrophe Protection Society</title>
<link rel="alternate" type="text/html" href="http://www.adamboddington.com/blog/2005/10/05/apostrophe-protection-society/" />
<modified>2006-02-13T01:02:22Z</modified>
<issued>2005-10-05T01:46:43Z</issued>
<id>tag:www.adamboddington.com,2005://1.31</id>
<created>2005-10-05T01:46:43Z</created>
<summary type="text/plain">Um, yes, there is an Apostrophe Protection Society. A quick look at the forums reveals it&apos;s quite active too! To each their own I suppose. Myself, I often forget the rules on when to (not) use an apostrophe, so a...</summary>
<author>
<name>Adam Boddington</name>

<email>adam@boddington.net</email>
</author>
<dc:subject>Everything Else</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.adamboddington.com/">
<![CDATA[<p>Um, yes, there <b>is</b> an <a href="http://www.apostrophe.fsnet.co.uk/">Apostrophe Protection Society</a>. A quick look at the forums reveals it's quite active too! To each their own I suppose. Myself, I often forget the rules on when to (not) use an apostrophe, so a website that lists them in a readable format is sometimes handy.</p>]]>

</content>
</entry>
<entry>
<title>Wireless Security</title>
<link rel="alternate" type="text/html" href="http://www.adamboddington.com/blog/2005/10/05/wireless-security/" />
<modified>2006-02-13T01:05:21Z</modified>
<issued>2005-10-05T00:20:09Z</issued>
<id>tag:www.adamboddington.com,2005://1.30</id>
<created>2005-10-05T00:20:09Z</created>
<summary type="text/plain">Well last night I finally turned on my ADSL modem&apos;s wireless access point and enabled my laptop&apos;s wireless network connection. Voila, instant wireless surfing. What took me so long? Didn&apos;t I realise it&apos;s 2005 and not the dark ages? Well...</summary>
<author>
<name>Adam Boddington</name>

<email>adam@boddington.net</email>
</author>
<dc:subject>Everything Else</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.adamboddington.com/">
<![CDATA[<p>Well last night I finally turned on my ADSL modem's wireless access point and enabled my laptop's wireless network connection. Voila, instant wireless surfing. What took me so long? Didn't I realise it's 2005 and not the dark ages? Well up to now wireless is just one piece of technology I haven't been too eager to try. I read a long time ago about the serious problems with wireless security: fundamental flaws in protocols, high hackability, etc. Since then wireless has been put in the "too risky to try" box, and I've essentially stayed away from it like the plague.</p>]]>
<![CDATA[<p>Undeniably, not everyone has shared my views. Wireless is everywhere! And it's in demand. So much so that my laptop came standard with it -- it wasn't an optional extra. The ADSL modem that I was after also came with a wireless access point built in; although I made sure it could be disabled before I bought it. So without actively seeking out wireless, I still ended up with everything I needed to run a wireless LAN. A sure sign I should roll up that ratty old LAN cable (the one with the baby teeth marks, and stretch marks from being kicked so often) and try the new jiggery-pokery out.</p>

<p>Before I did that, I took a look at the wireless security options in the ADSL modem. I had a choice of WEP or WPA Pre-Shared Key (or WPA-PSK). What do these mean? A quick search on Google found a great <a href="http://www.openxtra.co.uk/articles/wpa-vs-wep.php">explanation</a> of the differences between WEP and WPA. Wikipedia of course also had a lot of <a href="http://en.wikipedia.org/wiki/Wi-Fi_Protected_Access">information</a>. WEP is the old protocol, the one with all the problems I remember reading about -- the one that is hackable and should be avoided at all costs! WPA is markedly better, very secure, although essentially a retro-fitted stopgap and still theoretically hackable. We have to wait for 802.11i (WPA2) for true security it seems.</p>

<p>WPA-PSK is the small network version of WPA, for people that can't afford a separate authentication server. It relies on a shared key that both the access point and end point must have before a wireless connection can be made. Using a simple password as the key here is a major no-no; it can be hacked using brute force. Wikipedia recommends 22 random characters, but being the security freak I am I went for the full 63.</p>

<p>I also engaged the other security options on my ADSL modem which I suspect won't stop a determined hacker but should make life harder. I turned off the ESSID broadcast to stop my access point advertising its presence. I also limited the MAC addresses to just my laptop's MAC address. My final super security option? I turn off the wireless LAN whenever I'm not using it... just to be safe. ;)</p>]]>
</content>
</entry>
<entry>
<title>Home Connectivity</title>
<link rel="alternate" type="text/html" href="http://www.adamboddington.com/blog/2005/10/04/home-connectivity/" />
<modified>2006-02-13T01:06:29Z</modified>
<issued>2005-10-04T01:57:47Z</issued>
<id>tag:www.adamboddington.com,2005://1.29</id>
<created>2005-10-04T01:57:47Z</created>
<summary type="text/plain">Here is a fantastic guide on setting up secure access to a home network (or any network for that matter) using SSH and Remote Desktop Connection (RDC) or VNC. I recently found the need to get into my home workstation...</summary>
<author>
<name>Adam Boddington</name>

<email>adam@boddington.net</email>
</author>
<dc:subject>Everything Else</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.adamboddington.com/">
<![CDATA[<p>Here is a fantastic <a href="http://theillustratednetwork.mvps.org/RemoteDesktop/SSH-RDP-VNC/RemoteDesktopVNCandSSH.html">guide</a> on setting up secure access to a home network (or any network for that matter) using SSH and Remote Desktop Connection (RDC) or VNC. I recently found the need to get into my home workstation from remote locations, and after looking at a PPTP VPN with RDC, a L2TP IPSec VPN with RDC, RDC by itself, and finally SSH with RDC, SSH with RDC seemed to be the most secure and easy to setup option.</p>]]>
<![CDATA[<p>My initial plan was to set up a garden variety VPN and run RDC over it. My home <a href="http://www.billion.com.au/product/voip/bipac7402vgo.php">ADSL modem</a> came with a suite of VPN functionality which seemed perfect for the task, but unfortunately proved too difficult to get working stably. PPTP consistently timed out after one minute -- no idea why. L2TP with IPSec worked, but for some reason couldn't handle RDC traffic. Major frustration, and in the end, it wasn't worth the time and effort to get going.</p>

<p>All I really needed was RDC, so could I run RDC by itself securely, without a VPN? Well the answer turned out to be yes, provided I beefed up RDC before I opened it up to the big bad internet. This <a href="http://www.mobydisk.com/techres/securing_remote_desktop.html">guide</a> does a great job listing all the things that need to be done to secure RDC for internet use. The caveat at the bottom of the guide caught my eye however. RDC uses encryption but doesn't have an authentication process to ensure you're connecting to the right computer. Basically RDC is vulnerable to <a href="http://en.wikipedia.org/wiki/Man-in-the-middle">man-in-the-middle attacks</a>.</p>

<p>Well, being the paranoid security freak that I am, this wasn't good enough for me. I took the recommendation of the guide and looked into SSH. I found this <a href="http://www.securityfocus.com/infocus/1806">article</a> which describes how SSH protects against MITM attacks. Fortunately I also found the <a href="http://theillustratednetwork.mvps.org/RemoteDesktop/SSH-RDP-VNC/RemoteDesktopVNCandSSH.html">guide</a> that I mentioned before on how to setup SSH on Windows for use with RDC. Quick, simple, secure, and with the <a href="http://theillustratednetwork.mvps.org/RemoteDesktop/SSH-RDP-VNC/OpenSSH/Private-publicKey.html">public/private key option</a>, very secure. Not only do I have to have the password (or passphrase) to get into my home network, I also need to have my private key in a file too, or my home workstation won't even talk to me. Very nice!</p>

<p>I'm happy to report the entire SSH setup works as expected too. I'm writing this post on my home workstation using RDC from across town. ;)</p>]]>
</content>
</entry>
<entry>
<title>ObjectDataSource, Object Nirvana</title>
<link rel="alternate" type="text/html" href="http://www.adamboddington.com/blog/2005/07/21/objectdatasource-object-nirvana/" />
<modified>2006-02-13T01:06:53Z</modified>
<issued>2005-07-21T03:04:43Z</issued>
<id>tag:www.adamboddington.com,2005://1.27</id>
<created>2005-07-21T03:04:43Z</created>
<summary type="text/plain">I&apos;ve just started an ASP.NET 2.0 project and I have to say I&apos;m very impressed with the ObjectDataSource control so far. I point this nifty little control at one of my service objects (plain objects, not web services as yet),...</summary>
<author>
<name>Adam Boddington</name>

<email>adam@boddington.net</email>
</author>
<dc:subject>.NET</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.adamboddington.com/">
<![CDATA[<p>I've just started an ASP.NET 2.0 project and I have to say I'm very impressed with the <a href="http://beta.asp.net/QUICKSTART/aspnet/doc/ctrlref/data/objectdatasource.aspx">ObjectDataSource</a> control so far. I point this nifty little control at one of my service objects (plain objects, not web services as yet), specify the methods for insert, select, update, delete, tell it the type of business object to expect (optional I think), hook a GridView control up to it, and voila, everything is working. No code! You don't even have to specify the parameters for the CUD methods -- it will figure them out itself. I just have the business object as my sole parameter, but apparently it can also do properties as parameters if you prefer that instead.</p>]]>
<![CDATA[<p>There will be code of course once the pages are fleshed out. The ODS can handle <a href="http://beta.asp.net/QUICKSTART/aspnet/doc/data/advanced.aspx#conflicts">conflict detection</a> (aka optimistic concurrency), but code is still required to check for this. I use NHibernate, which has its own "conflict detection", so I will be placing code in the same place to check for an exception instead of the number of objects updated.</p>

<p>That's later. For now I'm amazed at how little code I'm actually writing to get this application up and running. Tables, business objects, NHibernate files, service objects (using the flexible NHibernate query language), and web forms with ObjectDataSource controls, all with very little code in them. I'm not using cheap data access code in web forms to get the UI in front of the user, this is a simple, scalable, maintainable framework I can easily add to as the feedback and additional requirements roll in. The experience is more akin to Ruby on Rails than ASP.NET 1.1 development, and I'm loving it so far.</p>

<p>In 1.1 I used to have to retrieve my objects myself in the code, employ all kinds of tricks to either serialize the objects in the ViewState or Session, or track the UIDs -- then re-retrieve on postback, write over the properties with the DataGrid data, blah, blah, blah. A lot of code to maintain on every page. I am wondering what 2.0 does with the objects between postbacks though... There doesn't seem to be a re-retrieve, so I suspect the objects are being serialized into the ViewState. I should really look into this and see what is actually happening -- some objects can be quite large, and if I'm showing 20 objects or so in a GridView, that can be a lot of ViewState, especially if I'm only displaying some of their properties.</p>]]>
</content>
</entry>
<entry>
<title>Reinventing the Wheel</title>
<link rel="alternate" type="text/html" href="http://www.adamboddington.com/blog/2005/06/27/reinventing-the-wheel/" />
<modified>2006-02-13T01:15:00Z</modified>
<issued>2005-06-27T10:26:31Z</issued>
<id>tag:www.adamboddington.com,2005://1.22</id>
<created>2005-06-27T10:26:31Z</created>
<summary type="text/plain">Well that was fun. I learnt something about Ajax, specifically Ajax.NET, and I got a nice code browser to boot. Inspired by Scott Watermasysk&apos;s Cojax, Cojay isn&apos;t as pretty, but it will do for now. Cojay is just for demonstration...</summary>
<author>
<name>Adam Boddington</name>

<email>adam@boddington.net</email>
</author>
<dc:subject>SevenCamels.Common.Cojay</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.adamboddington.com/">
<![CDATA[<p>Well that was fun. I learnt something about Ajax, specifically <a href="http://ajax.schwarz-interactive.de/csharpsample/default.aspx">Ajax.NET</a>, and I got a nice code browser to boot. Inspired by Scott Watermasysk's <a href="http://scottwater.com/blog/archive/2005/05/25/cojax">Cojax</a>, <a href="http://cojay.adamboddington.com/">Cojay</a> isn't as pretty, but it will do for now. Cojay is just for demonstration purposes at the moment since I haven't bought a license for the <a href="http://www.componentart.com/treeview/default.aspx">ComponentArt.Web.UI.TreeView</a> control just yet.</p>]]>
<![CDATA[<p>Cojay ('cause y is after x) is functionally very similar to Cojax. I used a frameset instead of a one page layout, so the scrolling works a bit better (but the printing is a nightmare). The frameset was ripped straight from the <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconhttphandlers.asp">MSDN Library</a> -- I still have the same blue bar in the middle. :S I didn't get around to using the <a href="http://aspnetresources.com/blog/code_highlighter_announced.aspx">code highlighter</a>, but I hope to do that sometime in the future.</p>

<p>The one fancy thing that I did manage to do was handle a user specified URL similar to how the MSDN Library works. This allows direct links to specific folders or files, complete with tree view synchronisation. Here is a quick demonstration of how that works...</p>

<ul><li>You can browse the Cojay code <a href="http://cojay.adamboddington.com/?Url=SevenCamels/Common/Cojay/0.1">here</a>.</li><li> You can take a look at the Cojay configuration file <a href="http://cojay.adamboddington.com/?Url=SevenCamels/Common/Cojay/0.1/Web.config">here</a>.</li></ul>

<p>Feel free to download the source code for the Cojay program <a href="http://www.adamboddington.com/downloads/dotnet/sevencamels/common/cojay/">here</a>. I've put it under the <a href="http://creativecommons.org/licenses/GPL/2.0/">GNU General Public License</a>.</p>]]>
</content>
</entry>
<entry>
<title>Cojax</title>
<link rel="alternate" type="text/html" href="http://www.adamboddington.com/blog/2005/06/25/cojax/" />
<modified>2006-02-13T01:17:25Z</modified>
<issued>2005-06-25T02:28:37Z</issued>
<id>tag:www.adamboddington.com,2005://1.21</id>
<created>2005-06-25T02:28:37Z</created>
<summary type="text/plain">Scott Watermasysk has written a very nice code browser he&apos;s called Cojax. Very fast, easy to use, and most impressively, he only spent a couple hours on it. Let&apos;s hope he makes the source code available, but in the meantime,...</summary>
<author>
<name>Adam Boddington</name>

<email>adam@boddington.net</email>
</author>
<dc:subject>.NET</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.adamboddington.com/">
<![CDATA[<p>Scott Watermasysk has written a very nice code browser he's called <a href="http://scottwater.com/blog/archive/2005/05/25/cojax">Cojax</a>. Very fast, easy to use, and most impressively, he only spent a couple hours on it. Let's hope he makes the source code available, but in the meantime, I'm tempted to have a crack at building something similar myself. What's on TV right now? :-)</p>]]>

</content>
</entry>
<entry>
<title>Random Thoughts on the Provider Pattern</title>
<link rel="alternate" type="text/html" href="http://www.adamboddington.com/blog/2005/06/24/random-thoughts-on-the-provider-pattern/" />
<modified>2006-02-13T01:17:37Z</modified>
<issued>2005-06-24T01:48:43Z</issued>
<id>tag:www.adamboddington.com,2005://1.20</id>
<created>2005-06-24T01:48:43Z</created>
<summary type="text/plain">I found an entry in Wikipedia on Aspect Oriented Programming (and no, I wasn&apos;t randomly reading Wikipedia, I got there from somewhere else... honestly). I know nothing about AOP, but from this quick overview in Wikipedia it occurred to me...</summary>
<author>
<name>Adam Boddington</name>

<email>adam@boddington.net</email>
</author>
<dc:subject>Design Patterns</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.adamboddington.com/">
<![CDATA[<p>I found an entry in Wikipedia on <a href="http://en.wikipedia.org/wiki/Aspect_oriented_programming">Aspect Oriented Programming</a> (and no, I wasn't randomly reading Wikipedia, I got there from somewhere else... honestly).</p>

<p>I know nothing about AOP, but from this quick overview in Wikipedia it occurred to me that the <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspnet/html/asp02182004.asp">Provider Pattern</a> is a model for handling crosscutting concerns in object oriented applications. Sounds fancy doesn't it, but it's not. Crosscutting concerns are simply the things that appear everywhere in applications -- things like logging and transactions. The crosscutting concerns get tangled with and obfuscate the core business logic, a.k.a. the business logic concerns. Yeah, everything is a concern in AOP...</p>]]>
<![CDATA[<p>The basic problem is of course that not only does the business logic become harder to read, but maintaining the crosscutting concerns becomes painful -- they're not contained in their own modules, they're instead scattered throughout the rest of the application. AOP seeks to place crosscutting concerns into their own modules, something they call aspects -- something that to me sounds very much like a provider.</p>

<p>Now I don't want to get into join points, pointcuts and weaving too much, except to say that weaving is the process of injecting the advice in aspects into join points -- basically getting the centralised logging and transaction code where it's supposed to be. Wikipedia lists five possibilities for weaving...</p>

<ul><li>A source pre-processor.</li><li>A post processor that patches binary files.</li><li>An AOP-aware compiler that generates woven binary files.</li><li>Load-time weaving.</li><li>Run-time weaving (trap each join point at runtime, and execute all relevant advice).</li></ul>

<p>The first four are beyond the abilities of a lowly C# developer, but the fifth one there rings a bell. By using providers, we've identified our join points with generic provider code. The advice in our provider is weaved into the application code when the generic provider code is reached. Maintenance of, revamping, or even replacing crosscutting concerns becomes much, much easier -- as long as you don't want to change the provider interface.</p>

<p>Of course, the core business logic is still obfuscated with the generic provider code, so that goal of AOP isn't fulfilled by the Provider Pattern at all. But at least it's easier to maintain to some degree.</p>

<p>Does any of this make sense? How about a point?</p>

<p>Well my point I guess is this. In defining the Provider Pattern perhaps some of this AOP language can be adopted. It seems to me there is a whole swag of named concepts in AOP that relate closely to what the Provider Pattern actually does. Thoughts?</p>]]>
</content>
</entry>
<entry>
<title>All Things Blog</title>
<link rel="alternate" type="text/html" href="http://www.adamboddington.com/blog/2005/06/23/all-things-blog/" />
<modified>2006-02-13T01:21:12Z</modified>
<issued>2005-06-23T11:50:04Z</issued>
<id>tag:www.adamboddington.com,2005://1.19</id>
<created>2005-06-23T11:50:04Z</created>
<summary type="text/plain">I&apos;m loving Wikipedia at the moment. Here are some great links on blogs. Helpful if you want to know what they&apos;re all about... What is a blog and where did blogs come from?What kind of blog software is available for...</summary>
<author>
<name>Adam Boddington</name>

<email>adam@boddington.net</email>
</author>
<dc:subject>Blogging</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.adamboddington.com/">
<![CDATA[<p>I'm loving Wikipedia at the moment. Here are some great links on blogs. Helpful if you want to know what they're all about...</p>

<ul><li>What is a <a href="http://en.wikipedia.org/wiki/Weblog">blog</a> and where did blogs come from?</li><li>What kind of <a href="http://en.wikipedia.org/wiki/Weblog_software">blog software</a> is available for running a blog?</li><li>Using a <a href="http://en.wikipedia.org/wiki/Blog_client">blog client</a> to post entries (optional).</li><li>Reading blogs with a <a href="http://en.wikipedia.org/wiki/News_aggregator">news aggregator</a>.</li><li>Finding a <a href="http://en.wikipedia.org/wiki/List_of_news_aggregators">news aggregator</a>.</li></ul>

<p>If you're interested in starting a blog, don't forget to check out <a href="http://en.wikipedia.org/wiki/Web_syndication">web syndication</a> and <a href="http://en.wikipedia.org/wiki/Creative_Commons">Creative Commons</a> as well. Of course the <a href="http://creativecommons.org/">Creative Commons</a> website is also a good place to go. :-)</p>]]>

</content>
</entry>
<entry>
<title>Syndicate Me</title>
<link rel="alternate" type="text/html" href="http://www.adamboddington.com/blog/2005/06/23/syndicate-me/" />
<modified>2006-02-13T01:25:03Z</modified>
<issued>2005-06-23T06:26:25Z</issued>
<id>tag:www.adamboddington.com,2005://1.18</id>
<created>2005-06-23T06:26:25Z</created>
<summary type="text/plain">Atom and RSS feeds for this blog have always been available, but for those folks who aren&apos;t using a browser that can automatically detect them (like, ahem, Firefox or Opera), I&apos;ve finally created direct links to them. See the links?...</summary>
<author>
<name>Adam Boddington</name>

<email>adam@boddington.net</email>
</author>
<dc:subject>Movable Type</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.adamboddington.com/">
<![CDATA[<p>Atom and RSS feeds for this blog have always been available, but for those folks who aren't using a browser that can automatically detect them (like, ahem, <a href="http://www.mozilla.org/products/firefox/">Firefox</a> or <a href="http://www.opera.com/">Opera</a>), I've finally created direct links to them. See the links? Just over there to the right... down a bit... under the heading Syndication. :-)</p>

<p>For those of you new to blogging (like me), <a href="http://en.wikipedia.org/wiki/Web_syndication">here</a> is a really good definition of web syndication and an explanation of what Atom and RSS feeds are all about. While my Atom and RSS feeds could be used for a variety of (license compliant) purposes (Movable Type automatically includes my Creative Commons license in the feeds), I've mostly provided them for the majority of blog readers out there that use some form of <a href="http://en.wikipedia.org/wiki/News_aggregator">aggregator</a>. Let's face it, I don't blog every day, so why not make it easy for folks to automatically get my content when I finally do write something? It can be a pain clicking on a website several times a week just to find nothing new has been posted.</p>]]>

</content>
</entry>
<entry>
<title>Google&apos;s Secrets</title>
<link rel="alternate" type="text/html" href="http://www.adamboddington.com/blog/2005/06/23/googles-secrets/" />
<modified>2006-02-13T01:31:25Z</modified>
<issued>2005-06-23T04:48:10Z</issued>
<id>tag:www.adamboddington.com,2005://1.17</id>
<created>2005-06-23T04:48:10Z</created>
<summary type="text/plain">Some of Google&apos;s secrets are out -- and some of them are very interesting reading. For example, the relative high ranking of my Optimising Movable Type for Google post could be in some part thanks to my five year registration...</summary>
<author>
<name>Adam Boddington</name>

<email>adam@boddington.net</email>
</author>
<dc:subject>Search Engine Optimisation</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.adamboddington.com/">
<![CDATA[<p>Some of <a href="http://www.buzzle.com/editorials/6-10-2005-71368.asp">Google's secrets</a> are out -- and some of them are very interesting reading. For example, the relative high ranking of my <a href="http://www.adamboddington.com/blog/2005/04/14/optimising-optimizing-movable-type-for-google/">Optimising Movable Type for Google</a> post could be in some part thanks to my five year registration of <a href="http://www.adamboddington.com/">www.adamboddington.com</a>. Who would have thunk it? I didn't expect that, but I suppose it makes sense if the majority of search engine spammers take up one year registrations.</p>

<p>(Did I mention that my <a href="http://www.adamboddington.com/blog/2005/04/14/optimising-optimizing-movable-type-for-google/">Optimising Movable Type for Google</a> post is back in the rankings? Probably not, since I decided I wouldn't blog about that stuff anymore. I don't know what's changed, but it's up there.)</p>

<p>The full analysis is interesting reading, but in the end it mostly confirms what we already know about search engine optimisation. Organic growth of good content will lead to high quality links, which in turn will lead to a handy search engine ranking. The optimisation tips help, but good content is much more important.</p>

<p>The article points out a couple of pitfalls though. One is the length of the domain name registration as already mentioned. The other (well known one) is knowing who is sharing your hosting server. If you neighbour is engaged in dodgy search engine spam tactics, your shared IP address might be banned. Could be a case for getting your own IP block whether you're sharing a server or not.</p>

<p>Thanks to <a href="http://conceptdev.blogspot.com/">Craig</a> for sending me this link.</p>

<h2>Update: 23 June, 2005</h2>

<p>There is some interesting discussion on the Google patent <a href="http://www.webmasterworld.com/forum30/28814.htm">here</a>. The actual patent application can be found <a href="http://appft1.uspto.gov/netacgi/nph-Parser?Sect1=PTO2&Sect2=HITOFF&p=1&u=%2Fnetahtml%2FPTO%2Fsearch-bool.html&r=1&f=G&l=50&co1=AND&d=PG01&s1=20050071741&OS=20050071741&RS=20050071741">here</a>.</p>]]>

</content>
</entry>
<entry>
<title>Version 1.1</title>
<link rel="alternate" type="text/html" href="http://www.adamboddington.com/blog/2005/06/22/version-1-1/" />
<modified>2006-02-13T01:34:10Z</modified>
<issued>2005-06-22T04:47:34Z</issued>
<id>tag:www.adamboddington.com,2005://1.16</id>
<created>2005-06-22T04:47:34Z</created>
<summary type="text/plain">I&apos;ve written a quick update to the SevenCamels.Framework.Configuration library. The first change is to allow regular plugins to be instantiated as needed. The second change is to require all plugins to take their key as their first constructor parameter. The...</summary>
<author>
<name>Adam Boddington</name>

<email>adam@boddington.net</email>
</author>
<dc:subject>SevenCamels.Framework.Configuration</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.adamboddington.com/">
<![CDATA[<p>I've written a quick update to the SevenCamels.Framework.Configuration library. The first change is to allow regular plugins to be instantiated as needed. The second change is to require all plugins to take their key as their first constructor parameter. The last change is the conversion of all collection classes to typed collections. More details on the three changes can be found below. You can download the latest version of the SevenCamels.Framework.Configuration library, with an updated Example program, <a href="http://www.adamboddington.com/downloads/dotnet/sevencamels/framework/configuration/">here</a>.</p>]]>
<![CDATA[<h2>Delay Plugin Instantiation</h2>

<p>It occurred to me that some applications might not need their plugins instantiated straight away. The instantiation of plugins as they're needed shouldn't be a feature of just the ProviderSectionHandler class alone, so I've made this the default behaviour of the PluginSectionHandler class instead. Since this was the only difference between the PluginSectionHandler class and the ProviderSectionHandler class, there's no need to keep the ProviderSectionHandler class anymore. It's gone.</p>

<p>So, the updated PluginSectionHandler class now behaves exactly the same way as the old ProviderSectionHandler class did. And a new class, the PluginInfoDictionary class, bridges the gap between the new and old behaviour of the PluginSectionHandler class.</p>

<p>To switch from the ProviderSectionHandler class to the PluginSectionHandler class, provider configuration information should change from something like this...</p>

<blockquote><code>&lt;configSections&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;sectionGroup name="example"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;section name="persistenceProviders" type="SevenCamels.Framework.Configuration.<strong>Providers</strong>.<strong>ProviderSectionHandler</strong>, SevenCamels.Framework.Configuration" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/sectionGroup&gt;<br />
&lt;/configSections&gt;</code></blockquote>

<p>To something like this...</p>

<blockquote><code>&lt;configSections&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;sectionGroup name="example"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;section name="persistenceProviders" type="SevenCamels.Framework.Configuration.<strong>Plugins</strong>.<strong>PluginSectionHandler</strong>, SevenCamels.Framework.Configuration" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/sectionGroup&gt;<br />
&lt;/configSections&gt;</code></blockquote>

<p>The actual provider configuration section won't need to change. It should continue to look something like this...</p>

<blockquote><code>&lt;example&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;persistenceProviders default="SqlPersistenceProvider"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;add key="SqlPersistenceProvider" type="Example.PersistenceProviders.SqlPersistenceProvider, Example"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;constructorParameter name="connectionString" type="System.String"&gt;blah, blah, blah&lt;/constructorParameter&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/add&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;add key="XmlPersistenceProvider" type="Example.PersistenceProviders.XmlPersistenceProvider, Example"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;constructorParameter name="fileName" type="System.String"&gt;blah, blah, blah&lt;/constructorParameter&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/add&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/persistenceProviders&gt;<br />
&lt;/example&gt;
</code></blockquote>

<p>The PluginSectionHandler class now returns the new PluginInfoDictionary class, so provider factory constructor code should change from something like this...</p>

<blockquote><code>static PersistenceProviderFactory()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;_providerInfos = (<strong>PluginDictionary</strong>)ConfigurationSettings.GetConfig("example/persistenceProviders");<br />
}</code></blockquote>

<p>To something like this...</p>

<blockquote><code>static PersistenceProviderFactory()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;_providerInfos = (<strong>PluginInfoDictionary</strong>)ConfigurationSettings.GetConfig("example/persistenceProviders");<br />
}</code></blockquote>

<p>The provider factory creation code won't need to change. It should continue to look something like this...</p>

<blockquote><code>public static IPersistenceProvider Create()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;// Find the configuration information for the default provider.<br />
&nbsp;&nbsp;&nbsp;&nbsp;PluginInfo providerInfo = _providerInfos.Default;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;// Instantiate it and return it.<br />
&nbsp;&nbsp;&nbsp;&nbsp;return (IPersistenceProvider)providerInfo.Instantiate();<br />
}</code></blockquote>

<p>Plugins aren't automatically instantiated anymore, so plugin code should change from something like this...</p>

<blockquote><code>PluginDictionary rules = (PluginDictionary)ConfigurationSettings.GetConfig("example/rules");</code></blockquote>

<p>To something like this...</p>

<blockquote><code>PluginInfoDictionary ruleInfos = (PluginInfoDictionary)ConfigurationSettings.GetConfig("example/rules");<br />
PluginDictionary rules = ruleInfos.Instantiate();</code></blockquote>

<p>Note that the PluginSectionHandler class no longer returns a dictionary of instantiated plugins, it just returns the plugin configuration information instead. Getting actual instances requires the extra step of calling the Instantiate method on the PluginInfoDictionary class. Of course, if you don't need to instantiate all the plugins at once, you can call the Instantiate method on the individual PluginInfo objects instead...</p>

<blockquote><code>PluginInfoDictionary widgetInfos = (PluginInfoDictionary)ConfigurationSettings.GetConfig("example/widgets");<br />
...<br />
Widget defaultWidget = widgetInfos.Default.Instantiate();<br />
...<br />
Widget myWidget = widgetInfos["MyWidget"].Instantiate();</code></blockquote>

<h2>Key the Constructor</h2>

<p>The second change to the library was to make each plugin take its key as its first constructor parameter. This is mostly a precaution in case an exception is thrown in the constructor of plugin. By having the key available in the constructor, it can be included in the exception message -- which can be crucial to figuring out which plugin actually went wrong.</p>

<p>Plugin (and provider) constructors should move from something like this...</p>

<blockquote><code>public Rule()<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;Key = string.Empty;<br />
}</code></blockquote>

<p>To something like this...</p>

<blockquote><code>public Rule(string key)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;Key = key;<br />
}</code></blockquote>

<p>Not a big change.</p>

<h2>Typed Collections</h2>

<p>The final change was to make all the collection classes (ConstructorParameterInfoList, PluginDictionary and PluginInfoDictionary) typed. This makes them a bit easier to use -- although they were a pain to write.</p>]]>
</content>
</entry>
<entry>
<title>Class Overview</title>
<link rel="alternate" type="text/html" href="http://www.adamboddington.com/blog/2005/06/07/class-overview/" />
<modified>2006-02-13T01:39:28Z</modified>
<issued>2005-06-07T04:43:05Z</issued>
<id>tag:www.adamboddington.com,2005://1.15</id>
<created>2005-06-07T04:43:05Z</created>
<summary type="text/plain">As promised, here is a rundown on the classes in the revamped SevenCamels.Framework.Configuration library. You can download the library here. Please note the license files in the download....</summary>
<author>
<name>Adam Boddington</name>

<email>adam@boddington.net</email>
</author>
<dc:subject>SevenCamels.Framework.Configuration</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.adamboddington.com/">
<![CDATA[<p>As promised, here is a rundown on the classes in the revamped SevenCamels.Framework.Configuration library. You can download the library <a href="http://www.adamboddington.com/downloads/dotnet/sevencamels/framework/configuration/">here</a>. Please note the license files in the download.</p>]]>
<![CDATA[<p>The first class in the library is the abstract SectionHandler class which serves as the base class for all the other section handlers. One thing about creating your own section handler is that if the XML in the configuration file is wrong, you can get some cryptic error messages, usually of the null reference kind. It&#39;s important to validate the XML on the configuration section you&#39;re dealing with and provide some nice helpful error messages for the folks who are writing the configuration files. Doing this manually in the code however through node counting and the like is tedious, and not easy to maintain. A quick and easy way to validate your configuration section is by using an XML schema instead.</p>

<p>That&#39;s mostly what the SectionHandler class deals with. It has an abstract property for the XSD (the complete XSD, not a filename) which the concrete classes implement. It takes that XSD and applies it to the configuration section using a standard <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemXmlXmlValidatingReaderClassTopic.asp">XmlValidatingReader</a>. If the reader finds any discrepancies, an informative <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemconfigurationconfigurationexceptionclasstopic.asp">ConfigurationException</a> is thrown. One nice thing about the ConfigurationException class is that if you provide it with the XML node where the error took place, it will translate that into a configuration file line number -- and that makes debugging the configuration file for the end user so much easier.</p>

<p>The next class is the DictionarySectionHandler class. The PluginSectionHandler class (which we&#39;ll talk about next) works very similar to the <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemconfigurationdictionarysectionhandlerclasstopic.asp">DictionarySectionHandler</a> class in the .NET framework in that it uses add, remove and clear XML elements to add, remove and clear plugins from its dictionary collection. It really makes sense to subclass from the .NET DictionarySectionHandler class and override its methods to handle the more detailed add XML elements (you might want to take a look at the "app.config" file in the Example program to see the kind of add XML elements I&#39;m talking about). Unfortunately the DictionarySectionHandler class doesn&#39;t provide enough members to override, so I quickly whipped up my own. There&#39;s no real reason to use it over the .NET framework version -- it&#39;s mostly there for subclassing.</p>

<p>Finally the meat of the library, the PluginSectionHandler class. By now you should be familiar with how section handlers work and specifically how the DictionarySectionHandler class works. Every time it finds an add XML element, it reads it and adds what it finds to a dictionary collection, which eventually gets returned to the calling code. The PluginSectionHandler class works in exactly the same way -- there&#39;s just a bit more to read when an add XML element is found. Rather than read all this configuration information itself, it passes this responsibility along to the PluginInfo class which uses the add XML element to initialise itself. Once the PluginInfo is constructed and no errors are found, the PluginInfo is used to instantiate the actual plugin. The new plugin is then added to the dictionary collection.</p>

<p>That&#39;s one of the key differences between how I&#39;ve implemented the Plugin Pattern and the Provider Pattern. Plugins are always instantiated and returned in a dictionary collection for the calling code to use. Providers are a bit more discretionary in that they only instantiate the actual provider when it&#39;s requested. As a result the ProviderSectionHandler (coming up) hangs on to the provider configuration information instead of the instantiated providers themselves. The provider factory does the instantiating later.</p>

<p>The PluginInfo and ConstructorParameter classes are pretty straight forward. They receive an XML element when they&#39;re constructed which they read to initialise themselves. The PluginInfo class is mostly interested in its key and type. The key differentiates it from other plugins and the type defines what the plugin is actually going to be when instantiated. Valid type strings can be anything from a simple type name, to a full name, to an assembly qualified name. If you&#39;re sure the assembly is already loaded before the application reads this configuration information, I&#39;d recommend at least a type full name, otherwise bung in the name of the assembly as well. If there&#39;s multiple versions of the same assembly floating around, go for the assembly qualified name instead. Here are some examples:</p>

<ul><li>Type.Name<blockquote><code>ExampleClass</code></blockquote></li><li>Type.FullName<blockquote><code>XYZ.Example.ExampleClass</code></blockquote></li><li>Type.FullName w/ Assembly Name<blockquote><code>XYZ.Example.ExampleClass, XYZ.Example</code></blockquote></li><li>Type.AssemblyQualifiedName<blockquote><code>XYZ.Example.ExampleClass, XYZ.Example, Version=1.0.1983.25223, Culture=neutral, PublicKeyToken=null</code></blockquote</li></ul>

<p>The add XML element can contain zero or more constructor parameter XML elements representing the parameters for one of the plugin type's public constructors. The PluginInfo class passes the responsibility of reading these XML elements along to the ConstructorInfo class. The ConstructorInfo class is interested in the name (which isn't really used, it's more for the user), the type and the inner text representing the string value of the parameter. The constructor parameter type can really be anything as long as it has a TypeConverter that can handle conversion <em>from</em> strings. Note, the number and type of constructor parameters must match the signature of one of the plugin type's public constructors.</p>

<p>Finally, the ProviderSectionHandler class. There isn't a lot of difference between this class and the PluginSectionHandler class for the reasons I've described above. Just one method is overriden -- and that is to store the provider configuration information (a PluginInfo) in the dictionary collection instead of the instantiated provider itself.</p>]]>
</content>
</entry>
<entry>
<title>Plugin the Provider Pattern</title>
<link rel="alternate" type="text/html" href="http://www.adamboddington.com/blog/2005/06/06/plugin-the-provider-pattern/" />
<modified>2006-02-13T01:45:19Z</modified>
<issued>2005-06-06T03:20:37Z</issued>
<id>tag:www.adamboddington.com,2005://1.14</id>
<created>2005-06-06T03:20:37Z</created>
<summary type="text/plain">I finally took a look at the Provider Pattern outlined by Rob Howard in MSDN&amp;#39;s &quot;Nothin&amp;#39; But ASP.NET&quot; column. There&amp;#39;s a Part II as well which comes with a nifty little code example. It&amp;#39;s very similar to some work that...</summary>
<author>
<name>Adam Boddington</name>

<email>adam@boddington.net</email>
</author>
<dc:subject>SevenCamels.Framework.Configuration</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.adamboddington.com/">
<![CDATA[<p>I finally took a look at the <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspnet/html/asp02182004.asp">Provider Pattern</a> outlined by Rob Howard in MSDN&#39;s "Nothin&#39; But ASP.NET" column. There&#39;s a <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspnet/html/asp04212004.asp">Part II</a> as well which comes with a nifty little code example. It&#39;s very similar to some work that I&#39;ve already done with plugins defined in configuration files, so I thought I would abstract my work out a bit more and see if I could get it to support the Provider Pattern as well. Extending it to cater for providers was pretty simple with a little refactoring, but before I start talking about the code, lets take a look at what the Provider Pattern actually is.</p>]]>
<![CDATA[<h2>The Provider Pattern</h2>

<p>At first glance the Provider Pattern seems to be the <a href="http://www.martinfowler.com/eaaCatalog/plugin.html">Plugin Pattern</a> renamed. Take a look at this excerpt from the first article.</p>

<blockquote>[A] provider is the implementation of [an] API separate from the API itself. For example, the new Whidbey Membership feature has a static method called Membership.ValidateUser(). The Membership class itself contains no business logic; instead it simply forwards this call to the configured provider. It is the responsibility of the provider class to contain the implementation for that method, calling whatever Business Logic Layer (BLL) or Data Access Layer (DAL) is necessary.</blockquote>

<p>There are some key concepts in there, mainly the separated interface/contract, multiple implementations to meet the contract, and the specific implementation configured at runtime. This runs very close to the Plugin Pattern by David Rice and Matt Foemmel described in Martin Fowler&#39;s book, <a href="http://www.martinfowler.com/books.html#eaa">Patterns of Enterprise Application Architecture</a>. Here&#39;s an excerpt from that book describing how to implement the Plugin Pattern.</p>

<blockquote>The first thing to do is define with a <i>Separated Interface</i> any behaviors that will have different implementations based on runtime environment. Beyond that, we use the basic factory pattern, only with a few special requirements. The <i>Plugin</i> factory requires its linking instructions to be stated at a single, external point in order that configuration can be easily managed. Additionally, the linking to implementations must occur dynamically at runtime rather than during compilation, so that reconfiguration won&#39;t require a rebuild.</blockquote>

<p>To me the Plugin Pattern basically boils down to a <a href="http://c2.com/cgi/wiki?StrategyPattern">Strategy Pattern</a> with the chosen strategy configured at runtime. The Provider Pattern definitely falls within the realm of the Plugin Pattern as described, but is in fact a more specialised/hybrid version. Take a look at the first excerpt again, specifically at the mentions of an API, business logic layers and data access layers. The provider itself sits between a defined API (the contract/interface) and the business logic / data access layers of an application/subsystem. This is kind of like a reverse <a href="http://www.martinfowler.com/eaaCatalog/serviceLayer.html">Service Layer Pattern</a>. The Service Layer Pattern by Randy Stafford (again from PoEAA) is described as this.</p>

<blockquote>A <i>Service Layer</i> defines an application&#39;s boundary and its set of available operations from the perspective of interfacing client layers. It encapsulates the application&#39;s business logic, controlling transactions and coordinating responses in the implementation of its operations.</blockquote>

<p>The Service Layer Pattern deals with the allowed operations on an application or subsystem by one or more external clients. It&#39;s purpose is to protect the application/subsystem from external clients but also to make it relatively easy to add or switch clients for an application. I say the Provider Pattern is kind of like a reverse Service Layer Pattern because it instead makes it relatively easy to switch business logic and data access code for an application instead. It&#39;s theoretically possible to use the Provider Pattern to substitute the entire guts of an application leaving only the client the same; but, in reality, the pattern typically only deals with one small part of the application, like the Membership example given by Rob Howard in the first excerpt. From the perspective of the proposed Membership provider, there is a real service layer involved since the Membership provider would be used by multiple clients. The service layer just happens to be identical across multiple concrete implementations of the Membership provider.</p>

<p>So there you go. The Provider Pattern is unique in that it defines the API for a complex subsystem, with a view to substituting that subsystem through the use of configurable plugins. In this day and age of making applications work with multiple storage technologies and integrating with an infinite variety of other applications, a pattern that deals with this kind of subsystem substitution is helpful. With a consistent set of APIs for common subsystems, applications can even focus on their core proficiency and leave the subsystem implementation to existing libraries, and as a nice little ancillary benefit, remain open to future libraries and technologies without having to recompile.</p>

<h2>The SevenCamels.Framework.Configuration Library</h2>

<p>Without boring you to tears, <a href="http://www.adamboddington.com/downloads/dotnet/sevencamels/framework/configuration/">here</a> is something for you to actually look at. Included in this download is my new SevenCamels.Framework.Configuration library, recently revamped to support the Provider Pattern, and a small Example program to demonstrate both plugins and providers. The SevenCamels.Framework.Configuration library is licensed under the <a href="http://creativecommons.org/licenses/LGPL/2.1/">GNU Lesser General Public License</a>, and the Example program is licensed under the <a href="http://creativecommons.org/licenses/GPL/2.0/">GNU General Public License</a>. The links take you to the human readable summaries of these licenses on the <a href="http://creativecommons.org/">Creative Commons</a> website. I won't bother talking about the licenses other than to say the GNU LGPL allows the free use of the library in any application, commercial or otherwise, with only a few conditions. You&#39;re also free to modify the source code.</p>

<p>Okay, lets actually talk about the SevenCamels.Framework.Configuration library. This library primarily deals with the reading of configuration files, specifically the reading of plugin and provider configuration information. This is something it does through custom section handlers, classes that implement the <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemconfigurationiconfigurationsectionhandlerclasstopic.asp">IConfigurationSectionHandler</a> interface. There are two main classes in the library, the PluginSectionHandler and the ProviderSectionHandler. They're very similar to each other in the way they work. The PluginSectionHandler class returns a dictionary collection of instantiated plugins, while the ProviderSectionHandler class returns a dictionary collection of provider configuration information with a view to actually instantiating the providers later on request. I won't get anymore specific than that for now, instead I'll save the details for another post. Let's move on the Example program to see how the library can be used.</p>

<h2>The Example Program</h2>

<p>To show off both plugins and providers, the Example program will simulate an email gateway service. The idea is to take emails previously saved, apply rules to them, and then send them off. Our provider example will be in the persistence mechanism for the emails, SQL Server or XML file. Our plugin example will be in the rules we apply to the emails. Rules can be written by anyone and "plugged into" the application through the configuration file. We're interested in all rules defined and we only need one instance of each -- perfect for the PluginSectionHandler to deal with.</p>

<p>As you can see in the code, providers still need a lot of work to get going. The library above helps with getting the configuration information out of the configuration file, it doesn't actually do much of what makes up a provider. The first thing to do is define the seperated interface/contract. This can either be an interface like the IPersistenceProvider interface, or an abstract class like the abstract PersistenceProvider class. I've provided both to demonstrate what they would look like. Other implementations of the Provider Pattern can use one or the other (or both) -- Rob Howard seems to favour the abstract class approach which makes sense if there is a lot of common code.</p>

<p>The next thing to do is create a provider factory class. Rob Howard's example code had a factory method on the abstract MembershipProvider class instead, but I prefer to seperate out the responsibility for instantiating the provider from the provider itself. This lets the provider class focus instead on what it's providing and not be cluttered up by factory code. Either approach is fine, it's a personal choice. The factory class reads the provider configuration information and stores it away for when it's needed, similar to the caching code in Rob Howard's example. The factory class also has a static Create method which uses the default provider's configuration information to instantiate it. The new instance of the default provider is then returned to the calling code. Not a lot to it.</p>

<p>That's pretty much all that would be standard between different implementations of the Provider Pattern. Some kind of interface/contract, and some kind of factory process. The rest of it, the actual providers, is academic. In the Example program the SqlPersistenceProvider and the XmlPersistenceProvider classes simply serve up a fake email for demonstration purposes.</p>

<p>So once the Example program has an email, it needs the rules to apply to them. Here the PluginSectionHandler comes into play, reading the plugin configuration information, instantiating the plugins, and returning them as a dictionary collection. The SevenCamels.Framework.Configuration library really makes this easy. Our plugin classes can have multiple public constructors (like the RedirectRule class does) which we can easily switch between simply by changing the number and type of constructor parameters in the configuration file.</p>

<p>In case you're wondering, the rules in the Example program implement the <a href="http://c2.com/cgi/wiki?DecoratorPattern">Decorator Pattern</a> (GoF, sometimes called the Wrapper Pattern). The email is wrapped by a rule, which itself is wrapped by another rule, and so on. Each rule exposes the public properties and methods of the object it wraps, altering only those that it needs to (effectively "decorating" it). The rules in the Example program override the properties they're concerned with and may alter the value of the properties depending on the rule itself and its criteria. Take the RedirectRule class for example. If its criteria match (and it always does for demonstration purposes), the To, CC and BCC email addresses are altered -- effectively "redirecting" the email.</p>

<p>To see how easy it is to configure an application that makes use of the Plugin and Provider Patterns, try altering the configuration file. Switch the default persistence provider, comment out rules, even add an extra rule. Try to break the application by altering the types, or by setting up constructor parameters that don't match a public constructor. You should get nice, informative error messages.</p>

<p>And that's all. If you have any questions, feel free to email me at adam@sevencamels.com. If you find any bugs or have any suggestions, please pass them along.</p>]]>
</content>
</entry>
<entry>
<title>app.config</title>
<link rel="alternate" type="text/html" href="http://www.adamboddington.com/blog/2005/06/01/app-config/" />
<modified>2006-02-13T01:45:30Z</modified>
<issued>2005-05-31T23:17:59Z</issued>
<id>tag:www.adamboddington.com,2005://1.13</id>
<created>2005-05-31T23:17:59Z</created>
<summary type="text/plain">You learn something new every day. I&apos;ve always put the config files for my console and windows applications in the &quot;bin/Debug&quot; directory. It&apos;s ugly, but it&apos;s always worked for me -- up until today. For some reason, with a brand...</summary>
<author>
<name>Adam Boddington</name>

<email>adam@boddington.net</email>
</author>
<dc:subject>.NET</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.adamboddington.com/">
<![CDATA[<p>You learn something new every day. I've always put the config files for my console and windows applications in the "bin/Debug" directory. It's ugly, but it's always worked for me -- up until today. For some reason, with a brand new project, my config file disappeared every time I did a build. I didn't solve that problem, but I did find out that if you put the config file in the project folder instead and call it "app.config", VS.NET is nice enough to copy it to the "bin/Debug" folder for you and rename it correctly when you build. I suspect the "bug" is related to the "feature" but I'm happy now that everything works again -- and better than before.</p>]]>

</content>
</entry>
<entry>
<title>Trackbacks Killed My Google Rank</title>
<link rel="alternate" type="text/html" href="http://www.adamboddington.com/blog/2005/05/26/trackbacks-killed-my-google-rank/" />
<modified>2006-02-13T01:45:55Z</modified>
<issued>2005-05-26T01:17:41Z</issued>
<id>tag:www.adamboddington.com,2005://1.10</id>
<created>2005-05-26T01:17:41Z</created>
<summary type="text/plain">I initially thought someone had finally dobbed me in to Google and let them know my blog was of no redeemable value whatsoever. It seemed my one post that was doing okay in the Google rankings, Optimising Movable Type for...</summary>
<author>
<name>Adam Boddington</name>

<email>adam@boddington.net</email>
</author>
<dc:subject>Movable Type</dc:subject>
<content type="text/html" mode="escaped" xml:lang="en" xml:base="http://www.adamboddington.com/">
<![CDATA[<p>I initially thought someone had finally dobbed me in to Google and let them know my blog was of no redeemable value whatsoever. It seemed my one post that was doing okay in the Google rankings, <a href="http://www.adamboddington.com/blog/2005/04/14/optimising-optimizing-movable-type-for-google/">Optimising Movable Type for Google</a>, had disappeared altogether from the <a href="http://www.google.com.au/search?q=optimising+movable+type+google">optimising movable type google</a> search. After some investigation though it turns out those <a href="http://www.adamboddington.com/blog/2005/05/20/google-pain/">damn trackbacks</a> have come back to haunt me.</p>]]>
<![CDATA[<p>Have a look at the <a href="http://www.adamboddington.com/images/blog/2005/05/26/trackbacks-killed-my-google-rank/1/" onclick="window.open('http://www.adamboddington.com/images/blog/2005/05/26/trackbacks-killed-my-google-rank/1/','_blank','width=800,height=800,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false">search results</a>. My post is still mentioned, but only by trackback (look for "those that like to tinker"). Three of the four posts I trackbacked to are in the top five (two of which weren't there before I trackbacked to them). My actual post however is missing from the results.</p>

<p>Now take a look at the <a href="http://www.adamboddington.com/images/blog/2005/05/26/trackbacks-killed-my-google-rank/2/" onclick="window.open('http://www.adamboddington.com/images/blog/2005/05/26/trackbacks-killed-my-google-rank/2/','_blank','width=800,height=800,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false">search results</a> with the "omitted results included". There's my post, just after the third post that I trackbacked to. You're probably familiar with the phrase "omitted results included". That's because Google usually has a line similar to this at the end of every search...</p>

<blockquote>In order to show you the most relevant results, we have omitted some entries very similar to the 190 already displayed.
If you like, you can repeat the search with the omitted results included.</blockquote>

<p>I've actually read about this happening to <a href="http://blog.tn38.net/archives/2005/03/why_has_my_site.html#c44">someone else</a>. The web designer for a carpet cleaning site kept a copy of their work on their own site. Google saw identical content and removed one of the sites from its search results. Unfortunately it chose the wrong one (I imagine there was a bit of abuse from the carpet cleaning company after they realised what had happened).</p>

<p>Anyway, it looks like something similar has happened to me. By putting four trackbacks out there, three of which are on posts that have ended up ranking higher than mine, Google has decided my post is too similar to the others and has omitted it from the search results. All based on my post's title and the tiny excerpt that gets passed along with the trackback. Damn trackbacks!</p>

<p>There's not a lot I can do about it apart from change the first paragraph of my post in an attempt to avoid being "very similar". Alternatively I could email these very nice people and ask them to remove my trackbacks from their posts. Or perhaps I should just stop caring about my Google rank and start blogging about something actually worthwhile. Yeah, I might give that a go instead.</p>]]>
</content>
</entry>

</feed>
