Showing posts with label ColdFusion. Show all posts
Showing posts with label ColdFusion. Show all posts

Friday 24 March 2017

Help explain closure to the Adobe ColdFusion Team

G'day:
OK, this is a CFML-centric article. But it's also a call to provide code analogies in different languages to a CFML example, to show the ColdFusion Team they dunno what they're on about.

Here's some CFML code:

function doit() {
    var a = ["a", "b", "c"];
    var b = ["x", "y", "z"];
    var counter = 0;
    
    arrayEach(a, function(foo) {
        counter = 0;
        arrayEach(b, function(bar) {
            counter++;
            // in dump counter is always 0
            writeDump({
                counter: counter, 
                foo: foo, 
                bar: bar
            });
        });
    });
}
doit();

This leverages closure to reference the outer counter variable within the innermost function expression. Ergo, it's the same variable. So the expected output of this would be:


Note how the counter is declared in the main function, reset in the outer arrayEach handlers and incremented for each iteration of the inner arrayEach call. So it'll cycle through 1,2,3 three times when output.

That was run on Lucee. Running it on ColdFusion yields:


See how the counter is messed up: it's always zero. It should increment for each iteration of the inner function expression.

Adobe - being their typical selves - is claiming this is "by design":

https://tracker.adobe.com/#/view/CF-4197194:


That's nonsense.

Other languages behave predictably:

JavaScript:

function doit() {
    var a = ["a", "b", "c"];
    var b = ["x", "y", "z"];
    var counter = 0;
    
    a.forEach(function(foo) {
        counter = 0;
        b.forEach(function(bar) {
            counter++;
            // in dump counter is always 0
            console.log({
                counter: counter, 
                foo: foo, 
                bar: bar
            });
        });
    });
}
doit();
VM128:11 Object {counter: 1, foo: "a", bar: "x"}
VM128:11 Object {counter: 2, foo: "a", bar: "y"}
VM128:11 Object {counter: 3, foo: "a", bar: "z"}
VM128:11 Object {counter: 1, foo: "b", bar: "x"}
VM128:11 Object {counter: 2, foo: "b", bar: "y"}
VM128:11 Object {counter: 3, foo: "b", bar: "z"}
VM128:11 Object {counter: 1, foo: "c", bar: "x"}
VM128:11 Object {counter: 2, foo: "c", bar: "y"}
VM128:11 Object {counter: 3, foo: "c", bar: "z"}


And PHP (apologies for the rubbish way PHP does closure):

function doit() {
    $a = ["a", "b", "c"];
    $b = ["x", "y", "z"];
    $counter = 0;
    
    array_walk($a, function($foo) use (&$counter, $b) {
        $counter = 0;
        array_walk($b, function($bar) use (&$counter, $foo) {
            $counter++;
            // in dump counter is always 0
            var_dump([
                "counter" => $counter, 
                "foo" => $foo, 
                "bar" => $bar
            ]);
        });
    });
}
doit();


array(3) {
  ["counter"]=>
  int(1)
  ["foo"]=>
  string(1) "a"
  ["bar"]=>
  string(1) "x"
}
array(3) {
  ["counter"]=>
  int(2)
  ["foo"]=>
  string(1) "a"
  ["bar"]=>
  string(1) "y"
}
array(3) {
  ["counter"]=>
  int(3)
  ["foo"]=>
  string(1) "a"
  ["bar"]=>
  string(1) "z"
}
array(3) {
  ["counter"]=>
  int(1)
  ["foo"]=>
  string(1) "b"
  ["bar"]=>
  string(1) "x"
}
array(3) {
  ["counter"]=>
  int(2)
  ["foo"]=>
  string(1) "b"
  ["bar"]=>
  string(1) "y"
}
array(3) {
  ["counter"]=>
  int(3)
  ["foo"]=>
  string(1) "b"
  ["bar"]=>
  string(1) "z"
}
array(3) {
  ["counter"]=>
  int(1)
  ["foo"]=>
  string(1) "c"
  ["bar"]=>
  string(1) "x"
}
array(3) {
  ["counter"]=>
  int(2)
  ["foo"]=>
  string(1) "c"
  ["bar"]=>
  string(1) "y"
}
array(3) {
  ["counter"]=>
  int(3)
  ["foo"]=>
  string(1) "c"
  ["bar"]=>
  string(1) "z"
}


But I'm quite keen to know if there's any language that behaves as ColdFusion does in this example? If you've got a mo', could you knock out an equivalent of this code in [your language of choice], and share the results?

I'm 99.999% sure Adobe are just not quite getting closure, but wanna make sure I'm not missing anything.

Righto.

--
Adam

Monday 29 February 2016

ColdFusion has 2000 new "customers" per quarter. Apparently.

G'day:
I was surprised to read this, from Rakshith:

[...] we get 20000 new customers ever year [...]
My ellision there does not change the context of what he said at all. It was just in the middle of a comment about something else.

This, obviously, raised some eyebrows. This morning Rakshith modified this claim:

@ Everyone: I stand corrected about new customers. I wanted to say 2000 new customers per quarter. We do not add 20000 new customers but rather it is 2000 new customers per quarter or 8000 new customers per year. I apologize for the confusion.

And yes, I am only referring to ColdFusion new customers here.

That is a bit less unbelievable than 20000, but I'm still keen to hear how they measure that.

I have asked for further clarification.

Interesting though, eh?

One thing I'd say about this though is that - if it's true - then... where are the people joining the online / visible community. If we are harsh and say each of those is a licence, and each of those means one developer doing the work... even if only 1% of them were interested in the online side of the community, we'd still see 20 new faces per quarter. Which... we're not, as far as I can tell. More's the pity.

Still: I think this is more a case of Rakshith presenting conveniently described numbers which do not in reality reflect what one might expect "2000 new customers per quarter" to actually mean.

Update:

Rakshith has just updated:

@Adam: New customers in this context are entities or organizations that have never bought ColdFusion from us in the past. Each such customer has bought one or more units of Standard or Enterprise. 8000 new customers will mean more than 8000 new units purchased.

Blimey. Where are they all?


--
Adam

Tuesday 23 February 2016

Adobe personnel who are relevant to ColdFusion

G'day:
It's bloody difficult to get out of Adobe exactly who is on the ColdFusion Team, and in what capacity. Very few of them are particularly forthcoming about their roles (or indeed, communications in any real way).

I've done some detective work (read: googling), and these are all the people I can find that have done something to do with ColdFusion over the last year or so, and are currently in Adobe's employ.

This information is in the public domain, so I don't think it's inappropriate to share it?


  • Akhila K Srinivas - Software Engineer
  • Anit Kumar Panda - Manager Technical Support at Adobe
  • Awdhesh Kumar - Senior Developer
  • Chinoy Gupta - COMputer Scientist
  • Dattanand M Bhat - bugbase
  • Deepraj Jha - bugbase
  • Elishia Dvorak - Solution Consultant at Adobe
  • Hari Krishna Kallae - Lead Software Engineer at Adobe
  • Himavanth Rachamsetty - Software Engineer at Adobe Systems
  • Immanuel Noel - Lead Software Engineer at Adobe
  • Jacob Jayakar Royal - (dunno Jacob's title, but he looks after the ColdFusion docs site)
  • Kailash Bihani - bugbase
  • Kishore Balakrishnan - Senior Product Marketing Manager at Adobe
  • Krishna Reddy - bugbase
  • Mayur Jain - Computer Scientist at Adobe
  • Milan Chandra - bugbase
  • Nikhil Siddhartha - Member of Technical Staff
  • Nimit Sharma - bugbase
  • Paul Nibin K J - Computer Scientist
  • Piyush Kumar Nayak - bugbase
  • Poonam Jain - Software Engineer
  • Priyatharsini K - bugbase
  • Rahul Upadhyay - Product Consultant at Adobe
  • Rakshith Naresh - Product Manager at Adobe Systems
  • Rupesh Kumar - Engineering Manager at Adobe Systems Inc
  • S Preethi - bugbase
  • Sandeep Paliwal - ColdFusion Engineering
  • Sandip Halder - Adobe ColdFusion product Consultant
  • Saurav Ghosh - Community Lead
  • Shambhuling Nashi - Quality Engineering Manager
  • Suchika Singh - Software Engineer
  • Suresh Jayaraman - Senior Engineering Manager
  • Tridib Roy Chowdhury - G.M. & Sr. Director Of Products at Adobe
  • Uday Ogra - Computer Scientist
  • Vamseekrishna Nanneboina - Quality Engineering Manager for ColdFusion, Adobe
  • Kapil Arora - Sr. Computer Scientist (Kapil runs the bugbase, but is not directly on the ColdFusion Team)


That's a whole bunch of people! Where I have listed job titles, that was from either their own LinkedIn page, or a bio page on the Adobe website. Where I've just listed "bugbase", that's the only place I could find their name. It's quite interesting how a lot of them don't actually mention "ColdFusion" on their LinkedIn profiles. For example even Rakshith doesn't mention it in his initial bio summary! I dunno what to make of that.

There have been a coupla departures from the ColdFusion Team in the last year: I have not listed those people.

Anyway... these seem to be the people that bring ColdFusion to you. Cheers all.

Righto.

--
Adam

Thursday 28 January 2016

ColdFusion: help with clarifying if an issue exists with CF's ORM implementation

G'day:
If you know something about Hibernate and/or using ColdFusion's wrapper around same, perhaps you could cast your analytical eye over this, and help determine whether Mingo has - as it seems - found a bug in it, or whether Himavanth has some basis to what he's saying, and it's not just a case of him (willfully choosing to ~ ?) not understanding what Mingo is saying, and there's actually no problem. Can you guess which side I come down on?

Here's the detail:

4024472: ORM entities are incorrectly created when using single table inheritance with mappedSuperClass

Problem Description:

When you have a base component (base.cfc) with MappedSuperClass set to true, a
persisted component (animal.cfc) inheriting from that and another (dog.cfc)
inheriting from that one ColdFusion throws an exception (a Hibernate one).
To make this bug more fun, CF doesn't always throw this exception.

The reason why this happens becomes clear when you set
this.ormsettings.savemapping=true and take a look at the hbmxml files.

The XML in dog.hbmxml contains the fields from base.cfc:
<property name="name" type="string"><column name="name"/></property>


Steps to Reproduce:

Use the files included with this bug [I'll include 'em inline here].


// base.cfc
component mappedSuperClass="true"
{
  property fieldType="id" name="id" generator="increment";
  property fieldType="column" name="name";
}

// animal.cfc
component extends="base" persistent="true" table="animal" discriminatorColumn="type"
{
  property fieldType="column" name="isAlive" type="boolean" default=true;
}

// dog.cfc
component extends="animal" persistent="true" table="animal" discriminatorValue="dog"
{
  property fieldType="column" name="furColor" default="brown";
}

Actual Result:

An exception: Repeated column in mapping for entity: {entity-name} column: {column-name} (should be mapped with insert="false" update="false")

Expected Result:

Correctly generated hibernate entities.

Any Workarounds:

You can write your own .hbmxml files to work around the problem.

Further information


For clarity: the dog entity gets the following HBM XML generated:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping default-cascade="none" default-access="property" default-lazy="true" auto-import="true">
 <subclass discriminator-value="dog" entity-name="dog" extends="cfc:18502eb2916b8041cf1e.animal" lazy="true" name="cfc:18502eb2916b8041cf1e.dog" dynamic-update="false" dynamic-insert="false" select-before-update="false">
  <property name="name" type="string" unique="false" optimistic-lock="true" lazy="false" generated="never">
   <column name="name" />
  </property>
  <property name="furColor" type="string" unique="false" optimistic-lock="true" lazy="false" generated="never">
   <column name="furColor" />
  </property>
 </subclass>
</hibernate-mapping>


Notice the extra name property, that's not supposed to be there, because that should be inherited from the animal class.

My knowledge of ColdFusion's ORM is pretty theoretical as I've never used it beyond testing it, and my knowledge of Hibernate is scant (I've scanned a Hibernate book whilst testing the initial ColdFusion 9 implementation).

The most telling thing is that Lucee does what Mingo expects, and it works. That kinda suggests ColdFusion has got it wrong. It would seem too coincidental that Mingo's expectations are off, and it just so happens Lucee's implemented things in such a way that match Mingo's expectations. Occam's Razor 'n' all.

So perhaps you lot can eyeball this and the rest of the detail in Mingo's ticket, and offer your input?

Cheers.

--
Adam

Wednesday 27 January 2016

ColdFusion: how not to document a function

G'day:
We've finally nailed down an Adobe ColdFusion Team member on the #documentation sub-channel of the CFML slack channel. So if you have issues with the documentation, post there, and direct it to +Jacob Royal (ooh: Google added that link for me automatically. Cool!).

Coincidentally this morning I read of a CFML newbie trying to write code, assisted by said documentation (ColdFusion parsing JSON). It's a reasonable question, and the root of the problem is they tried to use the online ColdFusion docs to learn how to do something. Worse: they tried to glean how the deserializeJson() function works from reading the code example. One cannot really fault a newbie for RTFMing, but this is often not a helpful thing to do when trying to learn CFML. Because the code examples on the Adobe ColdFusion documentation site are, generally, sh!t.

Here's the code example. How quickly can you spot the actual usage of deserializeJson():

<!--- Get the JSON Feed --->
<!--- JSON data is sometimes distributed as a JavaScript function.
The following REReplace functions strip the function wrapper. --->
<cfset theData=REReplace(cfhttp.FileContent,
"^\s*[[:word:]]*\s*\(\s*","")>
<cfset theData=REReplace(theData, "\s*\)\s*$", "")>
<!--- Test to make sure you have JSON data. --->
<cfif !IsJSON(theData)>
<h3>The URL you requested does not provide valid JSON</h3>
<cfdump var="#theData#">
<!--- If the data is in JSON format, deserialize it. --->
<cfelse>
<cfset cfData=DeserializeJSON(theData)>
<!--- Parse the resulting array or structure and display the data.
In this case, the data represents a ColdFusion query that has been
serialized by the SerializeJSON function into a JSON structure with
two arrays: an array column names, and an array of arrays,
where the outer array rows correspond to the query rows, and the
inner array entries correspond to the column fields in the row. --->
<!--- First, find the positions of the columns in the data array. --->
<cfset colList=ArrayToList(cfData.COLUMNS)>
<cfset cityIdx=ListFind(colList, "City")>
<cfset tempIdx=ListFind(colList, "Temp")>
<cfset fcstIdx=ListFind(colList, "Forecasts")>
<!--- Now iterate through the DATA array and display the data. --->
<cfoutput>
<cfloop index="i" from="1" to="#ArrayLen(cfData.DATA)#">
<h3>#cfData.DATA[i][cityIdx]#</h3>
Current Temperature: #cfData.DATA[i][tempIdx]#
<b>Forecasts</b>
<cfloop index="j" from="1" to="#ArrayLen(cfData.DATA[i][fcstIdx])#">
<b>Day #j#</b>
Outlook: #cfData.DATA[i][fcstIdx][j].WEATHER#
High: #cfData.DATA[i][fcstIdx][j].HIGH#
Low: #cfData.DATA[i][fcstIdx][j].LOW#
</cfloop>
</cfloop>
</cfoutput>
</cfif>

Note: I have not lost any formatting there... that's how it's presented in the docs.

What a f***ing mess. There's 43 lines of code there, and it's not until line 17 that deserializeJson() is actually used. Every single other line in there is a complete waste of time. What the hell has HTTP calls, treating the result like JSONP and mark-up got to do with deserialising JSON? Nothing.

Also note at no point do they actually show what the result of that bullsh!t might be.

The example should be this:

someJson = '{"stringValue":"a string", "arrayValue": ["a","b","c"], "booleanValue":true, "numericValue": 42}';
myStruct = deserializeJson(someJson);

writeDump(myStruct);

And simple show the output:


There should then be additional simple - and separate - examples showing the other options such as how to deserialise a previously serialised query, so that the deserialised object becomes a query again, not a struct of arrays of structs (or however the hell ColdFusion handles it).

And another example of using a custom deserialiser. Although even that is probably out of scope for this page, instead linking through to a broader section on custom serialisers.

None of this is rocket science. Even making the comparison to rocket science is like comparing... oh, I dunno... scribbling on a sheet of paper with a crayon to rocket science.

Almost all the docs for ColdFusion are like this. Crap.

cfdocs.org is better in this regard, but I think the example here does still let them down a bit:

person = deserializeJSON("{""company"":""Foundeo"",""name"":""Pete Freitag""}");
writeOutput( person.company );

It's nice and succinct which is good, but I think it unnecessarily muddies the water by using " as the string delimiter, as JSON itself requires that character as a delimiter, so the source string is - as a result - a bit confusing. For no good reason, given Pete could have instead simply used a single quote as a delimiter:

person = deserializeJSON('{"company":"Foundeo","name":"Pete Freitag"}');
writeOutput( person.company );

It's not much different, but I think it is a lot clearer. Always try to keep code examples on point. If somethign is unnecessary to the example: get rid.

One great thing about cfdocs.org is that it's community maintainable. So I expect by the time you come to read this, Dan Fredericks will have gone in and fixed this (that's me getting revenge on Dan for him volunteering me to write docs, yesterday ;-).

And one crap thing about the Adobe docs - ell: "another crap thing ~" - is that whilst they used ot be community maintainable, they removed that functionality recently. Cos they're daft.

Anyway, I'll jump on Jacob to get this sorted out, and hopefully encourage him to start weeding out the rest of the crap in there, and get the code examples more focused. I hasten to add that I doubt Jacob wrote those docs... they will predate his involvement in this. I don't blame him one bit for the lack of common sense employed on that site.

Righto.

--
Adam