Avoid Single Letter Variable Names

One of our sites gets an occasional error that position 12 of array "b" cannot be found. When I look at the code for the page, it has no comments as to what "b" is or where it was created (not in that file, needless to say).

Now, if the variable name had been descriptive ("aBacks", for example) then I would have some clue what it did without comments. I would also be able to search for it. I could search for "b", but that wouldn't really be helpful. So, now I have to go through a tedious process to find the problem just because the programmer used a single letter variable name.

I recommend that you avoid single letter variable names in all cases. Although this example wasn't my code, I will confess that I have used single letter variable names for loop iteraters before ("i", for example). No more! Even if I can't think of a goto variable name, I will at least use "ii" so that someone might be able to search for it.

In this case, the site architecture was pretty simple, so the problem didn't take long to track down. Even so, it would have been much easier with a real variable name. 

So the next time that you are tempted to use a single letter variable name, please resist.

DataMgr Tour of Two Cities

I got back Friday from my two city DataMgr users group tour. I had a lot of fun presenting in both Boston and Nashville. Both groups were a lot of fun and had good questions.

While in Boston, I had a chance to look around the the city for a few hours before the presentation and it is really beautiful. Then I had time to talk to both Brian Rinaldi and Bernie Dolan a bit before the meeting, which was both fun and educational - two very smart guys.

The presentation to the Boston CFUG went well and everyone I talked to said that they enjoyed the presentation. Feel free to read Bernie's humurous tale of the event (I took the title of this blog entry from his). Afterward, I went to a local pub for a drink with Bernie, Brian, and Tom. Tom bought me a beer, which was much appreciated. Another fun and informational discussion there.

From Boston I flew to Nashville. I was too tired to look around the town, so I stayed in the hotel and napped and tried to get caught up on email and reading. The presentation to the Nashville CFUG also went well (you can read Steve "Cutter" Blades description of the presentation). This presentation was recorded, so feel free to watch the presentation (apologies for some silent spots where I am listening to questions and suggestions).

Some of the Nashville members made some good suggestions for DataMgr which will be in the next build (proving wrong my previous statement that it was feature complete).

The first suggestion was that the getXml() method should be able to return all tables if no table was passed in to the method. It turns out that DataMgr did this already. I went ahead and made it do the same if an empty string is passed in as well.

The second suggestion was that the logAction() method should record the SQL used in the action. I have added that feature and it will be in the next release. As an aside, I said in the presentation that calling this method directly when logging is not enabled would not cause DataMgr to log an entry. This is not true, but startLogging() must have been called before a logAction() method is called (or else the logging table won't exist).

Members of both groups asked about the performance of DataMgr. I was disappointed that I had not done any performance tests on DataMgr, so I had to give a conservative response that it would be best to avoid its use in very high-traffic situations. I believe that it should actually perform very well in those situations (better, I would think, than an ORM approach), but until I test that I can't really recommend its use for high-traffic applications.

That being the case, I would love any suggestions for what people think would be the best approach for load testing and performance testing for DataMgr. Ideally, I would love to see a set of tests that can be performed against DataMgr as well as cfquery, Transfer, and Reactor. I think that this could help people choose the approach that is the best fit for their environment. 

Somehow, I had time to cover "Special" functionality and "Relation Fields" at the Boston meeting, but not the Nashville one. I'm sure that means I left out something else in Nashville. Both of these features can be seen in the DataMgr Demonstration site. If you want a more complete information, the DataMgr page includes links to the documentation as well as Flash tutorials and the CFC Docs for DataMgr.

I would love to present this to any other groups that are interested (via Adobe Acrobat Connect). Just let me know if you would like me to present on DataMgr to your group).

Finally, a big thanks to Brian Rinaldi and Aaron West for allowing me to come to their groups and say a few words about my current pet project. It was a lot of fun to meet everyone in each group and I hope I get to see many of them again in the future. 

DataMgr 2.0 Release Candidate

DataMgr 2.0 has reached Release Candidate stage. It is now feature complete. The best new feature? Documentation ! I now have a full 15 pages of documentation available.

The documentation is of a first-draft quality, but it is still better than what I have had already. It should provide at least an overview of all of the major (and most of the minor) functionality of DataMgr.

Other new features include:

  • The ability to only return structure data for only one table from getTableData()
  • Allow saving of concat Relation Field value (where list length matches)
  • A new choice for insertRecord: "OnExists" argument: "save" will update for primary key match and insert in all other cases
  • Some performance improvements
  • A small bug fix on insertRecord()

If you are unfamiliar with DataMgr, it is database abstraction tool. You might think of it in the save class of tools as ORM or a SQL Generator, but it is different from each of them.

DataMgr doesn't enforce an ORM style of interaction (though it could be used as the data-access layer for one). It also doesn't generate any code. This allows more dynamic and flexible interactions than are generally provided by generated SQL.

DataMgr does provide CRUD (Create Read Update Delete) functionality. Just because you use DataMgr for some of those interactions, however, does not mean that you need to use it for all of them. I generally use DataMgr for my insert/update/delete actions, for example, but I frequenty handle my select queries outside of DataMgr (though much less frequently as of 2.0).

DataMgr also simplifies a number of other common interactions that I have not seen other similar tools address (and certainly not with the same power and simplicity). For example, it simplifies setting sort order values and handling many-to-many relationships.

The biggest advantages for DataMgr come from version 2.0, where it adds features that I haven't seen elsewhere. For example, a simulated database which can allow you to switch between a simulated database (which provides QuerySim like functionality with the randomly generated data) and a real database by merely switching which DataMgr component you use - no need to change any of the code that uses DataMgr. This is ideal for prototyping an application.

The Relation Fields feature in DataMgr allows you to treat different types of data as though they existed as field in your database without actually creating that field in your database (a "FullName" field that uses FirstName and LastName fields for example or a "Category" field that gets its data from a field in a related database).

It also has several small touches that are generally helpful. It reports which field has too much data, if one does (to avoid the unhelpful "data truncation" errors). It also replaces the special characters for quotes and dashes that MS Word uses with their ASCII equivalents.

The documentation covers these features and more in detail, but hopefully this provides a general overview of what DataMgr does. It currently runs on MS Access, MySQL, MS SQL Server, and PostGreSQL with the exact same API. It is also easy to add support for another database.

If you would like to see DataMgr in use, take a look at CodeCop which serves as both a robust code checking application and an example DataMgr application. You can also view the demonstration site to see DataMgr in use. 

DataMgr is free and open-source.

cfdump for JavaScript

I try to avoid blog posts that just repeat what has been said elsewhere, but this is really nice.

I blogged earlier (mid-2005) about a JavaScript version of cfdump. I actually used this recently to help me implement JSMX (which I love!).

I saw an entry today the strikefish blog about another JavaScript CFDUMP which looks great. The advantage of this one is that the output more closely matches the output and behavior of cfdump. I like this in part because the format is familiar and in part because it is a really useful format.

If you just want to see the tool, take a look at JavaScript Dump

No More Next?

I just found an interesting article by Pete Forde arguing against the "next" button and paging through records entirely.

He even points to an example or two of how this could be done. 

His point is basically that since the web is non-linear, pages don't make sense. After all, the contents of "page 2" today won't necessarily match the contents of "page 2" tomorrow.

[More]

JSMX - Another AJAX API?

Today I was working on some AJAX code and realized that I would rather get my data from a CFC than from XML data. A few minutes of research later and I have JSMX up and running.

I already had a CFC with the method I needed to get my data with access="remote" (hopefully more on why I have this later - a new approach that seems promising). I thought it would be nice to add another remote method to generate the XML I needed for my AJAX.

This turned out to be rather easy, but I had to set returntype="void" and output="yes" and output the XML straight to the CFC page. This worked, but seemed a bit "hacky".

I was sure that someone had thought of a better way, so off to Google I went to find it.

JSMX advertises itself as an AJAX API - which it is (actually it advertises itself as "The Universal AJAX API"). It has some distinct advantages over other AJAX APIs that I have looked at (and never used). For one, it is just one 13K JS file. For another, it can easily digest data in a number of formats.

Notably, it can digest WDDX data. This is significant because that is the format of data you get if you do an HTTP "Get" on a remote method in a CFC.

The site has a few good examples of use , but none on WDDX. I was unable to find out how it structured the WDDX data in JavaScript. Fortunately, DP_Debug came to the rescue. This is basically cfdump for JavaScript - very handy.

I used the following syntax to test the results:

<script type="text/javascript">
http('GET', 'mycomp.cfc?method=mymethod', DP_Debug.dump);
DP_Debug.dump(MyObject)
</script>

This revealed that the results are basically identical to what you would get if you used <cfwddx> with action="CFML2JS". This made the JavaScript to digest the data even easier than it was to digest the XML.

My steps to implement JSMX:

  1. Copy the .js file to my site.
  2. Reference the .js file on my page.
  3. Change my JavaScript syntax appropriately (about a 5 minute job in my case) 

The result is that my JavaScript got smaller and easier to use and I was able to remove the file to serve up XML data and rely on the CFC to provide that data.

My only complaint about JSMX so far is that it could be much smaller than 13K if the comments and white-space were removed. Other than that small complaint, it is a thing of beauty!

DataMgr 2.0 Beta 3 - Getting Close!

The third beta of DataMgr 2.0 is ready and comes with some new features and with documentation. The final gold release is getting close, so any help that I can get with testing would be greatly appreciated.

The new features in Beta 3 release are:

  • You can now have relationships where the field name for one table is different than its related field in another table (see example)
  • You can now filter my concatinations (eg, filter by full name instead of first name and last name separately: see example)
  • Deprecated addColumn() in favor of the new setColumn() ( addColumn will be supported but is no longer the preferred syntax)
  • You can now use setColumn() to define columns that already exist in the database (to set "Special" values for example). This is especially handy if you don't use loadXml() but want to take advantage of "Special" functionality (see docs).
  • You now use setColumn to define relationship fields ( again, in case you don't want to use loadXml() )

The documentation for DataMgr 2.0 is now available (though it may change as I approach the final release). The new CFC docs divide up the methods into groups:

  • Major Methods: The main functionality of DataMgr
  • Informational Methods:  To get information from DataMgr
  • Support Methods: Public methods which are primarily for internal use but can be used independently as well

I have also updated the DataMgr demonstration site with examples of some of the new functionality. If you can think of any functionality that you would like to see demonstrated, let me know and I will do my best to get it added. Similarly, if you can think of any documentation or tutorials that you think would be helpful, let me know.

I am pushing for a February/March release of DataMgr 2.0, so any bug reports would be greatly appreciated (I still have a few more small features planned but most expect any new feature requests to get pushed back to a point release later on).

DataMgr is free for any use, so feel free to try it out

Referencing External Files From a SWF

I have seen several examples of a SWF movie being unable to find an external file when it loads (an mp3 file, for example) even though it worked during testing.

I don't pretend to be an expert in Flash, but I have seen this problem enough to recognize it.

In testing, the SWF and the external file are both in same folder as the HTML file that calls the SWF. On the live site, the SWF and the external file that calls it are in the same folder. The calling HTML page may be in the same folder or a different one (because the SWF file can be called from any of several pages on the site).

When the SWF is called from a page in a different folder, the external file fails to load (again, even though it did in testing).

The problem is that the path that the SWF uses to load the external file is relative to the page being loaded in the browser and not the location of the SWF file itself.

For example, if you have movie.swf in the images folder that needs to use a sound.mp3 file that is in the same folder. It seems like you should be able to reference the sound.mp3 file as "sound.mp3". This will only work, however, if the file being called from the browser is in the images folder as well.

If the browser is requesting the index.html in the root of the site then the SWF will look for sound.mp3 in the root of the site. You could place your sound.mp3 in the root of the site, but that will only work if all of your HTML files are in the root of the site (not a safe assumption).

If you changed the reference to "images/sound.mp3", then it would work when calling index.html in the root of the site. This approach, however will fail when calling a file from another folder. For example, if you are calling about/index.html, then that reference will cause the SWF to attempt to import "about/images/sound.mp3".

The real solution is to use references that are relative to the site root instead of the current file. So, in our example it would be best to reference the sound file as "/images/sound.mp3" (the / at the beginning is the key). This reference will find the sound.mp3 file in the images folder no matter where the SWF is and no matter where the HTML file calling it is. 

BlogCFC was created by Raymond Camden. This blog is running version 5.8.001.