Friday, 18 December 2015

Survey results: singular or plural for datetime component setters?

G'day:
Yesterday I asked you whether for methods for setting the discrete components of a datetime whether you prefer singular - eg: setMinute() - or plural - setMinutes(). The reason for this is that Adobe are adding those methods in ColdFusion 2016, and there seems to be some flip-flopping on whether each one should be singular or plural. Details here:  3374275: Add granularity to createDateTime().

I've had 50 responses now, and the trend is fairly clear, so I'll tabulate the results:

ComponentSingularPlural
Year96%4%
Month96%4%
Day96%4%
Hour80%20%
Minute76%24%
Second72%28%
Millisecond72%28%

So that's reasonably clear: most people prefer singular. That said, a decent percentage of people prefer singular for the date components and but plural for the time components.

Two people went plural for everything; 35 went singular for everything. One person went singular for everything except for the minute component (slightly odd choice, that one, I reckon).

There were a few comments too:

I would go for singular even though some sound better as plurals. Though in the end as long as it's consistently one or the other and not a horrible mix I would be OK with it.
This is my opinion too. It's not an exercise in grammatical accuracy or even to do with how human language would do it. They're methods of an object.

Arse Arse Arse
Yes. Yes you are. At least you spelt it right though.

you're setting an hour, not a range of hours
This came out a bit, and not something that occurred to me previously, but they're correct.

As far as getting or setting, I think the plural form is more conceptually consistent. Though both can be equally argued for. Second refers to the value place, but Seconds refers to values in that place. I believe both Java and Javascript use setSeconds(), which is probably more comparable to ColdFusion, but other languages use setSecond() and set('second'), and SQL uses dateAdd('seconds'...), so there doesn't seem to be a whole lot of consistency across languages. In the end, I hate date manipulation anyway, so whatever method they choose will work for me. Unless they go with something like changeTime('addSecond(s)'). :-)
I'd like it if you could tease out why plural is more conceptually consistent. I don't get that.

plural makes no sense to me here? You are setting the "hour of the day" not the "hours of the day"


I avoid plurals on my methods and DB field names. I have exactly 2 exceptions to this rule: Comments Details IMHO, these two by their nature are not singular. I also thing of these as being free-form text.


Consistency above all else. As indicated by my responses above, my preference is singular. This is in part because some just don't work (for me, mentally) as plurals. Consider: setYears()? Ew. Combine that logical preference for _some_ of them to be singular, with the desire for _all_ of them to be consistent, and you arrive at: All of them should be singular.


Either way, just please be consistent!
Good pragmatism.

use singular or plural to match JS implementation
Why JS? I don't think the JS implementation here is very sensible, and I was left wondering why they made the decision that they did.

I prefer all singular. Especially since year(), month(), day(), hour(), minute(), second() exist in the language. I think it'd be odd to keep those as-is and introduce .setHours(), .setMinutes(), setSeconds(). I'd rather introduce millisecond()/.setMillisecond(), even if I don't typically say "the millisecond", and retain consistency. On a different note, I am happy to see Adobe presented their proposal so that we can offer feedback. Very nice there. Thanks Adam for doing this survey!, -Aaron
Cheers dude.

Just follow what JavaScript has already done!


You are setting a single value of a property not several values although that value could be more than 1.


I would match the javascript date object setters: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date they use setDate() instead of setDay() for the date part of the month.
Again... I think JS ballsed this up, so not a good precedent to follow. There is also not intrinsic connection between CFML and JS to warrant following their precedent in the first place.

If you go look at the current date/time functions on cfdocs.org, you see MOST of the function names are singular (daysinMonth, daysinyear only plural), so it seems to me that Singular should be used to keep in sync with the rest of the date/time functions.
Good call. I did not check that. So internal consistency would be to be singular. The existing procedural "getters" are all singular, for example: year()... through to second().

You are setting a single value, therefore, it should be singular. setMillisecond() = set the millisecond value to
Correct.

Initially, I favored the plural for the Minutes, Seconds, and Milliseconds. But after thinking about it more, I think that the singular makes the most sense, and will help to keep the purpose clear. Otherwise, I could see someone saying those functions should take ranges.
Thanks for giving it some thought, and sufficiently so for you to actually change your position on the matter. Nice one.

Unsure as to why anyone would want some plural and some not. Let's pick a sensible rule and stick with it throughout. Signular all the way, as the method is referring to the property, not multiple things.


Date/Time is a singular entity If you were setting a range/duration, then this should plural


Adam loves the wallabies
Specifically their services to the All Blacks 2015 World Cup campaign. Cheers for that, Andy.


So there's a suggested case for following JavaScript's Date methods, which would be:

  • setFullYear() (setYear() is deprecated)
  • setMonth()
  • setDate()
  • setHours()
  • setMinutes()
  • setSeconds()
  • setMilliseconds()  

What a mess. There's four different approaches in the first four methods. Screw that. This is also ignoring the fact that those ones don't match the existing getter functions CFML already has. I think this is a pretty invalid position to take, to be honest.

The people advocating for this probably just meant in the context of plurals for hours, minutes, seconds, but I wanted to demonstrate that I think not a lot of thought went into how JavaScript did this, so I don't think there's a good reason to follow them.

Other people reckon using plurals for some but not others based on how one would use them in English: it's quite likely to refer to the year of the date, but the minutes of the hour. But the hour of the day. English is not a very sensible language, and not everyone speaks English so I think following English's weirdo rules (even though these words are in English) is about as helpful as following JavaScript.

So at the beginning of this I was fairly certain sticking with singular would be the better approach, and the more I think about it now and look at what other people say, I am even more adamant. I am going to advocate on 3374275 that they stick with singular. Which, indeed, is what they've already done and they were going to change it to plural for hours, minutes and seconds, so this saves them some work.

Cheers everyone.

And thanks, Andy, for reminding me how the All Blacks smashed the Wallabies in the Rugby World Cup final.

Righto.

--
Adam

Wednesday, 16 December 2015

Survey: singular or plural for datetime component setters?

G'day:
ColdFusion is adding date/time component setters methods to CFML, eg: myDate.setYear() etc. The ticket covering this is here: 3374275: Add granularity to createDateTime().

The methods could be implemented with a singular term for the date component, or plural. EG: setHour() or setHours(). There's currently some disagreement over the approach to take here.

I thought I'd put it to the CFML community, so have concocted a brief survey to ask the question: Date component setter methods for CFML. It basically asks what your preference is for each method, and there's a box for other observations.

Please go fill it out if you can be arsed.

Cheers.

--
Adam

Monday, 14 December 2015

ColdFusion: more on this encodeForHtml() crap

G'day:
This is a follow-up to last week's ColdFusion: please help me discourage Adobe from releasing bad code article; my inspiration drawing from Brad and Sean's comment on same. I found myself writing too much in reply, so have extracted it into an article instead.

First Brad:
[...] the word "encode" is noise in the method if the class is already called "Encode". I kind of like "Encode.forHTML()" to cut down on verboseness. I'm not too much of a fan of Ruby's uber-succinct shortcuts [methods like to_s() instead of toString() ] but I think there's something to be said for trimming down on unnecessary fluff typing.
I initially started with the same thought (see my comment on the ticket):
So they should be in something like:

String Encode.forHtml(String stringToEncode)
Sorry, was being hasty before. That class / method name example I gave was rubbish: Encode is a verb, so makes no sense as a class name; and the method suggestion had similar grammatical shortcomings. Something more like Encoder or StringEncoder or something for the class, and the methods themselves should be the same as their procedural counterparts, so:

static String StringEncoder.encodeForHtml(String stringToEncode)
The name of the method needs to stand on its own two feet (methods have two feet, just like you and I, apparently ;-). "forHtml()" does not adequately describe what the method does. This is a bit semantic given it'll generally be referenced in context with its class, but I still think a method name should describe what it does. "forHtml()" sounds like one is coming in half-way through the description.

Of course at that point, the only difference (to the average programmer) between

Encode.forHTML()

and

EncodeForHTML()

is one character and I think the latter is easier to remember and easier to type since it reads the same but isn't peppered with punctuation.
Well I'd be advocating StringEncode.encodeForHtml(), so that makes even more typing still. I think an appropriate level of brevity is a factor in language design, but not the chief one. And I programming is not an exercise in typing: it's an exercise in thinking. I am perpetually bemused by these people who think programming is some sort of typing race. In the bigger scheme of things, typing a few extra characters each time one wants to encode something? So what?

Also in equivocating over Encode.forHTML() and EncodeForHTML() you're arguing a case for something I'm not contesting. Or even talking about. This conversation is not about whether we should have a headless function or an OO method: that horse has already bolted.

I'm kind of torn here, because I like the highly-academic idea that a language does things "properly" and according to best practices (or at least the precedent set by other languages at the time) but I also like the idea that CF (and many other dynamic, loosely typed languages) bend rules here and there with an end result of making things as simple and easy for the developer as possible in order to get code out quickly and efficiently. (Push complexity on the compiler, not the programmer) At the end of the day, I'm not quite sure what real-world difference there is between a collection of related functions that differentiate themselves by starting with "Encode." and a collection of related functions that differentiate themselves by starting with "Encode".
This is - again - misdirected equivocation. This is not part of the discussion. The ticket is specifically about the member-function implementation of the encoding functions.

Wednesday, 9 December 2015

ColdFusion: so there won't be a ColdFusion 12?

G'day:
Yes, this is obviously a case of two things:

  1. Betteridge's law of headlines...
  2. ... being used for click baiting (or indeed in this case, click bating perhaps ;-).
There will definitely be a "next" version of ColdFusion, but it seems Adobe might  skipping forward 2005 major version numbers, and going with ColdFusion 2016 instead.

Well if this is anything to go by, anyhow:


This is on ticket 4097705, which is something about <cfpdfparam> or something. I did not read the detail as I don't care about PDFs. Or their params.

So... ColdFusion 2016? Yeah, why not.

Best I go re-tag all my "ColdFusion 12" articles as "ColdFusion 2016".

--
Adam

ColdFusion: please help me discourage Adobe from releasing bad code

G'day:
As you may or may not know, CFML has a bunch of headless functions for encoding strings according to OWASP security recommendations, eg:
These are - for all intents and purposes - wrappers for equivalent methods in OWASP's own Java library: org.owasp.esapi.reference.DefaultEncoder.

You should always use one of these functions when you are going to render untrusted content (user input, data from third-party APIs, databases, etc), eg don't do this:

Kia ora <cfoutput>#form.firstName# #form.firstName#</cfoutput>!

Do this:

Kia ora <cfoutput>#encodeForHtml("#form.firstName# #form.firstName#")#</cfoutput>!

Similarly if the value is going into JS, use encodeForJavaScript(), or a URL: encodeForUrl().

Also note these supercede older functions like htmlEditFormat() and urlEncodedFormat(), which do not do the job thoroughly, and should be actively removed from your codebase.

All good.

One thing that CFML has not had thusfar though are an OO approach to calling these functions, via a method rather than a headless function. It's really no great shakes that it doesn't, but it would be good if Adobe had done a thorough / complete job of implementing OO coverage of CFML's functionality. This is beginning to seem like their approach to CFScript coverage: it took about seven ColdFusion versions for them to complete the job, in the mean time CFML was marginalised as a language due to the play-school-looking code us CFMLers had to write our applications in.

There's a ticket in the bugbase to implement "member function" versions of these encoding functions: "Member functions for encoding". Cheers to Neil for raising that.

Unfortunately the Adobe ColdFusion Team have demonstrated their lack of OO nous in their implementation. Or lack of willingness to engage in language design. Or... really... preparedness to do good work.

The thought process seems to have been "well one passes a string to these functions, therefore they're clearly String member functions. We'll add them to the String class".

Well... no. A String class should have methods which describe the behaviour of a String object. Any String object so its methods should focus on ubiquious / generalised functionality relating to any string. Like finding & replacing sub-strings, comparing strings, etc. You know: the sort of general stuff that java.lang.String provides. Note how java.lang.String isn't a catch-all for every function which happens to take a string as an argument. That's not how OO works.

These encoding functions don't apply to most strings. They only apply to strings being used for a special purpose: a special sort of String, not the general String implementation. But these encoding functions are tricky ones. If there was a class "EncodableString" or something, then they'd be object methods of those. But what's the difference between a String and an EncodableString other than these functions? I don't think there's a decent case for that.

So what was OWASP's Java approach? Well one creates (or gets) an instance of an Encoder, and then passes the String to the encoder via the appropriate method. This makes sense in Java, and fits with the rest of the language. It looks a bit odd in CFML though:

<cfset myEncoder = new Encoder()>
Kia ora <cfoutput>#myEncoder.encodeForHtml("#form.firstName# #form.firstName#")#</cfoutput>!

Well it doesn't look odd, but it would be the first of a precedent of having built-in CFML classes which one creates instances of. Still: this sort of thing is where CFML should have gone with the release of CFMX 6.0: if they're in for a penny with OO, they should have been in for a pound.

So perhaps Adobe could have taken that approach.

However this still doesn't sit well with me. I rather more think that these methods are better suited to be static methods which one calls on the class. For CFML's needs there is no "object" needed here, as the Encoder doesn't have any stateful information. So I rather think the functions should be implemented as static methods:

Kia ora <cfoutput>#Encoder.encodeForHtml("#form.firstName# #form.firstName#")#</cfoutput>!

This follows on from the previous example: there's an Encoder class, and we just call the method on the class itself. I've suggested this in the ticket.

As is increasingly obvious, Adobe too often charges off and does work without public consultation, and then present some half-baked, half-working, design-absent solution. They have done this here too. There was never any community discussion, they simply did the work. And they plan to release it in ColdFusion 2016.

Adobe finally followed-up on the ticket (after a bit of should-be-unnecessary badgering), and seem to concede my suggested alternative makes sense. Cool. Except they also seem to be suggesting they're gonna release this current incorrect implementation in the mean time, and then - in a later ColdFusion release - look at fixing it. This is even more ill-conceived than their initial implementation! Once they release this stuff, it's out in the wild, and people will use it. Why would they release something that's been done wrong (you might think "wrong" is a heavy-handed description, but from a language design perspective, I don't see how it can be considered "right"?)? If they're short on time and/or resource, then they should simply park the work until they have time to do it properly. No-one's in a  rush for them to make CFML just that little bit more sh!t, are they? I can only surmise they're unprepared to concede "yeah that work didn't pass muster so should not be released", because that'd be an admission of error.

What I'd like people to do is to give this issue some thought, form yer own opinion, and express it on the ticket. From my perspective I'd like to vote for not releasing this solution until it's done right. I'd rather have no implementation than a bad one. We need to discourage Adobe form actually releasing sub-par work.

So have a vote and a comment if you feel like it (hey, vote and comment even if you don't agree with me; I'm not trying to ballot-stuff here. Well: maybe a bit ;-).

Righto.

--
Adam

Tuesday, 1 December 2015

Guest author: more on agile practices from Brian Sadler

G'day:
Once again I'm promoting a comment from another article (Guest author: a response to "Why good developers write bad code") to be an article in its own right, cos I reckon people ought to read it. Firstly I'll repost that to which Brian is replying (for context), then on with Brian's reply.

Estragon says:

@Brian - yes to smaller chunks of the elephant at a time, tasks that are too large are a major contributor to this behaviour ... but then what's too large for one dev is fine for another, and it can be hard to judge it right, especially when someone doesn't give early feedback on the requirements and then proves to be "quite reluctant to provide honest progress reports if things aren't going well". I guess getting the task size right for individual developers, and distinguishing legitimate concerns/cries for help from the usual background griping is one of the skills that makes a good team lead. Not easy though

I've actually never had the luxury of having a QA person on a dev team, so while what you say is no doubt true in those kinds of environments, my experience has been that there's no surer way to get a developer to lose sight of the big picture than presenting them with a bug list. At that stage it becomes all about fixing the bugs, not the code design

Brian says:

@Estragon Thanks for the comment! I'm nowhere near as engaged or as prolific as Adam, so apologies for the tardy response!

"what's too large for one dev is fine for another"

Agreed there's always going to be some variation in developer productivity, but I don't think that's hugely significant in most organisations. Rock star developers tend to clump together, as do mere mortals.

I'm going to assume that the developer(s) doing the work provides the estimates - and if that's not the case then run for the hills! :-) If we then impose time-boxing (estimate 1 day max per task) and mandatory progress reports (daily stand ups), then we have a mechanism for checking if the work is progressing as planned. The time-boxing addresses the potential issue of differences in individuals' capabilities. A slower developer might have to break down a large requirement into more one-day and sub-one-day tasks than a faster developer, but whatever speed developers work at, we have a daily report on progress.

"quite reluctant to provide honest progress reports if things aren't going well"

We then have to tackle the thorny question of getting honest progress reports. Again all sorts of things come into play, but in essence we have to:
1. encourage and reward honest reporting (especially when there's bad news to be delivered)
2. penalise dishonest reporting, and
3. enforce transparency.

The first two points are all about the culture you work in - and management must set the tone here. Raising your hand because you're falling behind schedule should result in assistance not admonition. If delays/problems are flagged up as soon as they are known by developers it gives management the largest possible amount of time to take corrective action. Hiding schedule problems and hoping to catch up time on other tasks is a recipe for disaster. The management's opportunity to take corrective action starts to recede and inevitably quality takes a nose dive on the other remaining tasks as we attempt to make up for last time.

Clearly we don't want a never ending stream of schedule problems, but that's where sprints / iterations and retrospectives come in. If we honestly, diligently and faithfully log the effort required to complete each task and, as part of our retrospective activities, compare expended effort against our initial original estimates we'll start to generate a feedback loop that should help us to get better at producing reliable estimates over time.

On the third point, Continuous Integration can play a major role here but we can also do things like define what "done" means to ensure that everyone has a common understanding of what it takes to complete a task. Many devs are quite happy to declare that they're finished when they press the save button on their IDE, more "enterprise" organisations might have a definition of done that includes all sorts of checks - unit testing, code review, functional testing, CI regression tests, performance tests etc. etc. The important point is that if a developer claims to have finished a task, then it must meet the organisation's definition of done, whatever that definition is (in agile circles that usually means, deployable to production).

On top of that, I'd mandate that any developer claiming to have finished a task should be able to demonstrate it. The conversation I've heard many times is,:

Dev: "Yeh I finished Feature A"
Colleague: "Great! Let's have a look!"
Dev: "Oh, actually you can't see it just yet, QA haven't signed it off"
Colleague: "OK... So, has your code been reviewed?"
Dev: "Err... no, not yet"
Colleague: "Have you even merged your code?"
Dev: "Erm... well, you see, I haven't committed my code yet"
Colleague: "So QA hasn't signed it off, the code hasn't been merged or reviewed, indeed you haven't even committed your code, but Feature A is done right?"
Dev: "Yeh!".

At this point I call BS :-) For a task to be finished it has to be in a state where it can at least be demo'ed. We're back to the agile principle of working software being the primary measure of progress. Add in the concept of binary milestones (there is no 90% done, it's either done or it's not done) and we start to concentrate minds.

"I've actually never had the luxury of having a QA person on a dev team"

It's not a luxury! ;-) I think the key here is shortening the feedback cycle. Some people use the analogy that unreleased code is akin to stock inventory in a traditional business, so unreleased code is just filling up space in the warehouse. Having code that is not only unreleased but untested is even worse. What it means is that we've got to manage code that we're not even sure is fit for purpose, and depending on your branching model it's either hanging around going stale on a feature branch or cluttering up your mainline.

Having testers and devs work together enables us to be much leaner, and get close to a kind-of JIT stock control system for coding. We write very small amounts of code which gets reviewed, tested and fixed very quickly, and as soon as possible we release it to production so that the business owners can make a return on their investment. If organisations deliberately choose to lengthen the feedback cycle they're just wasting time, money and effort. In my opinion that sort of waste is a luxury.

"especially when someone doesn't give early feedback on the requirements"

QA can play a key role here as well. If a requirement isn't testable, then there are almost certainly problems with it, so get QA involved before we start to code, maybe even before the devs look at the requirement. If QA has no idea how to test a requirement, how can a developer hope to know when they have finished the task? The only answer is to down tools until the customer / business analyst / project manager can provide clarity.

"there's no surer way to get a developer to lose sight of the big picture than presenting them with a bug list"

To my mind that's a symptom of the tasks being too big. If you keep to one day max per task, how much damage can a half-decent developer do in one day's coding? Another question this raises is, if working at a micro level produces a mountain of bugs, how can our development at a macro level be expected to be any better?

"At that stage it becomes all about fixing the bugs, not the code design"

Whether we're fixing bugs or delivering new features we should always be fixing the design - evolutionary architecture mandates constant refactoring, even when we're fixing bugs.

"Not easy though"

Absolutely - but (to mix my metaphors) Rome wasn't built in a day and there is no Silver Bullet! :-) Sadly, I think many people choose to take a very short-term, static view of how agile methodologies might apply to them or their team. They look at a bunch of agile-like practices and think, meh, that won't make us better, faster, stronger etc. I have some sympathy for such viewpoints, because taken in isolation, and in the very short term, they won't produce dramatic results, but they're wrong!

The last principle listed on the agile manifesto states, "At regular
intervals, the team reflects on how to become more effective, then tunes
and adjusts its behaviour accordingly" and to my mind this is the key
to producing the dramatic improvements and eliminating the problems described in the OP.

If we take a look at how individuals and groups learn and grow over time, I think it's self-evident that regular, frequent opportunities to measure, reflect, take on board feedback and make changes are crucial for improvement to occur. The agile principle above demonstrates that such opportunities are hard-wired into agile, but without such opportunities I'd argue that improvement is virtually impossible.
Yeah, I've highlighted some bits as if I'm a student reading a text book. This is great stuff, and it's as if Mr Sadler should be writing more stuff more often. Anyway, I'm glad to have the content for this blog, so cheers fella.

Time to address my day job...

--
Adam

ColdFusion: I learn something about query of query

G'day:
Just a quick one (I'm supposed to be doing Clojure this morning, not CFML). Here's somethng I did not know about QoQ in CFML. Well: in ColdFusion's implementation of QoQ. It's LIKE statement supports (very limited) regex patterns in its value.

Here's an example:

colours = queryNew("id,en,mi", "integer,varchar,varchar", [
    [1,"red","whero"],
    [2,"orange","karaka"],
    [3,"yellow","kowhai"],
    [4,"green","kakariki"],
    [5,"blue","kikorangi"],
    [6,"indigo","poropango"],
    [10,"violet","papura"]
]);

coloursWithOorU = queryExecute(
    "SELECT * FROM colours WHERE mi LIKE :pattern",
    {pattern={value="%[ou]%"}},
    {dbtype="query"}
);

writeDump(var=coloursWithOorU, format="text", metainfo=false);

And the result:

query

 
[Record # 1] 
en: red 
id: 1 
mi: whero
 
[Record # 2] 
en: yellow 
id: 3 
mi: kowhai
 
[Record # 3] 
en: blue 
id: 5 
mi: kikorangi
 
[Record # 4] 
en: indigo 
id: 6 
mi: poropango
 
[Record # 5] 
en: violet 
id: 10 
mi: papura

Cool. Note this does not work on Lucee.

I dunno what the grammar of the patterns are, but it's not simply standard CFML regex patterning. For example Initially I tried to have a pattern which would match words of six letters or more (ie: .{6}), but that didn't work. I was gonna say "it'd be really grand if Adobe actually documented this stuff", but actually they have! It's right there on the "Query of Queries user guide" page. OK, so the grammar is very limited. Just to what I've shown, basically: single character classes. It doesn't even support repetition modifiers. So it's a bit disappointing that the grammar is so limited, but it's handy nevertheless.

Thanks to Tim Brenner on the CFML Slack Channel for bringing this to my attention!

--
Adam

Friday, 27 November 2015

Unit testing (PHP): keeping sight of the intent of the tests

G'day:
An article with some actual code in it! That'd become a rarity. This is actuallya real-world challenge I'm faced with in backfilling some unit tests. Yeah, I know I'm an advocate of TDD so that should mean there's no "backfilling" of tests: they all get done up front. But for reasons I won't go into... I'm backfilling testing for this function.

Here's the function:

public static function loadValidatorMetadata(ClassMetadata $metadata)
{
    $metadata->addPropertyConstraint('languageId', new Assert\Range(
        ['min' => 1, 'max' => self::$maxLegacyLanguageId]
    ));

    $metadata->addPropertyConstraint('destinationId', new Assert\Range(['min' => 1]));

    $metadata->addConstraint(new Assert\Callback('validateArrivalDate'));
    $metadata->addConstraint(new Assert\Callback('validateNights'));

    $metadata->addPropertyConstraint('firstName', new Assert\NotBlank());
    $metadata->addPropertyConstraint('firstName', new Assert\Length(
        ['min' => 1, 'max' => GroupEnquiryRepository::SHORT_STRING_MAX_LENGTH]
    ));
    $metadata->addPropertyConstraint('surName', new Assert\NotBlank());
    $metadata->addPropertyConstraint('surName', new Assert\Length(
        ['min' => 1, 'max' => GroupEnquiryRepository::SHORT_STRING_MAX_LENGTH]
    ));

    $metadata->addPropertyConstraint('email', new Assert\NotBlank());
    $metadata->addPropertyConstraint('email', new Assert\Email());

    $metadata->addPropertyConstraint('groupTypeId', new Assert\Range(['min' => 1]));
    $metadata->addPropertyConstraint('groupSize', new Assert\NotNull());
    $metadata->addPropertyConstraint('groupSize', new Assert\Range(
        ['min' => GroupEnquiryService::MIN_GROUPS_THRESHOLD, 'max' => BookingService::MAXIMUM_PEOPLE]
    ));
    $metadata->addPropertyConstraint('youngestAge', new Assert\Range(
        ['min' => 1, 'max' => GroupEnquiryService::MAX_AGE]
    ));

    $metadata->addPropertyConstraint('telephoneCountryCode', new Assert\NotBlank());
    $metadata->addPropertyConstraint('telephoneCountryCode', new Assert\Length(
        ['min' => 1, 'max' => GroupEnquiryRepository::SHORT_STRING_MAX_LENGTH]
    ));
    $metadata->addPropertyConstraint('phone', new Assert\NotBlank());
    $metadata->addPropertyConstraint('phone', new Assert\Length(
        ['min' => GroupEnquiryService::MIN_TELEPHONE_NUMBER_LENGTH]
    ));
    $metadata->addConstraint(new Assert\Callback('validateMobileCountryCode'));
    $metadata->addConstraint(new Assert\Callback('validateMobile'));

    $metadata->addConstraint(new Assert\Callback('validateAdditionalInfo'));
}

First things first: yeah, normally I'd not write a function that's 40-odd lines long, but in this case there's very little actual logic, plus it's only setting some validation config. BTW this is using the Symfony 2 validation framework (Symfony: validation), as implemented by the Silex microframework (ValidatorServiceProvider: validating objects).

To provide context, we have a class - basically a validation bean - thus:

class GroupEnquiry
{
    public $languageId;
    public $destinationId;
    public $arrivalDate;
    public $nights;
    public $firstName;
    public $surName;
    public $email;
    public $telephoneCountryCode;
    public $phone;
    public $mobileCountryCode;
    public $mobile;
    public $groupTypeId;
    public $groupSize;
    public $youngestAge;
    public $additionalInfo;
}

And that loadValidatorMetadata() function provides the constraints for Symfony to enforce. As you can see: there's range validation, existence validation, length validation, date validation, and a coupla compound constraints implemented via callbacks.

So, anyway, I need to write the testing for loadValidatorMetadata(). Initially I was staring at the code going and going "how the hell?".

Then I thought: I'll assert the addConstraint() and addPropertyConstraint() methods are called for the correct properties, and the correct number of times. But that seemed unhelpful. What's the point of checking that some constraint is applied to a property, but not checking what sort of constraint. IT all seemed too contrived.

Then I thought that the constraints themselves don't need testing here because I'm either testing our callbacks elsewhere, or Symfony have done their own testing. In theory this is a fine notion, but in reality it does not actually help me test our validation code works.

I was stumped as to how to test this stuff, without basically replicating the function in parallel for test. And that clearly sucks as far as effort and common sense goes. It was the wrong approach.

Thursday, 26 November 2015

Guest author: a response to "Why good developers write bad code"

G'day:
I could get used to this. Another one of my readers has provided my copy for today, in response to my earlier guest-authored article "Why good developers write bad code". This originally was a comment on that article (well: it still is) but it stands on its own merit, and Brian's cleared me to reproduce it as an article. Brian's a mate, one of my colleagues at Hostelworld.com. The quote below is unabridged. I have corrected one typo, and the links are my own.

Brian says:

Really thought provoking post, Adam, and my immediate impression is that your mate seems to be describing an awful lot of dysfunctionality here. I'll get my declaration of interest out in the open straightaway and own up to being a massive Agile/XP fanboy, and consequently I think much of what your mate describes could be cured by the adoption of Agile/XP practices.

The "...but then he gets a chunky piece of work and, more often than you'd expect, it goes astray" quote is very revealing, because it would appear that there's no effort made to break large requirements down into smaller ones and we're on a slippery slope from here on in.

Developers often receive very coarse grained requirements and irrespective of our natural coding ability, we're not naturally adept at managing large pieces of work. That's not to say we can't manage large requirements, but without training, mentoring and support developers who might be first rate coders, can often struggle. In this case, it sounds like the developer in question is trying to eat an elephant in one sitting, and then being left alone to go dark and "fail". Reading between the lines it seems that this is accompanied by a seat of the pants estimate, which becomes a commitment as soon as he's uttered it, and before long we're into death march territory.

Also I wouldn't want to blame the developer in question, because as your mate points out, the same thing keeps happening time and again but there's no intervention or help from the guy's colleagues or his manager. Clearly they're at a loss as to how to fix the problem but unless someone can show him a better way, how is he going to improve?...

Anyway... if I was working with him I'd strongly encourage him to forget about eating the whole elephant, and just start by trying to nibble its trunk. Use TDD religiously from the outset, stick to the red-green-refactor cycle and You Ain't Gonna Need It (even more religiously), avoid Big Design Up Front, and let the application architecture evolve as he uncovers smells in the code that he's writing.

See how far he gets nibbling the elephant's trunk in one day, and if all goes then we'll reconvene and decide on the next bit of the elephant to consume, and carry on in that fashion. If he takes longer than a day - and we'll know that because we have daily stand-ups right? - then we'll pair up and see what the problem is. Invariably if the guy's a first rate coder, it will only be because he's bitten off more than he can chew, so get him to stop, re-plan the work, and decrease the size of the immediate task in front of him so he can actually finish it. In short, KISS, keep tasks small and try to conquer complexity. Writing code is intrinsically hard, we should actively avoid anything that makes it harder.

I think it's also worth bearing in mind that many, if not most developers, are naturally quite reluctant to provide honest progress reports if things aren't going well. Combine that with our tendency to give hopelessly optimistic estimates and we're already in a very bad place. I've found that it's almost endemic in our industry that developers are scared of giving bad news to anyone, let alone their line manager or project manager. Developers are usually clever people who spent much of their academic careers being praised for their intellectual prowess, and to be put in a position where they are suddenly the bad guys because they didn't hit an arbitrary deadline can be very distressing and something to avoid at all costs.

If there was just one thing I would wish for in the industry it would be to reform the attitude that project managers, team leads and developers have to estimation. Estimates should be treated by all stakeholders as just that, they are not cast iron commitments written in blood. They should be based on evidence (dude we go through six stages of peer review on every task, why did you give an estimate of 10 minutes?) and when the evidence is demonstrating that our estimates are wrong, then remaining estimates should be re-calibrated. All this is only possible if managers and developers are prepared to create a culture where realistic and responsible estimation, combined with predictable delivery is championed over masochistic estimation and constant failures to hit deadlines.

One final point, when your mate writes "it's a good idea to keep new features *out* of QA for as long as possible", I totally disagree! :-) I'd want feedback from the QA team as soon as possible. The shorter the feedback cycle the better and in an ideal world the QA team would be writing automated acceptance tests in parallel with my development efforts. I'm a firm believer in the agile principle that "Working software is the primary measure of progress" and feedback from QA I'm just guessing that the software I'm writing is actually working.


Sunday, 22 November 2015

ColdFusion: request for transparency and inclusion from Adobe

G'day:
A few days back I indicated some ire that a (IMO) wayward ER had been implemented for ColdFusion 2016: "ColdFusion: a piece of functionality should do one thing, and do it well". Poor old David Epler who raised it seems to feel a bit put upon cos it was something he raised three years ago, and with no further consultation Adobe have now implemented a solution. Without indication it was going to happen, or any communication with David about it, who now think it's perhaps not as good an idea as he originally might have thought.

This also got me thinking about another new feature in ColdFusion 2016: this whole ordered / sorted structs carry on (see "ColdFusion 2016: ordered/sorted structs"). Where's the ER for this one? I can't find one. So where did the impetus to do this work come from? Did Adobe just decide to do it off their own bat? If so why? Why the heck did they decide to do that work? Instead of any of a number of other features the community have actually asked for. Obviously there are probably some back channels via which people can ask for ERs - although there shouldn't be - but even if this came from some PHB or one of his minions at one of Adobe's special enterprise clients... why does this mean this is what gets implemented? All Adobe ought to say to the PHB et al in this case is "raise the ticket, engender some interest from the community, and let's see what people think".

Conversely the ColdFusion Team might have come up with this themselves. They really shouldn't do that, as - as far as I can tell - they are completely ignorant of CFML usage (I judge this based on everything they do and say about CFML, basically), so their decisions are not informed ones. But by accident they might have a decent idea... in which case they should... raise the ticket, engender some interest from the community, and let's see what people think. They definitely are not qualified by themselves to make decisions as to the direct on CFML.

I'm on the ColdFusion Pre-release Programme, and am under NDA to not divulge or discuss anything that gets mentioned on said programme (some people claim the PR has some sort of Fight-Club-esque rules about even mentioning it, or participation therein, but this is not true. They just want to make themselves come across as being "special". They do... but not in the way they think). So I won't. However I can speak freely on topics that have not had any discussion at all. And two of these are:

  1. Dave's issue about adding encoding functionality to <cfoutput>. This has been apparently implemented without any mention whatsoever on the pre-release.
  2. This sorted / ordered struct stuff. All I can say about that is that it exists in ColdFusion 2016. And there has been no discussion about its suitability or necessity for ColdFusion 2016 at all. Make of that what you will.
This is absolutely the wrong way of going about things. The ColdFusion Team might be fine Java developers (hey, they might be), but they seem woefully uninformed about CFML, and - as I have said already - don't use it, and don't really seem to have much of a handle on how we use it. They should not be making opaque decisions as to what goes into it. They have a CAB and a Pre-Realease Programme for this, and these decisions should be made there. And any work that is planned to be undertaken should be discussed out in the open, on the public bug tracker. An ER should be raised, public consultation should be allowed, and then the plan of how (or "if") the functionality will be undertaken should be proposed in public for further discussion. Not all opinions should necessarily be given equal weight (there's some bloody stupid opinions out there; some of them are my own), but they should be at least heard.

Here's an example of how it should be done, Here's the proposed schedule and feature-set for Java 9. There's no reason Adobe could not do that, at least at this high level. They could caveat the timeline with "all things being equal, and subject to change due to unforeseen circumstances", and they could caveat the feature list with "this is not a promise, but it's a guideline, and is also subject to change". We're all grown-ups and we understand things might prove tricky or not worth it, or something else might come along that's more important and needs to bump one of the "nice to have" features. And timeframes can change, etc. There's not even any commercial sensitivity to this, as ColdFusion isn't competing with anything. Well, other than "itself and its community" at times, I think.

PHP has similar timelines and have pretty organised RFC documentation these days for new features. I presume other language projects - well successful language projects - are similar.

Even LAS (those behind the Lucee CFML project, and the .lucee language) are heading in that direction, albeit in a more casual sort of way... but they're still finding their feet so it will probably round out as time passes.

I think the chief reason the ColdFusion Team don't take an inclusive communicative approach is that "inclusion" and "communication" are just devoid from their collective psyche, for whatever reason. They seem to treat their community with a degree of contempt that they seem to be "handing down manna from heaven" when they give us a ColdFusion release.

I think it's fine that Adobe marshal suggestions from their own team and from the "dark" part of their user base. But then they should open that up to the rest of the community so we can put our oar in. We have a great wealth of expertise in CFML usage to gauge how a feature might fit, and we've also got a great resource in the form of Sean Corfield who actually has designed languages in the past, so kinda knows how these things work (others in the CFML community might have experience here too, but I don't know about it). There's a few really old hands from the CAB and PR programme still around too, and they/we are kinda used to discussing how CFML should come together too.

Adobe have done a chunk of fine work in CFML, this is for sure. But they've also done some woeful shite, which I can't help but think never would have happened if they actually engaged their user base. As far as I can see there's no published plan for ColdFusion 2016, so I suspect there isn't really one. So it's not too late for them to kinda organise themselves a bit more, and include the rest of us in the language planning process. This would be bloody easy. For any public ER out there, simply tell us on Twitter or on Slack or on their own blog that they're looking at implementing it. And then encouraging people to have input. If there's not a public ER... create one, then do the same. Adobe have a vast pool of free planning resource. They should be using it.

Start using it.

--
Adam

Friday, 20 November 2015

ColdFusion: a piece of functionality should do one thing, and do it well

G'day:
One of my pet hates is having a function called doX(), and doX() does X, but it also does Y.

An example of this is CFML's isValid() function which not only checks validity - as one might expect - but also trims any string values its validating first. The function is not called isValidAfterTrim(), so it should not do the trimming. If one wants to trim a value before validating it... call trim() then isValid(). Simple. Another example is <cfdump> which picked up and abort attribute along the way. This was because some mungbean said "well usually I want to dump and abort, so why can't dump just abort too". And for some stupid reason Adobe went "oh yeah... let's do that". No. If you want to abort after you dump... do an abort after your dump. Don't change <cfdump> to be <cfdumpandabortifyoulike>. That's dumb. At least the Lucee ER to have <cfinclude> also do an abort got rejected ("Add optional abort Attribute to cfinclude"). FFS.

The reason to this is to keep units of functionality small, for starters. It makes them easier and more coherent to test. Also the more functionality one piles into a function (and for this purpose, a tag is just a function that looks funny ;-), the more potential for it being broken as it's maintained. Plus it makes code less clear and less clean.

A function should do one thing, and do it well.

Anyway, today I got wind of this ER: "encodeFor attribute for cfoutput, writeOutput". The intent is honourable, but it suffers from trying to do too much. The gist of it is:

While ColdFusion 10 added the various ESAPI encodeFor* functions, it is dependent upon the developer to properly wrap location where used with the appropriate function (e.g. <cfoutput>#EncodeForHTML(url.name)#</cfoutput> ). Adding an attribute encodeFor negates the need for wrapping individual variables and would process the entire block contained within <cfoutput>cfoutput>cfoutput> for anything within #'s with the appropriate ESAPI EncodeFor* function specified.

On the face of it this sounds reasonable. It still smacks of "doing too much", so I echoed my position as much.

I sometimes doubt I'm being too dogmatic about these things, so I asked on the #CFML Slack channel, and John Whish came up with a great counter example:

<cfoutput encodeFor="HTML">
    #url.name#
    <a href="whatever.cfm?id=#url.id#" onclick="get(#url.id#)">Go to whatever.cfm?id=#url.id#</a>
</cfoutput>

What's this gonna do? Encode all the expressions within it for HTML. Which is only correct for #url.name#. #url.id# should be encoded for URL, JavaScript and URL for each of its three respective uses. However a less than discerning dev might not "get" that, and now their output is encoded incorrectly.

So what we'd need to then do is this:

<cfoutput encodeFor="HTML">#url.name#</cfoutput>
    <a href="whatever.cfm?id=<cfoutput encodeFor="URL">#url.id#</cfoutput>" onclick="get(<cfoutput encodeFor="JavaScript">#url.id#</cfoutput>)">Go to whatever.cfm?id=<cfoutput encodeFor="URL">#url.id#</cfoutput></a>


What a mess. What we could do is this:

<cfoutput>
    #encodeForHtml(url.name)#
    <a href="whatever.cfm?id=#encodeForUrl(url.id)#" onclick="get(#encodeForJavaScript(url.id)#)">Go to whatever.cfm?id=#encodeForUrl(url.id)#</a>
</cfoutput>

Look familiar? Yeah... we already have the correct (and safe) implementation in place.

We don't need to mess with something that's supposed to just output, and make it do something different as well. It's a bad approach to designing the language.

I reckon this ER should be pulled. It's a pity the work has already been done...

Thoughts?

--
Adam

ColdFusion: help one of our community members with a PDF problem

G'day:
One of our community members, Prabha (I dunno the rest of their name), is having some problems with PDFs. They came to me for help, but I don't know the first thing about PDFs nor how to manipulate them with ColdFusion. And to be completely honest, I am completely content maintaining that ignorance. But I know a bunch of people out there do know how to do this stuff, so they might be able to help.

The question is this one, on StackOverflow: "When exporting PDF with CFChart images in ColdFusion It shows embedded font error". I can't actually make head or tail of it, but there seems to be two things:

They're getting this error:

"cannot extract the embedded font 'PCBOHZ + TimesNewRomanPS-BoldMT. some characters may not display or print correctly ( OR ) cannot extract TimesNewRomanPS-BoldMT"

And clearly they'd rather not.

Secondly there's something about images missing:

In the generated PDF the images are showing as red cross marks, while creating PDF, CFDOCUMENT makes HTTP URL calls to coldfusion server to get the images from the CF virtual folder CFIDE/CFSERVLET (because these images are saved in this folder by cfchart tags based on the charting settings in CF administrator) [...]
It's all greek to me.

Now these should be two different questions on StackOverflow, but... err... shrug.

If there are any ColdFusion/PDF experts out there, can you have a look-see and try to help? Cheers.

Righto.

--
Adam



Thursday, 19 November 2015

... and... Adobe hot fixes it

G'day:
Just a quick follow-up to this morning's article: "CAUTION: Latest ColdFusion 11 patch breaks (at least some) code using "/>" in CFML tags"

Well knock me over with a feather... they're released a hot-fix for it! How good is that?

It's attached to the ticket: "CFPOP doesn't create the query given by name="" with updater 7 installed".

I still think they need to withdraw update 7, bake that hot fix into it, and release it again (as update 8), but at least this should get Tom going.

I haven't tested it as I'm behind a firewall here and cannot get to a POP server, but I'll report back when I have confirmation it actually fixes the problem.

Good snappy work there Adobe. And good to see it's possible for you to release individual hot fixes.

Righto.

--
Adam

Guest author: Why good developers write bad code

G'day:
A while back one of my mates said there was a topic they had some thoughts on, and figured they should write a blog article about it. Their problem being they didn't have a blog. This seemed like a good way for me to get someone else to do my work for me, so I raised my hand to host it for them here. I've been waiting for... god... oh about three months for this. But 'ere' 'tis:

So there's a guy on your team, and he's a good developer. He knows the language inside out, he's up-to-date with all the latest technologies, he spots design patterns and code smells, and when you send him your code to review he cuts you a new asshole (and it turns out he's bloody right about everything)

... but then he gets a chunky piece of work and, more often than you'd expect, it goes astray. He's swearing at his screen, he's "almost done" for ages. Because it's late the code reviews are lighter than they should be, and QA raise a ton of bugs. He says they're all small but each one takes longer than the next to fix. When you try and spread out the bugfixing among the team it takes everyone else even longer so he ends up slogging through everything on his own. Eventually it's done and it works, but it's brittle and everyone is afraid to touch it. He blames it on over-complicated requirements and over-ambitious timelines and we all move on.

Maybe it was The Business's fault for coming up with stupid requirements, or just the fact that smart people can make mistakes in ingenious ways. Everyone gets unlucky now and again, but if a competent developer gets bogged down regularly then there's something else going on. What is it?

Good devs are often tinkerers, and are very good at figuring out ways to work around obstacles. The dark side of this is that obstacles can be seen as things-to-be-worked-around rather than problems to be solved.

At the code level this manifests as a reluctance to refactor. Tests make refactoring safer and easier, but even with good tests developers often see existing code as fixed, something to be built upon rather than restructured. The upshot of this is you get layers and layers of code, each layer adding a missing piece or working around a bad design decision in the one below, and the complexity quickly gets out of hand. This gets especially bad when time is tight, and guys don't want to go back to the start, and so treat their own almost-but-not-quite working code from a few days ago as immutable (especially after their feature has been through QA) - essentially they get into trial-and-error mode, and nothing gets re-thought, so underlying issues with their code design don't get fixed.

You also see it one level up from the code - when confronted with an over-complicated set of requirements, a capable developer will often just implement them as they are, logical contradictions and all. He'll bitch and moan, but will very seldom chase down a bad requirement and get it (or his interpretation of it) fixed so that it makes sense. We all bang on about elegance, but the requirements are the soil the code grows in, and without taking some responsibility for them your code cannot ever be consistently good.

There's no easy way to fix this. It's hard enough to find programmers capable of writing good code, harder still to find ones that consistently do so. If this is you, write tests you can trust then refactor refactor refactor. If for some reason you're not doing TDD then refactor anyway. If you've coded yourself into a corner create a new branch and work out a new approach in that. Be bold. It's just code, it's not set in stone, and neither are your requirements, so stop your moaning and take responsibility for them. And stay out of trial-and-error mode as much as you can.

If this is someone on a team you lead, TDD and code reviews (especially if they're done early enough to prevent a dev going too far down the wrong path) will help, also because bugs are often fixed by trial and error it's a good idea to keep new features *out* of QA for as long as possible. Really though there's no magic bullet - you'll just have to know who's susceptible to this kind of thing, and keep an eye out for it.

Yep, very true. I encounter this challenge all the time, and indeed sometimes I self-identify as having this problem too. I suppose we all do/did at some point.

CAUTION: Latest ColdFusion 11 patch breaks (at least some) code using "/>" in CFML tags

G'day:
I twittered about this yesterday, but didn't have time to follow it up here for one reason or other.

I think one should hold off on installing ColdFusion 11 update 7 for the time being, as it definitely has a minor code-breaking glitch, but it could be more far-reaching. This still needs to be clarified by the Adobe ColdFusion Team.

Yesterday Tom Chiverton drew my attention to this new issue: CFPOP doesn't create the query given by name="" with updater 7 installed, wherein:

Pre-updater 7, and as documented, CFPOP's name argument can be used to name the query returned.

Post-updater 7, this errors with " Variable MAIL is undefined. <br>The error occurred on line 10. "
Line 10 being the CFDUMP. Trying to use it in a QoQ also fails.

Test Configuration

<cfpop server="xxx"
action="getHeaderOnly"
username="xxx"
password="xxx"
timeout="60"
name="mail"
maxRows="100"
startRow="5"
/>
<cfdump var="#mail#" />

Seems inconvenient, and I think <cfpop> is a common enough tag that it needs an immediate fix. Bear inind that Update 7 is a security update, so all things being equal, ColdFusion 11 users really ought to have it in production as soon as they can.

Adobe then fed-back on the issue (props for feeding back quickly, btw), but the news ain't cool:

The work-around for this issue is to remove the "/" end tag "/" in cfpop tag, it would work.

Modified the code :

<cfpop server="xxx"
action="getHeaderOnly"
username="xxx"
password="xxx"
name="mail">

<cfdump var="#mail#" />


There is already a bug logged for this bug #3969304(though the description of the bug and the behavior is different. These are the side effects of having end tag), which is fixed and would be available in the next update.

My first reaction here is that "the next update" - unless otherwise stated - could be a coupla months off: the gap between update 6 and update 7 was 2.5 months or so. This is unacceptable. This bug was clearly introduced in update 7 - Adobe are not even contesting that - so they need to fix update 7. We can't be waiting around for 2-3 months until update 8 comes out.

Adobe, you need to own situations wherein you cause your clients grief.

Secondly... and this didn't occur to me initially... if closing the <cfpop /> tag causes it to not work... how many other tags are impacted by this? I don't see how the closed / not closed behaviour change can be individual-tag-specific. This needs clarification from Adobe.

[Actually "secondly" was a sense of epicaricary that people who unnecessarily close their CFML tags, further cluttering up already cluttered code have had their chickens come home to roost. But that is counterproductive in this situation].

Thirdly. This just demonstrates that Adobe need to rethink their security patching, and their approach to patching in general. A security patch should only impact the security issue. It should not be a roll-up of all previous patches, because it's too big a regression burden for the urgency of these security holes they keep finding in the sieve that is ColdFusion. Adobe need to change their work focus away from what's convenient for them, to be what's convenient for their clients. They also need to bear in mind that all of this, irrespective of the patch size and complexity is a) their fault; b) causing their clients work. This is another thing the Adobe ColdFusion Team need to start owning. They need to start acting like they're the stewards of enterprise grade software, basically.

So I think there's some question marks over ColdFusion 11 update 7 at the moment, and the ColdFusion Team need to get a hustle on to release update 8 as soon as they can.

I will be hitting the #CFML Slack channel to try to get this followed up ASAP, so we can get some visibility on all this.

Righto.

--
Adam

Monday, 16 November 2015

CFSummit (Tuesday): better frame of mind

G'day:
Well I was in a better frame of mind, until BlogSpot just wiped my entire article when I pressed CTRL-Z. And then it saved the blankness. FFS.

Anyhow, I'll be quick here as this is old news now, but I'll go over what I went to see on Tuesday last week anyhow.

Firstly - and I've said this before and I'll say it again - one of the best things about conferences is the between-presentation hallway chatter: there's a lot to be learned there too. Breakfast is no different, and is a good opportunity to be parked next to new people and chat for a bit about what they do and what they know. What I learned on Tuesday breakfast is that Gavin can talk non-stop for about 15min without drawing a breath or pausing to let anyone else participate in the conversation ;-). Still: it gave me a good chance to eat my breakfast whilst only nodding and going "and... [hmmm, OK he's not done yet]... but... [nope, still not my turn apparently]... aah... [hmmmm]...". Bloody hell Gav, you like to talk, don't you? ;-) That said, he was expounding on some good ideas that came out of the panel discussion and Adobe's and the community's general attitude to ColdFusion, so it was worth listening to. I pointed everyone to this before on Twitter, but here it is again: "Building a Bigger Better CFML Community". Read it and act on it.

The first presentation of the day was Roy Fielding talking on "REST and ColdFusion". He pretty much wrote the book on REST, so was worth listening to. Although perhaps also read Adam Tuttle's more accessible version: "REST Assured: A Pragmatic Approach to API Design". The bottom line I took from Roy's presentation is re-affirmation that REST isn't anything tricky, it's just using HTTP to deliver data. Like how web pages already does this. He also made the bold observation that whilst JSON might be the serialisation mechanism du jour, this doesn't mean it's the only way to ship data around the place. Nor will it necessarily be the way things are done in a few years time. Remember how we all used to like XML, but now it's just crap? Well yeah. I await for the other shoe to drop with JSON, TBH.

Nolan was on next with "MVC With and Without a Framework". I decided to go to this one over Kev's on on continuous delivery (etc) because I was intrigued by some of the chatter I was part of - or overheard -  on Monday. There are really a lot of CFMLers who seem blissfully unaware of things like "design patterns" and "frameworks" and stuff like that, and I thought this presentation might be reaching out to them. It's a demographic I've largely ignored on this blog, but perhaps I should be doing some more grass-roots stuff. Nolan always presents well, and I found this interesting even though there was nothing new in it for me. One interesting thing he observed is that in the process of taking a MVCless / frameworkless site and putting it into FW/1... really a lot of the code stays mostly as-is, with just hope it's called changing, and a bit of ceremonial stuff around the edges. I was surprised at the site-by-side diffs he was doing.

I had to skip the next slot as I needed to go Skype my wee son. Although his mum didn't put him on, so that was a waste of an hour. Then it was lunchtime, and more random chatter with random people.

After lunch was Anit taking the throng through what's involved in upgrading previous versions of ColdFusion to CF11. I basically wanted to see if there was anything I didn't know about (no), and also to check out what Anit was like as a presenter. He's definitely the best of the Bangalore-based bods (the BBBs!): speaking very clearly and engagingly, and - if I can be a bit bold - with a less thick accent than most of the other bods from the ColdFusion Team. I know the USAn audience struggles with this at times. And indeed even I could only understand about 10% of what Tridib was saying on the panel discussion the previous day, and I was sitting 2m away from him!

Mr Blinky Hat was up next to go commando (he refused to confirm this one way or the other): "Go Commando, with CommandBox! CLI + REPL + Package Manager for CFML". CommandBox continues to impress, I gotta say.

Lastly I went to Charlie's presentation on "10 Common CF Server Challenges and How to Find/Solve Them". This was typically thorough: Charlie knows his stuff. But I do have to say that by this time I was conferenced-out, and wanted to get away from the concept of ColdFusion.

Elishia wrapped things up in the main room, and we were done.

I never understood this. Organising developers to go have a drink is like herding cats using nothing but a bucket of water, so it seemed to take about an hour to get from the conference to the bar 200m, but that's what I did (once again it was the Todd English PUB). Having learned my lesson about excesses the previous day, I kept things "under control" this evening. I was in bed by 3am (after diversions to one of the bars in the casino itself, and Tim Cunningham's suite for even more beer, after the point at which I should have known better). Dear god. And on Wednesday I had to fly back to the UK...

Anyway, it was a good gig, and I'm glad I made it. Mostly for the people I hung out with, I have to say, more than the presentations. This is not an indictment of the presentation quality at all, but as time goes on, ColdFusion stuff is less and less relevant to me. But I had a good time. Hey I can't remember all the people I caught up with... I'm both shocking with names/faces, plus when it happens at the bar, my brain doesn't record events anyhow. It was excellent hanging out with y'all anyhow.

And that's all the lunchtime I have available for writing, so that's that.

Righto.

--
Adam

Wednesday, 11 November 2015

CFSummit: Yeah yeah yeah, all right Rakshith...

G'day:
So yesterday I said this:

To which Rakshith said this:

Them be fighting words, so we had a bet, and... having checked his presentation... I lost the bet.

So here's my penalty: you're right, I'm wrong. Sorry mate.

Now shouldn't you be here in the PUB having a pint???

;-)

--
Adam

Tuesday, 10 November 2015

CFSummit (Monday): I never learn

G'day:
Oh for the love of god: what did I do to myself? As I touched on yesterday - "CFSummit (Sunday): conference tips from a veteran" -  I had a bit of a late "night" on Sunday, so Monday morning was a bit "emotionally fraught" (read: I had a hellish hangover).

So I missed the keynote completely, as I was still trying to remember how to dress myself, and locating coffee (fortunately I managed to work out the first on that list before heading out for the second). I have subsequently learned that I was "announced" (whatever that means) at this keynote... so I'm in a bit of trouble for not being here. Yikes.

Once I actually arrived, Rakshith was giving us the once over ColdFusion 12, which was much the same as the presentation given at CFCamp. I've already written up what I am able to about that, in other articles:


I was hoping for some new code-centric stuff, but there wasn't really.

I had a chuckle when I thought I saw a reference to "Cold Fusion" on one of his slides, but he assured me I was seeing things (or "I was drunk", as he put it ;-).

Next up was Kevin Schmidt going through doing REST with CFML ("Building APIs with ColdFusion") - this was the code-centric side of things: how to configure one's CFCs etc. It was a good presentation and Kevin is an engaging speaker, but I was really let down to see all the code being written in tags. I know I keep harping on about this, but the community (and Adobe!) need to lead the way here in downplaying CFML being about tags. Tags have their place, but not in heavy lifting code. We need to start directing eyes away from tags for everything.

I was feeling dire so I went back to my room to try to smother myself with a pillow. And kipped for a coupla hours. I'm annoyed I missed Elishia's ColdFusion 12 API Manager presentation. And lunch. But so be it.

At 2pm I decided to check out Dan Fredericks' "CFML Features for More Modern Coding" presentation. I loved this... it was a true, sleeves-rolled-up code-centric presentation, and I think Dan's picked a topic that represents the cutting edge of complexity in CFML: closures and member functions (well: member functions aren't complex, but it's a mind shift fro CFMLers maybe). Hopefully his slide deck goes public at some point, and I'll try to link to it. I hope people enjoyed it, and got something out of it.

I still felt pretty sick.

3:30pm rolled around, and I had to get up on stage. And smile and stuff. It was the "Adobe Panel Discussion Q&A Session". This was interesting, and - again - I hope the audience took something away from it - but I think I was out of place being on the panel. The questions were mostly directed at Adobe, and I could not really participate too much in answering them. I think the panel should have just been Adobe people. I was there to field questions on code and dev practices and that sort of thing, but this is not the direction the Q&A took. It was more one of these marketing-speak things that I have indicated disillusionment with in the past: I don't want to be marketed at at a dev conference.

There were a number of things I wanted to talk about, but wasn't given the opportunity to. Oh well.

I think next time there should be maybe a dual (or do I mean "duel"?) panel thing: Adobe vs Community, or something. Or just get Adobe bods up there representing business, marketing, and tech, and let us community members ask them questions. Dunno. And it would have been better if I was in the audience, not on the panel, I think. Still: it was fun, and I really appreciate Elishia & the rest of the Adobe people giving me this opportunity. It must have seemed like a bit of a risk getting someone like me up on stage. I think I acquitted myself adequately, and I only accidentally swore once. That I can recall.

After that I surrendered, eschewed the chance for free beer and talking to people, and went back to bed. At 5pm. I woke up briefly at 2:30am and considered going downstairs, but my next thought occurred at 5am when I awoke properly.

So it was a bit of a waste of a day for me. There were a bunch of people I really wanted to catch up with and chat with, especially to see if we could get a conversation going around Dan's talk, and possibly try to corner Rakshith, hand him a beer, and have a chat.

The best thing was that I did get to meet Anit! I hardly spoke to him, but at least I've pressed the flesh with Adobe's resident CFML super hero. And I got a photo with him (it's been posted on the Slack channel, but I don't have it myself)! Cool. I also met Aaron Neff, who is one of ColdFusion's other superheros... he's by far the best CF tester Adobe have on tap. But his name is not one most of us will be too familiar with.

I reckon from what I saw and heard from other people, it was a really successful first day, and I hope today is just as good. And hopefully I manage to last beyond late afternoon, today. :-S

Righto.

--
Adam

Monday, 9 November 2015

CFSummit (Sunday): conference tips from a veteran

G'day:
Yes. Oh yes. The day before one is supposed to be actually participating in a conference... make sure to be out drinking until 05:18. This will ensure clean sailing the "next" day, and everything will go swimmingly.

Or so I'm telling myself.

Judge for yourself tomorrow afternoon. On the bright side: everyone's expecting me to be angry...

--
Adam

Saturday, 7 November 2015

CFSummit (Saturday): if I ever get there

G'day:
This is going to be content-free, for the most part. Be warned. Indeed currently I don't have the content for this planned, but I'm stuck at Houston airport with beer in hand and... time to kill.

OK, so I started my trek to Las Vegas for CFSummit this morning, with the first hitch being the coffee stand at the Tube station was shut, so I have now endured an entire day without an espresso. This seems... wrong. It was probably a portent, and I did not notice. Dammit.

When choosing my flights I decided to pick one flying a 787, to see if they are any good (I'd not flown on one before). I can't say I was that impressed: it didn't even seem new (either in age or in design), so it was a bit disappointing. I did like the new window blind concept they have: it's not a blind, it's an... electrically-sensitive-gel-based thing (apparently: "How The Magical Windows in Boeing's 787 Dreamliner Work"), which has a button which makes the window get gradually darker. This is cool except for the fact they can be controller centrally too, and the cabin crew decided we were going to be in night-time mode for most of the flight (which was entirely actually daytime). So I missed my favourite part of flying over unfamiliar countries: looking down at what it looks like. All I could see was a dull blue colour. To put in perspective of how much light the gel will block when on "full strength", one can look directly at the sun through it... although it's still very bloody bright and not something to do for a sustained period of time. That aside... I remain very impressed with A380s as far as "modern aircraft" go, but don't see the fuss about 787s. And, yes, I know I am "comparing" different classes of aircraft there.

En flight I had a Goose Island IPA (from a can, no less), and that was bloody good. Actually I had three of those. Then they ran out of those and they gave me a Miller Lite instead. That was awful.

I watched Terminator: Genisys, which I thought was pretty good (going against general opinion, I think), indeed I'd put it second best in the series after the original. I rank those films: Terminator, T:G, T3, T:S / T2. I know I'm an outlier when it comes to ranking T2 so low, but I don't really think it brought anything new to the story: it was a rehash of the original with a bigger budget.

I also watched something called Air, which was "interesting", but... didn't quite get there. it was all right.

Oh and I watched the first three episodes of "Humans", which was really good.

One disappointing thing about this 787 was that whilst it had power outlets on economy seats (two outlets per three seats), it wasn't switched on. But I didn't need my laptop anyhow, so no problem really.

Getting into George Bush International Airport (after 10h in the air), I girded my loins for "The Immigration Experience". True to form, whilst having a cavernous immigration hall, with 40 desks to process people, the US Border Force decided the 1000-odd people in the queue would be best processed via never any more than a dozen desks being opened. It took around an hour to get to the front of the queue-feed-queue to get into an actual queue in front of a desk. And another 20min after that to get through. This was the at Philadelphia for CF.Objective() a coupla years ago. Entering USA is by far the worst border experience I have encountered (and I've been to Russia...).

At this point I had 10min to find my bag, re-check it, and board my LAS flight. Which was pretty much stymied by the queue for customs after picking up my bag. I'd missed my connection by then (my brain was actually going "hooray! I have enough time for a beer now!"), so rebooked on the next flight - no charge, and no batting of eyelids... this is just "normal" for USA domestic air travel apparently.

After that I had another 20min in the security queue, operated by drittereichian TSA staff, who would - I imagine - be gleeful if their jobs involved processing people straight from rail cars, if they had the chance.

Oh... just to wind back a queue or two: here's a question for my USAn readers... why does a desk clerk at an immigration desk need a gun? What's wrong with you lot?  The only way I can see a gun being necessary in that environment is in a "They Shoot Horses, Don't They?" kind of way, if the people in the queue give up the will to live before being processed.

Ahem.

Anyway, I missed my connection as I said, but I'm on the next flight to LV, which doesn't leave for a coupla hours (well: an hour or so now...), so I've parked-up at "Rocket and Rye" (they seem to have no website), who have good beer, not bad food, and a coupla people to talk to.

I recommend the Weekend Warrior Pale Ale, Ryed Hard, and the chicken quesadilla, btw.

By the time I get to LV this evening (touch down @ 11pm, apparently), I doubt I'll be in any sort of state or mood to say "g'day" to people, but let's see...

[later]

Finally at the hotel, and at 11:58pm... it's bed for me. I'm too old to be starting to go out at midnight.

Up in three hours to Skype with my boy, back in Ireland.

--
Adam

Friday, 6 November 2015

PHP: getting my dev environment running on Nginx instead of Apache

G'day:
We're shifting from Apache to Nginx at work, and despite having other bods to look after that side of things - I'm just a developer, I avoid devops if I possibly can - I still need to write rewrites and the like, and so I need to be passably au fait with Nginx and how its rewrite system works.

So I decided to get a local site up and running via Nginx this morning. Well: I say "I decided to"... I needed to ;-)

As with anything I write about PHP and that sort of thing... I profess no expertise in how I throw things together, so I would not take these as model instructions or anything like that. I'm just documenting what I did.

Note: I'm running Windows.

Download and run

First up I downloaded Nginx from their site. It requires no installation: just unzip and run. Obviously however I need to configure the thing if I'm to do anything more than stare at gdayWorld.html on the screen.

FastCGI

Googling a bit, Nginx uses PHP's FastCGI module to run PHP, and one needs to configure NGinx to pass requests to PHP that way. This is all documented here: "PHP-FastCGI on Windows".

Basically I need to run php-cgi.exe, in the background, telling it to listen on a port:

C:\apps\php\5\5\php-cgi.exe -b 127.0.0.1:8550

(I'm running PHP 5.5 cos that's what we use on our live site)

Note - and this is one thing that caught me out cos the docs weren't 100% explicit (and I didn't engage my brain) - that port is not the port that Nginx listens to for incoming HTTP requests, it's just a port for Nginx and PHP to communicate on. And - obviously for those who do engage their brains - it does actually need to be a different port. Sigh... that stupidity held me up for about 15min of head-scratching until I started to pay attention to what I was doing.

php-cgi.exe just sits there running.

Nginx config

Here's my Nginx config file. Basically I took out all the commented-out clutter, changed some stuff to suit my environment, and put some extra bits in (as suggested by that page I link to above):

Wednesday, 4 November 2015

CFSummit: they've got who on their discussion panel?

G'day:
Ha. So this article just went up on the official ColdFusion blog: "Adobe ColdFusion Summit 2015 - Panel Participants Announced". The participant list is:


From Adobe:

Tridib Roy Chowdhury, Sr. Director of Products

Elishia Dvorak, ColdFusion Solution Consultant & Evangelist (moderating)

From the community:

Ray Uyemura – Director of Systems, City of Los Angeles

Leon O’Daniel – Sr. Web Application Developer and Leader of the Boeing ColdFusion Community of Practice, Boeing

Shirak Avakian – Sr. Web Architect, Century National Insurance Company

Adam Cameron – Sr. Software Engineer, Web Reservations International Group


Who's that frickin' turkey at the bottom there?

So... erm... that should be interesting.

;-)

--
Adam

ColdFusion 2016: arrays now passed by reference

G'day:
There's not much to say about this one. ColdFusion is finally playing catch-up, and standardising its approach to passing complex objects.

Traditionally, ColdFusion has passed "simple values" (strings, numerics, dates, etc) by value, and complex objects (structs, queries, XML) by reference (provided one understands "pass by reference" with these caveats: "Complex data-types in CF, and how they're not copied by reference"). The one exception was arrays. Arrays were passed by value. Why? I don't bloody know.

Right from the outset Railo decided that was bloody daft and has never done this, and this has been inherited by Lucee.

Now ColdFusion has caught up, even if I think the specific implementation is lacking.

There is a new setting for Application.cfc, this.passArrayByReference, which one can set to true (the default is false). If one sets that, then the behavour of passed arrays is changed.

Let's have a look at some code running on ColdFusion 11:

function arrayToUpperCase(array){
    for (var i=1; i <= array.len(); i++){
        array[i] = array[i].ucase();
    }
    return array;
}

rainbow    = ["Whero","Karaka","Kowhai","Kakariki","Kikorangi","Poropango","Papura"];

rainbowInUpperCase = arrayToUpperCase(rainbow);

writeDump(var=rainbow, label="rainbow", format="text");
writeDump(var=rainbowInUpperCase, label="rainbowInUpperCase", format="text");

This simple code has a function which takes an array, upper-cases each element and returns it. Afterwards, we dump both the original and returned arrays:

rainbow - array

1) Whero 
2) Karaka 
3) Kowhai 
4) Kakariki 
5) Kikorangi 
6) Poropango 
7) Papura 
rainbowInUpperCase - array

1) WHERO 
2) KARAKA 
3) KOWHAI 
4) KAKARIKI 
5) KIKORANGI 
6) POROPANGO 
7) PAPURA 

As you can see, when we modify the passed-in array, it does not impact the original array. Constrast this with the same operation with a struct:

function structToUpperCase(struct){
    for (var key in struct){
        struct[key] = struct[key].ucase();
    }
    return struct;
}

rainbow    = {red="Whero", orange="Karaka", yellow="Kowhai", green="Kakariki", blue="Kikorangi", indigo="Poropango", purple="Papura"};

rainbowInUpperCase = structToUpperCase(rainbow);

writeDump(var=rainbow, label="rainbow", format="text");
writeDump(var=rainbowInUpperCase, label="rainbowInUpperCase", format="text");

rainbow - struct

BLUE: KIKORANGI
GREEN: KAKARIKI
INDIGO: POROPANGO
ORANGE: KARAKA
PURPLE: PAPURA
RED: WHERO
YELLOW: KOWHAI
rainbowInUpperCase - struct

BLUE: KIKORANGI
GREEN: KAKARIKI
INDIGO: POROPANGO
ORANGE: KARAKA
PURPLE: PAPURA
RED: WHERO
YELLOW: KOWHAI

As you can see, because structs are passed by references, the argument in the function references the same struct as in the calling code, so changes to the argument are reflected in the original.