9

In the spirit of my other questions regarding "common programming mistakes ... to avoid"

What are some common programming mistakes for a ColdFusion programmer to avoid?

casperOne
  • 73,706
  • 19
  • 184
  • 253
Andrew Siemer
  • 10,166
  • 3
  • 41
  • 61
  • 10
    Asking overly broad questions on SO. ;) – Byron Whitlock Jul 27 '09 at 23:11
  • 1
    Fun questions...informative questions...not just overly broad! Some of these "mistakes" questions are getting good answers in them! Good reading. – Andrew Siemer Jul 27 '09 at 23:12
  • 5
    @Greg Beech +1 - while I must admit that I programmed with ColdFusion from CF 3 through 6.1...once a person finds a language/platform like C# and .NET it is very hard to maintain interest in the ColdFusion world. But looking back one must admit that ColdFusion 2.0 offered to ASP classic developers what .NET was only able to offer MANY years later. I would go so far as to say that ASP.NET was greatly inspired by ColdFusion in the same way that C# was inspired by Java. – Andrew Siemer Jul 27 '09 at 23:31
  • 5
    Funny how the same exact question gets downvoted and closed because the platform is not popular. The "Common javascript mistakes" thread (right below this ATM) has multiple upvotes. – Ed S. Jul 27 '09 at 23:50
  • 1
    I would wager that the a number of the downvotes were generated by people that have either never heard of ColdFusion or have never used ColdFusion. Most likely being downvoted not because it is ColdFusion though but because I have posted several of these questions today...and the "pureists" are tired of this type of question. No worries! – Andrew Siemer Jul 27 '09 at 23:54
  • The question "What frustrates you the most at work" is acceptable but a ColdFusion related question gets down votes and votes to close! We programmers are fickle folk! – Andrew Siemer Jul 28 '09 at 00:01
  • 6
    ... or just don't like people gaming the rep system. – Dour High Arch Jul 28 '09 at 00:05
  • So asking one good question is acceptable...but asking 5 different although equally good questions in the same vein as the first good question is not? Too funny. – Andrew Siemer Jul 28 '09 at 00:13
  • 3
    @Andrew - if you made these questions community wiki, you wouldn't get so much flak. As it is, you are only making them CW after lots of people call for it, and you're basically picking every language you can find and writing a copy of what was a popular question. It's rep farming, pure and simple. It looks like you've even stopped changing them to CW now too. – zombat Jul 28 '09 at 01:16
  • I only asked questions regarding languages/topics I am interested in. I didn't post a question regarding Perl, XAML, HTML, Lingo, Lisp, etc....but could have. Thanks for your dedication. It has made my day enjoyable! :P – Andrew Siemer Jul 28 '09 at 01:32
  • @zombat - I made this a CW just for you! – Andrew Siemer Jul 28 '09 at 01:33
  • 2
    I revoke my previous defense of this thread after noticing how many of them there are... – Ed S. Jul 28 '09 at 02:13
  • I never quite get what's CW is used for – Henry Jul 28 '09 at 02:23
  • 1
    CW is used to reduce the whines from people who wish they thought of asking a rep-scoring question first. ;) – Peter Boughton Jul 28 '09 at 23:01
  • @zombat calls the act of asking a good question, one that entices lots of people to respond and up vote the question, "rep farming". I love this term whether it is meant to be derogatory or not. And if asking many good questions that do indeed earn the question owner reputation is rep farming...then by all means call me a "rep farmer"!!! I love to ask questions and answer questions..reputation or not. It is fun to see all the interactivity created by it. – Andrew Siemer Jul 29 '09 at 05:33
  • @ Peter Boughton: No, it is to be used when there is no single correct answer for a question (like this one). The FAQ has more info – Ed S. Jul 30 '09 at 21:37
  • There is always the potential for a single correct answer - even questions that are a perpetual vote can have a summary of responses as the accepted answer. Of course, the lack of CW rep helps for vote-based questions so that the first person to provide a common answer doesn't get undeserved rep. But otherwise it's just a workaround for when there are multiple contributors (to a question *or* answer), removing the complexity of calculating value of modifications and dividing rep. – Peter Boughton Jul 31 '09 at 07:45
  • For a question like this one, Henry deserves the reputation for both raising the question and compiling a long thorough answer. – Peter Boughton Jul 31 '09 at 07:45
  • Andrew Siemer asked the question. Henry's name just shows up because he edited it. – Patrick McElhaney Jul 31 '09 at 12:06

9 Answers9

27
  • set <cffile> upload path to a web accessible, CF-enabled directory!!!

  • isStruct() before isObject() in a series of <cfif>'s expecting isStruct only catches struct (cfc component returns True from isStruct() as well)

  • no HtmlEditFormat() when displaying user-generated content (XSS)

  • forgot to add output=false on CFC methods

  • not using <cfqueryparam> inside <cfquery>

  • not scoping not-so-evident variables like cfquery name or loop index in a method

  • use <cfform> when all they need is plain-vanilla HTML <form>

  • forgot to UrlEncodedFormat() user-defined URL

  • use <cffeed> without sanitizing the content

  • trust isDate() too much (any number would return true)

  • expect string comparison to be case-sensitive (IS and EQ operators are case-insensitive)

  • sending strings "yes" or "no" to SerializeJSON() without appending a whitespace to preserve the string (otherwise SerializeJSON() or DeserializeJSON() will translate them to "true" and "false")

  • not putting singletons services in application scope

  • blindly create as much CFCs as one wants like one would do in JAVA

  • putting complex value/object into a list (can't, list is just a string of comma-seperated values)

  • writing functions that takes array as an argument and modify that array expecting that array will be modified (array in CFML is passed by value)

  • blindly changes access="remote" on a method and expect it to work (when remote proxy is generally more appropriate)

  • use a lot of WriteOutput() in cfscript when CFML is more appropriate

  • blindly uses IsDefined() when StructKeyExists() can generally do it more efficiently

  • blindly uses Iif() and De() without knowing they're as nasty as Evaluate()

  • update some code in onApplicationStart() and not seeing the difference on refresh (restart the app!)

  • <cfloop> or '' outside of <cfquery> causing multiple new query connections to be opened. 99% of the time it's better to have multiple statements inside of one cfquery to perform multiple actions, or to UNION data together.

  • hardcoding absolute path when ExpandPath() is generally better

  • forgot to turn on Unicode support in DSN (Unicode becomes '????')

  • not upgrading to the latest JRE and Hotfixes

  • misusing Client scope and blow up Windows registry...

  • uses depreciated/obsolete functions/features (i.e. flash form aka flex 1.x alpha, cftable, Verity full-text search, etc...)

  • passing CFCATCH to a function as argument type Struct (CFCATCH behaves like a Struct, but it is not. Just pass it as type 'Any').

  • Not reading CFC Best Practices from ColdBox wiki.

  • buying in the mindset of .ASP(X) or .JSP or [insert web technology] are always better.. ;)

  • not use PrecisionEvaluate() and getting all sort of floating point rounding error especially when calculating money.

Henry
  • 32,689
  • 19
  • 120
  • 221
  • 1
    @Henry - this is quite a list my man! Thank you. – Andrew Siemer Jul 27 '09 at 23:49
  • still thinking what to add onto the list... :) – Henry Jul 27 '09 at 23:53
  • 3
    @Henry: Small typo - it's `HTMLEditFormat()`. (One reason for the commonness of XSS vulnerabilities is that the HTML escape functions names are so verbose everywhere: `htmlspecialchars()`, `Server.HTMLEncode()`, you name it. Usually I make a wrapper function for `HTMLEditFormat()` and call that `h()`, which is very convenient. Along with a wrapper for URLEncodedFormat called `u()`.) – Tomalak Jul 28 '09 at 14:48
  • Oh, and +1. Very nice compilation of things to get wrong in CF. – Tomalak Jul 28 '09 at 14:55
  • I still see this in legacy code: execute("form.counted#i#") instead of form['counted#i#']. – Ben Doom Jul 28 '09 at 17:54
  • hope you don't mind i added the spacing and edited some spelling, great list! – ethyreal Jul 30 '09 at 20:52
  • @ethyreal, why would I mind? :) Thank you for editing. I've also added 2 additional points on the post. – Henry Jul 30 '09 at 21:32
3

Inappropriate use of #

SELECT *

Not scrubbing URL/form inputs

Debugging on in production environment (even if output is suppressed)

ale
  • 6,369
  • 7
  • 55
  • 65
3

Shamelessly stealing Henry's formatting...

  • it is faster and more accurate to check explicit boolean instead of implied; use <cfif query.recordCount GT 0> instead of <cfif query.recordCount>
  • do not use evaluate(), de(), or iif()... ever. there is always a way around these slow functions
  • understand structures, keys, values and how to access query and structure data using array notation. (this will usually get around your need for evaluate())
  • do not use pound signs unless you are outputting data or otherwise creating a string (don't do this: myFunction(arg = #myVar#) )
  • read and understand the difference between THIS and VARIABLES scope in a CFC
  • avoid extreme overuse of <cfsilent> when you probably need to use a <cfcontent reset="true"> just before you begin your output (before doctype, xml declaration, or <html>)
  • don't blindly drop ColdFusion values into an HTML script block (javascript) without using jsStringFormat()
  • if you are not using <CDATA> text in your XML, you may want to use xmlFormat() when creating an XML document
  • don't use Windows registry for Client scope data. Use the database.
  • if your IT architecture permits, use Session data instead of Client data.
  • use <cflock> correctly and consistently; shared data will leak in your Application.
  • if you are going to use Java objects, understand the Java error messages (for example, 'method cannot be found' may not mean the method does not exist at all, it means the method does not exist for the arguments you've supplied)
  • if you have to read large files, either use the new CF8 "File" functions or hand off the task to Java on CF6 & 7. <cffile> is inefficient for large files.
  • understand pass-by-reference and pass-by-value, and how those concepts work in CF; specifically when using functions to modify XML documents
  • as Henry stated, always use <cfqueryparam>; also ensure that you are using the correct CFSQLType parameter for your DBMS (for date, time, timestamp, etc)
  • don't chain together a series of <cfif> and <cfelseif> logic blocks, use <cfswitch> and <cfcase> if you have more than three conditions you need to handle
  • more of an architecture note: always do some sort of server side validation to catch the nasty data the wolf-shirt-wearing user may be passing you
  • last architecture note: let CF do your middle layer of data retrieval and display and let your webserver do webserver things like SEO URLs (I'm looking at you ColdCourse)
  • Douglas
    • 154
    • 1
    • 9
    • "don't chain together a series of and logic blocks, use and if you have more than three conditions you need to handle" - That's a bit of a definite statement! I think cfif/cfelseif/cfelse statements are easier to read because there are less tags. – Adrian Lynch Sep 09 '10 at 13:49
    2

    SQL Injection Attacks. It seems like cfquery is just made to allow them. So you should use cfqueryparams.

    JP Alioto
    • 44,864
    • 6
    • 88
    • 112
    • 2
      Can't stress strongly enough how good cfqueryparams are: cfqueryparam will stop sql injection - the sql server will never execute the value passed via cfqueryparam – Antony Jul 28 '09 at 02:23
    1

    In Coldfusion, all variables are global by default, unless they are declared with the var keyword. (Somewhat similar to the situation in Javascript.)

    So you either have to remember to var every variable used in a function, including things like names that are using in a cfquery name, or you can just use this trick:

    <cffunction name="MyFunction">
        <cfset var Local = StructNew()>
    
        <!--- Now anything Local. is automatically local --->
        <cfset Local.x = 42>
    
        <!--- Including cfquery name="" --->
        <cfquery name="Local.Customers" datasource="some_datasource">
            SELECT C.ID, C.Name
            FROM Customers C
        </cfquery>
    </cffunction>
    

    There's nothing magic about the name Local, it's just convention. Although Coldfusion 9 will add an explict local scope, so if you use Local it will probably ease upgrading to CF9 when the time comes.

    Note that the situation is a tad different for CFCs: In CFCs, the variables scope (the "default" scope) isn't global like it is for normal functions but rather exists per instance of your CFC. So while forgetting to use var is not quite as dangerous in a CFC as it is in a top-level function, the best practice is still to use var all the time.

    Jason C
    • 21,377
    • 10
    • 38
    • 33
    • 2
      "not quite as dangerous"? It is actually still quite dangerous since the code are not very thread-safe. – Henry Jul 28 '09 at 00:23
    • Well, yes, it's still evil and you should never do it, but the problems will be limited to that CFC, instead of potentially affecting any top-level function or .CFM page in your CF application. – Jason C Jul 28 '09 at 00:35
    1

    Failing to prevent users from seeing coldfusion errors.

    Add a onError method to a top level Application.cfc to prevent users from seeing those all to detailed dump messages exposing your inner workings(and failings).

    <cffunction name="onError" returntype="void" output="true">
        <cfargument name="exception" type="any" required="true" />
        <cfargument name="eventname" type="string" required="true" />
    

    varscoper is also a great tool for automating the check for variable scoping omissions in components.

    http://varscoper.riaforge.org/

    np0x
    • 166
    • 4
    0

    Overuse of 'query of query'. That is, further filtering or sorting of query results using the cfquery tag.

    This type of work is often done better by the database itself, particularly if the dataset is large.

    AlexJReid
    • 1,601
    • 1
    • 13
    • 17
    0

    One of the biggest mistakes would be not using cfqueryparam

    Very bad:

    SELECT UserName
    FROM Customers
    WHERE CustomerID = #URL.custid#
    

    Very good:

    SELECT UserName
    FROM Customers
    WHERE CustomerID = <cfqueryparam value="#URL.custid#" cfsqltype="cf_sql_integer">`
    

    Making that mistake will cost you a website.

    jyoseph
    • 5,435
    • 9
    • 45
    • 64
    0

    Putting variables in the wrong scope; even if you don't blow up the registry or crash the server, it's easy to slowly drain performance from your application by bumping variables up to the highest scope in which you think you might need them, or to lose information because you stored it in one scope and tried to access them in a different scope.

    Using cfcatch without capturing and/or transmitting some information about the error so that it can be found and fixed. (It's difficult to find an error that doesn't tell you it occurred.)

    Using listcontains() when you want listfind(). Especially if the list contains numbers. listfind() matches only an entire item in a list; listcontains() matches part of an item. (Yes, we made this mistake once.)

    With administrator access:

    • Leaving the defaults for a data source set up on the server. "Least privileges" applies on the CF side as well; don't give it any more permissions than it specifically needs. (GRANT, ALTER, REVOKE, DROP ... you don't really want those checked.)
    • Not checking the boxes for retrieving all the contents from a CLOB/BLOB field when that's what you're expecting. (It was really interesting seeing that applied to a field in which we were storing PDFs.)
    Dave DuPlantis
    • 6,378
    • 3
    • 26
    • 30