Math, PhantomJS and Command Line Arguments

So, recently I've been playing with PhantomJS. For those who are unfamiliar, PhantomJS is a headless webkit engine, that you can use to perform automated testing, take screenshots, and dozens of other things.

Phantom is still fairly new, and this has been a learning experience. My first trials were using the phantomjs-node module for NodeJS. I soon discovered (with some assist) that this bridge has some performance issues of it's own, and had to move to the command line.

When working with PhantomJS in this fashion, you write a script (in JavaScript), and pass it to PhantomJS along with any necessary arguments. I call this command line from NodeJS directly, but you can do so in Terminal or the cmd shell if you want.

Here was the catch. I had some math in my PhantomJS script. Not even complex math, really, just some basic equations converting milliseconds to seconds and rounding it off:

view plain print about
1var system = require('system'),
2 args = system.args,
3 pageArgs = {
4 elapsedTime: args[6] // this value is in the command line as 13762
5 };
7 var totalTime = Math.round((pageArgs.elapsedTime)/1000);
8 console.log("The answer is not " + totalTime);

Now, you and I know the answer is 14, but PhantomJS didn't seem to like that:

The answer is not 0

If I hard code the numeric value of elapsedTime (13762) into that statement then the math parses correctly. It appears that performing math on the values passed in causes the issue. I can change up the equation by adding 250 milliseconds:

view plain print about
1var totalTime = Math.round((pageArgs.elapsedTime+250)/1000);

But PhantomJS still doesn't like it:

The answer is not 413

Crazy, right? What I found was, if I needed to do any math to set some variables for use in the script, then I needed to do those in my node process, and pass the evaluated values to my PhantomJS script as arguments in the command line.

REVISION NOTE: Further testing shows that the command line arguments will all come across as a "string" type, which may be why these equations were miss firing. Remember to explicitly convert your command line arguments to the necessary data type, to avoid this type of issue.

Re-Imagining BlogCFC

Team CF Advance is dedicated to providing and maintaining Open Source software built in CFML. We welcome anyone to get involved, whether it's writing code, creating tests, or assisting with technical documentation, any contribution is a good one. There's already a decent list of ongoing projects that we are working on or maintaining.

On that track, how about giving us a little feedback. Let us look at a re-imagining of BlogCFC. BlogCFC was the first Open Source CFML based blogging platform, and still shares a wide install base. In that knowledge, it is important to consider not only maintaining full feature support, but also maintaining support for existing linking structures, data integrity in data migration, as well as support for multiple platforms.

There are several other ColdFusion based platforms for blogging. Mura CMS provides a way of creating blog pages. Mura is not truly a blogging platform, per se, but does make it possible. Mango Blog is also a fairly pervasive blogging platform, providing some additional level of extensibility as well. ContentBox is another platform, based largely on the popular ColdBox framework. Like Mura, ContentBox is really a CMS, so not really designed to be a blog.

Knowing that these options exist, one question then becomes "Why do ColdFusion developers adopt WordPress or Ghost as their blogging platform?" I believe this comes down to three core reasons. 1) ColdFusion hosting can be expensive, 2) the complexity of these other ColdFusion based applications, or the learning curve involved in their customization and maintenance, is more than some of these developers want to undertake, or 3) the developer was just trying to learn something different.

Issue #3 doesn't factor into this discussion. The decision of any developer to expand their knowledge base and learn new languages is a good thing. Doesn't necessarily look good to have a largely ColdFusion topic specific blog hosted on PHP, but we aren't writing this to solely serve developers. We want to build an application that anyone can deploy for their use, whether it's a development blog, a political blog, or just something to journal your trip to Istanbul. 

So, you then have two main issues you possibly need to address: 1) Hosting, and 2) simple install, usage, customization, and maintenance.

Issue #1 will still be hard to address (Team CF Advance is already in talks with a hosting provider who may offer low cost Blog hosting with everything preinstalled), but it's worth noting for future discussions. Issue #2 is more easily addressed.

Proposals For Discussion

  1. The current BlogCFC is actually two applications, one desktop and one mobile. I propose that we look at a responsive site design for a single maintainable codebase that is then viewable from multiple screen resolutions and devices. I propose adopting Bootstrap as the client-side CSS framework, to assist in that task. (One contributor has already done this with the current version of BlogCFC, so we may get a branch for this one soon...)
  2. There is currently no set style guide for skinning sites in BlogCFC. First, I think it would be extremely beneficial to build a template converter system, that could take existing themes for WordPress, and possibly Ghost, and convert them to BlogCFC themes. There is already a huge number of available WordPress themes out there, and the Ghost theme base is expanding daily as well. If we can leverage that, and make it dead simple for a user to implement, then we've covered a major hurdle to adoption. Ghost themes are the easier side of the coin, as their themes are already in Bootstrap, and already responsive designs. Second, a base template with well thought out HTML architecture and a solid CSS naming convention, that is then thoroughly documented, should make it easy for a user to upload a stylesheet that would completely customize their blog. At some point, we could even build a module for theme customization directly in the admin. And, with all of it, we heavily review page architecture to completely maximize SEO visibility.
  3. I think BlogCFC would thoroughly benefit from a server-side framework. I propose using FW/1 with DI/1. FW/1 (and DI/1) is extremely powerful and light weight, operates as a very natural extension of ColdFusion's built in application framework, and it's subsystem architecture lends well to extension/addition of new modules. I'm not positive, but we may also be able to leverage it's routing capabilities when considering legacy link support.
  4. I think we definitely need an "override" service architecture, where all instantiated objects are (at inception) blank objects that extend our base objects. This is used for individual developer customization, in a directory that never gets updated (other than the addition of new objects). Our tests should always pass, in development. Any individual overrides are the responsibility of that developer, and them running our tests should allow them to identify holes in their changes with any upgrade.
  5. I think we should employ REST services for Ajax interaction, and SOLR for site indexing and search. I do not propose the use of ORM. I think it is very important that our SQL is handwritten, well optimized, and that our indexes are carefully chosen for high availability/performance.
  6. I propose using AngularJS as a client-side JS interaction framework for the "admin" side of the blog, for data-binding and interaction. I think it best to avoid it on the front-end, in favor of generated code bits and more favorable SEO. Bootstrap should be sufficient for any "site" front-end functionality.
  7. I think we put considerable effort into the user stories centered around UI/UX, especially in terms of the admin area.
  8. I think that we generate output, where possible. Blog posts are, ultimately, static bits of page content.
  9. I think that we build in a simple plugin architecture, allowing others to contribute to furthering the platform by creating new add-ons that just be "dropped in".
    1. As with all projects overseen by Team CF Advance, we will be including tests for BlogCFC, written in TestBox. This will allow us to build out the project iteratively, testing each step along the way, to ensure that one patch doesn't break other parts of the system.

      Again, none of this is in stone. Just some random thoughts to get the ball rolling. This is just to really start the discussion, so please share your feedback. We already have a working group within Team CF Advance, who is contributing to this discussion. Ultimately these projects are community driven to fulfill a need, so knowing what you want is critical to the process. This also doesn't deter us from any ongoing patching efforts. If anyone has begun writing any patches, please let the team know so we aren't duplicating effort anywhere (or just join The Team).

Firefox, IE, and Why Browser Testing is Vital

OK, I made a mistake. I know, my wife will be amazed that I admit that, but it does happen. Testing another developer's code, I missed a critical error. Consider the following bit of code:

view plain print about
1cValue = $("#StartDate").val();
2cMessage += $.trim(StartDate).length == 0 ? "Start date is required.\n" : "";

Do you see it? The conditional, in the ternary operator, should be looking at cValue, but what the developer had intended to rename that variable. There is no StartDate variable in the script, so it should error out as undefined.

And, in Internet Explorer, it does error. StartDate doesn't exist. But, I screwed up. I tested this code in Firefox, and it didn't throw an error, even though that value was empty. You know why? Well, if you put StartDate in the Firebug console, instead of undefined it gives you this:

view plain print about
1<input id="StartDate" type="text" name="StartDate" />

Yes, that's right, because StartDate was an exact case match to the id of an element in the DOM, it returned the actual DOM element (which, by the way, is a valid string with a length).

Now, I'm not going to complain about who's right and who's wrong in this scenario (the value of StartDate), but it does underline the importance of testing in all browsers.

Once Bitten...

ColdFusion UI: cfwindow

Not sure why I forgot to blog this, but a few weeks back Ray Camden told everyone that he wasn't going to tell you to stop using ColdFusion UI tags anymore. Instead, he and Adam Cameron started the ColdFusion UI the Right Way project. This project is a collection of articles and demo assets to show people that you can use other methods for displaying these dynamic client-side "widgets" in your applications, without using the CFUI tags.

Why? Well, it was a nice concept, but honestly (and in my continuing opinion) ColdFusion doesn't need to do UI. Yes, cfoutput, and looping over queries is fine, but tags like <cfform>, <cfpod>, and <cfwindow> are the devil's work. There have been long running issues with letting ColdFusion write your HTML, CSS and JavaScript for you, the chief among them being that they're bloated, buggy, limited, and (ultimately) unnecessary. You have a much finer degree of control over your application, and how it functions, when you write it yourself.

The CFUI tags were provided to allow the lowest common denominator (i.e. someone who can't really write code) to crank out something that works. They are not intended for skilled developers who write web sites and applications for a living.

And so, Rey kicked off the project with an article on replacing <cftootip> with the jQueryUI tooltip plugin, and I wrote the next article on replacing <cfwindow> with Bootstrap's modal plugin. I just checked the repository, and now there are also articles for <cfajaxproxy> and <cfdiv>.

The idea of the project is to show you a) that it's possible to do these things without the CFUI tags, and b) show you examples using a variety of libraries, to reiterate that you aren't limited to a single option.

Build A Better ColdFusion App: Simple Conditionals

In really large apps, every line of processing can become critical. Every small process can add up, in terms of overall overhead. Especially in high traffic apps. Sometimes, the little things can really make a difference. Even your simple code might be...simpler. Take the following example:

view plain print about
1<cfset mySelections = "1">
2<cfif #mine# eq "0">
3    <cfset mySelections = "0">

I saw something like this in code this morning. Right off, the first thing you see is that all of the variables are unscoped, forcing the server to do a scopeCheck() to find out which scope each variable is a part of. Then there's the unnecessary bits to go along with it, like setting a variable, then checking another to reset the variable based on a condition. There's also the bit where the one variable is unnecessarily hashed. On top of all of that, variable assignments are one of those things it just makes more sense to write in CFScript. Let's take a look at how this might be improved:

view plain print about
1REQUEST.mySelections = (URL.mine) ? 1 : 0;

One line of code. Less keystrokes. Clearer references, and logic.

The "mySelections" variable, in this instance, is a part of the REQUEST scope (I upper case all variable scopes, to make them easier to spot when editing code).

In this situation, "mine" was a URL variable, param'd further up the page. We've used short-circuit boolean logic in our conditional statement. For those that don't understand that, any numeric value other than "0" is evaluated to true. If the value is "0", then it is false.

And speaking of numeric values, you don't need to quote them. Even though ColdFusion would figure it out, a quoted value is a string. Don't quote numeric, and don't quote Booleans.

We use the URL conditional inside of a ternary operator. Ternary operators were introduced in ColdFusion 9. The basics of this are, if the conditional is true, then use the value after the question mark. If the conditional is false, then use the value after the colon.

Finally, there's no need to hash the URL variable. You only need to hash variable references as part of output, or when they are used inside of quotation marks in code.

Now comes the really fun part. There really isn't any need for REQUEST.mySelections at all. Since the value or URL.mine was param'd, further up in the code, then the variable is always available here. Rather than copying that value to another variable (which takes up more memory), we can just reference URL.mine anywhere that REQUEST.mySelections was being used.

As you maintain your applications, it's always good to take some time and read through what's been written before. Refactoring little nuggets like this one, and a little testing, can eventually go a long way in preserving the life of your app and your server.

Out with 2013, and in with 2014

2013 was Exciting! I had several side contracts, which helped us buy a house. We left Jacksonville, and moved back to the Nashville area. I finally put some health issues behind me, allowing me to get out to some user group meetings again, as well as present. I put in a new topic for cf.Objective, which has been accepted. I picked up the camera I've been waiting a decade to buy, and jumped back in to photography with both feet. And, I carved in some time there to review a few books, do a CF Hour interview, and write a few blog posts (some even a little controversial). Now, there's downside here too. Heavy side contract work is not always conducive to a happy home. Buying a house, much less from another state (and the move that goes along with it) can be very grueling and stressful. Working at this kind of pace can bring on other health issues. The financial requirements of buying a house, moving state to state, setting up a new home, etc, make it impossible to do "other things" (like conferences, for instance). And, I still have several other book reviews I've yet to write, and didn't blog nearly as much as I would've liked. Well, you do what you can with what you have, and pray for the best. The two bright points in all of that are my wife, Teresa, and my daughter, Savannah, who continually support this crazed life, and without whom it really wouldn't be worth doing it all. I can never tell them enough how much I Love Them, nor just how much they mean to me. I never got the opportunity to talk about my conversation with Rakshith, concerning the future of ColdFusion. It was a great conversation, focusing quite a bit on Adobe's commitment to the platform, the strides in the education initiatives, and a focus on giving developers the tools (and language) they need to build better products. I think one of the greatest ColdFusion bits, to come out of this past year, was the creation of Team CF Advance. This group, entirely made up of volunteers, is working to produce Open Source applications and API's in ColdFusion. While it is still getting off the ground, the team has already made some pretty big strides. This is the kind of thing that will help bring ColdFusion back out front. I have high hopes, and high expectations, for what is to come from 2014. I've already committed to taking at least one picture a day, gotten seriously started on losing a few (too many) pounds, have several topics laid out for blog series, and am about to put some spit and polish on that preso I mentioned earlier. And that should be just the beginning. So, to all of my friends, colleagues, co-workers, and family, I wish you all the Happiest and most Prosperous of New Years.

What I'd Like To See Come Out of the ColdFusion Summit

So, the very first Adobe ColdFusion Summit is being held this week in Las Vegas, NV. What started out as a small conference, originally capped to 250 participants, is now nearly twice that size, with people coming from all over the world to attend.

We've had a lot of discussions here recently about What's Wrong With ColdFusion, and things that can be done to fix those perceptions. Ultimately, there's been a lot of positive feedback, some reasonable initial response out of Adobe, and a community that's started talking again.

What I'm hoping for is for that discussion to continue, hard, at the Summit. As much as I would like to be there, due to constraints I am unable to attend. So, I'm hoping that the community will come together to ask some hard questions. What really is being done to address the concerns brought up? How does this change current development practice, timeline, and direction? How soon can we expect to see x, y, or z? When, and how, is marketing of ColdFusion going to change?

It's important that we, the community, use this opportunity to speak to some of the engineers. "Why are we doing this? (in this new version) And not doing that?" We have to tell them what we think, and why, to assist in defining new directions. They're always gathering requirements, and you are the perfect focus group. The suits (management types that buy the licenses) can tell them that it should do this or that, but you (the developer) are the ones who truly know the things that are needed.

I know that I've talked a lot about "Adobe" ColdFusion. I am an Adobe Community Professional, so I have to choose my words carefully sometimes. Ultimately, any positive changes are changes that push innovation, competition, and advancement of the platform. In that vain, the Team CF Advance initiative, to write, support, and contribute to Open Source software solutions written with ColdFusion, is one of the single greatest things to come out of our discussion. (Big kudos to Denny Springle [with a side of Corfield], for pulling this idea back out of the hat and getting it up and running) Any time, and assistance, that anyone can give, is a good thing. While we need people to write code, we also need people that can assist with requirements gathering, documentation, and other things. Of all of the suggestions pushed in these discussions, this is the one that we (the developers) can have the most say and control.

Why I Like, and Use, CFScript

Many, many moons ago, I began a journey to learn web development. Actually it was a re-acquaintance, as I had gotten side tracked for a few years in a poor business partnership, having to catch up on how much things had changed. During that time, HTML had moved for v2 to 4, CSS was the crazy new thing replacing font and center tags, Dynamic HTML was making JavaScript hot again, and the browser wars were making life impossible.

Back then I was on the LA Tech Edu JavaScript mailing list (sadly retired, years ago). This guy named Peter Paul Koch was a major contributor to the list, and just ramping up this little site called QuirksMode. Scripting, though somewhat nightmarish with the browser wars, was actually a lot of fun. My first shopping cart was completely JS based.

I have always pushed for full parity between cfscript and tags, because scripting is more natural to me, in terms of writing programmatic logic. Sure, cfoutput and cfloop make a lot of sense in the middle of html display code, but CFC's don't (typically) contain display code, being data access and model objects.

I have issues with the implementation of CFScript. I find that there are a lot of functions of similar actions with completely different naming conventions, and argument requirements, and more. I think these things need to be addressed. That said, if I have to call the function anyway, I prefer script to tags when it's outside of display. It's a more natural approach, to me. 99 times out of 100 I end up with less lines of code, and find the logic more defined, clear cut, and easier to understand.

It's not for everyone. There are many that just plain hate cfscript, and that's their prerogative. But I will continue to use cfscript, and my examples will show that, because I personally find it a better way to write code. If it's not your preference, that's fine, you're welcome to translate my examples to tags if you need to, but for me this is how I do it. (For the record, many of the newer functions are not identical, under the hood [base Java code], as their tag counterparts, and some scripted functions have been proven to have better performance than their tag counterparts. There are benchmarks for this out there, somewhere, if you feel strongly enough to go look for them. I just take it on my experience with using it.)

New Series: Build A Better ColdFusion App

One common complaint, among opponents of ColdFusion, is the poor code that's out there on the web. I would counter that there's a ton of bad code out there in most any language (I know, I've written some of it), but I do "get it". ColdFusion, as powerful a language as it can be, also has an extremely low barrier of entry. It was created in such a way that anyone who could write HTML could turn around and write an application in ColdFusion (hence the language design decision to use a tag syntax).

Well, just because you can write code in one way, that doesn't necessarily mean that you should. There are thousands upon thousands of blog posts, articles and books out there showing people how to do various things in ColdFusion. Many (not all) are cobbled together rather quickly, offering up functional examples on how to do this or that. And, while awesome that someone bothered to take that time and share that knowledge, they didn't always consider best practices in their examples. After all, it was just a quick example, right? You wouldn't just copy and paste it into your editor. You'd tailor it to your application's needs, right?

Well, no. Many of us have copied some bit of code and just dropped it in without revision. And often it just stays like that, until it causes some sort of issue. To top it all off, chances are you copied and pasted the same bits of code into other areas of your app, or even into new applications, again without revision.

So, I want to start a new series here at Cutter's Crossing. I'm going to call it "Build A Better ColdFusion App", and in each article I want to highlight some small bit of best practice advice, with some code examples that match up accordingly. It won't be a "Tip of the Day" bit or anything, and the articles may come at any time, but they'll all get a common header, and I'll try to group them together so they're easy to find. If you have suggestions for some of these tips, or topic areas you think would be a good fit, please fill out the Contact Form and drop me a note with your suggestions.

By The Way: I'm not perfect. I might put up something and it's hosed too, or you might have suggestions on how to do it differently and/or better. Please, call me on it. We're a community of professionals, and want to put out info of value for any and all.

Are You Running ColdFusion on a Mac?

Yes, Apple is a fantastic company, making really nice products that work very well. If someone gave me one of those nice Macs with the 27" screens today, I'd probably switch. I wouldn't buy one myself. Nice as they are, I can't justify the expense when I can buy a machine twice as powerful for half the money, and actually repair it myself when I need to. But, that's my decision. I choose the imperfections of Windows on a PC architecture as a counter to the affordability and maintainability of the platform. And, it's done really well by me.

I watched Andy Matthews accidentally spill orange juice on to Aaron West's 17" MacBook Pro once, several years ago. Aaron finally got it back from the Mac Store about two weeks later. I can't afford that kind of productivity loss. No thanks.

Again, this is just me. Many others still use a Mac, and love it, and I get it. It's a fantastic operating system, and Apple does make pretty stuff.

But I wouldn't load ColdFusion server on a Mac. Not really. Not on to OS X directly. Yet, I've heard this complaint recently. About how buggy the ColdFusion install is, and what a hassle it is to get up and running.

You're running it on a Mac? On OS X? Why?

The web doesn't run on a Mac. Yes, there are OS X servers, but have you seen that market share? The web runs on *nix and Windows. And, if you're writing code for the web, then your environment needs to match. Load up a VM, and install ColdFusion on the VM, in *nix or Windows. That makes sense.

Is that where you're having trouble? I get CF up in about 20 min on my Windows Server VM, and that includes the download time.

Now, should the ColdFusion server install easily on a Mac? Sure, I think it should. There are way too many developers out there trying to do exactly what I've described, and they're in pain. Go badger the Adobe CF team to get it straight.

But, again, what's your site running on?

You can post comments if you like, but I'm not taking the bait.

Previous Entries / More Entries