Generic Getters
To ensure you don't access the internal state of variables within an object, they are often set to be inaccessible from outside the object and are accessed instead using getter methods. For example,if you wanted to get the value of the FirstName from a User object you would call User.getFirstName().
There are two primary benefits of getter methods: encapsulation and documentation.
Getter methods promote encapsulation as if you have a property that you don't want to share, you just don't create a getter for it. So, if you don't want to provide access to the DateofBirth for a User object, you just don't create a User.getDateofBirth() method. Also, if you want to vary how a property is accessed or calculated, you don't need to change any of the calling methods – you can just change the code within the getter method.
Getter methods also provide a clearly documented interface escribing the properties that are available to call on an object so you know just by looking at the class file what properties are available for accessing.
The one downside with getter methods is that they are verbose. If you do have a lot of simple business objects with “dumb” getters that simply access the internal variable without performing any transformations or calculations (which can easily happen when building simple web applications with a databased back end), you end up with class files full of methods that aren't doing very much and it can be harder to identify the methods that contain genuine business logic, making working with the code base a slower process.
With generic getters, you simply add a single “get()” method to all of your objects and it is used to provide access to internal state. This gets rid of a lot of boilerplate code, but there are two key features that generic getters must implement to avoid losing the benefits of getters. They must be able to delegate seamlessly to custom getters, and they must limit the properties that can be accessed.
Delegating to Custom Getters
In LightBase, the get() method looks to see if a custom getter exists, so if you call get(“FirstName”), the first thing the get method does is to see whether a getFirstName() method exists. If it does, it calls that method and returns the value provided by the custom getter. In this way, you can write an application calling the generic get() method, and you don't have to change any of your calling code if you want to use custom getters – the get() method will take care of it automatically.
Limiting the Properties that can be Accessed
In LightBase, instead of creating a bunch of boilerplate getter methods to document the properties that can be accessed, you simply provide a comma delimited list of property names that should be accessible. This is a much more concise way of documenting your intent and (because it is simply stored as a variable within the object), it is also possible to programmatically change the properties that are externally available. For example, often a business object can be looked at as a state machine and depending on the state of an object, it might provide access to different properties. You could also hook in a permissions based system very easily to change the properties that are “gettable” for different users at different times.
So, generic getters are (if implemented correctly – supporting both limiting the properties that can be accessed and auto-delegating to custom getters if they exist) a powerful way to keep a code base more concise while still getting all of the benefits of encapsulation and information hiding that the “getter” pattern can provide.



I can't stop railing against generic getters / setters whenever I see them.
You list one downside to real getters: they're verbose. Ok, boo-hoo: we should all have snippets or templates by now.
Downsides to generic properties, though, are very real.
I call person.set("dateOfBirth", now())...but nothing happens. Why?
Oh, oops, I need to look _inside_ the Person object's implementation to see that there's a magical string list that states which properties can/can't be set dynamically. That's bass-ackwards.
In a real API, a lack of setDateOfBirth would pretty well state things to the outside world.
I hope anyone using this technique has great typing skills and unit tests. I can't imagine how often set("DateOfBrth", now()) might cause me some serious confusion. Moreover, and more dangerous, what if they mistyped the magic string that determines generically settable properties?
In a highly available app, I can't imagine the wonderful performance of creating 1000s of business objects a minute, calling multiple generic setters on each, and having it parse that list of generically settable properties each time. Runtime string parsing is expensive, especially compared to development time "Hey, does setFoo() exist?".
Firstly, there is no reason why you can't "cfthrow" an error if you try to call set("dateofBirth", now()) which says "DateofBirth is not a settable property. That's how I do it in LightBase, so generic getters and setters are NOT an encapsulation violation - unless you do a lousy job of implementing them. That was one of the points I thought I'd made pretty clearly in the posting.
Similarly, if you get("FrstName") I have an optional setting to cfthrow so you get an error similar to if you'd tried to call getFrstName() - both appearing at runtime as we're running a dynamically typed language here.
I personally don't build high performance applications. If I did I wouldn't be coding in ColdFusion, so to use the idea of string parsing performance being a substantial concern is at the least not relevant to my use case and, to be honest, not relevant to most ColdFusion use cases. I'd worry much more about the fact that all of my methods are compiled down into individual annonymous inner classes. Come on - this isn't an N=1 query problem or a "instantiate 1000 objects with each request" kind of performance problem. This is the kind of lame "should we use cfif or cfswitch to speed up our app" kind of premature optimization that both of us usually rail against! In the general case, I'll take more maintainable over more performant. I do agree that there are two different ways of looking at more maintainable, however, which is to me where the division lies on generic getters.
I have a good number of business objects in my apps that have properties that should be available for displaying and perhaps editing and that have no logic or very little logic. I don't have anaemic domain models per se - some of my business object properties are quite rich, others are just inherently simple. I find it much easier to only have methods that actually do something as opposed to having to look through a bunch of methods to see whether they do something or not.
If I was working with a large team on a large code base, I'd probably opt for the more traditional documentation provided by explicitly written getters and setters and being able to generate API docs from the code. In LightBase, I generate the same docs but with much less code (heck, most of my business objects don't even exist if they don't have any methods that I can't describe declaratively using my DSLs). Having tried both approaches I much prefer mine (it isn't better - I just prefer it) and I would say it is no more than a continuation of the static vs. dynamic typing debate or the mixin debate - only taken one step further. Some people can't believe we don't code in a statically typed language and use interfaces. We manage to get by, and accept the trade offs. Same deal, just further down the road.
Two differences to onMissingMethod(). Firstly, this works on CF7 :-> I'm on CF8, but still have some servers running 7.
Secondly, I find in certain use cases generic getters provide a BETTER syntax. Let's say I want to display a list of values based on a PropertyNameList. With generic getters it is easy:
<cfloop list="#PropertyNameList#" index="PropertyName">
#Object.get(PropertyName)#<br />
</cfloop>
Syntactically, doing the same with onMissingMethod() is harder as you can't just write:
<cfloop list="#PropertyNameList#" index="PropertyName">
#Object.get#PropertyName#()#<br />
</cfloop>
You can cfinvoke, but that isn't available when looping through the properties of an object to process it if you're within a cfscript block. So even though I HAVE an onMissingMethod(), I just get it to delegate to my generic getters and setters as I have use cases where I find the get(PropertyName) syntax more useful than trying to implement get#PropertyName#() which only works using cfinvoke, which in turn is not available within cfscript blocks.
Make sense?
So, basically...
"cfthrow" in place of API - You're willing to let developers waste their time trying to set something that can't be set by having to write code, hit error, and fix, when they could just notice setFoo() doesn't exist.
Performance - You don't think CF can handle high performance apps? Maybe the problem is your techniques and not CF. It handles them fine for me. Further, string parsing absolutely not the same performance debate as switches versus ifs. Good grief, at least use a hash table instead of a list.
Anaemic domain models - logic in a getter does not a rich domain model make, and that's all I ever see you discuss. Behavior in a domain object makes it rich, not a "rich getter" for "name" that does <cfreturn firstname & " " & lastname />. That's a view concern, anyhow.
Code brevity - Who gives a rat's ass about the time it takes to create a getter and setter? Are you short of hard disk space and need to save bytes?
This isn't at all static vs. dynamic language. I embrace being dynamic. I just despise sacrificing architectual advantage and good practice in favor of laziness.
Firstly, when I'm in a view (for example), how do I KNOW MyObj.getFoo() doesn't exist? Do I have to go to the class file for MyObj and look and/or look at JavaDocs or similar? You can't get autocomplete in CF for object methods because CF doesn't know what kind of object you're dealing with - it's all magic strings. I have a simple page that displays the object model for an application so you can see in a browser what properties, relationships and the like exist. You have the context switching hit, but I still found it faster than navigating to a different directory and looking through a file to see what getters are inside of it.
Re: performance, I think we can both agree that CF is not going to be as fast for most use cases as something coded in Java. I don't deal with high performance apps, so it isn't a big thing, but I do agree that creating a hash table from the list on instantiation would make sense. It's more a case of premature optimization for me in that I really don't HAVE a performance problem yet and I have almost 50 sites using this kind of code. The hashtable would be the obvious performance boost, and it's something I could drop in after the fact.
The reason I use FirstName & LastName or Age vs. Date of Birth is for lack of space. Most of my business logic relates to fairly complex pricing and discounting rules for commerce applications, but I'd be writing books - not postings if I put actual sample code into the blog pieces. After all, I've only ever seen you build a blog in your demo's, but I'm guessing Model Glue isn't just for building blogging software - right?! *wink*
Code brevity is a HUGE concern. While my hard drive is as yet managing to keep up with my typing and it doesn't take ANY time to create a getter or setter if you generate them, I have generated applications with getters and setters, I have hand written apps with such getters and setters and I have hand written and generated apps that use generic getters and setters and a number of other techniques (such as methods described declaratively using DSLs in an XML concrete syntax) which mean I can create apps with about 10% of the code to capture the same amount of intent. Efficiency in capturing intent to me is critical. Not so much because it saves time typing, but because it really pays off in the maintenance phase when you only have 4,000 lines to look through - not 40,000 lines. It's the same reason you'd use Hibernate vs. generating 20,000 lines of custom SQL - you can see and change the intent much more easily when working with the DSLs that Hibernate provides rather than having to work with raw code in a given 3gl.
I also despise sacrificing architectual advantage and good practice in favor of laziness. We'll have to grab a beer at Scotch and try to decide who is guilty of such horrible crimes against software engineering and root them out!
I can see your concern, but I don't think the reasons you've stated illustrate it well. For instance, as you already noted, linearly searching a string list is probably going to be slow, but can be fixed by using a struct/hash. (Although, I can't imagine there are going to be 1000s of properties per object, so a simple linear search in 1-15 items probably isn't going to cause a problem in the first place).
Other than that, the other 3 of your problems seem to boil down to lack of IDE support.
1) I have to look into the class - The best our IDE does up to whatever version I'm currently using is tell us what methods are available in the sidebar - not with autocomplete, and that could be fixed to work with generic getters if someone really wanted to do it.
2) magical strings suck, but the simple case is that either way in CF, we're not going to know about the mistyping until we run the code in some form or another - that is true of magical strings and normally mistyped method calls on our objects. And if they can be fixed for normal objects, they can also be fixed for ones with generic getters and setters if someone wants to do it.
3) As you mentioned is fixed by using hash/struct. I'm not convinced it's a problem given how small the number of properties is expected to be, but it can be fixed for sure.
4) From your blog - lack of an API. Again, this can be rectified with tooling, just as it can if you do it the normal way.
I suspect there is something you're getting at, but I don't think those 4 arguments are getting there.
@Ryan, I keep going back and forward on this. It is one of the ways I consider implementing the metadata, and it would work well with what I'm trying to do in terms of adding additional metadata.
The only real limit with putting gettable/settable into the cfproperty tags is that it would be difficult to change at runtime. All of the talk of getters and setters providing an API is based on the often false simplifying assumption that the properties that are gettable and settable don't vary over the lifetime of an object. With a getter/setter based API, how do I know that I can't set the shipping date for an order that hasn't been placed yet. Sure I could just add code to the setter to check the order status, but that is an extremely inefficient way of documenting that intent.
I agree with you about the gettable/settable attribute. I would only do this for something that would always be read-only (ie. If I never wanted the ID of an object to be changed over the life of an object). In your example, that would be the complex sort of validation that would have to be delegated to a custom setter. I don't think that business logic like that can easily be documented in an object's metadata, and would instead need to be laid out in some sort of API programming guide.
I actually think that we could expand the definition of an object to include either the concept of states and/or the concept of roles that an object could be fulfiling at different times over its lifecycle. I think by doing so we could get rid of a LOT of extra custom code. It's one of the main enhancements I' m working on with LightBase right now and the goal is to be able to capture all of that intent in metadata so we can remove another bunch of code from our applications.
I always think of coding in a 3gl as a last resort rather than a starting point :->
http://www.pbell.com/index.cfm/2008/4/7/Adding-Sta...
I like the state/role idea for persistent business objects. I've been doing some work with the state machine pattern in client-side code, and find that it can be very powerful/extensible. Look forward to reading more of your thoughts on this topic.
Additionally, I am not clear as to how this is an extension to a static/dynamic debate as you can do generic mutators just as easily in static languages as well.
Firstly, I HAVE such documentation - I just create it using a web page from the metadata that describes my objects, so there is still documentation - it is just in a different place (but consistent across all projects so it is easy to learn).
Secondly, your "documentation" is wrong for at least two reasons! Firstly, if you use DI and setter injection, you have setters that you should probably (for many objects) never call. How do you make it clear that those setters are NOT callable by your everyday code? Secondly, the state of your objects often determines the gettable and settable properties. How do you capture in your documentation that you can't setShipDate() on an order that hasn't yet been placed? I think at the least you need to consider annotations of some kind to describe the states that getters are valid for and to distinguish "DI only setters" that you should never manually call.
It seems to me that while it is a standard practice (especially in the Java world), the idea of writing getters and setters which have no logic is a very inefficient way of expressing intent (how many characters is it taking to create an entire getter - especially in ColdFusion - compared to the length of the name of the method) and is also somewhat inaccurate as it is only a static - not a dynamic representation of the object, making it of limited use as an API as at any given time in an objects life it is probably inaccurate.
As for the static/dynamic debate, the point I was making is that putting types everywhere - as you have to do in explicit statically typed languages like Java or C# - is often argued to be beneficial as it makes the code more self documenting. I was just making the point that removing the logicless getters and setters could be seen as going just another step down the path of trading speed and flexibility for a code base that is less self documenting.
All the above said, if I was working in a larger team, I'd still probably just generate the getters and setters - if for no other reason than for consistency with most other well written code out there.
Dumb question - how can you write generic getters in a statically typed language? How would you handle the fact that different getters should return different types (string, int, various objects, etc.)?
If I have some dynamic code and it gets to a property named "Foo" on an object called "MyObject", I can ask StructKeyExists(MyObject,"getFoo"). If Foo is stored in a variable name "Bar", I can ask this: StructKeyExists(MyObject,"get#Bar#").
The generic getters/settings do make the calling logic cleaner as they don't require cfinvoke, but I do think they should have some mechanism whereby the object can be asked which gettable and settable properties it has (instead of having to rely on try/catch).
If implemented properly, you would have an idea of what gettable/settable properties exist. As Peter pointed out above, this kind of information could be stored in the object's metadata. As long as the means of accessing the metadata are consistent across all objects (could be implemented as a GetMetaData method in a base object which all objects implement) than this would give you the means to query the object's properties at any given time.
This would have the added benefit of being changeable of the lifetime of the object, to cover the case of different properties being available based on the state of the object.
Now that being said the framework I keep dilly dallying around with uses a generic mutator :) Reason being is I needed a nice way for a view to ask for properties an action set up for the view, in this case though it is all open for access so there is no restriction.
As to how you do generic accessors in something like Java; I thought about putting a caveat on my original comments but opted not to, so here's my caveat now. Generally our generic accessors returns a string or an object type of itself (quasi iteration for example). So on a calendar object (one where we have a real implementation) we have a generic accessors for day, time, year, fiscal year, period, next period etc. Once again though mutators are pretty much off limits, if I change the year I don't really have the same object anymore.
One final note, just b/c myself, Joe and others don't like this technique it should not keep folks from trying it and seeing if it works for them. Joe may want to obliterate the idea and keep it from happening but I think its important for folks to try new/different concepts. I did and I found some niche uses for it who knows what others might come up with trying it.
Store all properties in a hash/struct that stores Object, make the getter return type Object, and cast it everywhere. =)
@Sam, Dude, you've been writing Ruby code too long. IntelliJ must just love your ass if you really write Java that way :->
Also, I see generics as DRYer. Why repeat code that's identical apart from the variable names.
As long as you take steps to preserve encapsulation. Personally I just create custom methods for those variables I don't want to be directly accessible rather than maintaining lists/hashes or throwing errors. This seems more sensible given that there are generally far fewer vars that need protecting than not.
Recently I've started running with Hal's idea of combining both onMissingMethod with generics to allow the jQuery style:
myObject.foo(); // get
myObject.foo("bar"); //set
So far it's working out really well, making my code simpler and more readable.
"
myObject.foo(); // get
myObject.foo("bar"); //set
"
So what happens if for some reason you have to pass an empty string to foo? in the foo method are you simply checking if an argument exists or not to decide if it's being used as a getter or setter?