<?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: Category Delphi</title>
    <link>http://blogs.conceptfirst.com/articles/category/delphi</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Delphi, Web development, other stuff</description>
    <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>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>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>
  </channel>
</rss>
