Download Firefox -  a safer, easier to use web browser. Return to iribbit.net - Leap into the online experience! Return to iribbit.net - Leap into the online experience! iribbit.net - Leap into the online experience!

Project News :.

The latest project to launch was the site for Gorilla Offroad Company. Aside from their main site, a social media strategy was develop to launch the company into various industry specific automobile enthusist discussion board communities as well as popular social media fronts like Facebook, Pinterest, and Twitter.


Valid XHTML 1.0 Transitional

Valid CSS!

Section 508 Compliant

powered by: Macromedia ColdFusion MX

made with: Macromedia Dreamweaver MX

What is RSS

XML - often denotes RSS Feed information.

Macromedia - ColdFusion Programming
white horizontal rule

ColdFusion News :.

To bring a little life to my site, I've pulled a couple What is RSS Feeds into this page. You can currently choose between the technology related news stories from the following news sources:



You are currently viewing and RSS Feed from coldfusionbloggers.org.



Framework Is No Longer a 4-Letter Word

Raise your hand if you have ever used Fusebox, Model Glue, or Mach-II. (Do jazz-hands if you've used ColdSpring.)

Keep it up if you've ever seen your application time out on the first request while trying to load the framework configuration.

If you raised it for the first prompt, chances are you still have it up after the second prompt. I'm right there with you. You can put your hands down now.

I started coding web-spaghetti in CF 4.5, and learned about frameworks at around the same time CF8 was starting private beta (I don't think I was in that one). Model-Glue became my weapon of choice mostly because Joe was a captivating speaker and his sessions at CFUnited were awesome. I ended up maintaining some Fusebox apps later on in my career. And more recently I worked in a shop that was 100% Mach-II for the better part of the last decade.

They all suffer from the same problem: They were slow because object-creation was still slow in CF back then, and unless you were very careful and deliberate (and sometimes not even then), you were very prone to burying things too deep. XML that defines Listeners that proxy requests to Controllers that call Services that use DAOs. It was painful to make a tiny change because I had to make that change in 5 files... And I'm guilty of it too. Much of my code from this era is equally—if not more—cringe-worthy.

I don't think the developers behind these frameworks are guilty of anything. The tools they gave us were leaps ahead of what we had earlier (see also: <cfswitch>).

BUT... Depending on how bitter you allowed this experience to make you, the reputation that "frameworks" earned in your mind may have been deserved. Most people's experiences with frameworks (and I include myself here) was poor... and the jerk that originally wrote the app you're stuck maintaining is to blame.

Always code like the person that will inherit the app when you leave is a deranged serial killer that knows where you live.

Whether you blame the developer that came before you, or the system that allowed it to happen, many of us have painful memories of frameworks past.

I'm here to tell you that Framework is no longer a 4-letter word.

Modern frameworks use much (much!) less configuration, if any, and orders of magnitude fewer objects. FW/1 (a badass MVC framework) is one object. DI/1 (a badass Dependency Injection framework) is also just one file. And if I may be so bold as to place my own work on the same stage as Sean's, Taffy is only a small handful of files, has super-terse syntax that almost forces you to write as little code as possible, and runs fast as hell.

How well you know your tool matters much more than what tool you know.

At the end of the day, you can still write terrible messes of code with new tools. Just because you have a bad experience doesn't mean the tool is to blame. But framework developers are learning the common pitfalls their users (a.k.a. you and I) run into, and putting up police tape and stanchions to keep us on the path to success. If the word framework gives you sweaty palms and makes you start looking for the exit, I would urge you to come back and try more modern iterations.

You might be surprised.


(Tue, 02 Sep 2014 10:00:13 GMT)
[view article in new window]

Repro of structCopy() bug
G'day:
I could put this in a gist or just post the code directly, but it gives me something to write about today. Be wary of structCopy(). There's a bug been raised about it not working on ColdFusion scopes, which Adobe don't quite seem to be able to understand. The ticket is 3815793.

Firstly: some background. Don't use structCopy(). It's a shitty function, which doesn't do anything useful, coherently. Consider this demonstration:

// demo.cfm

test("Baseline");

test("Original updated", function(){
original.colours.black = "*****mangu*****";
});

test("Original added to @ top level", function(){
original.numbers.three = "*****toru*****";
});

test("Original added to @ inner level", function(){
original.colours.green = "*****kakariki*****";
});


function test(label,process){
writeOutput("<h3>#label#<h3>");
makeStructures();
isDefined("process") ? process() : false;
writeDump(var={original=original,ref=ref,copy=copy,dupe=dupe});
writeOutput("<hr>");
}


function makeStructures(){
original = {
colours = {
black = "pangu"
}
};

ref = original;
copy = structCopy(original);
dupe = duplicate(original);
}


Notes:
  • I have a function test()...
  • ...which creates a test struct...
  • ...and performs an operation on it...
  • ...dumping out the results.
  • I perform a number of tests:
    • A baseline
    • Changing a value in a sub-struct
    • Adding a value at the top level
    • Adding a value in a sub-struct

And here are the results:

Baseline

struct
COPY
struct
COLOURS
struct
BLACKpangu
DUPE
struct
COLOURS
struct
BLACKpangu
ORIGINAL
struct
COLOURS
struct
BLACKpangu
REF
struct
COLOURS
struct
BLACKpangu

Original updated

struct
COPY
struct
COLOURS
struct
BLACK*****mangu*****
DUPE
struct
COLOURS
struct
BLACKpangu
ORIGINAL
struct
COLOURS
struct
BLACK*****mangu*****
REF
struct
COLOURS
struct
BLACK*****mangu*****

Original added to @ top level

struct
COPY
struct
COLOURS
struct
BLACKpangu
DUPE
struct
COLOURS
struct
BLACKpangu
ORIGINAL
struct
COLOURS
struct
BLACKpangu
NUMBERS
struct
THREE*****toru*****
REF
struct
COLOURS
struct
BLACKpangu
NUMBERS
struct
THREE*****toru*****

Original added to @ inner level

struct
COPY
struct
COLOURS
struct
BLACKpangu
GREEN*****kakariki*****
DUPE
struct
COLOURS
struct
BLACKpangu
ORIGINAL
struct
COLOURS
struct
BLACKpangu
GREEN*****kakariki*****
REF
struct
COLOURS
struct
BLACKpangu
GREEN*****kakariki*****

The reference copy and the duplicate() works as one would expect:

  • the reference copy results in two references pointing to the same struct, so any changes to one is reflected in the other;
  • the duplicate is a completely new struct, so changes to the original have no effect on the duplicate.
However structCopy() does something completely useless: it duplicates the top level of the struct, but what it copies are the references, not the values. So this means if one alters the top level of the original, it's not reflected in the copy; if one alters any of the internal structs, then that is reflected in the copy.

Fence-sitting functionality like this serves no purpose, and simply causes confusion.



But that's not even the problem here. This is documented behaviour. It's how Allaire decided structCopy() ought to work.

The issue is that structCopy() doesn't even copy the top level keys when using it on (some?) ColdFusion scopes.

Repro:

// urlBug.cfm

URL.testKey = "value set in URL scope";
writeDump(var=URL, label="URL scope");

writeOutput('<br><div style="padding-left: 20px;">');
copy = structCopy(URL);
writeDump(var=copy, label="initial state of copy of URL scope");

copy.testKey = "value set in copy";
writeDump(var=copy, label="updated state of copy");
writeOutput('</div><br>');


writeDump(var=URL, label="URL scope after change made to copy");

Output on ColdFusion (on Railo it works correctly):

URL scope - struct
TESTKEYvalue set in URL scope

initial state of copy of URL scope - struct
TESTKEYvalue set in URL scope
updated state of copy - struct
TESTKEYvalue set in copy

URL scope after change made to copy - struct
TESTKEYvalue set in copy

Note how the change to the the value in the URL scope. Let's just compare that to using a struct instead of the URL scope:

// withStruct.cfm

struct.testKey = "value set in struct";
writeDump(var=struct, label="struct");

writeOutput('<br><div style="padding-left: 20px;">');
copy = structCopy(struct);
writeDump(var=copy, label="initial state of copy of struct");

copy.testKey = "value set in copy";
writeDump(var=copy, label="updated state of copy");
writeOutput('</div><br>');

writeDump(var=struct, label="struct after change made to copy");

The only difference there is that i'm using a struct instead of the URL scope. And the output is now as we'd expect:

struct - struct
TESTKEYvalue set in struct

initial state of copy of struct - struct
TESTKEYvalue set in struct
updated state of copy - struct
TESTKEYvalue set in copy

struct after change made to copy - struct
TESTKEYvalue set in struct

Changes to the copy at that top level do not impact the original struct. So that demonstrates the bug, Adobe. I can't help but think the original guidance offered should have been enough:

Steps to Reproduce:
1) do a form post
2) make a structcopy
3) update form key of copy
4) dump / output form
I don't see how that's unclear. Although it does depend on them actually reading what's in front of them, which I am finding to not be one of their strengths.

So I dunno what the chances are of them reading all this, but hey... as the saying goes "I can lead the horse to water (I just can't hold it's head under until it stops struggling)".

--
Adam
(Tue, 02 Sep 2014 09:02:03 GMT)
[view article in new window]

Error Events Don't Inherently Stop Streams In Node.js
Ben Nadel looks at the interplay between Node.js Streams and error events and finds that errors don't inherently stop streams....
(Tue, 02 Sep 2014 04:00:15 GMT)
[view article in new window]

Adding 4000 subscribers in 45 days
How 45 days of "testing" grew my email list by 53% after 9 years of "implementing".
(Mon, 01 Sep 2014 18:00:15 GMT)
[view article in new window]

Dell Sputnik Tip: Mouse / Cursor is broken or frozen after resuming from suspend or sleep
For some reason my third generation Dell Sputnik (aka Dell XPS13 with Ubuntu pre-installed) sometimes has a frozen or broken mouse / cursor after I suspend or sleep my laptop.  You can easily get it working again (this is not … Continue reading
(Mon, 01 Sep 2014 14:00:24 GMT)
[view article in new window]

Dell Sputnik Tip: Mouse / Cursor is broken or frozen after resuming from suspend or sleep
For some reason my third generation Dell Sputnik (aka Dell XPS13 with Ubuntu pre-installed) sometimes has a frozen or broken mouse / cursor after I suspend or sleep my laptop.  You can easily get it working again (this is not … Continue reading
(Mon, 01 Sep 2014 14:00:24 GMT)
[view article in new window]

Ext JS 5: View Controllers
If you’ve been paying attention to anything Sencha has been talking about since the release of Ext JS 5, you’ve certainly noticed a shift in emphasis in application structure. With Ext JS 4, Sencha provided a pretty robust architecture for developing scalable applications in an MVC(ish) approach. This was a MASSIVE upgrade from the 2.x and…
(Mon, 01 Sep 2014 14:00:14 GMT)
[view article in new window]

Looking at PHP's OOP from a CFMLer's perspective (part 2/?)
G'day:
So I continue my battle through PHP's OO implementation. See "Looking at PHP's OOP from a CFMLer's perspective (part 1/?)" for the first bit of this.

Static properties and methods

This is something I've wanted in CFML for ages. Well: static methods, anyhow. There are tickets for both ColdFusion (3756518) and Railo (RAILO-2941) for this. I'm not so interested in static properties as I think they're perhaps the wrong way to deal with most situations? Dunno, I'm sure someone will come up with a compelling case...

Anyway, so they're doable in PHP:

<?php
// Person.class.php
class Person {

public $firstName;
public $lastName;
private $fullName;

public static $population = 0;


public function __construct($firstName, $lastName) {
$this->firstName = $firstName;
$this->lastName = $lastName;
$this->setFullName();

self::$population++;
}

private function setFullName(){
$this->fullName = $this->firstName . " " . $this->lastName;
}

public function getFullname(){
return $this->fullName;
}

public static function getPopulation() {
return self::$population;
}


}

<?php
// person.php

require_once("app.php");

$boy = new Person("Zachary", "Cameron Lynch");
echo "Name: " . $boy->getFullName() . "<br>";
echo "Population: " . Person::getPopulation();
echo "<hr>";

$dad = new Person("Adam", "Cameron");
echo "Name: " . $dad->getFullName() . "<br>";
echo "Population: " . Person::getPopulation();
echo "<hr>";

$grandDad = new Person("Donald", "Cameron");
echo "Name: " . $grandDad->getFullName() . "<br>";
echo "Population: " . Person::$population;
echo "<hr>";

The output for this is:

Name: Zachary Cameron Lynch
Population: 1


Name: Adam Cameron
Population: 2


Name: Donald Cameron
Population: 3




Here we've added a static property population, which tracks the current head count of Person objects. This is definitely not how one would deal with this information in the real world, but it'll do as an example.

We also have a static method getPopulation() which we can use to fish-out the current value. Note because it's a public property, we can also access it directly.

In case you're not so familiar with static properties & methods, the thing to note is that they apply to the class, not to the instances of the class. that's why they're referenced via Person, above, not via $boy / $dad / $grandDad. Related to this, note that within the class, one refers to the current object via $this, but the class itself via self. Do not ask me why $this has a $ and self doesn't. Nor why references to static properties / methods use the :: operator, but it's the -> operator with object properties & methods. It makes no sense to me. Indeed WhyTF they don't just use . is beyond me. I guess because they chose that to be the string concatenation operator (which, itself, is pretty stupid).

Inheritance

PHP's allows one to extend on class with another using the extends keyword. Here's a basic example:

<?php
// Person.class.php
class Person {

protected $firstName;
protected $lastName;

public function __construct($firstName, $lastName) {
$this->firstName= $firstName;
$this->lastName = $lastName;
}

public function getFullname(){
return $this->firstName . " " . $this->lastName;
}

}

<?php
// Employee.class.php

class Employee extends Person {

protected $middleName;
protected $employeeId;

public function __construct($firstName, $middleName, $lastName, $employeeId) {
$this->middleName = $middleName;
$this->employeeId = $employeeId;
parent::__construct($firstName, $lastName);
}


public function getEmployeeId(){
return $this->employeeId;
}

public function getFullname(){
return $this->firstName . " " . $this->middleName . " " . $this->lastName;
}

}

<?php
// employee.php

require_once("app_autoload.php");

$person = new Person("Zachary", "Cameron Lynch");
echo "Name: " . $person->getFullName();

echo "<hr>";


$employee = new Employee("Donald", "Adam", "Cameron", 17);
echo "Name: " . $employee->getFullName();
echo "Employee ID: " . $employee->getEmployeeId();

echo "<hr>";

The output is predictable:

Zachary Cameron Lynch

Donald Adam Cameron



Curse my son for having a compound surname, but that's firstName lastName in the first one, and firstName middleName lastName in the latter one.

There's some hairy syntax in there around calling the parent-class's constructor, but other than that: no surprises.

However the "no surprised" quickly devolved into confusion. I decided to try to use polymorphism on the fullName property, by setting it once when the object was created; however having a different setFullName() method in each class:

<?php
// Person.class.php
class Person {

protected $firstName;
protected $lastName;
protected $fullName;

public function __construct($firstName, $lastName) {
$this->firstName= $firstName;
$this->lastName = $lastName;
$this->setFullName();
}

private function setFullName(){
echo "Used setFullName() from Person<br>";
$this->fullName = $this->firstName . " " . $this->lastName;
}

public function getFullname(){
return $this->fullName;
}

}



<?php
// Employee.class.php

class Employee extends Person {

protected $middleName;
protected $employeeId;

public function __construct($firstName, $middleName, $lastName, $employeeId) {
$this->middleName = $middleName;
$this->employeeId = $employeeId;
parent::__construct($firstName, $lastName);
}

private function setFullName(){
echo "Used setFullName() from Employee<br>";
$this->fullName = $this->firstName . " " . $this->middleName . " " . $this->lastName;
}

public function getEmployeeId(){
return $this->employeeId;
}

}



<?php
// employee.php

require_once("app_autoload.php");

$person = new Person("Zachary", "Cameron Lynch");
echo "Class: " . get_class($person) . "<br>";
echo "Name: " . $person->getFullName();

echo "<hr>";


$employee = new Employee("Donald", "Adam", "Cameron", 17);
echo "Class: " . get_class($employee) . "<br>";
echo "Name: " . $employee->getFullName() . "<br>";
echo "Employee ID: " . $employee->getEmployeeId();

echo "<hr>";


This isn't a fantastic example, but it demonstrates the problem I encountered. Here's the output:

Used setFullName() from Person
Class: Person
Name: Zachary Cameron Lynch


Used setFullName() from Person
Class: Employee
Name: Donald Cameron
Employee ID: 17




Note that PHP doesn't pay attention to the fact that my subclass has its own setFullName() method. Huh?

It wasn't until I was writing this article (and I've hastily had to rework the last paragraph, now that I see that it's my fault!) that I spotted what's wrong. My familiarity with CFML's peculiarities is getting the better of me.

Note this (from Employee.class.php):

private function setFullName(){
echo "Used setFullName() from Employee<br>";
$this->fullName = $this->firstName . " " . $this->middleName . " " . $this->lastName;
}

What does private access mean in PHP? Only the current class can see it. So my parent class - Person - can't see Employee's setFullName(), so just uses its own one. If I change both functions to correctly use protected access, the code works fine:

Used setFullName() from Person
Class: Person
Name: Zachary Cameron Lynch


Used setFullName() from Employee
Class: Employee
Name: Donald Adam Cameron
Employee ID: 17



Abstraction

One thing that PHP implements which CFML doesn't is class and method abstraction.

Here we have a class that represents the abstract concept of a shape. For the purposes of this exercise all a shape has is a number of dimensions (eg: a circle has two; a sphere has three):

<?php
// Shape.class.php
abstract class Shape {

protected $dimensions;

public function getDimensions(){
return $this->dimensions;
}


}

It makes no sense to create a Shape object, as it is just a concept, not an implementation. So if we try:

<?php
// shape.php

require_once("app_autoload.php");

$shape = new Shape();

We get an error:

Fatal error: Cannot instantiate abstract class Shape in D:\Websites\www.scribble.local\shared\scratch\php\www\experiment\oo\shape.php on line 6

Note that the Shape class - whilst itself being abstract - does actually implement a concrete method, getDimensions(). IE: once we have a concrete implementation extending this Shape class, then its objects will inherit that method and it can be used quite normally.

Continuing on...

<?php
// TwoDimensionalShape.class.php
abstract class TwoDimensionalShape extends Shape {

protected $dimensions = 2;

abstract public function getPerimeter();
abstract public function getArea();

}

Here we have another abstract class, which extends Shape, this time a TwoDimensionalShape. This time it's got a coupla abstract methods too. It's reasonable to conclude that all two dimensional shapes will have a perimeter and an area, but one cannot give a default implementation as the formulas vary according to the type of shape the implementation is. So this class cannot be instantiated, and its methods also are abstract, so they cannot be run: they simply define that the methods should be implemented (kinda like an interface).
<?php
// Circle.class.php
class Circle extends TwoDimensionalShape {

protected $radius;

public function __construct($radius){
$this->radius = $radius;
}

public function getCircumference(){
return 2 * pi() * $this->radius;
}

public function getPerimeter(){
return $this->getCircumference();
}

public function getArea(){
return pi() * $this->radius * $this->radius;
}

}

Finally we have a concrete implementation of TwoDimenstionalShape: a Circle. We can instantiate one of these, and call its methods:
<?php
// circle.php

require_once("app_autoload.php");

$circle = new Circle(7);

echo "Dimensions: " . $circle->getDimensions() . "<br>";
echo "Perimeter (circumference): " . $circle->getPerimeter() . " (" . $circle->getCircumference() . ")<br>";
echo "Area: " . $circle->getArea() . "<br>";


And this outputs some results:


Dimensions: 2
Perimeter (circumference): 43.982297150257 (43.982297150257)
Area: 153.9380400259


Cool.

What if we implement a Square, but don't implement the getArea() method?

<?php
// Square.class.php
class Square extends TwoDimensionalShape {

protected $sideLength;

public function __construct($sideLength){
$this->sideLength = $sideLength;
}

public function getPerimeter(){
return $this->sideLength * 4;
}

}

<?php
// square.php

require_once("app_autoload.php");

$square = new Square(7);

echo "Dimensions: " . $square->getDimensions() . "<br>";
echo "Perimeter (circumference): " . $circle->getPerimeter() . " (" . $circle->getCircumference() . ")<br>";
echo "Area: " . $circle->getArea() . "<br>";

This just results in an error:

Fatal error: Class Square contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (TwoDimensionalShape::getArea) in D:\Websites\www.scribble.local\shared\scratch\php\www\experiment\oo\classes\Square.class.php on line 3


So if a class extends another class with abstract methods, then it either needs to implement the methods, or it needs to be declared as abstract. The bottom line is that any class being instantiated needs to have all its methods accounted for in a concrete way.

Interfaces

PHP, like CFML, allows interfaces. They're about the same, too:

<?php
// Serialiseable.interface.php

interface Serialisable {
public function serialise();
}

I've adjusted the Shape class to implement Serialisable:

<?php
// Shape.class.php
abstract class Shape implements Serialisable {

protected $dimensions;

public function getDimensions(){
return $this->dimensions;
}

}

Note that it doesn't actually implement the required method though. I implement it in TwoDimensionalShape:

<?php
// TwoDimensionalShape.class.php
abstract class TwoDimensionalShape extends Shape {

protected $dimensions = 2;

abstract public function getPerimeter();
abstract public function getArea();

public function serialise(){
return json_encode([
"dimensions" => $this->getDimensions(),
"perimeter" => $this->getPerimeter(),
"area" => $this->getArea()
]);
}

}

And in action:

<?php
// interface.php

require_once("app_autoload.php");

$circle = new Circle(7);

echo $circle->serialise();

Result:
{"dimensions":2,"perimeter":43.982297150257,"area":153.9380400259}

One thing you might have noticed is the file name of the Serialisable interface: Serialisable.interface.php. My mentioning of interface in the file name is not a PHP thing, it's just a file-naming convention. This did mean I needed to change my autoloader file though:

<?php
// app_autoload.php
spl_autoload_register(null, false);
spl_autoload_extensions('.class.php, .interface.php');
spl_autoload_register(function($class){
$filePath = "./classes/" .$class . ".class.php";
if (is_file($filePath)){
return require $filePath;
}
require "./classes/" .$class . ".interface.php";
});

I now need to do a coupla extra things:
  • look out for an additional file extension
  • and infer the file name of the class or interface slightly differently, checking to see if the class file exists first, and if not assume it's an interface
I googled around for a more clever way of doing this, but basically that seems to be about it.

I was quite surprised that return require worked, given require is not a function. But it seems to. "Work", I mean.

Type-checking

As a final step in this article, i'll just demonstrate that the type inheritance of all this is what we'd expect:

<?php
// testCheck.php

require_once("app_autoload.php");

$circle = new Circle(7);

echo sprintf("A circle is a Circle: %b<br>", $circle instanceof Circle);
echo sprintf("A circle is a TwoDimensionalShape: %b<br>", $circle instanceof TwoDimensionalShape);
echo sprintf("A circle is a Shape: %b<br>", $circle instanceof Shape);
echo sprintf("A circle is Serialisable: %b<br>", $circle instanceof Serialisable);
echo "<br>";
echo sprintf("A circle is a Square: %b<br>", $circle instanceof Square);

That's self-explanatory. And here's the output:

A circle is a Circle: 1
A circle is a TwoDimensionalShape: 1
A circle is a Shape: 1
A circle is Serialisable: 1

A circle is a Square: 0


Cool.

There's more...

There's a bunch more stuff to go through, but this has taken about two weeks to write now (not constantly), and I've had a long day today and I want a beer. So I'm gonna proofread it and press send.

Righto.

--
Adam
(Mon, 01 Sep 2014 13:06:32 GMT)
[view article in new window]

Node.js Streams Inherit Error-Handling Behavior From EventEmitter
Ben Nadel demonstrates that the error handling behavior in Node.js streams is inherited from the EventEmitter module....
(Mon, 01 Sep 2014 10:00:11 GMT)
[view article in new window]

Bind Your Error Handler Before Your Readable Handler When Using Node.js Streams
Ben Nadel looks at the order of event-bindings on a Node.js Readable stream and why the order makes a big difference when it comes to catching errors....
(Mon, 01 Sep 2014 10:00:11 GMT)
[view article in new window]


© The connection to the CFBLOGGERS_FEED's RSS feed has timed out - please try again later. We are sorry for any inconvenience this may have caused.