By Peter Bell

What is an Object as a Struct?

Let's say you have an object and you'd like to turn it into a struct. What does that really mean, and what should the code do?

If I have an object which has been loaded with certain data, what should I return if I call asStruct() to return a struct representation of the state of the object. The unthinking answer might be just to return the instance data stored within the object. Something like:

<cffunction name="asStruct" returntype="struct" access="public" output="false" hint="I return the object as a struct.">
   <cfreturn variables.InstanceData>
</cffunction>

A little more thinking would suggest that while there might be use cases for that, most of the time what you're going to want to do is to loop through the gettable list of properties for the object, calling the getter for each one and putting the values of all of those getter calls into a structure. For the special case of an object without a gettable property list I'd just return the internal state.

That then gives the following code:

<cffunction name="asStruct" returntype="struct" access="public" output="false" hint="I return the object as a struct.">
   <cfscript>
      var ReturnStruct = StructNew();
      If (len(GettablePropertyList) GT 1) {
         For (key in GettablePropertyStruct) {
            ReturnStruct[key] = variables.InstanceData[key];
         };
         return ReturnStruct;
      }
      Else {
         return variables.InstanceData;
      };
   </cfscript>
</cffunction>

I think I quite like this as all I have to do is provide a gettable property list for an object and when I asStruct() it, I get the collection of externally shareable properties which will use any custom getters as appropriate so if the internal state has a FirstName, LastName and DateofBirth but the gettable property list is FirstNale, LastName, Age, providing there is a custom getAge() method, I'll get the users first name, last name and age as a struct just by calling User.asStruct().

Simple, but I can see where that would be useful. Thoughts (other than "duhh") welcome!

Comments
At the risk of shameless self promotion, I'd use PseudoObject.cfc (http://www.codeodor.com/index.cfm/2007/1/24/Pseudo...)

The struct will behave like an object, but be a struct.

I know that's not your point, but it was a fun programming exercise. =)
# Posted By Sammy Larbi | 4/14/08 5:14 PM
LOL. As you said, not quite on point, but a fun exercise, nevertheless!
# Posted By Peter Bell | 4/14/08 5:18 PM
I think its a good idea. My only suggestion would be to change the name to "ToStruct". I think it is more aligned with other "conversion" methods such as ToString() ToBase64() ToBinary(). Or maybe "GetStruct" since some java methods are like GetByteArray() or GetCollection().

That's my only feedback as I like your ideas.
# Posted By Ben Nadel | 4/14/08 6:37 PM
@Ben, Not a bad idea. Makes sense. I'll go change my API right now. Thanks man!
# Posted By Peter Bell | 4/14/08 7:14 PM
Where would this ever be useful further a good idea? I can not think of a time where my object should not go somewhere, but it's properties should.
# Posted By Adam Haskell | 4/14/08 7:26 PM
@adam, How about over the wire?! That's the main use case I've found.
# Posted By Peter Bell | 4/15/08 4:35 PM
I think there's definitely cases for this, but that going over the wire (assuming Ajax or AMF/Flex) may not be a good one - it's giving your object knowledge of a serialization format, which probably isn't a responsibility it should be accountable for (much in the same vein as separating persistence logic).

For the goal of going over the wire, I've had luck using an external serializer (mine relies on <cfproperty> tags, but I imagine with your DSL you can do someething similar) that relies on conventions to turn an instance into a different format (JSON, an amf-specific struct using __type__, etc). I typically wire it in via AOP.
# Posted By Joe Rinehart | 4/16/08 10:11 AM
@Joe,

Good point. I think you're absolutely right that the object shouldn't know about JSON and XML and the like - I briefly considered addint toJSON and toXML to my base object before realizing how terrible an idea that would be! However, at the other extreme I'm not sure that I want my external serializer to ask the object for a list of properties and then call each of the getters - the rule of thumb is that if you're asking an object for more than two or three things maybe you should tell it to do something for you instead, so I want considering allowing a toStruct() method in the base object and an external serializer would then take the struct and transform it into the appropriate format for sending over the wire.

What do you think? Does your external serializer ask the bean for a bunch of stuff or do you have an equivalent of the toStruct() it can call? Might this be a case where asking the bean for lots of things is appropriate? Is toStruct() a reasonable responsibility of a base object?

I'd appreciate any more thoughts you might have on this one . . .
# Posted By Peter Bell | 4/16/08 10:25 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.005.