i always thought invokeImplicitAccessors was a stu...
# cfml-general
w
i always thought invokeImplicitAccessors was a stupid idea from the get go. you've got the THIS scope if you need external exposure, and you have multiple options for referencing variables-scoped/property values within the cfc depending on how terse you want to be with your code. all this accomplishes is to make cfc variable scoping even more confusing and unintuitive for the masses, particularly new cf devs (as if there were any)
a
I think in that you dwell on the notion of "scopes" when you say that, you perhaps aren't quite getting what's going on. This has nothing to do with scopes. What it does have to do with is allowing the class to maintain control of its data encapsulation, which you don't get if you anti-pattern things by just slinging stuff in the
this
scope.
w
i guess. i've never seen a 'good' use of the THIS scope outside of application.cfc, but that's just me perhaps
a
That was a reference to your own observation: "you've got the THIS scope if you need external exposure"
Anyway, whatever you or I might think, having accessor/mutator methods accessed implicitly via
obj.property
rather than explicitly
obj.getProperty
/
obj.setProperty
has a fair bit of industry traction, by way of cutting down on boilerplate.
Personally, for dumb "data structure" type object (just data, no behaviour), I have NP making the properties public. Some ppl pedantically make everything private and then re-expose everything for read/write via getters / setters. UGH. Using
invokeImplicitAccessors
, one gets the brevity of accessing the properties directly, and the flexibility of still controlling what access one has when that becomes a consideration.
w
maybe i'm just dense. implicit accessors return
THIS
and allow you to therefore chain set() methods for example. it may just be how you've written your article examples but they all return void, thereby disallowing chaining, even if the syntax you're using to assign values isn't the only way. anyway, i guess i'm just missing where the boilerplate omissions gain you anything other than modelling some cf behavior to be more aligned with other languages
arguably the least amount of overall code is what you get using accessors=true
a
Oh, I was just writing minimum code necessary to demonstrate what I was talking about. I had no need to demonstrate method chaining as it was not relevant.
w
nothing i'd go to the mat over, but just not getting it
can you method chain using the examples in your code?
a
arguably the least amount of overall code is what you get using accessors=true
It's the opposite. Every time you want to access the property you have to go
myObject.getTheProperty
. That's what all this is trying to avoid
w
Copy code
person = new Person()
person.firstName = "Annie"
person.middleName = "Jean" 
becomes this
person.firstName("Annie").middleName("Jean") 
?
is that right?
a
I understand what you are saying. Why would you want to do the latter?
w
'less code'
i've never used the techniques you're outlining, i'm seriously asking
a
less readable code.
w
guess that's debatable, but you're entitled
a
You are trying to convert this:
Copy code
person.setFirstName("Annie").setMiddleName("Jean")
I think
w
to that position that is
i'm desperately trying to see the benefits of what your article was on
if it's just a way to express
person.setFirstname( "Annie" )
as
person.firstName = "Annie"
and
person.getFistname()
as
person.firstname
then fine, i have no objections i could mount
if not, then i'm still not seeing it (not your problem)
a
OK so back up a bit. There's a notion in OOP "Tell Don't Ask" (https://martinfowler.com/bliki/TellDontAsk.html). Calling getter/setter methods from calling code is an enabler for doing the work in the wrong place: the calling code gets/acts/sets the object's data instead of letting the object take care of it. So explicitly (over)using the getter/setter approach is considered a bit of an antipattern in general. It's def a code smell warning sign. However obviously an object needs to have properties, and they - sometimes - need to be read/written. The thinking is here is that when one defines one's property, one also defines one or both of the "get" and "set" behaviours. Something like:
Copy code
string firstName {
    get() {
        return firstName
    }
    set(value){
        firstName = value
    }
}
(both are optional) Here the behaviour for writing and reading to the property is self contained in the property definition. THIS is actually the important part of the functionality. CFML does not do a very good job of this, as I mentioned in the article: the
getFirstName
and
setFirstName
methods are "separate" from the property definition due to poor / absent design. What this means for the calling code is one doesn't have to faff around explicitly calling methods on the object, one just focuses on saying to the object "here have this" and "can I have this please?" This is all just nuance though, sure. --- Also one calls the code far more often than one writes it, so there definitely is also a perceived benefit in the calling code being able to just go
myObj.myProperty
to read it, and
myObj.myProperty = "new value"
to write it. Instead of
myObj.getMyProperty
and
myObj.setMyProperty("new value")
. Admittedly there is not much to it. Also at the end of the day, it's the property value yer interested in, so just... deal with the property value. Having explicit accessor methods is only a thing in the first place because or incomplete language design in CFML (properties came in in CFMX6, only got their implicit accessors in CF2016!). I guess the whole thing is one simply doesn't need to explicitly call the accessor methods any more. So why would one? --- I think there's perhaps little gain when already being in CFML before knowing about the functionality, and going "why should I change?", compared to coming from other languages where it's already a thing, and the way things are done.
It was summed up for me when I went from looking at Java code (getters and setters all over the shop, expecially in not-particularly-OO code) to C# which went "oh god we're not gonna make them do that" right from the outset.
Kotlin's done the same. For the same reason.
(and any number of other languages too for that matter)
Also this conversation is overbaking things a bit. It is not a "killer feature", it is - especially in CFML - syntactic sugar, for all intents and purposes. I did allude to this in the article.
w
i just wasn't seeing any major benefit from my standpoint and thought i was being too stupid to see it, wasn't trying to make it a bigger thing than it is
a
oh, nono. I did not mean that
w
thanks for the clarification above. i don't think there's anything wrong per se with what you describe (tell don't ask), and clearly other languages don't either
a
Just that with all the back and forth, I didn't want it to sound like I thought this was some major make-or-break thing.
It just required a bunch of words to try to articulate the situation (as I see it)
w
there's so many small things we can make a big thing out of, why would we choose this one?
or am i treading too far into your territory...?
a
If in 2002 CFMX6 had been released with this approach to things:
Copy code
string firstName {
    get() {
        return firstName
    }
    set(value){
        firstName = value
    }
}
And in 2022 someone from PHP / JS land came along and went how do I call
myObj.getFirstName()
we'd be going "oh... how quaint..."
w
no argument
a
Oh I literally only wrote today's article for the reasons cited in the first two sentences of the article, and no other reason:
I noticed this yesterday when I was writing my "Kotlin: the next morning learning Kotlin stuff" article. I was looking into how Kotlin handles accessor methods on properties, and remembered CFML had a similar bit of functionality, and quickly revisited it by way of comparison
It's a feature that has zero documentation. So I wrote some.
That was it.
Now if someone ever googles "how the fuck does this shit work", they'll find something.
w
somebody has to write the documentation, i guess
a
Well Adobe ain't gonna.
w
it's on the todo list
a
And as indicated in the article, they do have form for just stealing shit from my blog articles anyhow, so why not enable them 😉
I think there's an element of "someone is wrong on the internet" going on in my head too. Maybe. Just maybe.
w
you'll need some consistent easter eggy var naming convention to make it more clear
or just use profanity as the var names, that could be satisfying
and you won't alienate anyone already familiar with your work
a
I think it's safe to say that if Annie Jean Easley's name shows up in the Adobe docs anywhere, we will know where their "inspiration" came from.
w
i just feel like a search for Shitty Ass McFuckaroo might yield a much more targeted search result. i would speculate it would only be found on two domains.
a
HAHAHAHAHAHAHAHAHAHA
g
I wonder if it would break anything to fix it, "properly"? (doing away with the original setter/getter()s and "just" writing them, right?) I am "betting" (asking?) they don't actually "code" individual constructs and can just make the changes in "a" template to get rid of "all" the previous code and replace it with the "proper" way. Anyway - again - learning something new.... I never bothered to go into how accessors/mutators were "actually" implmented!
l
Isn't one of the advantages of using - for example - a getter, that if later on your requirement changes so that you always have to return the
lastName
upper-cased (contrived, ya...) then you could just override the implicit accessor with a hard coded one that
UCASE
the returned value and therefore not change any calling code. But if some/all of the calling code were using implicitAccessors then you'd have to make a number of changes? Or is there a way to work around that with implicitAccessors?
g
I am not speaking authoritatively, here... BUT I THINK... There is a Pre/post method "thing" that can be used? something like onMissingMethod()? As I type this - I am thinking perhaps I am mis-remembering - perhaps what I am thinking of is a "lifecycle" interceptor(s) from a "framework"? Even so, perhaps - you're using a framework that has this sort of thing for your the use case in your post?
a
@leftbower the point is that one just starts with a public property from the outset. If simply accessing and setting the value (with no further modifications) is all you need to do... then... crack on with it. So:
myObj.someProperty = "value"; writeOutput(myObj.someProperty);
If later you need to apply some behaviour to either access or change, then you add the relevant method. But the calling code remains
myObj.someProperty = "value"; writeOutput(myObj.someProperty);
One doesn't start by creating boilerplate code (
myObj.setSomeProperty("value"); writeOutput(myObj.getSomeProperty());
) one doesn't need, just for the sake of it.
t
omg, I thought I was crazy. But I was just wrong. I thought I had seen demoed somewhere that with
accessors=true
, it automatically added properties to
this
, so they could be get and set that way. But I couldn't get it to work, and couldn't find any documentation for it. But that's because it was actually this thing!