Wednesday, 15 April 2015

Survey results: A quick OO terminology survey

G'day:
I didn't quite get 100 responses, but 95 is close enough (and not bad for over a weekend, during which this blog's readership is pretty dire).

To recap, the first two questions related to this code:

x = new Y()

First I asked whether you were more likely to describe x as:

  • a class
  • a component
  • an instance
  • an object
  • or something else

Second I asked the same question of Y.

The third question was to guess what a CFML function createComponent() might be for.

All of this was asked due to the situation I describe in "Lucee 5 beta: createComponent()".

So, how did you answer?

Question 1

The first two questions gave %age likelihoods that you'd use each term to describe the element in question, ranging from 0% (I'd never use this term) through 25%, 50%, 75% to 100% (I'd always use this term). For scoring the results, I'm gonna tally them up with a weighting: zero points for 0% through to four points for 100%.

As far as the x in x = new Y() goes, the breakdown was thus:

AnswerWeighted percentage
Class0%
Component2%
Instance18%
Object77%
Other3%

95% of people correctly identified it as an object or an instance. 2% went with component.

NB: the "other" votes were all invalidated for a coupla reasons. Some people had said "variable" (which doesn't make sense in the context of the question):

Consider the variable x. What percentage of the time would you use the following terms to describe what that variable "is"?
In that context, declaring that the thing already defined as a variable is a variable is... not helpful.

A coupla other people repeated variations of what they'd voted for in the other options, so treated it as a "add a comment" not a "a different term" sort of option.

My answer was "object, 100% of the time". I might also call it a "Y instance" (that sounds silly; say the CFC was an Vehicle, I'd say "Vehicle instance"), but probably less than 5% of the time, so I just stuck with "object".

Only 2% (weighted) of people thought it was a component. This is significant.

Question 2

As for what the Y in x = new Y() would be described as, we have this:

AnswerWeighted percentage
Class44%
Component37%
Instance1%
Object15%
Other3%

There were a few "other" options here. One person said "CFC" so I weighted that with "component". One person gave 100% weighting to "class" but also 100% weighting to Other" with a value of "type", which doesn't make sense (the %ages, I mean), so I just ignored that one. Someone else said "bean / service / dao" which I think is too precise and at the same time being imprecise because there's no way of knowing from that example what sort of CFC Y actually represents (and this was on purpose). So I discarded that answer too. And one person said "function", which is just wrong, so I discarded it.

I said "class / component" with a 50/50 split.

So 37% of people identify with the term "component" when thinking of a CFC reference in code.

Question 3

In the context of your answers above: if CFML was to have a new function createComponent(), what would you think it would be used for?
There are some interesting answers here:

To create instances of ColdFusion components.
This is, indeed, actually what it is for.

Certainly not creating objects that are instances of an existing component ;)

The name of that function is really throwing me for a loop. I can only think it would be a way to programatically create code inside a component {} (or ) tag. Off the top of my head, I can't think why one would want to do that, but perhaps I'm not thinking outside the box.
This would be what I'd expect. Because a component is the actual CFC.

As an example of how not to design a language.
Well there is that, yes.

Only possible thing I can think of is it shorthand for CreateObject("component","nameofcomponent") ? Bit pointless if so

Create an instance of a class

an answer. (Sorry, I was just being meta {but not class}).
Yeah. Thanks.

That makes no sense. You create components by writing a .cfc / .lucee file.
Yup.

I would have to assume it is to create an instance of a component, as I cannot image a syntax where creating a component (read "class") is done via a function.
Well: quite.

a shortcut for createObject('component', 'x.x') (event though the component part is assumed)

Create an instance of a class, but I can only guess that because that is the subject of this survey, otherwise I would not have any idea.

I would, as I do now, naturally think of it the same as CreateObject(), which, in each case, is really creating an instance of something.

It might create a reference to a component or class, so you can have a name to reference when calling static methods or getting static properties.
Good thinking: this actually makes sense. But sadly it's not what it's for.

Not sure, I don't use that term even though CFC stands for CF Component.

Create Component would be a way to make an on demand component instead of having it in a separate component file. same as component { } probably pass in the items in the brackets and whether it extends something.

Creating an object of a particular class.

Some anonymous/lambda way of creating a component/class. NOT a method to instantiate a new object of that class/component.

I would think that based on a struct of data, one could dynamically create a component/class that doesn't exist within the request which could then be instantiated. For instance: x = new Y("foo"); Y.cfc must already exist | x = createComponent('Y', { name="foo", property1="bar" }) would dynamically create a cfc on the fly.

I expect it would be used for creating instances of objects defined by classes in component files.

Creating an instance of a class, although the function name could be clearer.

creating 'components'

As a badly named synonym for createObject()
And one with no distinction as to what the difference is.

I would assume to create an instance of an object

It should allow you to create a new class/component. Afterwards you would add methods to it like this: A = createComponent(); A.addMethod(someMethod); A.addProperty(name, value); ... b = new A();

If it was in ACF, I'd guess it was used for some half-assed serverside implementation of html 5 web components, or it makes a cheese sandwich
Shurely that'd be <cfwebcomponent> ?!?!? ;-)

create a class "on the fly" ... (?)

It would be unclear, but I would guess at some kind of code generation perhaps.

merging functions to Imitate a cfc file

to create an instance of a component

to create a CFC

It would be used for creating anonymous component like the one anonymous class in java.

(not knowing fur sure) I'd assume that it was someone's idea of a new way to create an instance of a CFC, without needing to indicate it was a CFC in the more generic createobject function, which would seem superfluous,

Adding awesomeness to my home entertainment (a/v) system.

Shorthand for createobject('component', ...)

nfi

maybe an inline cfc, meaning you would be able to create a cfc in the middle of another cfc or cfm page

creating a new instance of a component / class

Dont know

Can't really think of a use case. Maybe create a reference to a static class although not sure why you'd do that.

It will be used for creating the instance of a class.

Creating a new class / component

New up a class

Dynamically generating components.

Defining cfc code at runtime

I think it's used for instance creation of some component. But it's quite confusing for me because my view is that component is nothing more than declaration or class, neither object.

I would think it would be very similiar to new whatever() as shown above. I would struggle as to how it was different

Creating components

Instantiate an instance of a "component", where that would contain several objects and methods.

create an object based on a component template

Shortcut for createObject("component", ..)

when called with a string it would act as a chainable function call version of calling new Component(). it would also fire the init method. alternatively, it could be used to define components inline when a struct is passed in. something similar to Object,create in javascript. i.e. createComponent({ instanceVar: true, inheritsFromNothing: true, doSomething: () -> {} })

A shot cut for createObject.. "Componet"

I would assume it would do what a .CFC file does natively, to create a new "package" so-to-speak of functions or object properties. Cool idea!

Replacement for createobject, but not initializer.
Oops. It's like createObject() but with the init() being called as well. So analogous to new.

Create a new class I guess? But that doesn't make much sense.

Quick way to define an object with properies an getter/setter. Maybe like a CaseClass on Scal.

You mean CF Builder, right?

a dynamic object with either magic functions or properties, maybe passed with arguments or bei init-function.

Based on its name, I would assume it would be used for creating a component, but in the context of CFML I'm not sure what that would mean. In CFML, components are what other languages call "classes", so I'm not sure what a function with that name would do since I'm not sure how a function /could/ create a component/class. Functions named createInstance() or createObject() and which took an argument indicating the class/component from which the instance/object was to be created would make sense.

No fucking clue really, even though we have "components" I always think of these fuckers as modules or plugins for some goddamn reason.
Are you fucking channeling me with shit language like that? (is that you, Quackenbush?)

Creating a new component definition.

Instantiate a component

To create new components with functions inside.

In CF's usual back-asswards way of naming things (like old-style loops with "item"="collection key" & "index"="array item"), it creates an object of some kind (CF component, web service, Java class, ...) without initializing it and returns it so the result can be assigned to a variable. Still has its uses in many situations, like when you only want to inspect the underlying metadata.

To me a component is a CFC file containing one or more functions, so I'd presume it would just another alias for createObject.

Well I already know what it does and the name is wrong and the reason for having it is unclear. All it seems to do is the same as the new keyword but as a function instead and personally I don't see the point. If this is seen as "required" functionality why not just extend the attributes for createObject instead.

Used instead of "new"

Same as new above and/or create object "component"

Create new Y would be consistant with MY terminology, but I bet it just creates a new instance (again according to my terminology heheh..

Two thoughts. First, a very long way of creating a new instance as with the original example. Second a way to create an in-memory dynamic component definition without a cfc?

I dont really see the point but maybe I'm missing the point.

To create new classes, defined at runtime.

Dynamically creating a component.

The naming scheme makes me think of createObject but for creating CFC instances only as the term component is used.

Sounds like writing a cfc file to the file system. The distinction is easier to make in Java. You make a .java file, compile it to a .class file. A class here is a classification of object types - like a Fox class is an animal but a fox named Dennis is an individual object, an instance of a classification of Foxes. ColdFusion muddied the water by calling them components. Are they types in an OO system? Are they endpoints for web services? Do they handle flash remoting and JSON requests and REST services? Can you include them in your pages and pretend they are function libraries? Yes, yes and yes to all of that. They are the everything file, not just classes. -Nathan Strutz

To confuse developers?

Creating a class

It is named as though it would create a component (or class), rather than an instance

To be honest I have already seen your blog post on this, so I know the answer. Previously I would guess at a different naming of create object

Instantiating a class, using a string as a path, much like or createObject. However....if it could be used to BUILD a dynamic CFC and then instantiate it, that'd be the shiznit. Would GREATLY (maybe) increase the use of composition.

I've not got a great understanding of cfml so I would find this confusing. How would this tie in with creating functions inside a CFC?

To create a new component ( which is a class ). I would not expect it to return a new instance of the component or to create an instance of a different component.

To create a new object

I think createComponent() would instantiate an object/instance of a component and not actually create a component.

Creating an instance of the class

maybe a in memory object, so not needing a .cfc file for it. Like this: Obj = createComponent(); Obj.addProperty("name"); inst = new Obj(); inst.setName( "Adam" );

A longer name for new.

I was going to say "create a class" but that makes no sense since you don't really create a class, it's just there for you to call static methods on.

It would create an instance of a component and essentially be equivalent to new component(), and therefore be redundant.

instantiating methods inside a class.

To create a new instance of a component (CFC), like: x = new Y()

The same thing as createObject() probably. Although the way I use the terms, createComponent() should probably be seen as creating a new CFC file or something but that doesn't make sense.

Further muddying the OO nomenclature.

An instance of an existing cfc

[I know the answer, so my response can't really count] I'd expect it to do something different from the existing createObject() function. Perhaps the equivalent of creating a class object in Java?
(that's my answer)


The answer is...

This:

x = createComponent("Y", {arg1=1, arg2=2})

Is the same as this:

x = new Y(arg1=1, arg2=2)

Well, in a way, it's more the same as:

x = new "#Y#"(arg1=1, arg2=2)

Where the argument here is a runtime string containing the name of the CFC one wants to instantiate. This is as opposed to createObject():

x = createObject("Y").init(argumentCollection={arg1=1, arg2=2})

Because one needs to explicitly call init() if one wants to... call init(). new calls it implicitly. So does createComponent(). So it's basically a variation of createObject(), except with a different name.

I'll get back to my position on this in a bit.

Looking at the results, a lot of people did actually guess what the function would be for, but a number of people also questioned the need for it. This is a legitimate reaction, and should be a warning sign. I wonder how those people will react now that it gets explained to them (add a comment!).

What's most interesting here is that a lot of people correctly assess that something called createComponent() ought to do what it says on the tin: create a component. This is why I asked to clarify people's understanding of "objects" vs "components" (and threw some other terms in there as well to make it less obvious what I was asking).

Plainly put: a component is the code in the CFC file. It's what describes what an object of that type will be. An object is a realisation of that component: an instance of it in memory. In other languages, eg Java, there is actually a type of object "java.lang.Class", which is an object representation of the class definition. It has methods for returning info about the class, which can then be used for [whatever reason]. It's metaprogramming, really. CFML does not have this concept, however if it did, I could see that createComponent() might return a CFML equivalent of a Class object, for the given CFC.

So what could createComponent() be meaning then, if we actually look at the tin, and see what it says on it? Well just like it's possible to have function-literal expressions:

f = new function(){
    // do stuff
}

This defines a function at runtime, rather than at code-time.

It could also be possible to define a component at runtime. Something like this:

c = component {
    // some properties
    // some functions
    // etc
}

o = new C()

Here c is a component, and o is an object which is an instance of this component. This idea was actually something that I was expecting in Lucee 5, as Gert had said it was going to be in Railo 5.

So createComponent() might be a kind of function version of that. I can't actually work out how it would work, but perhaps like this:

c = createComponent()
c.addMethod(function=function(){}, access="remote")
c.addProperty({type="string", public=true,default="foo"})
// etc

o = new C()

But I think even then the function would be misnamed: it sounds more like createComponentFactory() or something like that. I dunno. That's not what it is and it sounds like a bad way of going about things, so I shan't dwell on it.

Note: in the interim, Micha has now offered to change the name to loadComponent(). This is not really any better, and still suffers from the inappropriate usage of "component". I also think "load" implies something relating to loading data from storage, not creating objects. createObject() sounds like it relates to creating objects. Funny that, eh?

OK, so that's it for that survey. Thanks for all the feedback, and it made for interesting reading. I'm also heartened that I don't seem to be a lunatic in going "WTF?" with this mooted functionality. Or at least if I am a lunatic, I'm in good company. Well: "company", anyhow.



But let's go back to the mooting of this functionality. I think this is where this entire exercise goes off the rails.

I think the need for this functionality - given it's already adequately covered by existing functionality - is questionable. When asked, Micha said it was sponsored work: one of his clients requested. I think it's great that he's getting paid work, but that should not automatically mean the results go into the product. It has to sell itself on its own merits.

If the burden of demonstrating the functionality has merit is met, then the given approach still needs to be examined. Basically an object in CFML has two different states: uninitialised (what one gets if one simply creates it with createObject()), and initialised: what one gets having created it with new. A sticking point here is that Micha - for reasons he has yet to validate - thinks that only the "initialised" state is desirable. By implication, createObject() currently does the wrong thing.

OK, so let's say we have decided that simply having new to effect this functionality is not enough, and we need a function version too. If the problem is that createObject() doesn't quite do the right thing, then surely the solution here is to fix createObject()? I don't understand how we get to "we need a new function".

Micha has cited a number of reasons why fixing createObject() is not a viable proposition:

  1. backwards compatibility.
  2. createObject() is already a mess (syntax variations; that it handling components, Java proxies, web service proxies, .Net... um... I guess they're proxies too, etc), so it's bad to make it worse.
  3. he's separated the Java and web service stuff out into their own functions, so it makes sense to separate the CFC version out into a new function too.
None of these are valid, as far as I can tell.

Backwards compatibility

o = createObject("component", "path.to.component") // leave it to work as it is now
o = createObject("path.to.component") // leave it to work as it is now
o = createObject("java", "path.to.class") // leave it to work as it is now (same with webservice, dotnet variations, etc)
o = createObject("path.to,component", args) // new functionality, calls init(), passing the args

There is no backwards compat issue here. Also given it's a small behavioural change, it makes sense to treat it as such. Also it's reasonably predictable that "if you don't pass init args, it doesn't get init-ed; if you do pass init args, it does get init-ed". More predictable than having one function to return an uninitialised object, and a completely different function to return an initialised one.

Micha has said that one cannot have one version of createObject() call init(), and another version not. However he has failed to explain why this is intrinsically true. Functions vary their behaviour according to which variation of them is called (as per their function signature) all the time. This is why languages like Java permit same-named methods with different signatures! He would have to make a very good case indeed to contradict that, and so far has not.

He has also said "it's not possible", but has neglected to explain why. I don't believe it's "not possible", but am prepared to be corrected on that.

createObject() is a mess

This is actually invalidated by the third point. It's a mess because it does all these different things: returns objects, returns Java proxies, web service proxies etc. But all of that is being deprecated in favour of other functions. So that mess is, for all intents and purposes, gone. I know "deprecated" does not mean "it's already gone", but that's beside the point. Given createObject() is now positioned as a function which only deals with CFCs, it only has two variations. That is not "a mess". Having a new function to perform almost the same job is "a mess".

I suspect also Micha is looking at the Java source code for createObject(), and I imagine what they have had to do to get it working in every way CFML currently needs it to makes for grim reading, and he doesn't want to make it worse. If this is the case, Micha is slightly misunderstanding his job. What he's delivering is CFML. He's not - really - delivering the source code which leads to CFML. What's important is that the CFML language is clean and coherent; whether or not his code is is neither here nor there as far as the deliverables go. So CFML shouldn't be polluted so that he gets to write cleaner Java code.

The other functionality has moved out of createObject(), so the CFC-oriented functionality should also move

This doesn't stand up to logical scrutiny. And, indeed, that the other functionality has been moved out suggests to me that leaving createObject() to handle just CFCs - which is what it will currently be primarily used for in almost all CFML written that uses it - makes the most sense.



In conclusion, I cannot see any valid reason why this function has been added. The need for a change of functionality at all is questionable, but the execution of that change is poor, and is bad for CFML.

Thoughts?

--
Adam