More Attributes in Delphi 2010

In my previous post on Attributes in Delphi 2010, I showed a basic view of the mechanics involved in creating, applying and querying Attributes. I didn’t really cover an example of why you might use them.

Probably the most common example given is for persistence, and indeed, someone over on the Wings of Wind website has posted an example along those lines. I’d like to show off a different use for them: Validation.

Note, what I’ll show you below is meant to be an example of attribute usage, not an example of a robust, complete validation framework. View it like a proof of concept, not finished code.

OK, disclaimers out of the way, in this scenario I’d like to be able to add meta-data to my classes specifying validation rules. Maybe I want to be able to say that for my TPerson class to be considered valid, it must have a non-empty Name value, and the Age value must be between 18 to 65. One way to achieve this is to decorate the relevant properties with Attributes specifying these rules, and then have some code that uses RTTI to walk through whatever object is passed to it and validates each of Click for full size image.the property values according to the attributes attached to it.

Make sense? OK, let’s have a look.

I’ve defined a few Validation attributes. Not a full set, just a few to show them working on different types. There’s a small hierarchy which makes the validation code a little more generic. So far I’ve only created Attributes for strings and Integers, but you should get the idea.

If we have a look at the source for one of the leaf classes, the definition looks like this:

The constructor just stores the two parameters, and the validate method is very simple (well, the rule is simple in this case). It looks like this:

Now that I have these attributes defined, I can use them like this:

Yes, another TPerson. Sorry, not very imaginative.

As you can see, I’ve tagged the Name property with the NonEmtpyString attribute, and supplied a failure message should it be found invalid. I’ve also tagged the Age property with both a minimum and maximum value attribute. What would probably be more useful is to define a validation attribute for a range, but I wanted an excuse to show tagging two attributes on a single property.

For the sake of this example, I’ve created a simple function that does the validation, like this:

First I do some checking to make sure that the instance passed in to be validated is not actually nil, and the same for the Errorlist where I’ll report any issues.

Then, for each property, I grab each of the attributes. Depending on what type of attribute it is, I call the Validate method, passing in the property value. If the call to Validate fails, I add the FailureMessage to the ErrorList.

This could certainly be improved. For example, I don’t like that I have to update the Validate method for each type I want to Validate, and simply dumping any errors into a TStrings is pretty lame. Providing a list of ValidationFailure objects would probably be more helpful. However, for 45 minutes work, I think it shows the concept reasonably well. You can download the sample code here.

Whether you want to use Attributes for persistence, validation or for something else entirely, hopefully this has been useful. A few people have said they don’t see the point of attributes. Maybe it’s worth exploring them and giving them some time to “bake” in your thoughts. It’s said that our language shapes our thoughts, and it may just be a case that because Delphi has not supported attributes in the past, we’re not used to thinking about solutions that use them. As with Generics, Anonymous Methods and Interfaces before them, I find that the more I become familiar with them, the more ideas come forward about how I might use them

32 Comments

  • Twitter Comment


    More Attributes in Delphi 2010 [link to post]

    Posted using Chat Catcher

  • ctx := TRttiContext.Create.Create;

    That’s a typo, right?

  • My first reaction to attributes (particularly with your example) is that you are putting implementation details and business logic (eg range validation) in the interface of TPerson which really belong in the implementation area. Or factored out into a separate validator.

  • JB : yes, it is. Thanks.

    MJ : hmmm, probably depends on the design of the attributes. In general I think the exact opposite is true, that attributes let you specify the ‘what’ in the interface and the ‘how’ somewhere else. This is mostly true in this example, it allows me to specify the constraints on the class up with the rest of the definition of the class, and how those constraints are validated is deferred to elsewhere. However, there are a couple of things about my example which maybe blur the lines: the fact that the failure message is specified in the interface section, and the fact that the attribute implementation contains the validation logic. Both these things could probably be refactored, but as I said, it was meant to demonstrate a scenario.

    In general I think attributes let you make the declaration richer through additional metadata.

  • […] Malcolm Groves | More Attributes in Delphi 2010 http://www.malcolmgroves.com/blog/?p=530 – view page – cached By Malcolm ⋅ August 21, 2009 ⋅ Email This Post Email This Post ⋅ Print This Post Print This Post ⋅ Post a comment Filed Under Attributes, Delphi, Embarcadero — From the page […]

  • […] Groves has more on Attributes in Delphi.  Attributes are one of those features – sort of like Generics – that many folks don’t […]

  • I can’t see anything there that couldn’t be done with good old object oriented inheritance. What was really needed in Object Pascal was multiple inheritance, I think. This looks like a solution to a non-existent problem. That’s what you get when techies are out of touch with real life.

  • Wow! At last!! Thank you, thank you, … thank you.

    Now I am finally about to use my personal favourite attributes

    like:
    [Obsolete]
    [WebMethod]

    [Url(“http://….”)]
    [PortOf(Language=ADA,File=”Card.ada”)]

    Btw shall the VCL support [Deprecated(“Use methodX instead.”] and [WebMethod] like in .NET?

  • […] More Attributes in Delphi 2010 […]

  • MJ is right – this is a mixing of concerns when we should be finding ways of *separating* concerns.

    A simple extension to the attributes support implementation would address this. Allow us to declare attributes (express our business rules) external to our business object implementations (by which I mean the entirety, not just the literal “implementation” section.

    e.g. a new “attributes” section. Must appear after “interface” and before “implementation”, this could then be $include’d if we wished to keep things entirely separate:

    interface

    TPerson = class
    fAge: Integer;
    fFirstName: String;
    // etc
    end;

    TCompany = class
    // etc
    end;

    attributes
    {$i ‘business rules.inc’}

    implementation
    //etc

    And in the attributes section attributes are declared and associated with symbols previously fully defined in the interface:

    TPerson = case
    // Example of multiple attributes
    fAge: [MinimumInteger(18);
    MaximumInteger(65)];

    // Example of single attribute
    fFirstName: MaximumLength(35);
    else
    Validate(); // Class attributes
    end;

    Or some similar syntax. In this entirely speculative example I’ve attempted to re-use existing keywords mixed-in with the attribute syntax.

    One key benefit of this variation in my mind is that it follows the far more prevalent pattern (in Pascal) of “symbol: decoration”, as opposed to the more C/.NET like “decoration applies to following symbol’.

    i.e. far more in keeping with “The Spirit of Delphi”.

    (in a similar vein it may be more verbose but it results in cleaner separation and overall greater clarity, imho)

  • Ossian : Well, sure, but the same could be said of just about everything we do in higher level languages. There’s nothing we do in Delphi today that couldn’t be done with hand-coded assembler. The real question we should be asking, in my opinion, is whether a new feature allows us to do something faster, or more safely, or where the intent is more clear, or more easily understandable, etc.
    I’m a bit surprised you find multiple-inheritance less “out of touch with real life”.

  • Jolyon : Sorry, still don’t agree. In my view Attributes do not automatically bring implementation details into your interface section. Poorly designed attributes may do that (and I’ve already acknowledged that my example probably falls intot hat camp), but so can a poorly designed class interface. Let’s stick with this scenario (if not my implementation). Defining further details of the constraints on a class clearly is part of the interface of that class and should be defined with the rest of interface. Deferring it to the implemntation would be the error, in my view.

    Put another way, are the details of what makes a property value valid something that the client of this class would want to know about? Yes, I think so, so it belongs with the definition of the class.

    Further, I don’t really see how putting it in an external file changes anything. Surely the discussion isn’t really about whether something falls above or below the implementation keyword in Delphi, it’s about whether, in the abstract sense, something belongs in the definition of the contract the class exposes to it’s clients, or whether it is something strictly internal to the class.

  • It’s about how much “noise” is in the interface.

    As attributes proliferate in source it quickly becomes near impossible to discern the true “shape” of a class.

    This is especially the case because, as with C#/.NET, in this implementation there is no way to say “Here is an attribute that I want applied to everything that follows”.

    i.e. if you have an attribute that merely “tags” multiple members without specific attribute instance parameters (e.g. the equivalent of the current “published” visibility) then you have to”tag” each and every single member individually.

    Imagine how class declarations would look if the visibility was required to be specified on each and every class member and you will have some idea of how quickly the level of noise will build.

    Attributes in the Delphi language: Nice

    Aping the C#/.NET declaration style without taking the opportunity to improve on it or adapt it to “The Spirit of Delphi”: A HUGE missed opportunity.

    But one that could still be corrected.

    By all means keep the current “wrong” approach, but provide a way for people inclined to use this feature without sacrificing the “clean lines” of their Delphi code to do so.

    As for putting the details in the interface because this satisfies the “contract”…. that is simply nonesense.

    The “client” doesn’t determine the “contract” by inspecting the interface source. That contract is supplied by the presence of the attribute itself. The client doesn’t care – nor should it need to – where that attribute declaration came from.

    Simplistically co-locating the declaration of the attribute with the thing that it applies to simply because it *IS* the thing it applies to entirely misses the point of a “contract”, imho and is a giant leap backwards in terms of software design.

    In web terms it would be like going back to the days before style sheets.

    Or, to give another example from the concrete world….

    … my employment contract is not filed in my pocket. Not even at my desk. There isn’t even a copy of that contract on my computer.

    The contract exists, it relates to me, but I am not required to produce it every day in order to prove to everyone that inquires that I am an employee, and when someone asks if I work for my employer they doe not wish to be presented with the terms of the contract – Salary, notice period, sick leave, termination clauses etc etc (which is precisely what co-locating attributes in this way does).

    If and when someone is interested in the terms of my contract, they make the relevant inquiry (the equivalent of obtaining the RTTI context). Their inquiry is satisfied with reference to the contract but the inquisitor neither knows, nor cares, where that contract is filed.

  • The Java and .Net guys have it all wrong! Attributes (or Annotations if you prefer) are completely pointless 😉 I guess I will need to rewrite all of that elegant Java persistence code ASAP!

  • Hi Jolyon,

    Before you get to far along telling me my opinions are nonsense, I think perhaps you need to read a little more carefully. Can you tell me where I said that the client of a class should retrieve the contract by inspecting the Delphi source? All I said was I thought Attributes did belong in the interface section because they very often articulate part of the contract, just as much of the rest of the interface section does.Nothing about how the client discovers that contract.

    Note this is not aimed at your point about tagging multiple elements with the same attribute, but at the assertion that having them in the interface section causes separation of concerns issues.

    As to tagging multiple-items, I get it, but I guess I’m not convinced how much of a problem it really is. Can you point me at some examples in the .NET world where this has proven problematic?

    Cheers
    Malcolm

  • Apologies if you feel I got over-defensive in an assertive fashion at your expression of opinion that my view was wrong. Two wrongs it seems don’t make either of us right. 🙂

    My point is that attributes may be part of the contract, but they are NOT a part of the contract that requires expression in the interface.

    Not all contracts (or indeed all parts of a contract) are made equal.

    The fact that (e.g) fAge is an integer and is private is a fundamental and fixed aspect of an implementation and something that I quite likely need to know when reading the code (as a human being I mean).

    The fact that fAge has a min/max value is a more arbitrary decision and doesn’t directly affect the code I write to interact with that member (the fact that it HAS attributes is a factor of course, but my dev environment/team practices will tell me what to expect on that score. We do communicate in ways other than by leaving breadcrumbs in source code after all. Don’t we?).

    Without attributes such a rule may be implemented in a property “write” method for a corresponding Age property. (And in fact, *that* is what the contract applies to – NOT the private fAge implementation detail, but the public Age property).

    And right there we have an exhibit of how the two details are separated, but associated.

    The private implementation declaration.

    The public exposure of that implementation detail, associated – by “reference” to that private detail.

    I do not think you would find any practical example similar to:

    private fAge: Integer;
    public property Age: Integer read fAge write fAge;
    private fName: String;
    public property Name: String read fName write fName;

    In Delphi. You will of course find something more like:

    private
    fAge: Integer;
    fName: String;
    public
    property Age: Integer read fAge write fAge;
    property Name: String read fName write fName;

    You are far more likely to find something similar to the former in C# or course.

    As I say, the implementation of attributes has mimiced the implementation in a language that aesthetically operates in a very different fashion that Pascal.

    But I digress (to a point that I do return to later on…)

    Anyhoo, the nature of attributes (by and large) is that the consumer of the aspect of the contract as expressed in attributes is – primarily – runtime code. Not the compiler and not – directly – the developer.

    So there is no need, and no point and no benefit in requiring that these be co-located with the things they relate to any more than there is any need to include style tags with every HTML element.

    And indeed, we learned the value in
    separating “style” from “substance” in that very case.

    The question really shouldn’t be “Why should we NOT co-locate them”, but “What practical reason or benefit is their do do so”, since there are quite clear disadvantages in the form of “clutter”.

    (I don’t think I’ll get my point across here as there is an increasing and inexplicable reluctance in our industry as a whole to accept and embrace that clean code = more readable and therefore more easily understood and more maintainable code, and a strange blindness to the fact that code spends 99.99% of it’s life in such reading/maintenance and a vanishing fraction of a % of it’s life in “creation”)

    w.r.t examples from the .NET world… no, not readily, because the people I know who operate in the .NET world have decided to *not* *use* attributes primarily for performance issues but they do recognise the issues I describe above in discussions we have had on the subject.

    Now, concerns w.r.t performance may not apply in the Delphi implementation, BUT, I can see that as attributes proliferate, the mechanism for retrieving/interrogating them *could* very easily and quickly bog down.

    But pick any code what makes extensive use of attributes in C# and you will likely see the noise issue that I refer to. It’s slightly less of a concern in C# because it is already a poor choice for a language as far as clarity goes.

    More noise in an already noisy environment isn’t as noticeable as noise in an otherwise quiet one.

    I guess I’m trying to hold on to the peace and quiet that I enjoy with Delphi.

    🙂

  • Oh, and more to the point, whether you or I are “right” in any particular case of a particular use of attributes, currently it’s “Your way or the highway”.

    So I simply don’t have the opportunity to implement my attributes that perhaps don’t require or benefit from the approach you advocate in any way but the way that suits your envisaged use of attributes.

    ROTFLMAO – Not at you, but at the captcha I just had to enter to past this short follow up:

    “crank Continued”

    Have you implemented a Captcha system that recognises me specifically? 😀

  • Hi Jolyon,

    >> Apologies if you feel I got over-defensive in an assertive fashion at your
    >> expression of opinion that my view was wrong. Two wrongs it seems don’t
    >> make either of us right.

    It wasn’t your tone, I’m thicker skinned than that (and well aware that tone is really hard to communicate in written communications). Just that you seemed to have misunderstood me.

    >> My point is that attributes may be part of the contract, but they are
    >> NOT a part of the contract that requires expression in the interface.

    It doesn’t REQUIRE expression there, I agree, but I’m not convinced we’re better off putting it elsewhere.

    >> The fact that fAge has a min/max value is a more arbitrary decision and
    >> doesn’t directly affect the code I write to interact with that member.

    Well, strictly, AGE has a min/max, not fAge, and in my view it’s not at all arbitrary. The constraints on a class are almost as essential to using the class properly as the fact that Age is an Integer. Just that in the past we’ve not had great ways to communicate it properly. It does affect your understanding of the code and its expectations, so there’s certainly an argument to say that the interface section is the right place for it.

    >> And in fact, *that* is what the contract applies to – NOT the private fAge implementation detail, but the public Age property

    Agreed, it applies to the property, not the field or a setter/getter method (assuming there is one). Note it not only is about writing the value, it’s also about retrieving it, giving you the details of what range you can expect the resulting read value to be.

    >> Anyhoo, the nature of attributes (by and large) is that the consumer of the
    >> aspect of the contract as expressed in attributes is – primarily – runtime code.
    >> Not the compiler and not – directly – the developer.

    Disagree. Yes, one benefit of attributes over, say, documentation, is that they CAN be read by runtime code, but I still think that the constraints a class operate under are a key thing for a developer (either maintaining the class or writing code to interact with it) to understand.

    >> And indeed, we learned the value in separating “style” from “substance”
    > in that very case.

    I think this is where we are coming aground. I’m not thinking of attributes as a parallel to stylesheets. Sure, they could probably be used that way, but that would be a mistake in my opinion. With a stylesheet, a big part of the point is someone could come along afterward and change the appearance but not have to change the HTML, or even have multiple appearances for the same item, whereas in my view attributes should be used to define something that is intrinsically part of the class, and not likely to be changed in isolation or differ for different uses of the class. This is actually why I have an issue with most of the implementations of persistence I’ve seen. They start out right but then cross over into details like table names, field names, etc. Those things, like a stylesheet, should be able to be defined differently for different implementations, without needing to edit or even have the sourcecode.

    >> I don’t think I’ll get my point across here as there is an increasing and inexplicable
    >> reluctance in our industry as a whole to accept and embrace that
    >> clean code = more readable and therefore more easily understood and more maintainable
    >> code, and a strange blindness to the fact that code spends 99.99% of it’s life in such
    >> reading/maintenance and a vanishing fraction of a % of it’s life in “creation”)

    Not from me, I absolutely agree. Where we possibly disagree is whether this leads to less clear code.

    I’ve been thinking about your example of attributes that apply to multiple, consecutive items, and I’m trying to think of a use case. Do you have one in mind?

    Cheers
    Malcolm

    PS. BTW, I am enjoying this. Your comments have provoked a lot of reflection on this, so thank you.

  • > So I simply don’t have the opportunity to implement my attributes
    > that perhaps don’t require or benefit from the approach you advocate
    > in any way but the way that suits your envisaged use of attributes.

    Maybe so, but without this discussion I’d be much less aware of differing views. Right now yours is about the only view on attributes that I can think about (that’s meant in a good way ;-))

    > ROTFLMAO – Not at you, but at the captcha I just had to enter to past
    > this short follow up:
    > “crank Continued”
    > Have you implemented a Captcha system that recognises me specifically?

    I hope it’s not that “user aware” as the one I’ve just been presented with to enter this is “Bum Cleaner” 😀

  • I can think about a further possible usage for attributes:
    ! version control of an object !

    Either the developer is using inheritance (“ActiveX paradoxon”: broken backward compatibility between V10 and V9) or he may label properties… of different versions of his object classes using attributes. e.g. :

    Original version:
    —————–

    TPerson = class
    private
    [Version(1, 0)]
    fName: String;
    public
    [Version(1, 0)]
    property Name: String read fName write fName;
    end;

    Later version:
    ————–

    TPerson = class
    private
    fName: String;

    [Version(1, 2)]
    [GROUPID(‘BankAccount’)]
    [Obsolete(‘REASON=private String replaced by get/set’)]
    fBankAccount: String;

    [Version(1, 3)]
    [GROUPID(‘BankAccount’)]
    function GetBankAccount: TBankAccount;

    [Version(1, 3)]
    [GROUPID(‘BankAccount’)]
    procedure SetBankAccount( aBankAccount: TBankAccount );
    public
    [Version(1, 0)]
    property Name: String read fName write fName;

    [Version(1, 3)]
    [GROUPID(‘BankAccount’)]
    [ModifiedInterface(‘private String replaced by get/set’, ‘OLDVERSION=property BankAccount: String read fBankAccount write fBankAccount’)]
    property BankAccount: String read GetBankAccount write SetBankAccount;
    end;

    Now you just need a parser to automatically produce some documentation, like:
    -> Class TPerson
    |_ Version 1.0
    |_ properties
    |_ Name
    |_ Version 1.2
    |_ properties
    |_ Name
    |_ BankAccount
    |_ Version 1.3
    |_ properties
    |_ Name
    |_ BankAccount
    |_ Modified Interface
    |_ private String replaced by get/set
    |_ Old version: property BankAccount: String read fBankAccount write fBankAccount
    and so on…

  • [OT]Uhhh, missing some kinda “preview” before posting a new comment.
    IUs there any alloowed “Tag” to format the comments? (like ...

  • […] The Members For The Attributes In this

  • Jolyon,

    >It’s about how much “noise” is in the interface.
    >
    > As attributes proliferate in source it quickly
    > becomes near impossible to discern the true
    > “shape” of a class.
    >
    > This is especially the case because, as with
    > C#/.NET, in this implementation there is no way
    > to say “Here is an attribute that I want
    > applied to everything that follows”.
    >
    > i.e. if you have an attribute that merely
    > “tags” multiple members without specific attribute
    > instance parameters (e.g. the equivalent of the
    > current “published” visibility) then you have to
    > ”tag” each and every single member individually.
    >
    Imagine how class declarations would look if
    > the visibility was required to be specified on
    > each and every class member and you will have some
    > idea of how quickly the level of noise will build.

    The main difference between ‘visibility’ of a member and attributes is that you can only have one visibility (eg. each member has ONE of private/protected/public/published) but you can have MULTIPLE attributes for each member.

    Example: Which is better?

    A) Decorate each member:
    [Undoable]
    [MinimumInteger(18)]
    property Age: Integer read fAge write fAge;
    [Undoable]
    [MaximumLength(100)]
    property Name: String read fName write fName;

    or

    B) Attribute sections (assumed declared within class but could be separate using class name prefix):
    [Undoable]
    Age;
    Name;
    [MinimumInteger(18)]
    Age;
    [MaximumLength(100)]
    Name;

    In one you decorate the attribute multiple times. In the other you list the member multiple times.

    Personally I’d prefer to see A).

    For easier attribute management then perhaps it would be better to have a popup class/attribute editor, or improve the structure view / class explorer to display members grouped by attribute and allow attribute editing (drag attribute onto member, drag member between attributes, etc).

    Cheers,
    Jarrod

  • […] more I become familiar with them, the more ideas come forward about how I might use them来源:http://www.malcolmgroves.com/blog/?p=530 Categories: Delphi Tags: Delphi 2010RTTI and Attributes in Delphi […]

  • I bulive that this improvments make no sense!

  • DelphiGeist : Meaning you don’t understand them, or you don’t think they are useful?

  • I mean, their just a waste of productivity time, nothing worthing interest… come on guys, we’re not script guys, we seek productivity not “OMG that’s so cool(even tho’ it waste’s my time”

  • Delphigeist : Well, everyone is entitled to their opinion, but you seem to be in the minority. There are plenty of people who a very excited about the possibilities this feature offers for productivity gains in the systems.

  • […] More Attributes in Delphi 2010 […]

  • I read the example and the comments and still can’t see the usefulness of attributes.
    The object itself must take care of validation, you usually do this in property setter or in a method that needs the proper value.
    I mean, MinInteger, MaxInteger add nothing useful. They’re not rules, but decoration, info about properties and are easily ignored.
    Rules on the other hand can’t be ignored and the class must enforce them, so if you break them, you get an exception with descriptive message.

    Second, with attribute classes you apparently left the usual naming convention – class name with Tprefix.
    Third, how are these attribute objects create/destroyed? It looks like they’re managed by TRttiContext.
    Fourth, example validates just properties, can you decorate method and/or their params and how to use that?
    Fifth and last for now, it would be a bit more polymorphic if you had Validate method in BaseValidationAttribute like this:
    function Validate(Prop:TRttiProperty;Target:TObject) : boolean; virtual;
    So each dencendent overrides this method, like in the example, but the function Validate would not need to know about each and every descendent and the code would be like this:
    for a in p.GetAttributes do
    if a is BaseValidationAttribute then
    begin
    if not BaseValidationAttribute(a).Validate(p,Target) then
    ErrorList.Add(BaseValidationAttribute(a).FailureMessage);
    end;

  • Btw, it was mentioned that attibutes would be useful for streaming. But you already have streaming in Delphi. It takes care of references, objects themselves take care of validation,… so where’s the place for attributes?

    I’d be gladly enlightened by a good example.

  • Hi Robert,

    I think you are getting confused between Attributes and my Validation example. The fact that you don’t find my Validation example useful is fine, but it does not mean Attributes are useless, just that maybe my example doesn’t speak to you. As I mention in the post, the example is NOT meant to be a fully realised Validation framework, it is a 45 minute example of Attributes.

    Regarding the naming convention, sure, but it’s just a convention, not a rule. It’s also not the first time it’s been “violated”, just look at Exceptions.

    Regards Streaming, I didn’t say that, but I did say a common example given is Persistence. If you look at the example I linked to you’ll see it’s about Object Relational mapping.

    Thanks for the RTTI code. This looks like what I originally wanted to do, but didn’t know the new RTTI API well enough to do. Nice one.

    Cheers
    Malcolm

Join the Discussion

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">