I’ve received a few requests to modify varscoper and add support for cfcs written completely in cfscript. I don’t usually write cfcs completely in script, so I’m looking for a little help in order to expedite development.
Things I’m looking for…
- Code samples – I’d like to get a representative sample of what people are writing. This might be included/released as part of a test case, so please don’t send anything sensitive.
- RegEx help – Are you a regex wiz? If you can help provide an expression that can isolate function blocks it would be a huge help.
- New ideas on how to parse code – varscoper is heavily dependent on regular expressions. This isn’t the ideal tool to use when parsing irregular strings, any ideas on other tools/libraries to use would be a big help
Amazon recently released updated pricing on reserved ec2 instances. If you’ve been left high and dry by Go Daddy, or are simply looking for a cheaper alternative for hosting cfml applications it might be a good time to take a look at Amazon Web Services.
For a little more than a year, I have been running a number of personal sites on an ec2 micro instance. It is a linux based instance running railo/mysql/apache. I currently run 2 Mura sites, an instance of Mango Blog, 2 wordpress sites, and various low traffic bespoke cfml applications. I’ve been averaging around 1500 cfml requests/day, and at the end of a 2 year period my average monthly hosting cost will be approximately $4.50/month.
At the entry level, Amazon offers dedicated virtual servers (Micro Instances) that come with 613MB of memory and are burstable up to 2 EC2 Compute Units (One EC2 Compute Unit provides the equivalent CPU capacity of a 1.0-1.2 GHz 2007 Opteron or 2007 Xeon processor). The downside of using this type of instance is that you can be severely throttled for short amounts of time if you have sustained periods of high CPU utilization. (I hope to write about this more in depth in an upcoming post). This is an extremely cost effective option for non mission critical applications (personal sites, blogs, testing environments, etc.).
Amazon offers a full 12 months of hosting on a single micro instance for FREE. After that you are looking at between $14.60-$18.25/month to run a spot instance on demand. Prices vary based on the region you are running your instance in. Now back to reserved pricing… If you are planning to run your instance for at least 12 months, you can pay an up front fee of $62 that cuts your hourly pricing by 75% effectively dropping your monthly fee to $8.80. Throw in your free year and you’re down to $4.40 over a 2 year span. Other costs you might incur are minimal bandwidth charges, and $.10/GB/Mo for disk usage as Micro instances don’t include dedicated disk space. Prices for windows instances are higher, but still reasonable.
Overall, I’ve been extremely happy with my experience so far, the management tools that amazon provides are unmatched, and you have the ability to scale up almost infinitely if the need arises (for a price). If you are looking for a cost effective CF host, it’s definitely worth taking a look at.
First off, I’d like to apologize to any of you that received a flood of new posts from me in your feed reader. My blog has a new and hopefully more permanent location and this time I’m not trying to preserve guids in my feed. Sorry about that, feel free to do a mass delete/mark all as read.
Second, I’ve moved back to San Francisco after my 2 year adventure in Sydney. It was an incredible experience and I had a chance to meet and work with some exceptional people. Now that I’m back I’m hoping the lack of hot weather and perfect beaches will allow me to blog more than I did when I was there (one post).
Finally, I’m planning to make this blog less CFML-centric going forward. I find myself working more and more with technologies and tools that are not cfml based, so I’m now calling this “Mike on Software” instead of “Mike Schierberl’s ColdFusion Blog”. I’m still planning to write on CF topics, but hopefully I’ll be able to write about other topics you can use to supplement your toolkit.
varScoper 1.30 is now available to download on RIAForge. This release fixes over 17 reported issues and also works properly on both Railo and OpenBD.
Additionally, Raymond Camden’s ColdFusion builder extension code has been integrated. Hopefully the consolidation will make life easier for everyone. You can either install the zip, or import the extension if it’s already unpacked. In case you haven’t used it yet, this feature allows you to right click on a file or folder in CF Builder and run varScoper directly from the IDE.
At the moment, this release will not correctly identify variables based on CF9 syntax (LOCAL scope and ability to identify var anywhere in a function). The test cases are in place and I’ll be working on it soon. As a result you will notice the unit test will throw an error if you aren’t running cf9.
Thanks again to Ray, Pat Santora, and everyone else who has reported issues. If you have any problems, please report them at RIAForge and I will get to them eventually.
At 10:30pm tonight I will be getting on a plane to relocate to Sydney, Australia. The bags are packed, and I’m looking forward to the next exciting chapter in my life. As of Monday, my company was acquired by Thomson Reuters, and I will be working as an independent consultant for them.
I’m looking forward to getting involve with all of you in the CF community when I arrive. Don’t be a stranger, please introduce yourselves as I hardly know anyone there. I’m really hoping that I can win a pass to @webdu in their twitter competition, it would be a great opportunity to make some connections. If you’re on twitter I wouldn’t mind a shameless plug for a ticket :) (@mikeschierberl).
Additionally, if you are in Sydney, I’d love recommendations on things to do/see from a locals perspective. I’ve been there a few times, but I will be coming with a clean slate and an open mind.
If you are using YSlow or an equivalent tool you’re probably aware of some of the best practices to follow to optimize client-side load times. In this post I’m going to outline a quick and easy approach that we use at Planitax to deploy static content using Ant.
The best practices that I hope to address with this build strategy are…
1) Add an Expires or a Cache-Control Header
When we developed a deployment strategy we wanted an approach that was transparent to the end user, easy to build, and had minimal impact on developers checking in code. We needed to meet the following criteria.
- Content should be able to have a Expire date at any point in the future
- Content can be deployed to QA/Production at any time using a one step build
- Webserver should automatically apply expires headers to static assets without additional deployment steps.
- Developers should always be able to check into a single repository location. Branching/Deploying should not require a copy of a file to be checked in.
- Developers should not be required to run a build target in order to see changes to static content.
- js/css should be minified on production deployments, but not in the source code repository.
From these requirements we came up with a strategy that looked something like this.
- Static assets that can be cached will always live in the /assets folder off the application root. Content will be organized into subfolders for /assets/js, /assets/css, and /assets/images.
- Developers will work with expires headers turned off for these folders so changes will appear immediately.
- Developers will check files in directly to this location. The repository location will always be /assets.
- When deploying to QA/Production, a copy of the static assets will be created with a new version identifier. This copy will also be minified as part of the deploy step.
- The application will be able to determine the correct copy of static content to use regardless of the deployment environment.
- QA/Production web servers will automatically add an expires header to any content located in the /assets folder.
The first step was to build an ant target that would take care of creating a new folder, copying the assets and minifying content appropriately. We use JSMin to minify our JS. In order to execute this example you will need to download the JSMin Ant Task from Google Code. Note, when setting up your taskdef, the classpath attribute should point to the relative location that you have saved the .jar file. For this example it will be in the /lib subfolder off of root.
This code creates a folder with a name that looks something like this… ./assets/js200901141546 , it’s named this way so we can do alpha sorts easily as you will see in the next step. We don’t check this folder in to source control.
Note: You can adapt this code for css or images by modifying the copy command, if you only need to copy/minify JS you might be able to get by without the copy command.
The next step is to make your application aware of the correct folder to be used. This is easy to do with a cfdirectory based on the naming convention we used above. First we will create a variable that identifies the most recent/current folder created by the name that contains the timestamp. The nice thing about this is that it will identify the correct folder for prod servers as well as developers who only have a ./assets/js folders. It does not require developers to run the build target in order to see changes.
The only tricky part is to make sure that all your links to assets include the new variable that you have created. Your links will look something like this…
I’m sure there are countless ways to approach this, and your deployment strategy may differ significantly based on your environment, and or application. I’m interested to see how others have approached this and other deployment tasks.
Recently, I've talked to a few developers who knew about the var scope, but didn't quite grasp the concept of making a variable local to a function. Additionally, I've come across a few posts that indicated that setting a var statement was strictly to conserve memory (along with other reasons that missed the point).
To help anyone struggling with understanding the impact of the var scope I've put together a quick example to demonstrate what can happen when you improperly scope a variable.
The example here focuses on CFCs that are loaded into a shared scope (session, application, etc), and are accessed simultaneously by multiple users.Running the code will make 2 simultaneous requests to the same function in separate iframes. The example contains a loop that outputs the index of a loop from 1 to 100. If the loop executes correctly the numbers appear in green, if the numbers are out of sequence, they will be red. To make the results more dramatic I've included a 1-40ms pause in each loop iteration.
Here's the cfc that is loaded in server scope (simplified for reading). Note the only difference in the functions is that the "count" variable has a var statement in one function and doesn't in the other function.
#count# #count# executing "VarFunction()"
If the example executed correctly, you should have seen all green numbers in both windows for the var scope example, and a mix of green and red in the example that executed the function without the var statement. The presence of the "var" statement makes the variable local to the function. This means that when the function runs, it creates a new instance of the variable that is unique each time the function is executed. Without the var statement in place, the variable gets "shared" between everyone who is accessing this component. When a component lives in a shared scope (session, application) the variable will be shared for everyone accessing that scope. Think of the following scenario.
User 1: set count = 1
User 2: set count = 1
User 1: set count = count + 1
User 2: set count = count + 1
User 1: count = 2
User 2: count = 3
In this case the developer most likely intended to have both users see count = 2, however the variable was shared and as a result a user's result was impacted by another user's request. Note: this may be the intended behavior of the code, and that's why there is no definite rule on why you should "always" or "never" var scope a variable.
Unfortunately, recognizing issues that appear as a result of improper scope can be difficult. Many times they result in server errors that are intermittent and only appear under load. This can sometimes make it practically impossible to reproduce the error in a test environment. Also, many tags create variables that are easy to miss (cfquery, cfloop, etc).
Luckily, there's a tool to help (shameless plug here). Take a look at varscoper. Hopefully this will become an integral tool in your development process.
A new release candidate is available for my varScoper tool.
Please download and run against your code. If you find any issues please report them at RIAForge.
Thank you to everyone who provided feedback on 1.21. At least 16 bugs were identified and are now fixed in the RC. All reported issues and corner cases have been added to the unit test to ensure that it won’t break the same way in the future. Additionally, thank you to Pat Santora, who was responsible for a majority of the fixes.
Finally, based on feedback, I’ve included a cfset statement generator to generate blocks of cfset var statements. However, I take no responsibility for the consequences of using this generated code.
Version 1.21 of varscoper is now available to download . This is a minor update that fixes some of the CF6, CF7, and *nix issues that were reported when I released 1.20.
Additionally, there was a minor fix to cfscript parsing when using a function inside a struct set. Something similar to this…
mystruct[someFunction()] = "";
Many thanks to Pat Santora for this release. The majority of the content in this release is a direct result of his hard work.
- Improvements to cfscript parsing engine
- RIAForge issues 6,7,8,9,10,11 are fixed
- Improved handling of script comments
- Ability to exclude files/folders
- configured through properties.xml
- Ability to exclude individual files or directories from your search
- Integrated Unit Testing
- testCaseCFC.cfc now includes positive/negative test cases for all reported issues
- Currently still reporting 2 known issues that will be addressed in a future release
- Improvements to parsing engine
- Fix for Ray’s cffeed bug (also fixes cfprocparam)
- More agressive var scope checking (re-run against all your code, we found 2 new unscoped vars at Planitax)