Friday 31 October 2014

TDD presentation

G'day:
A coupla weeks back I was tasked with giving a presentation to the new PHP troops: an introduction to TDD. I'm not on the PHP team now, but they might need to be doing some TDD shortly, so I figured I'd at least expose them to the presentation slides if not actually take them through it. And I figured I might as well put it up for everyone to have a look at, in case it's of any use to anyone.

It's very bare bones, and I dunno how useful it'll be if I'm not there discussing each slide, but... oh well. It's here: "TDD".

If nothing else, it might solicit some questions from people, which will be a good thing.

Cheers.

--
Adam

Thursday 30 October 2014

Just for Andy Allan

G'day:
More times that you probably thought when you said that, I wager.

--
Adam

ColdFusion bug challenge: how quickly can one find a bug in ColdFusion 11?

G'day:
Yesterday at lunchtime, I set myself a challenge: how quickly could I find a new, unreported bug in ColdFusion 11.

If you're in the UK, can you please do me a quick favour?

G'day:
Hey, if you're in the UK, can you please run some code for me and let me know what you get?

Oh yeah... I'm back doing ColdFusion for the time being

G'day:
Not that it's particularly important, but for one reason or another, I'm been seconded back into our ColdFusion Team from the PHP Team. And will probably remain here for a month or so.

--
Adam

Monday 27 October 2014

FFS, Adobe. Stop being such bloody amateurs

G'day:
Now this irks me (in case you had not noticed).

Here's a couple new bugs that have gone into the Adobe ColdFusion Bug Tracker:

A quick look at WireBox

G'day:
A coupla days ago I had "A quick look at DI/1", after having my interest piqued by Chris' presentation "Dependency Injection with DI/1". That went quite smoothly, so to kill some time after CFCamp, I decided to do the equivalent exercise with WireBox.

Friday 24 October 2014

Would you install a ColdFusion hotfix/updater/patch without testing?

G'day:
First things first, this is my position (and the one I believe anyone who's not a lunatic should have): "bloody hell no, are you insane?"

But I polled the community yesterday, via Twitter:



Tuesday 21 October 2014

CFCamp 2014 hindsight

G'day:
So CFCamp 2014 is over. First things first: Mike, you're a star. Everyone who attended thinks this. Thanks so much for organising yet another excellent CFCamp, and dealing with all the various... erm... "idiosyncracies" that sponsors and speakers and others threw at you.

I'm not flying out until tomorrow afternoon, and I don't fancy going into Munich for a night out, so I'm just hanging @ the Stadthalle in Germering. As I just said on Twitter: I seem to have the place to myself, other than the four people working on the bar here. I'll probably go over to visit my favourite wolpertinger later on for dinner, but it's too early for that. So beer and blogging it is. I've just started my third pint (well: 400ml rather than a pint, anyhow).

This is my wash-up of the conference.

A quick look at DI/1

G'day:
I'm at CFCamp at the moment, and one of the better presentations yesterday (out of a lot of good presentations, I might add) was Chris' presentation, "Dependency Injection with DI/1". It looked sufficiently interesting I thought I'd have a quick look-see at it. I have downloaded it in the past, but that's about as far as I had got.

I've been using ColdSpring at work for the last few years, but DI has come a long way since ColdSpring's heyday. So I'm familiar with the concepts of dependency injection, but only ColdSpring's implementation of it.

If you don't know what DI is, go read up on it first otherwise none of this will be very meaningful. I'm not able to get an internet connection at the moment, so I can't find a decent link for you, but I'll try to remember to update this later on. Or, hey, you probably know how Google works.

Monday 20 October 2014

CFCamp: a Crocodile Dundee moment for me

G'day:

That's not a shot glass. This is a shotglass.

It was a bit of a messy night last night. Well, indeed, we basically sat around all afternoon @ the Stadthalle at Germering drinking Tegernseer Hell, so it was getting messy even before the evening.

Am currently sitting in Luis' CommandBox presentation. CommandBox continues to look impressive.

Quite a content-lite article this. I just liked the size of that shotglass, basically.

I'll try to write something more useful later on. But I'm also doing Twitter updates tagged with "#CFCamp" as things occur to me. That might be a better way to find out about what's going on @ CFCamp.

--
Adam

Saturday 18 October 2014

PHP: getting AspectMock to work

G'day:
First things first: Luis, Brad, everyone at Ortus Solutions: I bloody love you guys. Working with TestBox and MockBox is an absolute pleasure compared to getting their PHP equivalents installed and working properly.

Over the last coupla weeks, meself and Duncan have been investigating unit testing on PHP, and specifically how to mock dependencies. On our old CFML code base, we have 1000s of test, and we use MockBox heavily, as we have rather a lot of dependencies which interfere with testing if they're not mocked. We only ever really moved to TestBox as a proof-of-concept before our CFML codebase was put into maintenance mode, and we shifted to PHP. Prior to that we had been using MXUnit for a number of years.

PHPUnit is a bit rough-and-ready in comparison to TestBox, but it's solid and will do the trick. However we both had an arsehole of a time getting AspectMock to work. And we both failed and moved on to other things. Earlier I'd looked at Mockery as a solution for mocking - its docs are better than AspectMock's (both a recommendation for Mockery, and an indictment of AspectMock), but it did not do something things we expect to need to be doing, whereas AspectMock claims it can (mocking static methods).

Anyway, this afternoon I found myself furrowing my brow and thought "I'm going to get that bloody thing to work... or else". Fortunately after a lot of swearing and wondering if I can hunt down and punish AspectMock's author... I finally noticed what I had been doing wrong. I presume Duncan was doing the same thing wrong, but don't know. Anyway, I got it working.

So here's my AspectMock mission from this afternoon.

TickintheBox

G'day:
I watched a good amount of bickering between two fellas who should know better last night:


(click through and read the "conversation" if you want to. I'll not reproduce it here as it's a bit embarrassing for the participants, I think).

Also, I "published" some misinformation of my own about CommandBox a day or so ago (as a comment on Cutter's blog:  "What's Wrong With ColdFusion - 2014 Edition"). So I figured I owed to Brad and Luis to actually have a look at CommandBox (which I do like the sound of, see "Ortus does what Adobe / Railo ought to have done...").

Thursday 16 October 2014

WTaF?


ColdFusion 2016 in 2016? ColdFusion 2016+1 in 2018?

G'day:
Brad posted an interesting (if very blurry) image from CFSummit earlier:



CFML: Gert points out a schoolboy error in my prime numbers generator logic

G'day:
I was messing around with using closure to mimic a generator the other day: "CFML: prime number generator UDF, and overhead of using inline function expressions". Gert had a look at it, and spotted a shortfall in my implementation. He's provided some code as well but I've not really looked at that yet, instead wanting to nut it out myself (part as a penance, part as an exercise).

Wednesday 15 October 2014

Warning: people have been having issues with ColdFusion 10 update 14

G'day:
I've nothing much to say other than what it says in the headline: people have reported issues with the ColdFusion 10 update 14 that was released yesterday ("ColdFusion: new security patches for 9.0, 9.0.1, 9.0.2, 10.x, 11.x"):

As is my advice with anything the Adobe ColdFusion Team produces: it does not pay to be an early adopter. Let other people find the issues first, and let the resolutions bubble up before you run the risk of experiencing them yourselves.

And if you feel you must install it immediately, as I said yesterday: install it in a test environment and fully regression test your applications first.

Don't just install it on production servers without first testing it. This obviously applies to any change you're thinking of making to the system.

Oh... the ColdFusion Team have also got around to mentioning these new updates on their blog: "Updates for ColdFusion 11, ColdFusion 10 and ColdFusion 9 released". I recommend you go and read the comments and subscribe to the thread so as to stay on top of people's findings, and Adobe's responses.

--
Adam

Tuesday 14 October 2014

ColdFusion: new security patches for 9.0, 9.0.1, 9.0.2, 10.x, 11.x

G'day:
Patches just came out for all versions of ColdFusion from 9.0 upwards. Details in their security document: "ColdFusion Help / ColdFusion Security hot fix APSB14-23".

I've not checked the content of it, but I will say that if at this late stage of ColdFusion 9's like (it's EOL on Dec 31 this year) they're releasing individual patches for all of 9.0, 9.0.1, 9.0.2, then I am guessing it's fairly serious. So get your test machines updated as soon as possible and regression-test your apps, then look to move it to live as soon as it seems stable.

And in the mean time, we're still waiting for a more useful bug-patch for both CF10 and CF11. Wonder when to expect thosethat? They'reIt's been promised as coming out "soon" since about August, I think..?

I've just notice that the ColdFusion 10 one is actually a fairly substantial patch, fixing 60-odd issues! So that's quite good. Details in "ColdFusion Help / Bugs fixed in ColdFusion 10 Update 14".


Anyway, there you go.

--
Adam

Monday 13 October 2014

CFCamp: what I'll be having a look at

G'day:
Blimey. It occurred to me on the train this morning than this time next week I'll be in the keynote of CFCamp 2014. That kinda snuck up on me. I guess I've been a bit distracted with PHP and stuff like that.

OK, so what am I gonna go see?

Sunday 12 October 2014

CFML: prime number generator UDF, and overhead of using inline function expressions

G'day:
I continued to play around with faux generators in CFML after I finished "CFML: emulating generators with closure" yesterday. Whilst I didn't think the world would benefit from there being a palindrome generator on CFLib.org, it might benefit slightly by having one that generated primes. CFLib.org already has a function which returns an array of primes up to a threshold (GetPrimes()), but that's a slightly different requirement than being able to generate them one at a time. And I wanted to fiddle about anyhow, so that became my mission.

The actual code is not mention-worthy in and of itself, but a coupla things I noticed along the way probably are.

Saturday 11 October 2014

If you're missing the @CFMLNotifier feed: @CFNotifications has picked up the slack

G'day:
SSIA, really. Adam Tuttle just asked if I still did the @CFMLNotifier Twitter feed; I do not.

But there's the @CFNotifications feed which covers the same ground, and does a more polished job of it than I ever did. This new feed is managed by Stephen Walker, of @cfuser fame.

The received wisdom of TDD [etc]: Sean's feedback

G'day:
During the week I solicited feedback on my assessment of "The received wisdom of TDD and private methods". I got a small amount of good, usefull feedback, but not as much as I was hoping for.

However Sean came to the fore with a very long response, and I figure it's worth posting here so other people spot it and read it.


'ere 'tis, unabridged:

There are broadly two schools of thought on the issue of "private" methods and TDD:

1. private methods are purely an implementation detail that arise as part of the "refactor" portion of the cycle - they're completely irrelevant to the tests and they never need testing (because they only happen as part of refactoring other methods when your tests are already passing).

2. encapsulation is not particularly helpful and it's fine to just make things public if you want to add tests for new behavior within previously private methods.

The former is the classical position: classes are a black box except for their public API, and it's that public API that you test-drive.

The latter is an increasingly popular position that has gained traction as people rethink OOP, start to use languages that don't have "private", or start working in a more FP style. Python doesn't really have private methods (sure, you can use a double underscore prefix to "hide" a function but it's still accessible via the munged name which is '_TheClass__theFunction' for '__theFunction' inside 'TheClass'). Groovy has a 'private' keyword (for compatibility with Java) but completely ignores it. Both languages operate on trust and assume developers aren't idiots and aren't malicious. In FP, there's a tendency toward making everything public because there are fewer side-effects and some helper function you've created to help implement an API function might be useful to users of your code - and it's safe when it has no side-effects!

When I started writing Clojure, coming from a background of C++, Java, and CFML, I was quite meticulous about private vs public... and in Clojure you can still easily access a "private" function by using its fully-qualified name, e.g., `#'some.namespace/private-function` rather than just `private-function` or `some.namespace/private-function`. Using `#'` bypasses the access check. And the idiom in Clojure is generally to just make everything public anyway, possibly dividing code into a "public API" namespace and one or more "implementation" namespaces. The latter contain public functions that are only intended to be used by the former - but, again, the culture of trust means that users _can_ call the implementation functions if they want, on the understanding that an implementation namespace might change (and is likely to be undocumented).

My current position tends to be that if I'm TDD-ing code and want to refactor a function, I'll usually create a new test for the specifics of the helper I want to introduce, and then refactor into the helper to make all the tests pass (the original tests for the existing public function and the new test(s) for the helper function). Only if there's a specific reason for a helper to be private would I go that route (for example, it isn't a "complete" function on its own, or it manages side-effects that I don't want messed with outside of the calling function, etc). And, to be honest, in those cases, I'd probably just make it a local function inside the original calling function if it was that critical to hide it.

Google for `encapsulation harmful` and you'll see there's quite a body of opinion that "private by default" - long held to be a worthy goal in OOP - is an impediment to good software design these days (getters and setters considered harmful is another opinion you'll find out there).

That was longer than I intended!

Yeah Sean but it was bloody good. It all makes sense, and also goes a way to make me think I'm not a lunatic (at least not in this specific context).

And I have a bunch of reading to do on this whole "encapsulation harmful" idea. I'd heard it mentioned, screwed my nose up a bit, but didn't follow up. Now I will. Well: when I have a moment.

Anyway, there you go. Cheers for the effort put in to writing this, Sean. I owe you a beer or two.

Righto.

--
Adam

CFML: emulating generators with closure

G'day:
Half way through my other article this morning ("PHP: Inspired by Duncan: palindromes via generators"), I was thinking how cool generators are, and how it sucks CFML doesn't have them (go vote, btw: RAILO-2942; and for ColdFusion: 3555025).

Then I had a watershed moment.

PHP: Inspired by Duncan: palindromes via generators

G'day:
My mate Dunc is making a habit of being my muse @ the moment. I guess it's cos we're both learning PHP at the same time, and he's blogging about it as well. This morning he has a new article following his foray into translating his CFML (and Python occasionally) knowledge into PHP: "Project Euler: problem 36 (PHP)".

Thursday 9 October 2014

Proposed TDD logic flow

G'day:
I've been really busy this week, and haven't been able to discover much interesting about either PHP or CFML or anything, hence being quite quiet. I'll admit this is very much a filler article, and a bit of a cheeky nod to something Andy said the other day:



Earlier I asked for people's opinions regarding TDD vs private methods: "The received wisdom of TDD and private methods".

I didn't get much feedback [scowl], but thanks to Dom and Gerry (there's a cat 'n' mouse joke in there somewhere) for offering up some thoughts.

I needed to provide a workflow for the team, and I thought I'd stick it up here as well, as a bit of closure on the previous article. And to give Andy a picture to look at.

What do you think of this approach (other than "unreadable at that size". Click here):


Forget the first two steps "Assign Ticket", etc, as that's just our Jira workflow and a bit of context for our peeps, but the rest of it after that. Also the associated process of how to maintain private methods whilst still adhering to TDD.

I think there's a reasonable mix of pragmatism and dogmatism in that?

Thoughts?

--
Adam

Tuesday 7 October 2014

The received wisdom of TDD and private methods

G'day:
As you might know, I've recently taken on a different role as a PHP developer. My employer are shifting our code base from CFML to PHP for various reasons ("So long, and thanks for all the CF"). One facet of this is we're moving off a venerable, well-established CFML code base to a new code base in the infancy of its existence (some work on it had been done before we picked up the project). In a different language.

And we've got from having about 4000 unit tests to zero.



A coupla of us are having a quick exploratory look at PHPUnit to see what it can do, and whether there's any "gotchas" we need to be aware of when testing in PHP. So far the findings seem to be that unit testing in CFML via MXUnit and TestBox - especially in conjunction with MockBox - is a bit easier than the hoops we need to jump through in PHP to achieve the same ends. This is mostly down to CFML's objects being far more dynamic than PHP's, so injecting testing helper methods and exposing non-public methods for testing is much easier.

The challenges that PHP has thrown at us has caused us to revisit our TDD and unit testing strategy. Not necessarily to revise it, but to revisit it and see if it does need revision.

Our existing policy is that all code is written via a TDD & "Clean Code" approach:
  1. the need for a piece of functionality is identified;
  2. a failing test is written to test a facet of the functionality;
  3. code is written to pass the test;
  4. repeat from 2 until the functionality is complete;
  5. refactor if necessary.

This is applied both to new functionality as well as maintenance of existing functionality. The TDD side of things drives the code design, and also demonstrates that downstream changes don't have adverse effects on earlier requirements. The usual sort of thing.

On new work, this will mean creating a new public method (and the class it needs to go in, as required), and implementing the requirement. So all the tests are on that public method. When we refactor the code, those tests all still work, which is fine.

As a result of the refactoring we might end up with some of the code moving out into public methods of other classes, or - as often - private methods of the same class.

The newly refactored public methods go through the same TDD approach as the initial one, although this is quite often just a re-homing of the tests which were previously testing the unfactored functionality from the original public method. And the original public method's tests are selectively updated to remove any tests which are now the domain of the new methods, and mocks are used in lieu of calling these factored-out methods in the remaining tests of the original function.

And traditionally we have done exactly the same thing with the refactoring that was simply moved into private methods.

Perhaps I can demonstrate this with some pseudocode. At the end of our first TDD round, and before refactoring, we have this:

Sunday 5 October 2014

PHP: include paths... it gets worse...

G'day:
This follows on from my article from an hour or so ago "PHP: include paths are relative to the current working directory". The situation there was daft but at least had a precedent in other languages.

But this? This beggar's belief.

PHP: include paths are relative to the current working directory

G'day:
This one had me confused for a day or so last week. It seems the relative paths in include / require calls in PHP are relative to the current working directory, not the file the include statement is actually in. I'm not sure I agree with this.

Friday 3 October 2014

Good work, CFML community

G'day:
A few days ago I knocked out a quick article about the Bitnami contest that Railo is a participant in: "Ballot stuffing: vote for Railo".

At the time Railo was on the first page of participants, but well down the list.

But the CFML community has really stepped up here I think, because as I type this, Railo is now in the lead (425 votes; second place 423). I dunno when the contest ends, and the margin is still really tight so if you want to support CFML and encourage getting the word about it out there more, go and vote.

Update:


Blimey, whilst I was writing this, Railo's vote went up to 461!

And good work everyone who did vote, and who did circulate the word.

--
Adam

Comments in code: avoid if possible

G'day:
This came up in a code review yesterday... I thought I had already written about it, but cannae find the article anywhere so perhaps I imagined it. On the other hand I apologise if I have already written about this and it's a repeat. Point it out to me if so.

So, anyway, my contention today is that comments in code are grossly over-utilised, and in general one should avoid them. The code I was looking at yesterday had a case of stating the obvious. This is not the actual code, but an analogous example:

Wednesday 1 October 2014

Nano-optimsation of looping code. Fascinating but pointless

G'day:
It's PHP, Railo and ColdFusion today. A few days ago I was researching my "PHP: looking at some interesting "unexpected" behaviour with references" article which related to a StackOverflow question: "Assign by reference bug". One statement in one of the answers fascinated me:
(using reverse looping mostly because not enough people remember that's a thing you can do, and is more efficient than a forward loop =)
Interesting. And sounded like something I could get my teeth into and have a look at.