Earlier today, Peter Bell posted again on using "generic" getters and setters in CFCs. He's posted about it on his blog repeatedly over the past few years, and he and I recently butted heads a bit on the Model-Glue list about why I feel they're a bad (ok, I've used much stronger terms than that...) idea.
-
Subscribe
Enter your email address to subscribe to this blog. -
Categories
- .NET and ColdFusion (7)
- Arf! (11)
- Best Practices (11)
- Blog News (3)
- Broadchoice (6)
- Cairngorm (4)
- Causing Trouble (28)
- ColdFusion MX (173)
- Conferences and Speaking Engagements (31)
- Firemoss (7)
- Firemoss Tools and Products (1)
- Flex (40)
- Flex and ColdFusion (35)
- Flex and Java (2)
- Fling (1)
- Frameworks (3)
- Hiberailooving (4)
- Hoagie (1)
- jComponents (5)
- Joe Drinks Java (8)
- Model-Glue (138)
- Model-Glue:Flex (4)
- Movies (1)
- Off Topic (89)
- OOP (5)
- Photos (21)
- Railo (1)
- Reactor (3)
- RIA Platforms (2)
- See Also (20)
- Site News (16)
- Site News (1)
- The AM Agg (8)
- Web Development (3)
- Worst Practices (1)
Comment 1 written by Axel on 8 April 2008, at 12:07 PM
hope the baby is doing good.
Axel
Comment 2 written by Jean Moniatte on 8 April 2008, at 12:53 PM
Comment 3 written by Sean Corfield on 8 April 2008, at 1:16 PM
obj.find_by_email_and_password("me@domain.com","secret")
Comment 4 written by phill.nacelli on 8 April 2008, at 1:17 PM
I'm all for reduced work, but c'mon folks don't be lazy! Spend the one minute it takes to create a snippet for your getters and setters if it's all that much work!
my 2 cents...
Comment 5 written by Joe Rinehart on 8 April 2008, at 3:04 PM
I do like onMissingMethod, but not for creating properties on the fly. Maybe I'm just stodgy, but I really like having objects that have properties before runtime...again, mistyping setBirthDat(now) could really screw me up if it created the property and then I called getBirthDate() later on..
I think onMissingMethod is great for proxy purposes and tooling, but not for creating the attributes of my core model...
Concerning ActiveRecord's generic finders, I really just don't get their point or their advantage. Sure, the readability of the syntax is nifty, but when did favoring passing lists of strings (instead of a message) become a good idea?
Doing:
user.find({email:"me@domain.com"}, {password:"secret"})
...allows the message's recipient (User) to figure out what it's supposed to do with the message (maybe never allow users to be seeked by password!) rather than blindly letting calling code do fairly powerful stuff.
Comment 6 written by Peter Bell on 8 April 2008, at 4:03 PM
@Phil, it isn't about creating the getters and setters. I can generate those in no time flat or use snippets as you suggest. It is about being able to express intent as concisely as possible so you have less code to wade through or maintain when making changes to an application. I think Sam made some great points in the comments on my posting and would recommend you check them out.
Also, there is the problem of getters and setters that they provide a FALSE API. According to my order object I can call setShipDate() on an order that hasn't been placed. The setter method is there, and short of calling it at runtime there is no way I can deduce that the Order object needs to have a particular state for the setter to be callable. By using generic getters and setters I can introduce the concept of state into my business objects and change the gettable and settable properties and throw smart messages like "ShipDate can not be set when the order is in "pending" state" without having to write any custom code at all.
I'd agree if we were using a statically typed language with code completion for methods (which rocks), but CF doesn't KNOW what object we're talking about before runtime (and certainly doesn't know which methods will or won't have been mixed in) so without that kind of code completion support, I don't see the benefits of the extra boilerplate code obsfucating my intent.
Comment 7 written by Joe Rinehart on 8 April 2008, at 4:52 PM
> "BirthDat is not a settable property"
Clear as mud. You made no mention of this until _after_ I commented.
> It is about being able to express intent as concisely as possible
Being concise is not always a good thing. It often hurts communication.
In the range of enterprise software design / development, where we build larger systems with teams of developers, I'd much rather be able to *communicate* my intent than express it "concisely."
I can't think of a much more obscure way of expressing intent (or looking up that intent) than making developers open a CFC file, find a comma-delimited list of settable properties, and read that list.
> Also, there is the problem of getters and setters that they provide a FALSE API.
> According to my order object I can call setShipDate() on an order that hasn't been placed.
That's not a problem with getters and setters. That's a problem with your lousy design of Order.
Why doesn't Order.ship() do the setting of shipDate, take shipping action, and model the knowledge of whether or not it's settable, exposing only a getter for shipdate()? That'd be OO design and treatment of order as a real object, not just a glorified database record.
Setters (and getters, to a lesser extent) can weaken encapsulation in this manner. It's up you to know what you're doing, not to blame getters and setters and go off thinking that state machines can save you.
Comment 8 written by Sean Corfield on 8 April 2008, at 8:49 PM
If your business object has state, it can determine how a get/set method behaves and that method can throw appropriate exceptions. You don't need generic get/set for that.
Comment 9 written by Sean Corfield on 8 April 2008, at 8:54 PM
I find the syntactic benefit to be big enough that the overhead is worthwhile.
Mostly I use onMissingMethod() to implement delegation from service to gateway (if appropriate) and to automate get{Object}ById(PK) and similar calls.
Since I use Transfer for all my business objects, I'm not writing get/set methods anyway.
Comment 10 written by Cliff Meyers on 9 April 2008, at 2:27 AM
As Joe suggests, encapsulate the logic into a meaningful method. Google "fowler contextual validation" for more info.
Comment 11 written by Peter Bell on 9 April 2008, at 9:21 AM
Fair point about the Order example - it is a bad example - I'm still thinking through the whole concept of dynamic properties/interfaces for objects based on their state or roles over lifecycles, so I'm not sure yet whether it could be a really useful technique or a complete dead end as I haven't thought it through or played with it in production code. I still think it's an interesting concept and no doubt will post more on that separately if I do find good use cases for it.
@Sean, Maybe - I'll reserve judgement until I've played with it a little more. I know that my business objects can determine how getters and setters should behave based on state. My question is whether it's really appropriate to be hand writing code to solve that fairly common use case or whether it should be baked into the idea of an object. Was chatting with a guy at SPA who had a system for declaratively describing objects that included as a central thesis the idea of the behaviors and properties of an object being dependent on it's state with certain behaviors providing for state transitions. I'm currently playing with the idea of adding modeling either of state or of dynamic roles (think of an object as implementing n of m interfaces at any given point in time) to my description of business objects so I don't have to hand code those concepts. Still no idea whether it'll be practical or useful in real world projects.
@Sean, I agree that a class should be solidly designed. But why should that design be limited to the static set of attributes that a class can encompass rather than designing state right into the concept of a class and making both the attributes and behaviors of a class a dynamic function of the state of the class? Doesn't that better model how code often works in practice? I haven't done a literature search on the idea yet, but at the least it seems to me to be an interesting approach to class design. No?
Comment 12 written by Peter Bell on 9 April 2008, at 9:29 AM
One more:
> I can't think of a much more obscure way of expressing intent (or looking up that intent) than making developers open a CFC file, find a comma-delimited list of settable properties, and read that list.
Well, firstly, I provide a web based UI for ALL metadata about a project, but let's take the comma delimited list of properties. What is your alternative? In CF would you make someone open up a CFC file and then scan through the entire file to see whether or not there is a set#PropertyName#() class? I get the code completion of methods being really nice, but we don't have that in CF and it's faster to find a list of property names at the top of a file than having to scroll all the way through the file to see if a given setter exists. How do you check for a given setter in CFE?
Comment 13 written by Ben Nadel on 9 April 2008, at 9:45 AM
http://www.bennadel.com/blog/1193-Happy-Medium-Bet...
Comment 14 written by Rachel on 9 April 2008, at 10:25 AM
Comment 15 written by Peter Bell on 9 April 2008, at 10:46 AM
I'm coming from a perspective where source code in a 3gl is a necessary evil and not necessarily the definitive source of information about a project. I see an executable model as being a more useful way of seeing the structure of an application, so I'm willing to put up with losing quite a lot of documentation in the code base in return for being able to code most of my apps using DSLs.
To me tooling support or readablity of the code base is less important than conciseness of expression providing I can generate the appropriate documentation from other artifacts such as the metadata that describes the application.
Comment 16 written by Peter Bell on 9 April 2008, at 11:06 AM
Comment 17 written by Joe Rinehart on 9 April 2008, at 5:39 PM
>I put the reference to limiting the gettable properties
>in the original article
...with nothing about what would happen if an "ungettable property" (which is an encapsulation what-the-heck in the first place) was requested.
> I'm currently playing with the idea of adding modeling
> either of state or of dynamic roles (think of an object as
> implementing n of m interfaces at any given point in time)
Peter, I've tried not to be sarcastic or rude up to this point, but using something that shifts an instance's API over time in place of halfway decent OO design is one of the worst ideas I've heard from you yet.
(Harsh? Yes. Why?)
I've had few people ask me why I let things like your "generic getters" bother me so much - I tend to be pretty easygoing and pragmatic.
Simply put, my pragmatism ends when I see bad ideas being put forth by community voices as powerful techniques. Someone has to say "That's not a good idea. On this topic, that someone was me. It's nothing personal.
I know you work in a different world than most of us, acting as a one-man team that produces small data-oriented applications quickly. Some of these ideas may work in that context. In the larger realm of software teams, especially in terms of integration concerns (which is where costs quickly go from mildly exponential to a Keanu Reaves "Whoa" inspiring upwards curve), much of what I hear you discuss on a CFC design level has horrible consequences. While some of what exists in "enterprise" software design may seem stuffy or like overhead, a lot of exists for very real and high dollar reasons.
Finally, code is not a necessary evil. Code is a tool, and the usual double-edged sword nature of tools apply.
In the hands of someone good at both code and designing code, 3gl code is concise, expressive, and capable of doing reams of logic safely with a single, well-named method call.
Like anything else, it's also possible to shoot yourself in the foot if you don't master the basics of both writing and designing code.
When someone misses one or two of these basic "a-ha" moments, especially on OO design, it's very easy to go off on strange tangents. They'll find buzzwordy phrases like "state machine," misinterpret them at will, and think they apply to the problems they've encountered when good design fundamentals would have eliminated the problem before it surfaced.
For example, discussing the state pattern (which is what you're more closely discussing, as opposed to the state machine pattern, which does differ) in terms of having the stateful object change its interface implementations over time defeats the goal of the state (and machine) pattern to begin with! I'll leave it up to you to read up and learn what that is.
Comment 18 written by Peter Bell on 9 April 2008, at 6:02 PM
Where to begin? Firstly, I don't take it personally - there is always a learning from a frank exchange of ideas providing ad hominens are avoided.
Generic getters are not a bad idea. They are not a bad idea in my implementation, they are not a bad idea in Ruby, they are not a bad idea period. They are simple a pattern whose appropriateness depends on design forces. I get that they may not be appropriate in your use case. That doesn't mean they are wrong. That means that there is a trade off between using them and not. I think that I, Sam and others have done a pretty decent job of delineating those trade offs (it's not like I'm saying they are perfect for all use cases or involve no trade offs - I think I've been pretty responsible in positioning them appropriately). When you call them wrong you remind me of the Java zealots who are absolutely convinced that without an explicit, static typing system and interfaces it is impossible to build non-trivial software. Not that the extra compiler support doesn't help, and I don't know that I'd want to do a really large team project in a dynamically typed language, but it is possible to write decent apps without static typing and it's possible to write certain classes of apps without writing or generating getters and setters for every property.
3gl code can be many things, but it is not nearly concise or productive enough for my use cases. On the whole it's not terribly reusable either - even when well designed.
I never suggested that a stateful object change the implementation of its interfaces over time, but rather that it change the interfaces that it implements over time (which is a completely different thing). I don't know whether that idea/approach will be useful/practical/appropriate as I'm in the middle of thinking about it/playing with it. If it does work, it is a way of declaratively expressing more intent in 3gl agnostic DSL that allows me to create richer web applications while minimizing the amount of code I have to actually write in CF or Java or Python or whatever.
Comment 19 written by Joe Rinehart on 9 April 2008, at 8:39 PM
First, Ruby doesn't have "generic getters" that are anything like what you've described. Ruby allows you to define an attribute accessor for a given private property (attr_accessor, attr_writer, attr_reader). Mechanically and functionally, they're much more like implicit properties in AS3 or C#. A number of us, me included, have asked for them in CF...
Secondly, while I do agree that basic use cases such as creating simple HTML screens that focus on master/detail sets of data can be more concisely expressed in a DSL, I wholeheartedly disagree that a rewarding user experience where "all the screws line up" (http://www.joelonsoftware.com/articles/Craftsmansh...), high performance, or specialized applications can be much more concisely expressed in a DSL than they can be in a 3gl. Most of us out here don't crank out Yugo's on an assembly line - we work on one-off custom projects. Not acknowledging the difference between low-fi mass-produced software and enterprise development but disseminating your techniques as good practice across the board is largely why I disagree with you so emphatically.
Last, the idea of having an object "change the interfaces that it implements over time" is exactly the idea that I said was miserable. Earlier this week you took a good shot at encapsulation - are you going to destroy polymorphism next week?
If the force driving you is to change an object's behavior based on its state, that's already quite tersely expressed in a 3gl implementing a couple of different possible patterns It wouldn't be hard to design a DSL that'd shift the concrete state implementation assigned to an instance (actually, context) based on rules also expressed in the DSL. However, the amount it'd reduce the code...about nil. It'd be more readable by noncoders, which may suit a given situation.
Comment 20 written by Peter Bell on 9 April 2008, at 9:59 PM
Domain Specific Languages aren't for simple use cases.
DSLs are for use cases where repetition exists within the problem or solution domains. It's why we create classes with methods (a very simple language expressed as an API), it's why we create XML configuration files, it's why we create content management systems (and metadata management systems), it's why we write little languages and parsers, and why we create languages using visual language toolkits like Microsoft DSL tools, openArchitectureWare and MetaEdit+.
Software product line engineering is about creating a combination of frameworks, re-usable code snippets, DSLs for unbounded variability spaces and configuration managers and feature modelers for bounded variability spaces - often in a structure where ad-hoc custom code can be added for functions that are not worth developing a DSL and an interpreter (framework) or compiler (code generator) for. The balance point for an ROI on the effort of developing a DSL depends on the tooling, experience and inclinations of a given developer.
There is no application you can write that I can't generate. There are parts that it may not be worth me generating, but there are patterns of best practices in everything from object modeling to UI design and I think that much more of our skills and best practices can be turned into reusable heuristics than we might like to admit.
Comment 21 written by Joe Rinehart on 10 April 2008, at 6:21 AM
Model-Glue's XML is an external DSL (XML-based) for describing an implicit invocation architecture. That's unnecessarily putting big words around a simple concept, which is why I avoid saying "Domain Specific Language" all that often - people get the concept quite well until it gets all this fluffy terms wrapped around it.
I question your continued use of the term DSL. The broader its target problem, the less specific a DSL. Put differently, if you had a DSL for Web applications that really could generate any application I've written, it wouldn't be very specific, would it?
> There is no application you can write that
> I can't generate. There are parts that it may not
> be worth me generating
This is one of the smartest things I've heard you say. Generation is all fine and dandy when you work on repetitive projects. The apps I work on are so specialized (even when they're master lists and detail views, they have to be "just so" in terms of both UI and backend) to their users and customers that the cost of building a generator would quickly be more than building a well-designed code base, as it'd have to support the same level of variation and tweaking as its outputted lower-level languages.
"Good, cheap, fast. Pick two." Software product lines aren't going to buck that equation.
Comment 22 written by Peter Bell on 10 April 2008, at 8:01 AM
More importantly, for non-trivial systems, the real problems with language design (API design, DB schema design, XML schema design - they all have similarities at a fundamental level) lie around managing change and evolution - especially of syntax, and being able to look at the literature on DB schema evolution, XML evolution and API evolution and to understand that they are all solving similar classes of problems can be extremely useful when trying to create languages that will be tolerant of grammatical change over time. (Have you ever had to write an API that evolves in non-backwards compatible ways but still accepts calls against older versions of the API? There are some patterns, but it isn't a trivial problem to solve!)
As for the "good, cheap, fast", there is a fourth variable which is sometimes forgotten which is efficient. If there wasn't, then a website built in model-glue instead of with a homemade framework would ALWAYS be worse (because it is cheaper and faster) and using Hibernate would also be a technique for lowering quality as it also speeds and cuts the cost of development.
Like the DSLs implemented in model-glue and Hibernate, those in a SPL can also speed up development without lowering quality. How much they can do so obviously depends on the amount of repetition within an application and the elegance of the distinctions within the language used.
Comment 23 written by John Farrar on 10 April 2008, at 6:17 PM
Comment 24 written by Elliott Sprehn on 14 April 2008, at 1:53 PM
This is so blatantly false I'm not sure what to say.
Python doesn't even implement real "private" members, and in fact all objects are hash tables and instance data can generally be accessed directly, or set directly using obj[name] = value.
Ruby has built in functions instance_variable_get, instance_variable_set and instance_variables. Idiomatically there's automatic getter/setter creation, but that's certainly not required.
JavaScript, IO and Lua don't even implement traditional class based object systems with private members.
And most important of all, Objective-C and Cocoa relies heavily on KVC: http://developer.apple.com/documentation/Cocoa/Con... which is a system that is essentially all about generic get/set methods and implements exactly what Peter Bell is talking about.
Which has been used in WebObjects for ages... http://wiki.objectstyle.org/confluence/display/WO/...
WebObjects and Objective-C have been around as least as long as ColdFusion (ObjC much longer), and has had traditional class/component based OO support ages before both Java existed or CF had cfcomponent. Smalltalk, SELF and NetwonScript have been around for even longer!
Explicit Getters and Setters are in *your* very limited "general realm OO programming". It really bugs me how people start preaching their "one and only way" of OO coding in the face of so many other ways of solving the same problem.
Seriously people, get off the pedestal and stop telling everyone else they're wrong just because *you're* stuck in a specific mindset.
Comment 25 written by Joe Rinehart on 14 April 2008, at 3:33 PM
Short version:
Most of the examples you list implement a property system that allows objects to retain an interface (good) while hiding accessor behavior (also good).
The "generic" system discussed hides accessor behavior (good) while stripping objects of their interface (very bad). This basically makes them non-object, as they state no contract on which collaborators can rely.
They're very different things, and stating that they're equivalent is a good-sized fallacy.
Long version:
Python, Ruby, Objective-C, WebObjects, EnterpriseObjects, Actionscript 3, C#, and probably more than a few others do _not_ implement generic getters and setters in any manner that can architecturally be called "exactly what Peter Bell is talking about."
They all implement a much smoother system, commonly called properties or accessors. Many people (including myself - http://www.firemoss.com/blog/index.cfm/2007/11/26/...) in the CF community have asked for. Personally, I think they'd go a long way to advance us as a community past the "let's make CF Java-light" mentality.
Under a system of properties (be it simply "contact.name" or "contact.getName()), an object has an interface and may look internally for the definition of returning the value of the "name" property .
Under the "generic" system, an object may still look internally, but it *lacks an interface* beyond get() and set(). Once objects are stripped of contracts via which they may communicate, it's hard to call whatever is done OO programming.
Taking the idea of "generics" to an extreme makes the problem with them more obvious: why have any real functions or objects at all? Why not just have this "stuff":
myObject = new Thing();
// Set a value
myObject.set("value", value);
// Get a value
myObject.get("value")
// Do something
myObject.do("somethingThatShouldBeAMethod")
If you need examples of how Python, Ruby, or any of the languages you've listed do a good deal more than simply expose table[key], I'd be happy to send them your way.
Comment 26 written by Elliott Sprehn on 15 April 2008, at 10:31 AM
This is not what I said at all, and you're also wrong. I said Objective-C and Cocoa use KVC (WebObjects too) which is "exactly what Peter Bell is talking about," and it is.
If you read the KVC guide I linked it explains what Key-Value-Coding is and how it works.
Your code would be:
[object setValue:@"value" forKey:@"value"];
[object valueForKey:@"value"];
First it looks if the object responds to "setValue:", if not it sets the instance variable directly. For get it looks for a message "value" (Objective-C discourages 'get' prefixes), and if that doesn't exist it calls it directly.
There's also Key Paths that allow recursively going into objects and properties.
For instance:
[obj valueForKeyPath: @"delegate.description"];
This is exactly how EnterpriseObjects works too: http://developer.apple.com/documentation/WebObject...
"The basic methods for accessing an object’s values are takeValueForKey and valueForKey, which set or return the value for the specified key, respectively. Key-value coding uses the first accessor it finds when both setting and getting the value for a given key."
(there was a longer comment I posted previously... but it seems you didn't make it visible...)
Comment 27 written by Joe Rinehart on 15 April 2008, at 11:15 AM
I think you missed my point and stepped right to language-specific details.
For something to be an object, it must have characteristics (properties) and behaviors. Generics remove characteristics entirely - to its collaborators, an object using Peter's generic system *has no properties* because it exposes no meaningful API.
Comment 28 written by Elliott Sprehn on 15 April 2008, at 3:52 PM
That is not the case though. There *are* properties, and they're accessible through get() and set(), and they're documented in the object's API reference.
And it seems you keep dodging the bullet here. I've pointed out many languages with generic get/set systems, one language that uses them heavily and requires it, and several frameworks too.
All your claims are false. This isn't about magic numbers or strings, this isn't about encapsulation, and this isn't about APIs. It's about you just not liking the idea.
Even Hal Helms has promoted the use of generic get() and set() for a number years.
So to bring this back to what I originally said:
"Explicit Getters and Setters are in *your* very limited 'general realm OO programming'. It really bugs me how people start preaching their 'one and only way' of OO coding in the face of so many other ways of solving the same problem."
This applies to you thinking AS3 style property get/set is the only solution as well.
Comment 29 written by Joe Rinehart on 15 April 2008, at 4:26 PM
Peter and I can disagree vehemently about this but not resort to personal flames - I'd like to be able to do the same with you. Please avoid putting words into my mouth. I've never said anything about a one and only way, or that AS3 properties are the only solution. Reading the blog entry I posted after this one would've saved you from making this error.
A Contact with properties looks like this:
Contact {
firstname:String
lastname:String
}
A Contact with Peter's generics looks like this:
Contact {
set():void
get():*
}
The latter is not an API, and does not describe properties. It describes a ball of mush with no form.
All four of my arguments stem from this base. It's nothing to do with the syntax (which it has in common with the examples you've put forther), but rather with the domain model Peter's system leaves behind (which is not a model at all, entirely different from the languages and frameworks you've cited).
(Regarding pulling Hal into this, I believe he uses the <cfproperty /> tag to describe properties. I've done this, too: http://www.firemoss.com/blog/index.cfm/2008/4/10/G...)
Comment 30 written by Elliott Sprehn on 15 April 2008, at 4:56 PM
You seem to be linking the idea of properties and directly accessible methods. The documentation of the object can list out the properties.
Contact {
//properties: String firstname, String lastname.
set():void
get():*
}
Or just list members directly:
Contact {
firstname:String
lastname:String
set():void
get():*
}
This achieves the same goal. This is after all just IDL, not the code itself.
My intent was not to put words in your mouth. You said this:
" it's hard to call whatever is done OO programming. "
"They're just not in the general realm of OO programming."
"stripping objects of their interface (very bad). This basically makes them non-object, as they state no contract on which collaborators can rely."
Sean called them "monstrosities".
How have you not said that your way is not the only correct way? You've essentially stated all the other ways are wrong or bad.
And my point is that generic get/set *are* in the general realm of OO programming. KVC is used in Objective-C, WO and EnterpriseObjects, and is the preferred method for accessing object properties in many cases.
btw, Hal Helms implements an even looser version of what Peter is talking about: (see his BaseComponent.cfc http://www.halhelms.com/)
His version doesn't throw errors if a property doesn't exist. You can just get and set directly. And I'm reasonably sure he's advocated not adding getters and setters at conferences before, stating that set()/get() made more sense.
Comment 31 written by Joe Rinehart on 15 April 2008, at 7:27 PM
(Sorry about not not noticing the second "t"!)
> You seem to be linking the idea of properties and
> directly accessible methods.
I directly link properties and accessible methods - they're the same. Both represent capabilities of an object and its responsibilities.
It's upon this link (everything's a just message recipient - whether it's called a "method" or "property" or "accessor" or "mutator") that the property systems of your favorite examples (Python, Ruby, WO, etc.) rely.
As far as me stating that others ways are bad, I guess I don't have a problem doing so, but at least let me make the statement directly:
Object designs that do not describe a public contract describing the objects' responsibilities (their state and behavior) are weak and a bad idea.
Sean did put it more succinctly.
Comment 32 written by Hal Helms on 17 April 2008, at 12:27 AM
If I need a getter or setter to do something other than directly access an instance variable, I can "override" the implicit getter/setter. But for 98% of cases, a getter is a getter is a getter. Same for setters. In a strongly-typed language, where every method's arguments and return type must be declared, getters and setters are understandable. I think with ColdFusion, we can do better. But I certainly agree with Joe that magic strings and other non-obvious tricks obscure the nature of the type. Over time, I've learned to be very clear about the type's intention so that there are no surprises for users of the code.
Comment 33 written by Hal Helms on 17 April 2008, at 12:37 AM
My points briefly are:
1. Both sides have excellent points.
2. We can have both API declaration and implicit accessors using cfproperty.
3. Code readability should be a major concern.
Comment 34 written by Joe Rinehart on 17 April 2008, at 8:06 AM
Just dropping through real quick.
Your comments didn't show up because I've had to turn moderation on - spammers posted a bunch of links to a site featuring "younger" models, and I can't tolerate that. Sorry for the inconvenience.
[Add Comment] [Subscribe to Comments]