What are Attributes Good For?

The documentation

http://developer.xojo.com/userguide/advanced-oop-features$attributes

does an OK job of explaining what attributes are and how to create and access them, but not so much what they might actually be used for in real-world situations. Can anyone give some examples of how they can be useful?

Deprecating and refactoring. Need to remove a method, just add a Deprecated attribute and analyze your code, every use will be highlighted. Add a value to the Deprecated attribute, and the warning will tell you what to use instead.

Sure, you could just rename the method and look for compile errors, but this allows you to change them one at a time instead of all at once.

From my perspective of working on the compiler, attributes can be a good way to do additions to the language that don’t have semantic impact. For example, structure alignment, deprecation warnings, etc.

In my Expression Evaluator class, all of the operator and function methods available to the user have attributes which give the symbol, number of operands, evaluation precedence etc. Upon the first instantiation, these attributes are all loaded into various arrays using introspection. This way, everything that needs to be known about invoking the method is stored with the method itself. They’re self contained. So it’s easy to add new operator and function methods without messing around anywhere else in the code. Without attributes it would be a lot messier.

How is this better than using constants, which don’t require introspection?

These may help:

https://web.archive.org/web/20080913062322/http://ramblings.aaronballman.com:80/2008/07/attributes_in_realbasic.html

https://web.archive.org/web/20080916190957/http://ramblings.aaronballman.com:80/2008/07/hands_on_with_attributes.html

https://web.archive.org/web/20081001193030/http://ramblings.aaronballman.com:80/2008/09/attributes_and_constant_values.html

I have two main uses for attributes:

– Sometimes a method may be working, but clearly beyond optimum, but the project presses on and I decide to return later to it for refinements. I could write this don in my ticket system, make notes, remarks or bookmarks or add a warning attribute with the value “unfinished” or similar. The latter will remind me each time I compile the project.

– I like to create my classes debugger-friendly: If some value can be a property, it will become a property instead of a method so I can see its content when examining the instance in the debugger. Quite often I use computed properties with only a getter so the user (or I) can see the content but not change it. With the result that I see both the computed property and the private property in the debugger. So I usually attribute the private properties with a hidden attribute and have a cleaner debugger.

If I used constants, then they’d have to be stored elsewhere in the program code, separate from the method, probably in several different places. If I add or delete one of these methods, I’d have to go hunting around changing code in multiple places. Easy to miss things that way.

Edit:
I should also add that since I’m already using introspection in order to invoke the methods, there’s no real disadvantage to storing this data as attributes.

I see. Not to be argumentative, but one can of course put constants in a method, using the Const keyword. But if you have a lot of them I suppose it might clutter up your method’s code editing window.

No problem. Further explanation:
If they were implemented as constants in the method, then they would only be accessible when the method executes, but this isn’t information that the method itself needs; it’s information that’s required by other code that executes before the method executes. The class compiles a user entered mathematical expression into pseudo code. The parser/compiler needs the attribute information from these methods during the compile stage, well before the method ever executes. For example, one of these methods, X_Log, performs the logarithm function. Its attributes include information that tells the parser/compiler:

  • My symbol is “Log”
  • I require exactly 1 operand
  • I’m a prefix type function (as opposed to infix or postfix)
  • My precedence is 7
  • My associativity is 1

The compiler needs to know this so that it can tell which method to call when it sees “Log(x)” in the expression it’s parsing, and it needs to know how many operands the Log function requires so that it can check that there are no syntax errors. It needs the other attributes so that it can set the proper execution order (eg., multiplication before addition, etc.). It’s only much later that the actual method that performs the Log operation is executed.

Got, it, thanks for the detailed explanation!