<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>A frank exchange of views</title>
    <link>http://blogs.conceptfirst.com</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Delphi, Web development, other stuff</description>
    <item>
      <title>Hints on upgrading OS X to Leopard</title>
      <description>&lt;p&gt;Having just returned from two holidays: Colorado with a motorbike (lovely people, stunning scenery) and Firenze with a girlfriend (lovely people, stunning architecture and art) I decided to update my OS X partition to the new shiny leopard. Here are a couple of notes of how I got on, which is hopefully useful to anyone else doing the same.&lt;/p&gt;

&lt;h1&gt;Leopard&lt;/h1&gt;

&lt;p&gt;Initially I chucked the disk in and just did an install, this installed the OS over the previous one. Everything seemed to work fine, except I had installed Java 1.6 beta from Apple, and this didn&amp;#8217;t work in the new OS (see google for rants about 1.6 JVM not being supported). I needed a working Java for programs such as &lt;a href="http://freemind.sourceforge.net/"&gt;FreeMind&lt;/a&gt;. I tried to sort it out by changing symlinks in the system folders, uninstalling the beta, but basically just broke everything. I decided to reinstall the whole thing, which requires you to notice the &amp;#8216;customize&amp;#8217; button on the installer, allowing you to request it clear the disk first (but usefully also allows you to not install various things like printer device drivers which saves you gigs of space !).&lt;/p&gt;

&lt;p&gt;Having a new install, things definitely felt faster. I also booted into bootcamp, put in the 10.5 disk which installed the latest windows drivers for everything.&lt;/p&gt;

&lt;p&gt;I got most of my development software sorted in an hour or so. The new OS seems to have lots of development tools built in (I installed the XCode package from the install disk as well), like subversion, ruby and even ruby on rails (saves on things to install via &lt;a href="http://www.macports.org/"&gt;MacPorts&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;When you buy a Mac, it comes with the iLife software (iPhoto, iDVD and all that) but an OS upgrade doesn&amp;#8217;t contain them, so I reinstalled iPhoto from my 10.4 disks which worked fine.&lt;/p&gt;

&lt;h1&gt;Parallels&lt;/h1&gt;

&lt;p&gt;To get Parallels working I had a look on google and people recommended running the newly released Beta 5540 (your license will work fine with this, no need for beta license) - find it &lt;a href="http://www.parallels.com/products/desktop/beta"&gt;here&lt;/a&gt;. I installed it, it detected my bootcamp partition, but trying to run it caused an immediate OS X crash. I restarted the machine any everything was fine. Or so I thought.&lt;/p&gt;

&lt;p&gt;Next time I logged into windows I got an error immediately after entering my log in details: &lt;strong&gt;A problem is preventing Windows from accurately checking the license for this computer. Error code: 0x80070002&lt;/strong&gt;, followed by an immediate logout. I tried both Parallels and Bootcamp and the same issue on both ! A Microsoft &lt;a href="http://support.microsoft.com/kb/310794"&gt;kb&lt;/a&gt; describes this as related to an issue in Windows paranoid licensing checks. Other similar issues seemed related the use of Volume Licensing keys (I use our companie&amp;#8217;s VL keys for my windows machines) - I tried the suggested fixes but no help. After lots of messing around, I found a &lt;a href="http://www.jsifaq.com/SF/Tips/Tip.aspx?id=8521"&gt;post&lt;/a&gt; on the interweb that suggested it was an issue with some files in system32, oembios.*. Looking at these 3 files, they had change dates in the last 24 hours. A copy of the files from another XP SP2 installation fixed the issue (via Safemode and a USB key) , returning change dates back to 2004, got everything working perfectly again.&lt;/p&gt;

&lt;p&gt;No idea what broke these files, whether it was Parallels, Bootcamp drivers or something else ?&lt;/p&gt;

&lt;p&gt;Another oddity, to fix windows to run in both Parallels and Bootcamp, I had to apply the fix once in each mode (which is really weird - somehow related to the use of different hardware configurations to allow parallels to do its magic - anybody understand how this works ??)&lt;/p&gt;

&lt;h1&gt;Misc&lt;/h1&gt;

&lt;p&gt;The only other issue I have come across was that once connected to a VPN (to a windows 2000 server), DNS lookups on my Mac were really slow (like 20s). Looking on the net, there were suggestions that the resolver stack had changed slightly in the new OS, and may be working badly with old routers / dns servers in some way. Adding my local DNS server to the VPN&amp;#8217;s DNS settings (under Advanced in Network system preferences) seems to have done the trick though.&lt;/p&gt;

&lt;p&gt;Now having everything working fine and dandy, there&amp;#8217;s no excuse for putting off actual useful work, how disappointing ;-)&lt;/p&gt;</description>
      <pubDate>Fri, 02 Nov 2007 10:41:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:f0a317f5-e98c-4e32-9e85-03f9414f7bc6</guid>
      <author>David Glassborow</author>
      <link>http://blogs.conceptfirst.com/articles/2007/11/02/hints-on-upgrading-os-x-to-leopard</link>
      <category>OS X</category>
      <category>leopard</category>
      <category>parallels</category>
    </item>
    <item>
      <title>Remote Desktop for OS X</title>
      <description>&lt;p&gt;If you need to do remote desktop / mstsc on a Mac, you can either use the flakey unreliable implementation from Microsoft, or use the brilliant open source &lt;a href="http://cord.sourceforge.net/"&gt;CoRD&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Wed, 08 Aug 2007 12:06:21 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:8428437b-0f87-457b-9a9d-bd69055f5c09</guid>
      <author>David Glassborow</author>
      <link>http://blogs.conceptfirst.com/articles/2007/08/08/remote-desktop-for-os-x</link>
      <category>OS X</category>
    </item>
    <item>
      <title>Accessing Mac Files from Windows</title>
      <description>&lt;p&gt;If your booted into windows via bootcamp and still need access to a file on your Mac partition, you can use &lt;a href="http://hem.bredband.net/catacombae/hfsx.html"&gt;HFSExplorer&lt;/a&gt; to access them read only (via &lt;a href="http://www.macosxhints.com/article.php?story=20070717090846961"&gt;Mac OSX Hints&lt;/a&gt; )&lt;/p&gt;</description>
      <pubDate>Thu, 19 Jul 2007 12:58:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:f174c01d-b3db-4cd0-9530-2e3b0938b3d1</guid>
      <author>David Glassborow</author>
      <link>http://blogs.conceptfirst.com/articles/2007/07/19/accessng-mac-partition-from-bootcamp</link>
      <category>OS X</category>
    </item>
    <item>
      <title>Cheap Mac Software</title>
      <description>&lt;p&gt;&lt;a href="http://macheist.com/"&gt;MacHeist&lt;/a&gt; are once again doing a great bundle of shareware software for $50.&lt;/p&gt;

&lt;p&gt;With the Dollar being very weak compared to Sterling at the moment, this is a bargin for us in the UK.&lt;/p&gt;</description>
      <pubDate>Mon, 16 Jul 2007 11:56:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:2a43d083-8aa4-434d-9f63-d59e7e4a56b8</guid>
      <author>David Glassborow</author>
      <link>http://blogs.conceptfirst.com/articles/2007/07/16/cheap-mac-software</link>
      <category>OS X</category>
    </item>
    <item>
      <title>Professional Development on a MacBook Pro</title>
      <description>&lt;p&gt;Like a number of people in the Delphi Community ( &lt;a href="http://www.stevetrefethen.com/blog/RunningWindowsVistaOnAMacBookPro.aspx"&gt;Steve Trefethen&lt;/a&gt;, &lt;a href="http://www.distribucon.com/blog/PermaLink,guid,0966f2d8-377b-4223-99b0-b4feff53cd60.aspx"&gt;Dan Miser&lt;/a&gt; ), and the development community as a whole, I now do all my development on a MacBook Pro. I changed to an Apple machine six months ago, for a number of reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I needed a new laptop, and the MacBook Pro hardware is so goddamn thin, light, and good looking.&lt;/li&gt;
&lt;li&gt;I am becoming increasingly disillusioned by Windows, especially the new &lt;a href="http://www.forbes.com/security/2007/02/10/microsoft-vista-drm-tech-security-cz_bs_0212vista.html"&gt;DRM&lt;/a&gt; stuff.&lt;/li&gt;
&lt;li&gt;I fancied trying out OSX, a change is as good as a rest and all that.&lt;/li&gt;
&lt;li&gt;Bootcamp and virtualisation allow me to use Windows XP on an Apple laptop.&lt;/li&gt;
&lt;li&gt;The web is freeing us from being locked into particular Operating Systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a professional developer, most of my clients run Windows, and most of my native development is done using Visual Studio 2005 or Delphi 2006, connecting to SQL Server or Oracle backends. I boot my laptop into Windows to do this work, or use Parallels to run it with Mac OSX (when I got my MacBook Pro I got it with 3G of RAM so Windows runs pretty fast inside OSX). Increasingly though I am doing web development, which means I can do much more work inside just OSX.&lt;/p&gt;

&lt;p&gt;The more I have used OSX, the more I prefer it to Windows, so I have put together this list of tools and hints for doing professional development on OSX:&lt;/p&gt;

&lt;h2&gt;Using Bootcamp&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Steve has got an excellent &lt;a href="http://www.stevetrefethen.com/blog/WindowsKeyboardShortcutsOnAMacBookPro.aspx"&gt;list&lt;/a&gt; of the keyboard mapping for Windows&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.parallels.com/products/desktop/"&gt;Parallels&lt;/a&gt; allows runs Windows (from a bootcamp partition) in OSX&lt;/li&gt;
&lt;li&gt;As does &lt;a href="http://www.vmware.com/products/desktop/fusion.html"&gt;VMWare&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Using OSX&lt;/h2&gt;

&lt;p&gt;One of the things there first confused me using OSX is the link between a visual Window and a running program. Having used Windows for the best part of 15 years, I had the stong mental link between having a open window and having a program running. OSX is much more like the systray in a way. In most instances, a program carries on running even if all its windows are shut. At first this seems odd, but now I am actually used to Mail and iCal running in the background, collecting mail and showing me reminders, without having windows cluttering up the place or being minimised. Also the dock changes icons depending on status of the program, so I can see that new mail is waiting, without requiring an open window to tell me.&lt;/p&gt;

&lt;p&gt;I guess it is the unix heritage, but OSX seems much happier having loads of programs running a the same time, than Windows would (or maybe this laptop has just got too much memory).&lt;/p&gt;

&lt;p&gt;Another change from the Windows way of thinking is about installation of software. In OSX an application is a directory with a name of BlahBlah.app. It contains all that is necessary to run. So drag and drop to install software, move things around as desired, and delete it when no longer wanted. Only software that needs to make system changes needs to have install scripts.&lt;/p&gt;

&lt;p&gt;You need to install &lt;a href="http://quicksilver.blacktree.com/"&gt;Quicksilver&lt;/a&gt; for launches programs, and more advanced voodoo. Have a look at some of the screen casts at &lt;a href="http://feeds.feedburner.com/TheAppleBlogScreencasts"&gt;The Apply Blog&lt;/a&gt;, a good beginner one is &lt;a href="http://theappleblog.com/2007/06/29/screencast-quicksilver-for-beginners/"&gt;here&lt;/a&gt;. You won&amp;#8217;t believe for a powerful bit of software it is.&lt;/p&gt;

&lt;p&gt;Another thing worth getting your head around is this idea of OSX services. These are simple &amp;#8216;services&amp;#8217; that are provided to all programs running, accessible of the programs menu. While there are some useful ones built in, there really come into the own where you start changing them using &lt;a href="http://www.manytricks.com/servicescrubber/"&gt;Service Scrubber&lt;/a&gt; and &lt;a href="http://wafflesoftware.net/thisservice/"&gt;This Service&lt;/a&gt;. See some examples from &lt;a href="http://daringfireball.net/2007/04/google_lucky_thisservice"&gt;John Gruber&lt;/a&gt; about writing your own scripts and making them available to all apps (although I&amp;#8217;d recommend using Ruby over Perl ;-).&lt;/p&gt;

&lt;h2&gt;Web Development&lt;/h2&gt;

&lt;p&gt;It goes without saying that you should be using Firefox with Firebug for web development. Day to day browsing I use &lt;a href="http://www.caminobrowser.org/"&gt;Camino&lt;/a&gt; which is the firefox engine inside a more OSX integrated and looking program.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://macromates.com/"&gt;Textmate&lt;/a&gt; is a great editor, as most people know, but if you are doing any JavaScript development make sure you get the &lt;a href="http://macromates.com/blog/2007/javascript-tools/"&gt;JS Tools&lt;/a&gt; bundle. Having your script &amp;#8216;lint&amp;#8217;ed everything you save is a great productivity improver. Also get the &lt;a href="http://projects.validcode.net/getbundle"&gt;GetBundle&lt;/a&gt; bundle to make it easy to manage extensions and find new ones. Blog writing is easy with the built in &lt;a href="http://daringfireball.net/projects/markdown/"&gt;markdown&lt;/a&gt; support.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.eclipse.org/"&gt;Eclipse&lt;/a&gt; (especially with the new CodeGear betas running inside Eclipse ) has plugins to do pretty much everything (although I still use Textmate most of the time).&lt;/li&gt;
&lt;li&gt;Anybody know of a Fiddler equivalent for OSX ?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Subversion&lt;/h2&gt;

&lt;p&gt;Does anybody use anything else anymore ?
I use the tigris plugin &lt;a href="http://scplugin.tigris.org/"&gt;scplugin&lt;/a&gt; to have subversion integration with the finder. It is not quite as good as tortoise. There is also &lt;a href="http://www.lachoseinteractive.net/en/community/subversion/svnx/features/"&gt;Svnx&lt;/a&gt; which is ok, but I don&amp;#8217;t find the UI all that intuitive.&lt;/p&gt;

&lt;h2&gt;Database Access&lt;/h2&gt;

&lt;p&gt;For connecting to Oracle, I use the free &lt;a href="http://www.oracle.com/technology/products/database/sql_developer/index.html"&gt;SQL Developer&lt;/a&gt; which has a native OSX version. Most of the open source databases have native clients (e.g. Postgres), but otherwise I use &lt;a href="http://www.aquafold.com/downloads.html"&gt;Aqua Studio&lt;/a&gt; v4.7 which is free. One of the nice things is most of the tools are Java based, so if you can find a JDBC package for your database, chuck it in /Library/Java/Extensions and then all the Java apps on your machine have connectivity to it (I have found ones for SQL Server, Oracle, MySql and Postgres).&lt;/p&gt;

&lt;h2&gt;Other Languages / Database Engines&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Anything available in the Open-source world, if not explicitly released for OSX, is normally available on &lt;a href="http://darwinports.com"&gt;DarwinPorts&lt;/a&gt; or &lt;a href="http://finkproject.org"&gt;Fink&lt;/a&gt;, projects to make linux/unix software compilable on OSX (which is a unix variant behind the scenes), and easily installable handling all the dependancies etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr/&gt;

&lt;p&gt;Are there any useful development tools or hints I have missed ? Let me know and I&amp;#8217;ll try and keep a development bias list &lt;a href="https://blogs.conceptfirst.com/pages/Tools"&gt;here&lt;/a&gt; or on this page.&lt;/p&gt;

&lt;p&gt;And if your still using boring old Windows, come and join the revolution !&lt;/p&gt;</description>
      <pubDate>Thu, 12 Jul 2007 16:26:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:39a801bc-bc97-4dd4-a3f1-8ea96da0beda</guid>
      <author>David Glassborow</author>
      <link>http://blogs.conceptfirst.com/articles/2007/07/12/professional-development-on-a-macbook-pro</link>
      <category>Web Development</category>
      <category>OS X</category>
      <category>Business</category>
      <category>Delphi</category>
    </item>
    <item>
      <title>Rules of thumb to make a project work</title>
      <description>&lt;p&gt;I am currently coming to the end of a large project for one of our clients, where I have been acting in the Business Analyst and Technical Lead roles. It has been a fun and successful project, and I wanted to pass along some of the lessons I&amp;#8217;ve learnt (again) about how to make Technical Analysis (and the project as a whole) successful (and also make a checklist for next time around ;-).&lt;/p&gt;

&lt;p&gt;It must be remembered that IT solutions (and really any business change) are all about two things: Incentives and Trade-offs.&lt;/p&gt;

&lt;h2&gt;Incentives&lt;/h2&gt;

&lt;p&gt;Incentives are important because ultimately people are lazy, and this is A Good Thing. We all have way too many things to do in our lives, both personal and professional, and therefore being lazy is a very successful evolutionary adaptation on the part of Homo Sapiens. The body only bothers to grow stronger muscles when we actually need them, rather than paying the cost of having them all the time. The same approach can be seen in our behaviour.&lt;/p&gt;

&lt;p&gt;To make people want to use your new approach / program / business process, you need to make it worth their while. This seems obvious but I see it being forgotten time and again. Sometime the incentive is fear of being fired, but ideally you want to make your user&amp;#8217;s lives easier and more efficient. If you can&amp;#8217;t incentivise them to change their behaviour, they won&amp;#8217;t.&lt;/p&gt;

&lt;h2&gt;Trade-offs&lt;/h2&gt;

&lt;p&gt;Any new system involves trade-offs. If it was a simple no brainer, it would have been done ages ago. Management often want better visibly of information (and normally control as well), but they need to be made to understand that this will have added costs, whether that is in increased paperwork, administration, or work enjoyment for the staff. Often people assume they get increased efficiencies (or whatever) for free, but there is always a downside. Not that that is a problem, but it needs to be understood and communicated (it goes into the areas of risk management). Communicating this as quickly as possibly, and ideally suggesting different cost/benefit scenarios, makes sponsors think more about why they are asking for things, and better controls their expectations.&lt;/p&gt;

&lt;hr/&gt;

&lt;p&gt;From these two overriding principles, we then have a randomly ordered list of my current best practises.&lt;/p&gt;

&lt;h2&gt;Technical Analysis Best Practise&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Always sit with the users&lt;/li&gt;
&lt;li&gt;It&amp;#8217;s all about incentive&lt;/li&gt;
&lt;li&gt;Mastery of language is important&lt;/li&gt;
&lt;li&gt;Its easier if you don&amp;#8217;t care&lt;/li&gt;
&lt;li&gt;Avoid the middle men&lt;/li&gt;
&lt;li&gt;Flexibly and Power =&gt; Complex and slow&lt;/li&gt;
&lt;li&gt;Easy to think != Easy to do. Details matter&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The above points in more detail:&lt;/p&gt;

&lt;p&gt;1 - Always sit with the users&lt;/p&gt;

&lt;p&gt;Sounds obvious, but on every project I see it being ignored. 30 minutes of sitting with the actual users you are providing a solution for, will give you better and more accurate understanding than talking to management or reading analysis documentation for days. Business processes change, often the experts on that process are out of touch with what is actually going on. As well as getting a good detailed understand of what they do, and what their problems are, another benefit of watching users is how often there are tiny little changes you can make (trivial software changes like adding a shortcut, or making some non-modal) that can save each user huge amounts of time and stress everyday !&lt;/p&gt;

&lt;p&gt;If you haven&amp;#8217;t sat and watched your users recently, you&amp;#8217;re probably not building a system that solves their real problems ! &lt;/p&gt;

&lt;p&gt;2 - It&amp;#8217;s all about incentive&lt;/p&gt;

&lt;p&gt;A reiteration of the point about, but really a reminder to think of the incentives of each distinct groups of users. Management will have different incentives than the day to day users. It is worth thinking how to incentivise each different group to use the system in the way you want it used.&lt;/p&gt;

&lt;p&gt;3 - Mastery of language is important&lt;/p&gt;

&lt;p&gt;The language you use, both in your application, but especially when communicating ideas and progress to project sponsors, is incredibly important. Firstly words are very powerful in the human mind, they are the key way we link thoughts, feelings, expectations and fears together. The project I have been working on was half way through when I came on board, and because it was late and not delivering, had a number of perceptions, worries and expectations, all hanging off the &amp;#8216;name&amp;#8217; of the project. One of the first things the team did was change the project name. This gave us a blank sheet to work with, meant that people&amp;#8217;s previous perceptions were &amp;#8216;invalidated&amp;#8217;, giving us breathing room to solve the problems in a different way.&lt;/p&gt;

&lt;p&gt;Secondly, unless you use terms like Risk and Trade-off, management and sponsors won&amp;#8217;t consider these things. Just by using the words, you can make them better consider that they are asking for, and incentivise them to make better decisions (I am labouring the theme enough yet ? ;-)&lt;/p&gt;

&lt;p&gt;4 - Its easier if you don&amp;#8217;t care&lt;/p&gt;

&lt;p&gt;I am an outside supplier, so it is much easier for me to tell people the situation as is, rather than having to worry too much about internal politics. You obviously don&amp;#8217;t go out of your way to cause problems, and need be sensitive to the people from the business that you work with who don&amp;#8217;t have the same freedoms as you, but being truthful about situations is very important to the overall success of a project. Having said that, obviously always keep copies of all emails, and confirm verbal conversations via email, so you always have an audit trail to support your decisions.&lt;/p&gt;

&lt;p&gt;5 - Avoid the middle men&lt;/p&gt;

&lt;p&gt;In any remotely large business there will tend to be lots of layers of management (unless you work somewhere very groovy like Google Inc). Each layer will have there own agendas, desires and aims, and will wish to communicate information in ways that either make them look good or at least reduce how bad they look. Whilst this is understandable, and just human nature, projects are much more successful if you can talk honestly to the ultimate users at one end of the spectrum, and the key sponsors / decision makers at the other end. The more layers in the way, the more the problems, drivers, issues, etc. get obscured and less clear. Politically this can be hard, and take time, but it is worth it in the end.&lt;/p&gt;

&lt;p&gt;6 - Flexibly and Power =&gt; Complex and slow&lt;/p&gt;

&lt;p&gt;This is really a more concrete example of the trade-off principle. Flexibility and powerful is what everybody wants their computer systems to be. However these two requirements ALWAYS imply complexity, and complexity implies complex (and potentially) slow running software. The art of being a good designer or architect is coming up with abstractions that are both powerful and a simple as possible, but always remember that powerful and flexibly implies clever decision making which implies complexity. Bacteria are very simple, but don&amp;#8217;t do a huge amount but breed. Look at the complexity, both in body and mind, to get something as flexible and powerful as a human being. Fight to keep things simple, and your are much more likely to get a working solution ready in time.&lt;/p&gt;

&lt;p&gt;A good example of this is the control issue. Management quite often want to stop people using systems in certain &amp;#8216;incorrect&amp;#8217; ways (not entering data in certain ways, formats, sequences, whatever) . Often their approach is to wrap these systems in further layers that prevent the &amp;#8216;incorrect&amp;#8217; use from occurring. Two problems with this though: 1. It&amp;#8217;s loads of work and 2. There are often certain exceptional situations where it is necessary to put in data &amp;#8216;incorrectly&amp;#8217;. Often the simpler approach is just to provide an exception report. Management can use this to make sure systems are being used correctly, and if there is a valid reason using it wrongly, its not a problem. Making it a management rather than IT issue.&lt;/p&gt;

&lt;p&gt;7 - Easy to think != Easy to do. Details matter&lt;/p&gt;

&lt;p&gt;This is obvious to developers, but sometime can be hard to communicate to project sponsors. It is something I still have problems with conveying successfully. Steve Yegge &lt;a href="http://steve.yegge.googlepages.com/nonesuch-beast"&gt;discusses&lt;/a&gt; the same point. For the same &amp;#8216;lazy&amp;#8217; reasons as discussed at the start, people don&amp;#8217;t think through what they are asking for, and whilst this is annoying, your job as a technical analyst is to communicate the consequences of what people are asking for. In a similar vein, any technology you have been asked to use should be &amp;#8216;proof of concept&amp;#8217;ed as quickly as possible. Things often work in principle, but in practise are too buggy, slow or unreliable to actually use in production systems. Ultimately this is why I don&amp;#8217;t trust analysts who can&amp;#8217;t program, they never understand the need to capture the exact details of a project, because they don&amp;#8217;t actually have to build working systems, they don&amp;#8217;t really realise its importance.&lt;/p&gt;

&lt;hr/&gt;

&lt;p&gt;Hope this list is useful for somebody. I&amp;#8217;m off to work out what the trade-offs and incentives for writing blog articles are ;-)&lt;/p&gt;</description>
      <pubDate>Thu, 12 Jul 2007 15:00:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:f81f3e7f-7b0a-4142-9d83-28a9922608dc</guid>
      <author>David Glassborow</author>
      <link>http://blogs.conceptfirst.com/articles/2007/07/12/rules-of-thumb-to-make-a-project-work</link>
      <category>Business</category>
    </item>
    <item>
      <title>Feedburner and Apache redirects</title>
      <description>&lt;p&gt;Looking at the load this blog is causing, virtually all of it&amp;#8217;s requests are for the syndication feeds so I decided to off-load the network bandwidth to &lt;a href="http://www.feedburner.com"&gt;Feed Burner&lt;/a&gt; ( recently acquired by Google).&lt;/p&gt;

&lt;p&gt;Feedburner basically checks your site every 30 minutes (you can also manually request an update) and caches the response. Rather than ask my subscribers to change the feeds source, I decided to use Apache to redirect all requests to my feeds to feedburner, unless it was actually feedburner requesting the information.&lt;/p&gt;

&lt;p&gt;To get this to work took a bit of Apache shenanigans, so I thought I would document it here both for myself and for anyone else who needs to do the same. It is also a useful example of how powerful Apache is, particularly as a forward facing server than manages the virtual URL space and links it up to various webs server technologies and platforms behind the scenes (loose URL =&gt; implementation coupling). The blog is running on Ruby on Rails, Typo engine, running on port 4000 internally. Our firewall blocks outside access to this port, so we use Apache to proxy it for us (it rewrites any URL&amp;#8217;s on the way out to be the correct external address). We also use it as an SSL gateway, so we setup all the certificates in just one place.&lt;/p&gt;

&lt;p&gt;All configuration in Apache is done in the http.conf file. Here is the setup I am using for the blogs subdomain with notes of what is going on. There is also a similar &lt;code&gt;VirtualHost&lt;/code&gt; setting for 443 (SSL Access), but doesn&amp;#8217;t really add much by posting it here. I will give a quick summary of what is going on here, but full details can be found on the excellent &lt;a href="http://httpd.apache.org/docs/"&gt;Apache documentation&lt;/a&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Concept First blog
&amp;lt;VirtualHost *:80&amp;gt;
  ServerName blogs.conceptfirst.com
  DocumentRoot "e:/Blogs/www"
  ErrorLog "e:/blogs/logs/error.log"
  CustomLog e:/blogs/logs/access.log common
  DirectoryIndex index.html
  &amp;lt;Directory "e:/Blogs/www"&amp;gt;
    Options none
    AllowOverride None
    Order allow,deny
    Allow from all
  &amp;lt;/Directory&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Tell apache which virtual host name this is for, where static files are, where to put log files, etc.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  RewriteEngine on
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;RewriteEngine on tells apache to apply the following rules. Apache can handle redirects and proxying using &lt;code&gt;Redirect&lt;/code&gt; and &lt;code&gt;ProxyPass&lt;/code&gt; directives, but I had issues with the order things were being done in, so used rewrite rules for it all. Rewrite rules are more flexible and powerful than the individual Redirect or ProxyPass directives, so its worth understanding their capabilities in full.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  RewriteLogLevel 0
  # RewriteLog "e:/rewrite.log"
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If having problems debugging rewrite rules, I&amp;#8217;d recommend just setting up a log file and turning RewriteLogLevel to 9. Turn it off by putting back to 0 when everything is working.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  # Redirect feeds to feedburner unless actually feed burner. Only do main ones
  RewriteCond %{HTTP_USER_AGENT} !FeedBurner  
  RewriteRule /xml/rss20/feed.xml$ http://feeds.feedburner.com/ConceptFirst [R,L]
  RewriteCond %{HTTP_USER_AGENT} !FeedBurner  
  RewriteRule /xml/atom10/feed.xml$ http://feeds.feedburner.com/ConceptFirst [R,L]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is the configuration that tells Apache to redirect all my traffic to feedburner unless its from Feedburner itself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RewriteCond: A condition rule, applies to the next line. It is negated by !&lt;/li&gt;
&lt;li&gt;RewriteRule: A rewriting rule, with a match part (regular expression) and a target
&lt;ul&gt;
&lt;li&gt;[R]: Send a HTTP 302 redirect&lt;/li&gt;
&lt;li&gt;[P]: Do a internal proxy&lt;/li&gt;
&lt;li&gt;[L]: Stop applying rewrite rules after this one&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the first two lines tells Apache (in random syntax pseudo-code): &lt;code&gt;IF (HTTP_USER_AGENT &amp;lt;&amp;gt; 'FeedBurner') AND (URL = '/xml/rss20/feed.xml') THEN SEND_REDIRECT_TO('http://feeds.feedburner.com/ConceptFirst') AND STOP_PROCESSING_RULES&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Feedburner uses the HTTP header USER_AGENT set to FeedBurner so that is how we detect it and don&amp;#8217;t redirect it to itself ! I am only redirecting my main feeds here, the categorised feeds and individual comment feeds are still handled by the blog engine.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  # Make admin secure
  RewriteRule /accounts(.*) https://blogs.conceptfirst.com/accounts$1 [R,L] 
  RewriteRule /admin(.*) https://blogs.conceptfirst.com/admin$1 [R,L]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These two lines use a similar rules to make sure the admin parts of the blog are handled through HTTPS so we don&amp;#8217;t get any cleartext passwords floating around on the net. The $1 at the end of the redirect is the matched data from (.*) in the regular expression. So if the URL is /admin/login, $1 will be /login.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  # Proxy to mongrel for everything but the media directory
  RewriteCond $1 !^Media/(.*)
  RewriteRule /(.*) http://localhost:4000/$1 [P,L]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is the rule that actually gets the blog pages from the internal ruby on rails app. The condition rule is checking the URL match to make sure it is not part of the Media subdirectory (this is a static directory that apache serves up, it contains images for blog entries, etc). Everything else gets passed to the server running on 4000.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  ExpiresActive On
  ExpiresByType text/html "now plus 1 day"
  ExpiresByType image/gif "now plus 1 week"
  ExpiresByType image/jpeg "now plus 1 week"
  ExpiresByType text/css "now plus 1 week"
  ExpiresByType image/png "now plus 1 week"
  ExpiresByType image/jpg "now plus 1 week"
&amp;lt;/VirtualHost&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Expires stuff is the Apache way of setting the HTTP expires headers when sending responses. I&amp;#8217;ve set images to be cached on the client for a week to help reduce bandwidth and load on the server.&lt;/p&gt;

&lt;p&gt;I greatly recommend Apache, its very easy to setup, and very powerful (although it does test your knowledge of regular expressions :-), we&amp;#8217;ve used it to proxy Ruby On Rails, Cold Fusion, IIS and home grown web servers, and its great for rewriting URLs to make them technology agnostic and nice and RESTful.&lt;/p&gt;</description>
      <pubDate>Tue, 05 Jun 2007 18:56:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:de45467d-34eb-4574-9269-8f2375df8e3d</guid>
      <author>David Glassborow</author>
      <link>http://blogs.conceptfirst.com/articles/2007/06/05/feedburner-and-apache-redirects</link>
      <category>Web Development</category>
      <category>Apache</category>
    </item>
    <item>
      <title>SQL Server Spatial</title>
      <description>&lt;p&gt;SQL Server 2000 has always been one of my favorite bits of software. I have written various software that runs on top of MSDE and always been really pleased with it.&lt;/p&gt;

&lt;p&gt;Having spent a great deal of time recently working woth Oracle 10, I have really noticed how much easier administration is with SQL Server. I have also had lots of issues with Oracle drivers (in particular where CLOB fields are used).&lt;/p&gt;

&lt;p&gt;I have to admit to being rather unwealmed by SQL Server 2005. I&amp;#8217;m not a great fan of stored procedures (I belive the logic should be in a middle tier) and certainly not of running .net code inside a DB server.&lt;/p&gt;

&lt;p&gt;One thing I was looking forward to was the addition of spatial algorithms to SQL Server.&lt;/p&gt;

&lt;p&gt;Wikipedia notes that spatial data is planned for the next version, but for the mean time I will be using Oracle for my clients, and personally Postgres.&lt;/p&gt;

&lt;p&gt;I think Microsoft really missed out here. More and more of my clients need to store spatial data, I would love to use SQL Server, but my money has to goes to Oracle or an open source database.&lt;/p&gt;

&lt;p&gt;Pull your finger out Microsoft and make sure 2008 is spatial enabled !&lt;/p&gt;</description>
      <pubDate>Tue, 05 Jun 2007 15:26:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:72fdebd9-35a9-4a22-bb97-98bf6b826f07</guid>
      <author>David Glassborow</author>
      <link>http://blogs.conceptfirst.com/articles/2007/06/05/sql-server-spatial</link>
      <category>Web Development</category>
    </item>
    <item>
      <title>Comments on my Weblog, Firebug</title>
      <description>&lt;p&gt;I&amp;#8217;ve been having a lot of problems with comments on this blog taking forever to post, being silently rejected, etc.  After lots of messing around, I found it to be a combination of a) A theme that doesn&amp;#8217;t handle problems with comments being locked and b) the built in anti spam protection making comments take 30 seconds rather than half a second to post.&lt;/p&gt;

&lt;p&gt;I never want to calculate how much of my life I&amp;#8217;ve lost to spam or spam filters, doesn&amp;#8217;t bare thinking about.&lt;/p&gt;

&lt;p&gt;Apologies to anybody who tried to post a comment.&lt;/p&gt;

&lt;p&gt;Whilst doing this, I used a great new feature of the absolutely essential web development plug in for Firefox, &lt;a href="http://getfirebug.com/"&gt;Firebug&lt;/a&gt;. One of the new views, network activity monitoring, shows all the files loaded (the contents of the request and response) and how long overall the process took.&lt;/p&gt;

&lt;p&gt;Absolutely essential for debugging AJAX code, but also brilliant to see where you can speed up your page load times.  The following shows me debugging some time issues on one of a site using &lt;a href="http://dev.live.com/virtualearth/default.aspx?app=virtual_earth"&gt;Virtual Earth&lt;/a&gt;. Watching some of the files load from Microsoft&amp;#8217;s site, and take 10 seconds, suggested I make key files local. This massively reduces the load times, and makes the whole site feel much nicer.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://blogs.conceptfirst.com/Media/firebug.png" alt="Firebug"/&gt;&lt;/p&gt;

&lt;p&gt;I cannot recommend Firebug strongly enough !&lt;/p&gt;</description>
      <pubDate>Thu, 01 Feb 2007 20:28:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:25da348b-cad2-40c0-ad69-bba25d893f96</guid>
      <author>David Glassborow</author>
      <link>http://blogs.conceptfirst.com/articles/2007/02/01/comments-on-my-weblog-firebug</link>
      <category>Web Development</category>
      <category>VirtualEarth</category>
      <category>Firefox</category>
      <category>Typo</category>
    </item>
    <item>
      <title>Useful Delphi code</title>
      <description>&lt;p&gt;Just realised I haven&amp;#8217;t written a blog post for 2.5 months, and I&amp;#8217;ve just got back from a lunchtime surfing session, so I&amp;#8217;m not really in the mood for real work.
I thought I&amp;#8217;d post some of my basic Delphi library code I use time and again in the hope it is of some use to other Delphi developers. Do what ever you want with it, I don&amp;#8217;t guarantee its without bugs, but most of it has been used in production code for quite a long time.&lt;/p&gt;

&lt;p&gt;The full file with all the implementation can be found here: &lt;a href="http://blogs.conceptfirst.com/Media/blog.pas"&gt;Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The following are useful for conditional logic for development vs production code, debugging, etc.:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;procedure BreakpointInIDE;
function CurrentExceptionMessage: string;
function IsRunningUnderIDE: boolean; inline;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The following function is useful for preventing the unsitely errors that can occur as a Delphi Application throws Exceptions as it shuts down. While ideally this should never happen, previous exceptions can leave forms in a have constructed state, and the TApplication&amp;#8217;s attempt to clean up them then causes horrible dialogs frightening users. Even the IDE has been known to do this. The code hooks the various Exception raised pointed in the RTL to silently ignore the errors. If running inside the IDE, it will also post a message to the event log, and cause the IDE to breakpoint to highlight there is an issue.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;procedure HookShutdownToHideExceptions;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href="https://blogs.conceptfirst.com/articles/2006/05/08/class-helpers-good-or-bad"&gt;Helper Classes&lt;/a&gt; for TList, TStream and TStrings. In particular I use the ID accessors of TStrings a lot when putting records into UI elements. Makes it very easy to look up the ID of the record in a combo box, for example. It uses the Object field in a list item to store the ID. Helpers require at least Delphi 2006.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;TListHelper = class helper for TList
  procedure FreeSelfAndContainedObjects;
end;

TStringsHelper = class helper for TStrings
private
  function GetID(Index: Integer): ID;
  procedure SetID(Index: Integer; const Value: ID);
  function GetDescFromID(ID: ID): string;
  function GetIDFromDesc(const Desc: string): ID;
  function GetObjectByString(text: string): TObject;
public
  function AddPair(const Name, Value: string): integer;
  function AddID(const Desc: string; PrimaryKey: ID): Integer;
  function AddObj( const Name, Value: string; Obj: TObject ): Integer;
  function ContainsKey( const Key: string ): boolean;
  function ContainsString( const Text: string ): boolean;
  function ContainsValue( const Value: string ): boolean;
  procedure FreeSelfAndContainedObjects;
  function IndexOfID( ID: ID ): integer;
  property DescFromID[ID:ID]: string read GetDescFromID;
  property IDFromDesc[const Desc: string]: ID read GetIDFromDesc;
  property IDs[Index: Integer]: ID read GetID write SetID;
  property ObjectByString[ text: string ]: TObject read GetObjectByString;
end;

TStreamHelper = class helper for TStream
public
  function AsString: string;
  function RewindToStart: TStream;                                      // Returns self to allow easy chaining of calls
  procedure WriteString( const Text: string );
  procedure WriteStringAndBreak( const Text: string );
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The following two classes are 2 example simple container objects based on records rather than classes. The nice thing is they don&amp;#8217;t have to be memory managed like classes do, the compiler will handle all of that for you. They are not as fully featured as string lists, but are useful for simple tasks. They are also reasonabilly efficient, as the dyanmic arrays they use are copy by reference. The only thing to remember is to use the Clone method if you actually want a whole new copy of the data. I have about 4 or 5 different variants of these to store ID =&gt; Name, Name =&gt; Variant, etc, but you get the idea.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;TSimpleStringList = record
private
  FItems: array of string;
  function  GetCount: integer; inline;
  function  GetItem(index: integer): string;
  procedure SetItem(index: integer; const Value: string);
public
  function  Add(const line: string): integer;
  procedure Clear;
  function  Clone: TSimpleStringList;
  function  Contains(const s: string): boolean;
  function  IndexOf(const s: string): integer;
  function  IsMissing(const s: string): boolean;
  property  Count: integer read GetCount;
  property  Items[index: integer]: string read GetItem write SetItem; default;
end;

TSimpleStringListHelper = record helper for TSimpleStringList
public
  function AsNewStringList: TStringList;
  function StringsCommaSeperated: string;
end;

TSimpleDictionary = record
private
  FKeys: array of string;
  FValues: array of string;
  function GetCount: integer; inline;
  function GetKey(index: integer): string;
  function GetValue(const Key: string): string;
  function GetValueByIndex(index: integer): string;
  procedure SetKey(index: integer; const Value: string);
  procedure SetValue(const Key, Value: string);
  procedure SetValueByIndex(index: integer; const Value: string);
public
  function  Add(const Key, Value: string): integer;
  function AsNewStringList: TStringList;
  procedure AddStrings(Strings: TStrings);
  procedure Clear;
  function Clone: TSimpleDictionary;
  function ContainsKey(const Key: string): boolean;
  function IndexOfKey(const Key: string): integer;
  function IndexOfValue(const Value: string): integer;
  property Count: integer read GetCount;
  property Keys[index: integer]: string read GetKey write SetKey;
  property Values[const Name: string]: string read GetValue write SetValue; default;
  property ValueFromIndex[ index: integer ]: string read GetValueByIndex write SetValueByIndex;
end;

TSimpleDictionaryHelper = record helper for TSimpleDictionary
public
  function KeysCommaSeperated: string;
  function SemicolonDelimitedString: string;
  procedure LoadFromSemiColonDelimitedString( Text: string );
  procedure LoadFromStringList( StringList: TStringList );
  function Text: string;
  function ValueOrDefault( const Key: string; const Default: string ): string;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here is a simple subclass of Exception to allow Assertions on any Exception derived object. I tried to do this via a helper class, but the &amp;#8216;self&amp;#8217; object in a class level helper called on a class does not appear to be a valid reference, so I couldn&amp;#8217;t find a way to get it to work. Looking through the code to Indy inspired this approach to using Exceptions, I never use the raise statement anymore.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;EBase = class( Exception )
  class procedure Assert( Test: boolean; const Msg: string );
  class procedure Throw( const Msg: string ); virtual;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The last function is &lt;code&gt;function ShowHourglass: IUnknown;&lt;/code&gt; This can be called in a UI function to make a form show a cursor, and when the function exits (normally or after an exception) be sure the cursor is returned to its previous state. The return value (IUnknwon) does not need to be stored, behind the scenes Delphi will store it anyway and make sure the compiler puts a hidden Try &amp;#8230; Finally in at the end to make sure it is cleaned up. The cleaning up of the interface is what we use to reset the cursor.&lt;/p&gt;

&lt;p&gt;Anyway hopefully this of some use to somebody. Happy New Year to everyone, here&amp;#8217;s to a good year from CodeGear.&lt;/p&gt;</description>
      <pubDate>Thu, 04 Jan 2007 11:12:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:a1823a9e-6971-499b-bb8c-79206fcf97fb</guid>
      <author>David Glassborow</author>
      <link>http://blogs.conceptfirst.com/articles/2007/01/04/useful-delphi-code</link>
      <category>Delphi</category>
    </item>
    <item>
      <title>ATOM / RSS and Comments</title>
      <description>&lt;p&gt;After all the effort of changing Weblogs, I&amp;#8217;ve realised that Typo &amp;#8216;out of the box&amp;#8217; does not support comments added to its syndication streams. I&amp;#8217;ve hacked around in the code and managed to get something working. Rails XML helpers make this stuff pretty easy.&lt;/p&gt;

&lt;p&gt;Weirdly there does not seem to be an agreed format for doing comments in ATOM at all, where as RSS has various different comment tags. I&amp;#8217;ve used &lt;em&gt;wfs:commentsRss&lt;/em&gt; and &lt;em&gt;slash:comments&lt;/em&gt; nodes in both formats, with the &lt;em&gt;comments&lt;/em&gt; just in Rss 2. The &lt;a href="http://feedvalidator.org/"&gt;Feed Validator&lt;/a&gt; seems happy.&lt;/p&gt;

&lt;p&gt;Anyway the following work well with my aggregator, &lt;a href="http://www.rssbandit.org/"&gt;Rss Bandit&lt;/a&gt;, as well as IE 7. If anyone has any problems with other aggregators, can you let me know. Thanks.&lt;/p&gt;

&lt;p&gt;Local feeds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://blogs.conceptfirst.com/xml/rss20/feed.xml"&gt;Rss 2.0&lt;/a&gt; (all)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.conceptfirst.com/xml/rss20/category/delphi/feed.xml"&gt;Rss 2.0&lt;/a&gt; (Just Delphi articles)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.conceptfirst.com/xml/atom10/feed.xml"&gt;Atom 1.0&lt;/a&gt; (all)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blogs.conceptfirst.com/xml/atom10/category/delphi/feed.xml"&gt;Atom 1.0&lt;/a&gt; (Just Delphi articles)&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Tue, 17 Oct 2006 10:00:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:da6d2df4-56b5-4baa-a43c-1a8983637386</guid>
      <author>David Glassborow</author>
      <link>http://blogs.conceptfirst.com/articles/2006/10/17/atom-rss-and-comments</link>
      <category>Web Development</category>
      <category>Delphi</category>
      <category>Typo</category>
      <trackback:ping>http://blogs.conceptfirst.com/articles/trackback/8</trackback:ping>
    </item>
    <item>
      <title>Devco Wish List</title>
      <description>&lt;p&gt;This is my wishlist for Delphi when the new company running it is planning the next version.  My requests are not large things (except maybe the last one), and are in order of priority.&lt;/p&gt;

&lt;p&gt;Summary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Language construct: return&lt;/li&gt;
&lt;li&gt;. operators on basic types&lt;/li&gt;
&lt;li&gt;Include all source code (midas, dbExpress)&lt;/li&gt;
&lt;li&gt;Ruby&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Return&lt;/h1&gt;

&lt;p&gt;Readable concise code is something we all try to acheive when coding.  I really miss the &amp;#8216;return&amp;#8217; statement from C, because it makes code more concise. I&amp;#8217;m bored of writing:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if blah then
begin
  Result := -1;
  exit;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I want to be able to write just&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if blah then Return(-1);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Shorter, and the intention of the statement is much more obvious.
I would imagine it would be fairly easy to add to Delphi as a pseudo function (like &amp;#8216;continue&amp;#8217; and &amp;#8216;break&amp;#8217;).&lt;/p&gt;

&lt;h1&gt;Dot Opeators&lt;/h1&gt;

&lt;p&gt;I&amp;#8217;ve been doing a fair amount of Ruby recently, as well as some C#. Having the dot operator available on all basic types is lovely, and makes code much more readable. I&amp;#8217;d much prefer&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;address.length
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;over&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;length(address)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Less visual clutter, much more OO.
Even if behind the scenes is just syntactic sugar to call the length procedure, that would be a huge win for the readability of Object Pascal in these Object Orientated times.&lt;/p&gt;

&lt;h1&gt;Source Code&lt;/h1&gt;

&lt;p&gt;At Concept First we currently use the following third party libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Devexpress: Quantim Grid, Quantum Bars&lt;/li&gt;
&lt;li&gt;TChart charting component&lt;/li&gt;
&lt;li&gt;CoreLabs dbExpress driver for SQL Server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will &lt;em&gt;only&lt;/em&gt; buy a component if it comes with full source code.
Why ?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fixing bugs when we find them&lt;/li&gt;
&lt;li&gt;Adding new features&lt;/li&gt;
&lt;li&gt;Tracking their changes under source control&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We&amp;#8217;ve made changes to all of the components we use, and I have all their source code under Subversion, so I can see what they have changed and see what possible impact it could have on my code.&lt;/p&gt;

&lt;p&gt;One of the great strengths of Delphi has always been that the VCL comes with full sources.  The two exceptions are the TClientDataset (midaslib.pas) and the dbExpress drivers.  Its very annoying not to be able to debug into their code.  I know Midas is in C++, but I have the full BDS with C++ support so that is not an issue. I use TClientDataset all over the place, and there are a few easy extensions that could make life much easier.&lt;/p&gt;

&lt;h1&gt;Ruby&lt;/h1&gt;

&lt;p&gt;As mentioned before, i&amp;#8217;ve been playing around with Ruby and Ruby on Rails recently, and the first thing I had to do with is knock up a quick syntax highlighting editor using the SynEdit control. Having Ruby (and in an ideal world Javascript) in Delphi, with code complete, would be great, something I would be happy to pay for). Web development seems to be the way of the future, and having a nice IDE supporting Ruby could be a big win for Delphi / Devco.&lt;/p&gt;

&lt;h1&gt;Summary&lt;/h1&gt;

&lt;p&gt;I don&amp;#8217;t know if my use of Delphi is similar to the majority of other users, but my priorities from it are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast to develop in&lt;/li&gt;
&lt;li&gt;Looks nice (generally easy thanks to DevExpress)&lt;/li&gt;
&lt;li&gt;Source code so I don&amp;#8217;t get held up by bugs&lt;/li&gt;
&lt;li&gt;Reliable and fast IDE&lt;/li&gt;
&lt;li&gt;Small self contained EXEs, without frameworks to install.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I use delphi for Win32 client applications.  I don&amp;#8217;t use it for web applications. I now use either Ruby on Rails ( my personal choice ) or Cold Fusion ( trusted in Enterprise environments ).&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m not interested in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Delphi.net&lt;/li&gt;
&lt;li&gt;64 Bit support&lt;/li&gt;
&lt;li&gt;Mobile development (be nice if Delphi supported, but such a small % of our work I&amp;#8217;d be happy enough to use Visual Studio).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anyway if I could have the requested changes made by the end of next week, that would be great DevCo ;-)&lt;/p&gt;

&lt;p&gt;Pretty Please ?&lt;/p&gt;</description>
      <pubDate>Mon, 16 Oct 2006 13:26:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:a4f5e973-7b25-4b62-ac4c-693bc2169ddd</guid>
      <author>David Glassborow</author>
      <link>http://blogs.conceptfirst.com/articles/2006/10/16/devco-wish-list</link>
      <category>Delphi</category>
      <trackback:ping>http://blogs.conceptfirst.com/articles/trackback/7</trackback:ping>
    </item>
    <item>
      <title>Weblog moved to Typo</title>
      <description>&lt;h1&gt;What&lt;/h1&gt;

&lt;p&gt;I&amp;#8217;ve moved my blog away from Blogger.com and on to a &lt;a href="http://typosphere.org"&gt;Typo&lt;/a&gt; installation hosted ourselves. Typo is a weblog application that runs on top of &lt;a href="http://www.rubyonrails.org/"&gt;Ruby On Rails&lt;/a&gt;, the latest posterchild of the open source community. I chose a rails based blog because I&amp;#8217;ve been doing work with rails recently, I understand it, and I really like it (I&amp;#8217;m half way through writing up an entry about why I like it).&lt;/p&gt;

&lt;h1&gt;Why&lt;/h1&gt;

&lt;p&gt;The main reason is that blogger feed does not include comments people make. I personally read most blogs in an aggregator, and without comments being included, its only one half of the conversation.&lt;/p&gt;

&lt;p&gt;For the last year we have been working on a product for a client that uses &lt;a href="http://en.wikipedia.org/wiki/Queuing_theory"&gt;Queuing Theory&lt;/a&gt; to model how servers operate under load, an area known as &amp;#8216;Capacity Management&amp;#8217;. Performance agents log ongoing behaviour on the server, and then the results are plugged into various mathmatical formulae that show how the server will work if your email doubles, your websites have 10 times as much load, etc.&lt;/p&gt;

&lt;p&gt;Here at Concept First we have a data centre hosted server that handles email, ftp, and various client&amp;#8217;s websites.  In the spirit of &amp;#8216;dog-fooding&amp;#8217;, I&amp;#8217;ve been running monitoring software on our hosted server, and building models of its spare capacity.&lt;/p&gt;

&lt;p&gt;The results are: we have stupid amounts of spare capacity. The server is a 1U rack mounted server from Dell, 1G of RAM, mirrored RAID disks, a single 2Ghz processor.  A fairly low spec machine these days, we bought it about 3 years ago.  And basically it never does anything. I&amp;#8217;ve never seen the CPU loads rise about 5%, same for disk utilisation.  Modern hardware is so fast, that a few web requests and a bit of email are not not giving it much of a workout.&lt;/p&gt;

&lt;p&gt;For that reason, I&amp;#8217;m happy to run an interpreted language framework for this blog, because we really do have CPU cycles to waste, and I don&amp;#8217;t have time to waste.  Having a Rails app running on my server full time will also allow me to understand if it&amp;#8217;s stable under Windows.&lt;/p&gt;

&lt;h1&gt;How&lt;/h1&gt;

&lt;h2&gt;Style&lt;/h2&gt;

&lt;p&gt;Typo is easy to install if you&amp;#8217;ve worked with Rails, its just a load of files in a directory. You can choose from 2 built in themes or download lots of others. I&amp;#8217;ve taken one of the built in ones and just changed it to make use of the full screen.  &lt;/p&gt;

&lt;p&gt;I &lt;em&gt;hate&lt;/em&gt; fixed width websites.  What is the point of my lovely 1920 wide screen laptop if the site is only 500 pixels wide !!  Adjusting to the display has always been a key strength of HTML.  Too many people are still designing for the web as though it was a piece of paper ! &lt;/p&gt;

&lt;p&gt;However the move away from fixed width has caused a small bug to display in IE 6, when using the search box in the top right hand corner.  There is flickering as the AJAX call is done.  However the issue does not occur in IE 7 or Firefox so it is no doubt one of the boatload of IE 6 rendering bugs, so i&amp;#8217;m not going to pursuit it. Life is too short.&lt;/p&gt;

&lt;h2&gt;Database&lt;/h2&gt;

&lt;p&gt;Typo supports just about every database, but I&amp;#8217;ve just left it running on a simple &lt;a href="http://en.wikipedia.org/wiki/SQLlite"&gt;SQLite&lt;/a&gt; database. Typo caches everything so i don&amp;#8217;t really need the hassle of putting it in a real RDBMS.  The server is already running SQL Server, MySQL and Oracle XE. Maintaining what apps use what databases, where, is a bit of a headache. A file based database is just easier to manage if you can get away with it.&lt;/p&gt;

&lt;h2&gt;Webserver&lt;/h2&gt;

&lt;p&gt;Our server is running, or has run in the past, various different websites running on lots of different technologies: ASP, Websnap, Coldfusion, Zope, Php, Perl. To manage all this, we use Apache 2 running on Windows Server 2000. Apache has been good to us.  Its very flexible, well documented, secure, and scalable. It is our Internet facing webserver. It handles SSL, compression (via mod_deflate) and virtual hosting.&lt;/p&gt;

&lt;p&gt;To connect our hosted sites up to the Apache &amp;#8216;gateway&amp;#8217; we&amp;#8217;ve tried various things. We&amp;#8217;ve tried Apache modules, ISAPI, &lt;a href="http://www.fastcgi.com/"&gt;FastCGI&lt;/a&gt;, SCGI, mod_php.&lt;/p&gt;

&lt;p&gt;Apache modules / ISAPI: Nice and fast, but too tightly bound.  When Apache versions change a recompile is required.  Restart the server and you lose server state, like current sessions. Bugs can jeapodise the server stability.&lt;/p&gt;

&lt;p&gt;FastCGI: Works well, we have various websnap sites running over FastCGI. However the protocol is complex, binary, and the whole FastCGI protocol is not actively developed any longer.&lt;/p&gt;

&lt;p&gt;SCGI: A simpler version of FastCGI, I&amp;#8217;ve run a couple of Rails sites on SCGI.  The protocol is easier to understand, but its another set of config to learn, and not all technologies support SCGI.&lt;/p&gt;

&lt;p&gt;With this in mind, we now use simple HTTP proxing.  Each different application runs its own webserver on an internal port number, the firewall preventing any access to the outside world.  Apache then uses its mod_proxy settings to pass the request to the applications webserver, before passing it back to the web browser.&lt;/p&gt;

&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Debugging is simple. Just fire up a copy of &lt;a href="http://www.fiddlertool.com/fiddler/"&gt;Fiddler&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;All applications support SSL, Apache handles it.&lt;/li&gt;
&lt;li&gt;All applications support compression, Apache handles it.&lt;/li&gt;
&lt;li&gt;All application logged in same format, I can use the same tools.&lt;/li&gt;
&lt;li&gt;Apache can use its redirect rules to enforce my rules (e.g. admin in Typo must be secure).&lt;/li&gt;
&lt;li&gt;Upgrading any individual application has no effect on the others, everything is loosly coupled.&lt;/li&gt;
&lt;li&gt;Most importantly: One set of syntax for me to remember.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It all works beautifully.  It&amp;#8217;s happily proxing to Rails, to web services exposed in Indy components. It&amp;#8217;s fast, and it &amp;#8216;Just Works&amp;#8217;, not often you get to say that in the world of computing &amp;#8230;&lt;/p&gt;</description>
      <pubDate>Sat, 14 Oct 2006 11:37:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:05d3530e-8760-474c-a37a-82bd90c11b01</guid>
      <author>David Glassborow</author>
      <link>http://blogs.conceptfirst.com/articles/2006/10/14/weblog-moved-to-typo</link>
      <category>Web Development</category>
      <category>Apache</category>
      <category>Typo</category>
      <trackback:ping>http://blogs.conceptfirst.com/articles/trackback/6</trackback:ping>
    </item>
    <item>
      <title>GIS</title>
      <description>&lt;p&gt;I&amp;#8217;m writing this posting for two reasons. Firstly my company is currently engaged in a project with a client about getting
more of their data onto their intranet based mapping tool, so I&amp;#8217;ve spent the last 3 days researching and getting back up to speed
on the industry.&lt;/p&gt;

&lt;p&gt;Secondly my brother has just got a new job working as sales manager for a company providing GIS data, so I thought an introduction
and overview of the subject might be of use to him. Apologises if I get too technical Mike.&lt;/p&gt;

&lt;h1&gt;Geographic Information Systems&lt;/h1&gt;

&lt;p&gt;A GIS is a system the stores and displays maps electronically. Its a smart tool that helps us understand the world around us better,
to get our work done more efficiently.
I&amp;#8217;ve been interested in GIS since one of my first jobs where I was in charge of writing a routing and optimising algorithm for
solving a variant of the &lt;a href="http://en.wikipedia.org/wiki/Traveling_salesman_problem"&gt;Travelling Sales Problem&lt;/a&gt;. Essentially our product was in charge of figuring out routes for workman
to get their work down in the most efficient way possible, and send them routes on their mobile devices so they didn&amp;#8217;t get lost.
It was really interesting work, we worked with providers of GIS data about the road network, and with the UK goverment for access
to electronic versions of their maps.&lt;/p&gt;

&lt;p&gt;I think part of my interest also comes from travelling. When I first go to a new city, I&amp;#8217;m always keen to find a map, to give
me a feel of the layout. I always choose Lonely Planet over Rough Guide, because their maps are better. It was very strange when I
was in Guyana in the Jungle, the only maps we had were from satelite images taken over 10 years ago, at a very low resolution. 
Most of the time we only have a vague idea of where we were at any time. Rivercourses flood, move, the tree cover prevents
identification of key features. It made me realise how much we take accuracte maps for granted.&lt;/p&gt;

&lt;p&gt;GIS is everywhere at the moment. Tom Tom are advertising their navigation products on TV. Google Local can show me a map of my local
city in the time it takes to click a mouse, and Google Earth can let me zoom in from space to see my parents house, the roof of my
dad&amp;#8217;s landrover. NASA can let me look at the surface of Venus.&lt;/p&gt;

&lt;h2&gt;Raster and Vector&lt;/h2&gt;

&lt;p&gt;The most important division in GIS to understand is the different between Raster and Vector information. Raster information is
pictures, its pixels that show us what our cities look like from space. Its the images that digital cameras give us. Its resolution 
dependant. Vector information is mathmatical in nature, its descriptions of things in terms of lines, circles, polygons.&lt;/p&gt;

&lt;p&gt;Google earth is predominaly raster based, as you zoom in loads in images with more detail.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://blogs.conceptfirst.com/Media/GoogleEarth.jpg" alt="Google Earth"/&gt;&lt;/p&gt;

&lt;p&gt;Google Local is vector based, it shows you your local highstreet as a series of straight lines, it shows you the nearby river as a polygon.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://blogs.conceptfirst.com/Media/GoogleLocal.jpg" alt="Google Local"/&gt;&lt;/p&gt;

&lt;p&gt;The real power comes when we use raster and vector together. When we turn on the country boundaries in NASA&amp;#8217;s &lt;a href="http://worldwind.arc.nasa.gov/"&gt;World Wind&lt;/a&gt;
we seem them overlayed over the raster images of earth:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://blogs.conceptfirst.com/Media/NasaWindWalker.jpg" alt="WindWalker"/&gt;&lt;/p&gt;

&lt;p&gt;Raster information is an approximation to the real world, its pictures of the world. Vectors are mathmatical, they are &amp;#8216;idealised&amp;#8217;
versions of the world. The mathamtical nature of vectors allow us to use maths to answer questions like: &amp;#8220;How many roads are there
within 2 miles of the river ?&amp;#8221;. Or this more relevant example &amp;#8220;Show me all the pubs within 2 miles of where I live&amp;#8221; in Mappoint 2004:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://blogs.conceptfirst.com/Media/Mappoint.jpg" alt="Mappoint"/&gt;&lt;/p&gt;

&lt;p&gt;Raster examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pictures of landscapes, from space or from aircraft&lt;/li&gt;
&lt;li&gt;Pictures of clouds&lt;/li&gt;
&lt;li&gt;Infrared pictures showing heat usage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vector examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Countries, Regions, Postal boundaries&lt;/li&gt;
&lt;li&gt;Streets, Motorways, Garages&lt;/li&gt;
&lt;li&gt;Wind speeds, wave heights&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Organisations&lt;/h1&gt;

&lt;h2&gt;OpenGIS&lt;/h2&gt;

&lt;p&gt;The main organisation dealing with GIS standards appears to be the &amp;#8220;Open Geospatial Consortium&amp;#8221;, a group of 300 organisation 
worldwide. It has prepared various specifications for open standards:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GML: A geographical data format based on XML&lt;/li&gt;
&lt;li&gt;Simple Features (SFSQL): A standard way to store data within standard SQL Databases&lt;/li&gt;
&lt;li&gt;Various web interfaces for providing both vector and raster information in agreed formats (GML)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Companies&lt;/h2&gt;

&lt;p&gt;The leaders in the industry for GIS software seem to be &lt;a href="http://www.esri.com/"&gt;ESRI&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/MapInfo"&gt;Mapinfo&lt;/a&gt; and &lt;a href="http://intergraph.com/"&gt;Integraph&lt;/a&gt;.
The two largest data provders are &lt;a href="http://www.navteq.com/"&gt;NAVTEQ&lt;/a&gt;, used by Google maps, and &lt;a href="http://www.teleatlas.com/"&gt;TeleAtlas&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;Representation&lt;/h1&gt;

&lt;p&gt;An important thing to understand in GIS is that there is no universal &amp;#8216;best&amp;#8217; representation for coordinates on Earth. The earth
is not an exact sphere, its not flat, so various different schemes have been invented. Which is used is, as ever, is dependant 
on what your trying to achieve.&lt;/p&gt;

&lt;h2&gt;Longitude and Latitude&lt;/h2&gt;

&lt;p&gt;The standard way of representing points on the earth is obviously using long and lat. Longitude is the lines from the North Pole to
the South Pole, with 0 degrees going through Greenwich, London. Latitude is the lines around the &amp;#8216;waist&amp;#8217; of the earth, with 0 degrees
at the equator, + 90 degrees being the north pole.
&lt;img src="http://blogs.conceptfirst.com/Media/LongLat.png" alt="LongLat"/&gt;&lt;/p&gt;

&lt;p&gt;Longitude and Latitude are measured against a known &lt;em&gt;datum&lt;/em&gt;. This is the reference model used, i.e. the mathematical figures used
for calculating the best fit shape of the Earth. The most common currently in use is the WGS84 datum (WGS stands for &amp;#8216;World 
Geodetic System&amp;#8217;). It is possible to convert from one datum to another, but this can require some quite complex mathematics.&lt;/p&gt;

&lt;h2&gt;GPS&lt;/h2&gt;

&lt;p&gt;Global Positioning System is where alot of GIS data is coming from. It is a set of satelites flying through space, transmitting
signals allowing the calculation of very accurate position. GPS figures are long/lat figures based on the WGS84 datum.&lt;/p&gt;

&lt;h2&gt;Grid References&lt;/h2&gt;

&lt;p&gt;Rather than capture coordinates as spherical coordinates (like long/lat), coordinates can be stored as a reference on a grid.
As the Earth is obviously not flat, this is an approximation, but can be easier to deal with when mapping smaller areas. The UK uses
a grid reference system for its &amp;#8216;Ordance Survey&amp;#8217; (OS) maps. In this coordinate system, points are measured in Eastings and Northings.
This grid is based on a different datum, OSGB36, based on a slightly different elipsoid representation of the Earth. The &amp;#8216;Helmert&amp;#8217;
datum transformation can be used to convert to WGS84, but with an approximate error of 7m (depending on location). The image below
shows where the eastings and northings are measured from. The letters in the grids allow another way of specifying location, called
&lt;em&gt;National Grid References&lt;/em&gt; (&lt;a href="http://en.wikipedia.org/wiki/British_national_grid_reference_system"&gt;NGR&lt;/a&gt;s), with further digits specifying easting and northing offsets within each 100km grid square.
More digits give more accuracy or specify a smaller area. An example of an NGR is &amp;#8216;NN 166 712&amp;#8217;. This gives a 100m square area in
Scotland. The good thing about NGS&amp;#8217;s is that they are useful shorthand to give approximate position, or for capturing an &amp;#8216;area&amp;#8217;.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://blogs.conceptfirst.com/Media/OSGridReference.JPG" alt="OS GridRef"/&gt;&lt;/p&gt;

&lt;p&gt;The UK goverment can provide digitial maps of the country in GML, with currently 440 million distinct features taking up 660
Gigabytes of storage. The data is called &lt;a href="http://en.wikipedia.org/wiki/OS_MasterMap"&gt;OS Mastermap&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;Formats&lt;/h1&gt;

&lt;h2&gt;GML and SVG&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Geography_Markup_Language"&gt;GML&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Svg"&gt;SVG&lt;/a&gt; are both XML based standards that are used within GIS. GML stands for &lt;em&gt;Geography Markup Lanaguage&lt;/em&gt;, and
is a format designed to hold geographical features, geometry (vector), raster information, as well as units, coordinate
representation systems, and map styles.&lt;/p&gt;

&lt;p&gt;SVG is actually just a generic format for holding vector graphic information, and stands for &lt;em&gt;Scalable Vector Graphics&lt;/em&gt;.
Its like an Open Standard version of Adobe&amp;#8217;s Flash files, and supports both raster and vector information of any kind, not just
geographic info.
The customer we are doing the GIS work for currently uses SVG for their display of GIS data inside a webbrowser, using
Adobe&amp;#8217;s free SVG plugin for Internet Explorer (note: firefox supports a subset of SVG natively now). SVG has well defined Javascript
bindings so its easy to create interactive displays.&lt;/p&gt;

&lt;p&gt;To me GML seems a better storage format and SVG a better display format.&lt;/p&gt;

&lt;h2&gt;Other&lt;/h2&gt;

&lt;p&gt;There are various file formats in use within the industry. Although the OpenGIS is pushing GML, most data seems to be available
in either ESRI&amp;#8217;s shape format, or Mapinfo&amp;#8217;s standard file format. Both are proprietary, but easy to parse formats that most tools
support.&lt;/p&gt;

&lt;h2&gt;Databases&lt;/h2&gt;

&lt;p&gt;There seems to be a big push to moving &amp;#8216;spatial&amp;#8217; capabilities into databases at the moment. This makes sense as really geometry
is just another attribute of an entity. Moving the geometry into database tables allows this data to be kept alongside other
attributes, as well as allowing databases to carry out geospatial queries.&lt;/p&gt;

&lt;p&gt;The market leader in geospatial databases is &lt;a href="http://www.oracle.com/"&gt;Oracle&lt;/a&gt;. All versions of their database support what they call &lt;em&gt;Locator&lt;/em&gt; features.
This allows the storages of complex vectors into tables, as well as support for complex queries (e.g. find me all objects that
lie within the boundary of this polygon, find me there nearest 5 customers to our store). The top end product also has &lt;em&gt;spatial&lt;/em&gt;
features that allow very complex geometric calculations to be done. The nice thing is that the free Oracle Express (10g at the
moment) supports the locator features. IBM&amp;#8217;s DB2 seems to have some sort of spatial &lt;em&gt;extender&lt;/em&gt; but I couldn&amp;#8217;t find any information 
on the web about it.&lt;/p&gt;

&lt;p&gt;Some of the GIS software companies provide software to help with database storage, like ESRI&amp;#8217;s ArcSDE, but these are just &amp;#8216;layers&amp;#8217;
that sit between software and the database, and are not open formats, tying you into using a particular vendor.&lt;/p&gt;

&lt;p&gt;Two of the open source database engines have recently added spatial features to their engines. Postgres SQL has the addon
&lt;a href="http://postgis.refractions.net/"&gt;PostGIS&lt;/a&gt; that supports the SFSQL specification mentioned above (as does Oracle). &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/spatial-extensions.html"&gt;MySQL&lt;/a&gt; also has spatial extensions based
on the SFSQL spec, but the current version (5.0) seems only to support planar (flat) and not spherical coordinate systems. The
mathematics used for distances, areas, etc. are different for planar and spherical representations.&lt;/p&gt;

&lt;p&gt;It was hoped that Microsoft SQL Server would add some spatial features to the new 2005 release, but this was not the case. There
is however an interesting &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnsql90/html/TblValFuncSQL.asp"&gt;MSDN article&lt;/a&gt; showing how spatial features can be added to SQL Server, but this does not support
open standards (surprise surprise).&lt;/p&gt;

&lt;h2&gt;Spatial Indexes&lt;/h2&gt;

&lt;p&gt;When reading about GIS formats, one of the key issues is how the formats are &amp;#8216;indexed&amp;#8217; to make retrieval efficient. Oracle uses
&lt;em&gt;Helical Hyperspatial Codes&lt;/em&gt; (HHCodes), a data structure developed by the Canadian Hydrograph office. Dispite the fancy name, 
it seems to be a binary tree, dividing each dimension in order. Its designed to support as many dimensions as desired, to an 
arbitray level of detail. The &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnsql90/html/TblValFuncSQL.asp"&gt;MSDN article&lt;/a&gt; discusses the use of &lt;em&gt;Hierarchical Triangular Meshes&lt;/em&gt;, which is a technique of
covering a globe with a mesh of subdivided triangles. These seems work well for spherical mapping, but does not seem as general
case as HHCodes. PostGIS and MySQL seems to use extensions of standard database indexes, rather than specific spatial indexing.&lt;/p&gt;

&lt;h1&gt;Summary&lt;/h1&gt;

&lt;p&gt;The GIS industry is becoming more and more important, as developers I can see us having to deal with spatial information more and
more. If i get time I&amp;#8217;ll try and write an article on how to access SFSQL spatial data from within Delphi. For more information
see &lt;a href="http://en.wikipedia.org/wiki/Category:Geographic_Information_Systems"&gt;Wikipedia&lt;/a&gt;&amp;#8217;s entry.&lt;/p&gt;

&lt;h1&gt;Comments (originally on blogger.com)&lt;/h1&gt;

&lt;p&gt;Paul Ramsey said&amp;#8230;&lt;/p&gt;

&lt;blockquote&gt;
    &lt;blockquote&gt;
        &lt;p&gt;PostGIS and MySQL use R-Tree indexes, which are rather specifically for spatial data (well, any data type which can be 
        decomposed to a range rectangle). So does Oracle Spatial, for that matter. Space-filling curves, which map multi-dimensional 
        data to something sortable into a B-Tree are ways of leveraging non-spatial database technology to be more useful for 
        spatial data. Space-filling technicques tend not to be as balanced as R-Trees, however. The heirarchical grid is the final 
        trick, and can be quite performant, but needs to be carefully tuned to the characteristics of the data, unlike R-Trees which 
        automagically work for data of uneven scales.&lt;/p&gt;
    &lt;/blockquote&gt;
&lt;/blockquote&gt;</description>
      <pubDate>Tue, 23 May 2006 16:09:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:84f09f1b-9cfe-4ede-ba99-7d9afbacc81a</guid>
      <author>David Glassborow</author>
      <link>http://blogs.conceptfirst.com/articles/2006/05/23/gis</link>
      <category>Mapping</category>
      <trackback:ping>http://blogs.conceptfirst.com/articles/trackback/5</trackback:ping>
    </item>
    <item>
      <title>Class RTTI</title>
      <description>&lt;p&gt;This post follows up my &lt;a href="https://blogs.conceptfirst.com/articles/2006/05/11/interface-rtti"&gt;previous&lt;/a&gt; one about RTTI in Delphi, inspired by Hallvard&amp;#8217;s 2 posts &lt;a href="http://hallvards.blogspot.com/2006/04/published-methods_27.html"&gt;here&lt;/a&gt; and 
&lt;a href="http://hallvards.blogspot.com/2006/05/under-hood-of-published-methods.html"&gt;here&lt;/a&gt;, and covers some advanced RTTI features in Delphi that I haven&amp;#8217;t seen mentioned anywhere else.&lt;/p&gt;

&lt;h1&gt;$METHODINFO&lt;/h1&gt;

&lt;p&gt;While playing around with Websnap in Delphi, trying to extend some of the objects available for scripting, I
came across the compiler directive METHODINFO. &lt;/p&gt;

&lt;p&gt;The online documentation says:&lt;/p&gt;

&lt;blockquote&gt;
    &lt;p&gt;The $METHODINFO switch directive is only effective when runtime type information (RTTI) has been turned on with the 
    {$TYPEINFO ON} switch. In the {$TYPEINFO ON} state, the $METHODINFO directive controls the generation of more detailed
    method descriptors in the RTTI for methods in an interface. Though {$TYPEINFO ON} will cause some RTTI to be generated
    for published methods, the level of information is limited. The $METHODINFO directive generates much more detailed 
    (and much larger) RTTI for methods, which describes how the parameters of the method should be passed on the stack and/or in registers.
    There is seldom, if ever, any need for an application to directly use the $METHODINFO compiler switch. The method 
    information adds considerable size to the executable file, and is not recommended for general use.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My &lt;a href="https://blogs.conceptfirst.com/articles/2006/05/11/interface-rtti"&gt;previous&lt;/a&gt; article showed this isn&amp;#8217;t completely accurate, detailed RTTI is available for any Interface which
has $TYPEINFO or $M around it. $METHODINFO seems to affect classes, in particular it will store detailed RTTI information
for not only Published methods, but also Public ones.&lt;/p&gt;

&lt;p&gt;Doing a search for this compiler directive in the delphi win32 source code gives us only 1 instance in WebSnapObjs.pas.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{$METHODINFO ON}
TScriptableObject = class(TObjectDispatch)
private
  FLookupList: TStringList;
  FLookupValues: TInterfaceList;
protected
  FPreferChild: Boolean;
  function DispatchOfName(const AName: string): IDispatch; virtual;
  function FindObject(const AName: string): TObject; virtual;
public
  constructor Create;
  destructor Destroy; override;
  class function DispatchOfObject(const AObject: TObject): IDispatch;
  function GetIDsOfNames(const IID: TGUID; Names: Pointer;
    NameCount: Integer; LocaleID: Integer; DispIDs: Pointer): HRESULT;
    override;
  function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
    Flags: Word; var Params; VarResult: Pointer; ExcepInfo: Pointer;
    ArgErr: Pointer): HRESULT; override;
end;
{$METHODINFO OFF}
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Websnap&lt;/h2&gt;

&lt;p&gt;Websnap is the poor cousin in the web framework world for delphi. Its never had much support, and seems now to be
overshadow by ASP.net and Intraweb. I personally quite like it, although I code my own templates in VBScript or JavaScript
rather than use any of the Design Time webpage design stuff.&lt;/p&gt;

&lt;p&gt;Under the hood, websnap uses the &lt;a href="http://msdn.microsoft.com/scripting/"&gt;ActiveScript&lt;/a&gt; engines provided in Windows. ActiveScript is a scripting host that can support
many different COM based scripting languages, and Windows comes with VBScript and JScript (which is basically JavaScript).
Other ActiveScript lanaguages are avaialbe including &lt;a href="http://www.activestate.com/Products/ActivePython/"&gt;Python&lt;/a&gt; and &lt;a href="http://www.activestate.com/Products/ActivePerl/"&gt;Perl&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The original ASP by Microsoft uses the ActiveScripting engine to do its work. The asp template is turned into a vBScript or
JScript program containing the HTML to output as well as the logic of the page. This is fed into the ActiveScripting engine
and compiled ready for running. The ActiveScripting engine then has &amp;#8216;objects&amp;#8217; added to it so the program can do useful work.
The most obvious one is the Response object, but there are others like the Session object, etc. The program is then run and
the page rendered.&lt;/p&gt;

&lt;p&gt;Websnap pages, at least those using a TPageProducer, use this same process to produce HTML pages. The problem for the Delphi
deisgners was how to link arbitary Delphi objects up to the ActiveScripting engine, which uses late bound IDispatch COM for
communication. The IDispatch interface, one of the main underpining of the COM framework in Windows, uses a single call,
&lt;em&gt;Invoke&lt;/em&gt; for all method calls. This is where $METHODINFO comes it, the rich method RTTI is provided to allow a single procedure
entry, Invoke, to call arbitary Delphi methods.&lt;/p&gt;

&lt;p&gt;The VBScript or Javascript script running in the scripting of the websnap page needs to talk to Delphi objects (e.g. Page,
Session), and it uses this Rich RTTI to acheive this. You can see the websnap objects that are exposed to the script, have a look in
WebSnapObjs.pas, where TResponseObj, TProducerObj, etc.&lt;/p&gt;

&lt;p&gt;The unit ObjAuto contains the code and header for retrieving the RTTI information using the following function:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function GetMethodInfo(Instance: TObject; const MethodName: ShortString): PMethodInfoHeader;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In turn, the base class of TScriptableObject (marked with $METHODINFO) uses the RTTI to find methods, and call them, at run time.&lt;/p&gt;

&lt;h2&gt;ObjAuto.pas&lt;/h2&gt;

&lt;p&gt;This contains the code to search for a method&amp;#8217;s RTTI. Looking at GetMethodInfo, you can see it uses the system.pas vmtMethodTable
offset to get hold the method table for the class. It then uses a search to find the correct entry. It also contains the code that
allows an arbitary call to an object supporting RTTI to jump to the correct routine:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function ObjectInvoke(Instance: TObject; MethodHeader: PMethodInfoHeader;
  const ParamIndexes: array of Integer; const Params: array of Variant): Variant;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see you just pass it parameters and variants, and it packages them into the correct types and does the call. The source
code to this call shows all the complexity of packaging up all the parameters according different conventions, etc. This is ultimately
how VBScript objects call methods on Delphi objects inside Websnap.&lt;/p&gt;

&lt;h2&gt;DetailedRTTI.pas&lt;/h2&gt;

&lt;p&gt;While playing with the metadata, I coded a few &lt;a href="https://blogs.conceptfirst.com/articles/2006/05/08/class-helpers-good-or-bad"&gt;helper classes&lt;/a&gt; to aid exploration. You can download the &lt;a href="http://blogs.conceptfirst.com/Media/DetailedRTTI.pas"&gt;code&lt;/a&gt; if you want to
have somewhere to start. Just calling .RTTIMethodsAsString() on any object to get a list of its methods and their parameters. Its a
bit rough and ready but you&amp;#8217;re welcome to use it for whatever.&lt;/p&gt;

&lt;h1&gt;Summary&lt;/h1&gt;

&lt;p&gt;This article, and the &lt;a href="https://blogs.conceptfirst.com/articles/2006/05/11/interface-rtti"&gt;previous&lt;/a&gt; one have shown that rich metadata for methods is available in Delphi, with supporting routines
for accessing it. Interface metadata allows the VCL to support SOAP, multiple methods multiplexed to a single call. The rich class
metadata allows the VCL to support a single function automatically being routed to other methods, allowing Websnap to
expose objects to COM IDispatch automatically.&lt;/p&gt;

&lt;h1&gt;Comments (originally on blogger.com)&lt;/h1&gt;

&lt;p&gt;Hallvard Vassbotn said&amp;#8230;&lt;/p&gt;

&lt;blockquote&gt;
    &lt;blockquote&gt;
        &lt;p&gt;Great posts, David!&lt;/p&gt;
        
        &lt;p&gt;I reference them &lt;a href="http://hallvards.blogspot.com/2006/05/david-glassborow-on-extended-rtti.html"&gt;here&lt;/a&gt;&lt;/p&gt;
    &lt;/blockquote&gt;
&lt;/blockquote&gt;</description>
      <pubDate>Mon, 22 May 2006 16:09:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:9efce3ba-1da1-4de9-b630-9d71210af4f9</guid>
      <author>David Glassborow</author>
      <link>http://blogs.conceptfirst.com/articles/2006/05/22/class-rtti</link>
      <category>Delphi</category>
      <trackback:ping>http://blogs.conceptfirst.com/articles/trackback/4</trackback:ping>
    </item>
    <item>
      <title>Interface RTTI</title>
      <description>&lt;p&gt;Reading an &lt;a href="http://hallvards.blogspot.com/2006/04/published-methods_27.html"&gt;article&lt;/a&gt; and its &lt;a href="http://hallvards.blogspot.com/2006/05/under-hood-of-published-methods.html"&gt;follow up&lt;/a&gt; by Hallvard about RTTI inspired me to put together a couple of posts about two 
related areas of RTTI in Delphi. In particular one of the comments on Hallvard&amp;#8217;s blog about using this RTTI to call 
objects in some late bound fashion. This post and the next cover some of the advanced RTTI that I haven&amp;#8217;t seen covered
in other places. This post covers some of the possibilities for Interface metadata, and the next one will contain
details about richer &lt;a href="https://blogs.conceptfirst.com/articles/2006/05/22/class-rtti"&gt;class RTTI&lt;/a&gt; for methods.&lt;/p&gt;

&lt;h1&gt;Interface Metadata&lt;/h1&gt;

&lt;p&gt;Delphi actually has richer metadata support for methods in an Interface that in a normal class. It looks like this was added
to support the SOAP features of the VCL. I&amp;#8217;m not sure which version of Delphi it was added so your mileage may
vary if your not using 2006.&lt;/p&gt;

&lt;h2&gt;IInvokable&lt;/h2&gt;

&lt;p&gt;To use SOAP, you use a WDSL file to specify the method calls, parameters, etc.
If you import a WSDL in Delphi, you will notice that all Interfaces in the generated file will be derived from IInvokable.
A quick peak in the System unit will show that IInvokable is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{$M+}
  IInvokable = interface(IInterface)
  end;
{$M-}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I.e. just a standard interface, but with RTTI metadata compiled in.&lt;/p&gt;

&lt;p&gt;Looking at the help in BDS 2006 for {$TYPEINFO ON} mentions this:&lt;/p&gt;

&lt;blockquote&gt;
    &lt;p&gt;Note: 
    The IInvokable interface defined in the System unit is declared in the {$M+} state, so any interface derived 
    from IInvokable will have RTTI generated. The routines in the IntfInfo unit can be used to retrieved the RTTI.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;IntfInfo.pas&lt;/h2&gt;

&lt;p&gt;The main procedure of interest in IntIfnfo is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;procedure GetIntfMetaData(Info: PTypeInfo; var IntfMD: TIntfMetaData; IncludeAllAncMethods: Boolean = False);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will give us a series of records describing the methods on the interface and the parameters needed for these interfaces, as
well as the unit it was defined within, the ancestor Interface and the interface&amp;#8217;s GUID. All the names are available. both
function / procedures and the names of their parameters. Calling this procedure with an interface not having RTTI will 
raise an exception, calling it with a class&amp;#8217;s typeinfo will just cause an a/v :-)&lt;/p&gt;

&lt;p&gt;When doing SOAP calls, the developer just uses the defined interface like a normal interface.
Behind the scenes, Delphi packages up the parameters and sends them via a SOAP envelope to the remote server.
How Delphi does this shows us some of the potential of this RTTI in Delphi, and respect for the &lt;em&gt;Voodoo&lt;/em&gt; that is TRIO.&lt;/p&gt;

&lt;h2&gt;RIO.pas&lt;/h2&gt;

&lt;p&gt;Located in the soap folder of Delphi&amp;#8217;s source code, RIO.pas contains the class TRIO. TRIO is an object that represents
a remote object, presumably it stands for Remote Interfaced Object.&lt;/p&gt;

&lt;blockquote&gt;
    &lt;p&gt;When an application casts a TRIO descendant to a registered invokable interface, it dynamically generates
    an in-memory method table, providing an implementation to that invokable interface.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Looking at the source for TRIO, I&amp;#8217;ve come to the conclusion that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;MyRioObject as IMyInvokableInterface
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Will cause the TRio object to&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get the meta data for IMyInvokableInterface (from a registry InvRegistry object defined in InvokeRegistry.pas)&lt;/li&gt;
&lt;li&gt;Allocate memory for a vtable for the interface&lt;/li&gt;
&lt;li&gt;Allocate memory for &amp;#8216;stub&amp;#8217; routines, marks it as containing executable code&lt;/li&gt;
&lt;li&gt;Writes machine code stubs that takes the parameters and packages them up, then calls TRIO.Generic&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is a very crude representation I knocked up in Visio: &lt;/p&gt;

&lt;p&gt;&lt;img src="http://blogs.conceptfirst.com/Media/InterfaceRTTI.gif" alt="image"/&gt;&lt;/p&gt;

&lt;p&gt;When you then make a call on the &amp;#8216;generated&amp;#8217; interface, Delphi calls the vtable, the vtables holds the address of the
generated machine code. The generated machine code pushes the parameters then calls the Generic function. This packages
up the parameters, and then uses a SOAP call to call the remote service. The return is then packaged up and returned
in a similar way, back through the generated stub. If you are interested in how the actual machine code
is generated (taking into account the 5 different calling conventions, etc.) take a look at TRIO.GenVTable function.&lt;/p&gt;

&lt;p&gt;I don&amp;#8217;t know which of the Delphi team wrote this code, but its very very impressive. &lt;/p&gt;

&lt;p&gt;Anwyay I hope this has given you a feel for some of the advanced metadata available with Interfaces. The RIO
approach would allow you to write Interface proxies of any Interface with metadata, for security, logging and indeed other
forms of RPC remoting. Let me know if anybody suceeds in such a thing !&lt;/p&gt;

&lt;p&gt;My followup article on &lt;a href="https://blogs.conceptfirst.com/articles/2006/05/22/class-rtti"&gt;class RTTI&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Thu, 11 May 2006 16:07:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:f4e3d8aa-b23c-454b-be07-ff58da4f6bf9</guid>
      <author>David Glassborow</author>
      <link>http://blogs.conceptfirst.com/articles/2006/05/11/interface-rtti</link>
      <category>Delphi</category>
      <trackback:ping>http://blogs.conceptfirst.com/articles/trackback/3</trackback:ping>
    </item>
    <item>
      <title>Class Helpers - good or bad ?</title>
      <description>&lt;p&gt;One of the things I love about the latest versions of Delphi is the compiler changes, originally made for .Net, that
are being rolled back into Win32 code. I like finally having procedures in records, and I love class helpers.&lt;/p&gt;

&lt;h1&gt;Class Helpers&lt;/h1&gt;

&lt;p&gt;Helper classes were introduced in Delphi 8 as a way of binding the VCL to the .Net framework. To quote the Delphi 
help: &amp;#8220;Class helpers are a way to extend a class without using inheritance. 
A class helper simply introduces a wider scope for the compiler to use when resolving identifiers.&amp;#8221;&lt;/p&gt;

&lt;p&gt;Very simply, they allow you to add your own code to existing objects without requiring the source code or recompiling.
The new code only has public access to the original object, so it cannot access private or protected data.&lt;/p&gt;

&lt;p&gt;A simple example from my library code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;TStreamHelper = class helper for TStream
public
  function AsString: string;
  procedure WriteString( const Text: string );
  procedure WriteStringAndLineBreak( const Text: string );
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I got bored of writing the same code for writing a string to a stream, so I put it into a class helper, and because
TStream is a base class, it works for TFileStreams, TBlobStreams, whatever.&lt;/p&gt;

&lt;p&gt;Really a class helper is a compiler trick, behind the scenes it is just functions operating on the class, but it doesn&amp;#8217;t polute
the name space, and works with intellisense. I find myself using them more and more. The other day I was writing some code to
do a gradient fill for a custom background. Very quickly the code became a helper function on the TCanvas object.
Some more examples from my company&amp;#8217;s library code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;TCanvasHelper =  class helper for TCanvas
  procedure FillGradient( Bounds: TRect; StartColour, EndColour: TColor; IsHorizontal: boolean );
end;

TListHelper = class helper for TList
  procedure FreeSelfAndContainedObjects;
end;

TDatasetHelper = class helper for TDataSet
public
  procedure InsertIntoStrings( Strings: TStrings; NameField: string; IndexField: string = '' );
  function HaveFieldsChanged: boolean;
  procedure PostIfEditing;
end;

TFieldHelper = class helper for TField
public
  function HasChanged: boolean;
end;

TTreeNodesHelper = class helper for TTreeNodes
public
  procedure ExpandToLevel( Level: integer );
  function FindOrCreateNode( NodePath: string ): TTreeNode;
end;

TRectHelper = record helper for TRect
  function ContainsPoint( Point: TPoint ): boolean;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note: the last example shows that, at least in BDS 2006, you can also write helpers for records.&lt;/p&gt;

&lt;h2&gt;Bad Design&lt;/h2&gt;

&lt;p&gt;Reading the rest of the Borland help on class helpers, you come to this statement: &lt;/p&gt;

&lt;blockquote&gt;
    &lt;p&gt;Class helpers provide a way to extend a class, but they should not be viewed as a design tool to be used 
    when developing new code. They should be used solely for their intended purpose, which is language and 
    platform RTL binding.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I don&amp;#8217;t agree with this, they are far more useful than just a trick for &amp;#8220;language and platform RTL binding&amp;#8221;&lt;/p&gt;

&lt;h1&gt;Humane Interfaces&lt;/h1&gt;

&lt;p&gt;Recently I was reading some content on &lt;a href="http://www.martinfowler.com/bliki/"&gt;Martin Fowler&lt;/a&gt;&amp;#8217;s website, a site
that always has an interesting perspective on software development. One of his articles that struck a 
cord was on &amp;#8220;Humane vs Minimalist&amp;#8221; interfaces.&lt;/p&gt;

&lt;p&gt;To briefly summarise his &lt;a href="http://www.martinfowler.com/bliki/HumaneInterface.html"&gt;article&lt;/a&gt;, he talks about the 
different attitude between Ruby developers, who favour rich easy to use interfaces, compared to the Java 
crowd who tend to favour minimal interfaces. The example he gives is of a list class and how to get the last item:&lt;/p&gt;

&lt;p&gt;Java: &lt;/p&gt;

&lt;pre&gt;&lt;code&gt;aList.get(aList.size -1)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ruby:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;anArray.last
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Ruby interface has 78 methods, the Java one 25. However the Ruby one is clearly more readable, with less visual clutter.&lt;/p&gt;

&lt;p&gt;At Concept First our 2 overriding rules for writing code are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It should be as human readable as possible&lt;/li&gt;
&lt;li&gt;It should be as concise as possible&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For this reason I favour the humane interfaces. However writing minimalist interfaces I feel leads to more concise design and less
easier to test. It seems to me that class helpers give us the best of both worlds. Objects can be designed with minimal
interfaces, making them quicker to develop and easier to test. We can then use class helpers to make the 
interfaces more humane, more readable, easier to use. The fact that class helpers can only use public 
methods of the object also makes sure the minimalist interface is complete.&lt;/p&gt;

&lt;p&gt;I started off using Class Helpers to add library code to VCL objects, for library code. I now find 
myself using them as a design decision, putting minimalist interfaces on my objects, and adding all the 
helper and nicety functions as helper objects. As Marco Cantu 
&lt;a href="http://blog.marcocantu.com/blog/Delphi_past_its_peak.html"&gt;points out&lt;/a&gt;, it looks like the next version of C# 
will support a similar feature. Personally I feel its another great feature of Delphi giving us a competitive advantage
when developing with Object Pascal.&lt;/p&gt;

&lt;p&gt;So what does everybody else think, design feature or abomination ?&lt;/p&gt;

&lt;h1&gt;Comments (originally on blogger.com)&lt;/h1&gt;

&lt;p&gt;Anonymous said&amp;#8230;&lt;/p&gt;

&lt;blockquote&gt;
    &lt;blockquote&gt;
        &lt;p&gt;Well, Anders Hejlsberg would seem to agree with you that they, or at least the idea of being able to extend a class, is a good thing to expose as part of the language.
        See http://channel9.msdn.com/Showpost.aspx?postid=114680 and http://mtaulty.com/blog/(zu0cer45karubu55u0cqsa45)/archive/2006/03/20/9271.aspx&lt;/p&gt;
        
        &lt;p&gt;Specificl look at Extension methods. AKA Class Helpers in Delphi.&lt;/p&gt;
    &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;Anonymous said&amp;#8230;&lt;/p&gt;

&lt;blockquote&gt;
    &lt;blockquote&gt;
        &lt;p&gt;Brilliant article&lt;/p&gt;
    &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;Daniel said&amp;#8230;&lt;/p&gt;

&lt;blockquote&gt;
    &lt;blockquote&gt;
        &lt;p&gt;Hi, David!
        Great article!
        I personally use class helpers to hide implementation details of some code on the server side of my app, while still publishing classes to the client side. Specially in our SOAP application, when we want our clients to use the same class definition as in the server.
        Looking forward to seeing your article about REST x SOAP&amp;#8230;&lt;/p&gt;
    &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;TOndrej said&amp;#8230;&lt;/p&gt;

&lt;blockquote&gt;
    &lt;blockquote&gt;
        &lt;p&gt;My gut feeling is that what the help says about class helpers is correct, ie. they shouldn&amp;#8217;t be a part of new design.
        For various reasons, already written classes become sealed, ie. their interface cannot be changed anymore. An ideally written class would provide all the functionality specified in the design phase, and expose enough information for descendants to extend it as new requirements come. In the real world, however, classes often hide too much or, if you like, do not expose enough. That&amp;#8217;s where I think class helpers are a big help, they&amp;#8217;re a way out if you&amp;#8217;ve locked yourself in.
        Your argument for writing minimal classes and, at the same time, more humane class helpers seems to be based on the fact that minimal classes are easier to test and debug. I agree, but don&amp;#8217;t you have to test and debug the class helpers, too? Isn&amp;#8217;t the effort the same or even greater after all? Why not write, test and debug the full class right from the beginning?&lt;/p&gt;
        
        &lt;p&gt;The above is just my 2c; I haven&amp;#8217;t used class helpers yet at all. Perhaps I have to play with them a bit and get a better feeling about them first.
        P.S. A very nice blog so far, cheers!&lt;/p&gt;
    &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;David Glassborow said&amp;#8230;&lt;/p&gt;

&lt;blockquote&gt;
    &lt;blockquote&gt;
        &lt;p&gt;Tondrej I think my point is that testing a class helper is much much easier because it can only affect the public interface, not the internals of the class. If your written the minimalist class properly, its very unlikely the class helper can break it.&lt;/p&gt;
    &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;TOndrej said&amp;#8230;&lt;/p&gt;

&lt;blockquote&gt;
    &lt;blockquote&gt;
        &lt;p&gt;OK, that&amp;#8217;s an interesting point. I guess I&amp;#8217;ll take a closer look at those helper beasts ;-)&lt;/p&gt;
    &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;p&gt;Anonymous said&amp;#8230;&lt;/p&gt;

&lt;blockquote&gt;
    &lt;blockquote&gt;
        &lt;p&gt;The limitations seem (no private field access) seem to prevent a lot of goodies.
        What probably happens is that if you use type X, all imported units in the interface are searched for helper&lt;em&gt;for&lt;/em&gt;x, since this is the only way to avoid to scan &lt;em&gt;all&lt;/em&gt; units in the entire project for helpers to compile a unit.&lt;/p&gt;
    &lt;/blockquote&gt;
&lt;/blockquote&gt;</description>
      <pubDate>Mon, 08 May 2006 16:01:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:80fbaf71-b38f-4cc6-885d-68c82c595279</guid>
      <author>David Glassborow</author>
      <link>http://blogs.conceptfirst.com/articles/2006/05/08/class-helpers-good-or-bad</link>
      <category>Delphi</category>
      <trackback:ping>http://blogs.conceptfirst.com/articles/trackback/2</trackback:ping>
    </item>
    <item>
      <title>Introduction</title>
      <description>&lt;h1&gt;Why Blog&lt;/h1&gt;

&lt;p&gt;Because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;There are lots of technical details about delphi I&amp;#8217;ve explored that may be useful to other developers. 
I&amp;#8217;ve learnt loads from the Delphi community and I&amp;#8217;d like to return the favour&lt;/li&gt;
&lt;li&gt;There are lots of design &amp;#8216;discussions&amp;#8217; (i.e. arguments) i&amp;#8217;ve had with other developers, 
especially my busness partner, and I&amp;#8217;m interested in the opinions of other people on the issues&lt;/li&gt;
&lt;li&gt;To quote Paul Graham: &amp;#8220;Expressing ideas helps to form them&amp;#8221;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I&amp;#8217;ve been meaning to write a blog, and host it, for a while, but haven&amp;#8217;t got around to writing a web application to host it (although I&amp;#8217;m still looking at doing it in &lt;a href="http://www.rubyonrails.org/"&gt;RoR&lt;/a&gt; just to learn what all the fuss is about. So I&amp;#8217;ve decided to host this on blogger for the moment, and maybe move it at some future point.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m going to write all the posts in &lt;a href="http://en.wikipedia.org/wiki/Markdown"&gt;markdown&lt;/a&gt; because thats the format we use
internally at work, and its very easy to work with. If anybody knows any groovy tools that can markup delphi code into a web blogger friendly format, I&amp;#8217;d really appreciate it.&lt;/p&gt;

&lt;p&gt;In development, my prefered tool is &lt;a href="http://www.borland.com/delphi"&gt;Delphi&lt;/a&gt;, for lots of reasons. The greatest thing about it for
me is that it comes with all the source code. My coding quality has improved more from reading the Delphi sources than anything
else.&lt;/p&gt;

&lt;p&gt;I live in the south west of England, in the UK. I live here because of the quality of life, especially being close tp the coast. In my spare time I love surfing, running, travelling, and going on expeditions to far away place like Guyana and West Papua.&lt;/p&gt;

&lt;h1&gt;Concept First&lt;/h1&gt;

&lt;p&gt;I work as a technical consultant for a small software company I started with my business partner, Dan Jones, called
&lt;a href="http://www.conceptfirst.com"&gt;Concept First Ltd&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We are in our fifth year of trading, and do various types of work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Business Process mapping and development&lt;/li&gt;
&lt;li&gt;Web sites in ASP, Coldfusion, Websnap&lt;/li&gt;
&lt;li&gt;Application development in Delphi (by choice), VB6, VB.Net, C# (by request)&lt;/li&gt;
&lt;li&gt;Anything else that pays the bills !&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A large number of our projects are integrating data in Enterprise environments (i.e. lots of random technologies chosen for reasons other than technical, fighting with vendors to get access to data, dispairing at money being wasted left right and centre &amp;#8230;)&lt;/p&gt;

&lt;h2&gt;Technologies&lt;/h2&gt;

&lt;p&gt;At Concept First we like and use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Delphi&lt;/li&gt;
&lt;li&gt;DevExpress grids&lt;/li&gt;
&lt;li&gt;Apache 2&lt;/li&gt;
&lt;li&gt;Subversion&lt;/li&gt;
&lt;li&gt;SQL Server (especially MSDE/Express editions)&lt;/li&gt;
&lt;li&gt;Anything to do with geospatial data and mapping&lt;/li&gt;
&lt;li&gt;Mind mapping software for writing specs&lt;/li&gt;
&lt;li&gt;Bulleted lists ;-)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We dislike:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Analyists who can&amp;#8217;t develop&lt;/li&gt;
&lt;li&gt;Developers who can&amp;#8217;t analyse&lt;/li&gt;
&lt;li&gt;The new hoops you have to jump through to be a Microsoft Certified Partner company&lt;/li&gt;
&lt;li&gt;Tying ourselves to Microsoft technologies&lt;/li&gt;
&lt;li&gt;How bad most enterprise software is&lt;/li&gt;
&lt;li&gt;How fickle the software industry is for the latest silver bullet&lt;/li&gt;
&lt;li&gt;Fixed width webpages and tables for layout&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Articles&lt;/h1&gt;

&lt;p&gt;I&amp;#8217;ve got various ideas I want to write up into posts, to be done when I get time/motiviation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rich RTTI in delphi objects&lt;/li&gt;
&lt;li&gt;Delphi&amp;#8217;s class helpers, good or bad OO design ?&lt;/li&gt;
&lt;li&gt;Websnap: good and bad points, how to extend it&lt;/li&gt;
&lt;li&gt;Websnap and FastCGI&lt;/li&gt;
&lt;li&gt;Null Object pattern in databases vs. explicit NULLs&lt;/li&gt;
&lt;li&gt;Case sensitive languages and why they must be destroyed&lt;/li&gt;
&lt;li&gt;Functionality vs Complexity - Time vs Money vs Quality&lt;/li&gt;
&lt;li&gt;Business Logic in databases&lt;/li&gt;
&lt;li&gt;REST vs SOAP&lt;/li&gt;
&lt;li&gt;Tips to prevent premature optimisation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also need to convince my business partner, Dan, to sort out a blog, coz I&amp;#8217;m bored of him preaching to the converted.&lt;/p&gt;

&lt;p&gt;Expect some rantings on &lt;em&gt;&amp;#8216;semanctic markup in html&amp;#8217;&lt;/em&gt; asap :-)&lt;/p&gt;</description>
      <pubDate>Sun, 07 May 2006 15:58:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:dc89a98f-bf13-4889-827d-c6ee44666b20</guid>
      <author>David Glassborow</author>
      <link>http://blogs.conceptfirst.com/articles/2006/05/07/introduction</link>
      <category>Business</category>
      <trackback:ping>http://blogs.conceptfirst.com/articles/trackback/1</trackback:ping>
    </item>
  </channel>
</rss>
