CFC’s and Access = Package

I was asked today:

Could someone please explain the differences between cfc package and public access? I thought that package access made the method available to other templates within the same application, but that doesn’t seem to be the case.

Now, I remember being confused by this when I first started doing CFC’s so figured I would share.

A function with an access of “package” will be restricted to calling CFC’s and templates in the same directory as the CFC file of the function.

In my personal experience, I haven’t found access=package to be terribly useful. I tend to organize my files into subfolders like cfc, and then further subdivide by type of CFC. (Gateway, DAO, utility.) So to access them, I tend to put functions as either public or private. All in all, “package” just makes it harder to work with all of this stuff.

However, I have the luxury of working on private server, and not a hosting provider for the majority of my work, so my view maybe atypical. Anybody have a different viewpoint?

A Family that Codes Together

My wife, Janice, and I work for the same company. In fact we work for the same boss. It has its ups and downs. But if we didn’t work together, situations like these would never happen:

Janice was working on a Perl script that handles integrating Active Directory and MajorDomo. It was buggy and confusing and overall not well written. Janice was struggling with the parts that were crappy, basically trying to grok the ungrokable, and she calls me over.

Janice: Can you tell me what this section of code does:

## Im not really sure why I did this. It works so back off! my $max = $mesg->count; for($i = 0 ; $i < $max ; $i++) { my $entry = $mesg->entry($i); foreach my $attr ($entry->attributes) { $dn=$entry->get_value($attr) } }

Me: No.

Janice: Why not?

Me: I didn’t understand it when I wrote it. What makes you think I understand it now?

You see, I’ve worked for our current department on and off for the past 6 years. My first past through the group was doing Exchange and Windows Domain systems administration. I managed the upgrade from NT4 to Windows 2000 and Active Directory. I wrote the first batches of code that we used to integrate Active Directory and our legacy systems. That meant Perl. I learned it sort by accident back in the day, and at my height of ability I was never one of those guys who would write twenty lines of function in one line.

Which brings us back to this section of code; I wrote it in my first Active Directory LDAP Perl to CSO script. It was copy and pasted by another developer, and reused again. Until my wife had to deal with it… six years after I wrote it.

Sorry, hon.

Issues with cfntauthenticate

I’ve been meaning to blog about <cfntauthenticate> for awhile, but I keep forgetting. However, someone had an issue with it today, and it spurred me on.

Disclaimer

I don’t work for Adobe, so I have no idea why they did anything they did. Any supposition posted here is just that my supposition. Additionally, it’s not meant as criticism, as for the most part <cfntauthenticate> does exactly what it is supposed to do.

We’re a Window shop that relies heavily on out Active Directory Domain. We use it for LDAP mail routing, Exchange, and single sign on across our environment. From time to time we’ve had issues with <cfntauthenticate> under certain outlier conditions. Let me take you through some of them.

Too Many Groups

Occasionally, we’ll run in to singular users that cannot log into some applications but can log in to others. We’ll tease out variations in form inputs, and ensure the username and password works, and still can’t figure it out. We’ll look at our logs that track the reason for failure, and we’ll see “UserNotInDirFailure.” Even turning on the throwError option of the tag doesn’t help.

Eventually we trace it back to the listGroups flag. Turn it off, it succeeds, turn it on, it fails. So it’s something with the groups. Try taking some groups away from the user. Voila it stops failing.

Turns out, there is some number, N, of groups over which some sort of uncaught error will start to be thrown. It gets caught by the default error code and gets thrown as “UserNotInDirFailure.” N is a little nebulous, as it is unclear to me what effects domain local groups versus global groups versus distribution groups has on N. But in my last set of tests, N was 23.

To workaround, if you aren’t using groups, don’t use listGroups, as you don’t need it. If you are using groups for let’s say, authorization, revert to using LDAP for retrieving groups information. Also you could just prune your group membership…

Service Account Issues

This is the one that happened today. Every user’s login was returning “UserNotInDirFailure,” but only for a particular server. No changes in underlying networking were made.

My default recommendation: restart the server. When the admin of that server did that the ColdFusion service didn’t start. A quick check of the system logs showed that the login for the account the ColdFusion service was running under was failing. Turns out someone changed the password of it and didn’t change it in the services configuration on the server. It took about 36 hours before the problem was noticed.

According to the documentation, “ColdFusion must run as a user that has the privilege to authenticate other users in the specified domain.” So problems with the service account would cause problems with the tag.

No workaround here, just manage your service accounts properly.

PDC emulator

Active Directory domain controllers are intended to be redundant. Except for something called Flexible Single Master Operations roles, or FSMO roles. Each FSMO role makes the domain controller that hosts it unique in a fashion. I’m not going to go into all of it, but suffice it to say one of those FSMO’s is “PDC Emulator.” PDC stands for Primary Domain Controller, and was a feature of NT 4 and below. Basically the PDC was the domain controller to which domain information was read from and written to. Other domain controllers only allowed read operations. When Microsoft moved to Active Directory and multiple domain controller model, they left the PDC Emulator role in order to provide backward compatibility with tools that used NT 4 API’s for various operations.

What does all this have to do with ColdFusion? It’s my theory that <cfntauthenticate> uses the vestigial NT 4 API’s. I base this theory on the fact that if your PDC emulator is inaccessible, <cfntauthenticate> will fail for all users. However, if you have throwError set to false, you won’t know what is going on you’ll get a “UserNotInDirFailure” error. However, if you set throwError to true, you will see the real message, “Could not find domain controller for this domain XXXX” Where XXXX is the name of your domain.

There’s not much you can do about this. If the PDC emulator is unreachable from your Coldfusion server, <cfntauthenticate> will not work. The only solution I have come up with to replace <cfntauthenticate> with an analogous CFC that uses Secure LDAP queries against the domain controller instead.

Conclusion

I blogged this because when I’ve gone looking for <cfntauthenticate> errors, I’ve only found my own random posts on CF-talk. Hopefully, someone else will be less mystified by errors with this very useful tag.

Thinking About Code Objectly

I’m not talking about being unemotional about code, which would be “objectively”. No, “objectly,” I’m talking about code generation. When I first started writing Squidhead, I was writing procedural code to generate my code. After all, it’s tempting to think of it procedurally, as code tends to read from top to bottom. One of the breakthroughs for me was figuring out that most of the coding structures I was using can be expressed as objects. I mean the actual code text itself can be expressed as objects. In ColdFusion, this means a CFC.

Let me show you an example of what I’m talking about:

<!—************************************************—>

<!—create—>

<!—This function inserts a single comment record into the database.—>

<!—************************************************—>

<cffunction
access=“public”
name=“create”
output=“FALSE”
returntype=“numeric”
hint=“This function inserts a single comment record into the database.”
>

<cfargument
name=“body”
type=“string”
required=“FALSE”
default=“”
/>

<cfargument
name=“authorID”
type=“numeric”
required=“FALSE”
default=“0”
/>

<cfargument
name=“createdBy”
type=“numeric”
required=“FALSE”
default=“0”
/>

<cfargument
name=“updatedBy”
type=“numeric”
required=“FALSE”
default=“0”
/>

<cfset
var commentID = “”
/>

<cfset
var results = “”
/>

<cfstoredproc
procedure=“usp_comment_insert”
datasource=“#application.datasource#”
username=“#application.dbusername#”
password=“#application.dbpassword#”>

<cfprocparam
type=“OUT”
cfsqltype=“CF_SQL_INTEGER”
variable=“commentID”
dbvarname=“@commentID”
maxlength=“4”
null=“NO”
/>

<cfprocparam
type=“IN”
cfsqltype=“CF_SQL_LONGVARCHAR”
variable=“body”
dbvarname=“@body”
value=“#arguments.body#”
maxlength=“16”
null=“NO”
/>

<cfprocparam
type=“IN”
cfsqltype=“CF_SQL_INTEGER”
variable=“authorID”
dbvarname=“@authorID”
value=“#arguments.authorID#”
maxlength=“4”
null=“NO”
/>

<cfprocparam
type=“IN”
cfsqltype=“CF_SQL_INTEGER”
variable=“createdBy”
dbvarname=“@createdBy”
value=“#arguments.createdBy#”
maxlength=“4”
null=“NO”
/>

<cfprocparam
type=“IN”
cfsqltype=“CF_SQL_INTEGER”
variable=“updatedBy”
dbvarname=“@updatedBy”
value=“#arguments.updatedBy#”
maxlength=“4”
null=“NO”
/>

<cfprocresult
name=“results”
/>

</cfstoredproc>

<cfset results = commentID />

<cfreturn results />

</cffunction>

This is a basic insert function. We’ve all written this type of function as part of a CFC.

Let’s break this down into its properties:

Documentation

<!—********************************—>

<!—create—>

<!—This function inserts a single comment record into the database.—>

<!—********************************—>

Header

<cffunction
access=“public”
name=“create”
output=“FALSE”
returntype=“numeric”
hint=“This function inserts a single comment record into the database.”
>

Arguments

<cfargument
name=“body”
type=“string”
required=“FALSE”
default=“”
/>

<cfargument
name=“authorID”
type=“numeric”
required=“FALSE”
default=“0”
/>

<cfargument
name=“createdBy”
type=“numeric”
required=“FALSE”
default=“0”
/>

<cfargument
name=“updatedBy”
type=“numeric”
required=“FALSE”
default=“0”
/>

Local Variables

<cfset
var commentID = “”
/>

<cfset
var results = “”
/>

Content

<cfstoredproc
procedure=“usp_comment_insert”
datasource=“#application.datasource#”
username=“#application.dbusername#”
password=“#application.dbpassword#”>

<cfprocparam
type=“OUT”
cfsqltype=“CF_SQL_INTEGER”
variable=“commentID”
dbvarname=“@commentID”
maxlength=“4”
null=“NO”
/>

<cfprocparam
type=“IN”
cfsqltype=“CF_SQL_LONGVARCHAR”
variable=“body”
dbvarname=“@body”
value=“#arguments.body#”
maxlength=“16”
null=“NO”
/>

<cfprocparam
type=“IN”
cfsqltype=“CF_SQL_INTEGER”
variable=“authorID”
dbvarname=“@authorID”
value=“#arguments.authorID#”
maxlength=“4”
null=“NO”
/>

<cfprocparam
type=“IN”
cfsqltype=“CF_SQL_INTEGER”
variable=“createdBy”
dbvarname=“@createdBy”
value=“#arguments.createdBy#”
maxlength=“4”
null=“NO”
/>

<cfprocparam
type=“IN”
cfsqltype=“CF_SQL_INTEGER”
variable=“updatedBy”
dbvarname=“@updatedBy”
value=“#arguments.updatedBy#”
maxlength=“4”
null=“NO”
/>

<cfprocresult
name=“results”
/>

</cfstoredproc>

<cfset results = commentID />

Results

<cfset results = commentID />

Footer

</cffunction>

Once you’ve established the structure of the CFC, you make these properties into variables. Anything that could be a list is actually an array. So arguments and local variables are actually an array of <cfargument> declarations, as is local variables. You write getter and setters. Actually I tend to write adders instead of setters as I’m just adding content to properties that grow. The getter that I write just concatenates all of the code and outputs it.

Here’s the code:

Function.cfc

You can even break it down even further. If you wanted, each <cfargument> could be an object with each attribute being a property. I didn’t go that far in Squidhead, but I did break the <cfstoredproc> declaration into an CFC.

This works very well for highly structured code, like <cfcomponents>’s , <cffunction>’s and <cfstoredproc>’s but it can be extended into less obviously structured code like custom tags. I was able to convert most of my procedural code creators to object oriented code creators.

So for whatever that’s worth, maybe this can help someone else out there.

Yet another Framework Post

I know, I know, we don’t need another framework post. But the latest posts from Sean Corfield, Brian Rinaldi, and Jake Munson make me want to speak up. While I’m naming dropping, I feel the need to cite Joel Spolsky’s In Defense of Not-Invented-Here Syndrome.

I am not against frameworks. I’ve tried coding against a couple. I’ve at least looked at most of them. I don’t currently use one. The one I got the furthest with was Model Glue 2. I like it a lot, but I’m just not productive enough in it yet to rely on it. That means that I can accept that Joe Rinehart came up with a better solution to my problems than I, but I can’t use them as productively, as I can use my own, perhaps flawed solutions.

It’s that bit of logic that I think should be the key to using frameworks. Use them where they will be more productive than your own efforts.

Follow what I mean here.

Let’s say you are a database wiz. You design textbook perfect databases in your sleep. You love seeing execution plans with no table scans. You think it’s cool when your queries have to use parallelism. It would not be in your best interest to use a database framework like Reactor. Why? Because you would be substituting Doug Hughes‘ judgment for your own, where you provide the most value.

Well that’s not quite true, because you don’t exercise the full extent of your knowledge on every single piece of SQL interaction code you write. If Reactor makes 80% of what you do take 20% of the time it used to, then it still might be worth it to use, and then manage the exceptional cases.

Okay, I haven’t convinced you – you still prefer the way you deal with your database to the way Reactor does. Okay, but you’re still probably doing a lot of repetitive, rule based code like writing <cfstoredproc> code blocks with are more characters the actual SQL stored procedures you’ve written. Perhaps you should write your own code generator. That’s essentially what I did with Squidhead, and it was easier than I thought, and a great experience for me.

Okay, database wiz, now it comes to the UI. You need to do an Ajax front end. What do you do? Start writing JavaScript? No! You told us you were a database wiz. If you’re not a JavaScript wiz then stop and download an Ajax framework. Because at some point someone has better judgment than you about some of the technology you use.

Now I started with a database guy, but I could have started with an Ajax wiz, or a designer and the advice would have been analogous.

If your expertise is based on a certain set of skills, you would be nuts to accept someone else’s judgment for yours. But if you’re not an expert in an area, that it is equally nuts to assume your judgment is better than an expert.

Pick frameworks and techniques that strengthen your weak spots.

MyWoes with Squidhead

One of the requests I’ve gotten for Squidhead is a MySQL version. Being the responsible Open Source author (or wanting to suck up to the people that are actually interested in it,) I tried to make it work with MySQL 5.0.

It did not go well. Specifically, I cannot call MySQL stored procedures from ColdFusion using <cfstoredproc>. (I get a null error from indexOfIgnoreCaseRespectQuotes in the MySQL driver.) It isn’t an absolute deal breaker, but makes my job much, much harder. I have to branch off more than just the database interaction. I would also have to branch off the CFC code too. (Which is much more complicated than the database stuff.)

So now I’m stuck at a quandary:

  • Do I do the work to get it to interact with MySQL at Squidhead’s present level of features? OR
  • Do I start adding features to Squidhead, along just the MSSQL path, and go back later and add MySQL support for the whole thing?

Part of my original logic behind doing it in MS SQL only, was that the problem I was trying to solve with Squidhead was DBA mandates of “You must use stored procedures!” My gut feeling was that this type of mandate was more likely to found in a shop with a more established database. I’m not knocking MySQL here, but stored procedures were just introduced in version 5.0, and a lot of shops don’t run it yet. Therefore less shops would mandate stored procedures with MySQL. So it would be smarter to go after an Oracle version than a MySQL version.

Then there are the features that I would like to add.

  • I would like to remove the requirement identities. (I would do CRUD against Primary Keys.)
  • I would like to add support for configuration metadata for things like “ORDER BY.”
  • I would like to decouple the custom tags from the data retrieval cfc methods.

Does anyone out there with either an interest in Squidhead, or experience with an open source product have any advice?

My Slow Switch to CFEclipse

This is the third time I’ve tried to switch to CFEclipse. It looks like this time it might stick.

My big problem with CFEclipse to date is that it has been incompatible with the way I have worked. I tend to work on many small projects, each with its own network share. In Dreamweaver each of my sites point to the UNC address of the project’s share. CFEclipse does not seem to handle files over UNC path’s directly. From the little bit of information I have been able to find, it looks like a problem with Eclipse, not CFEclipse specifically. It works just fine with mapped drives, but I have many projects, each with their own share, and that’s a lot of mapped drives.

Now, one of the guys I work with, newly minted MXNA blogger Dave Konopka, pointed out that I could just map the root of my web server. I have the ability to do so, because I have elevated privileges on my ColdFusion servers, seeing as how I built them. Now I’ve always viewed this as abusing my administrative rights since not all of our developers have these rights. I try to consume the services we provide as the rest of the developers here do, because 1, there’s usually a good reason for doing things the way we do, and 2. It helps me spot . However, come to think of it, the whole reason that I have a whole bunch of smaller projects is because I am an administrator. So maybe it’s not really cheating to do it this way.

Anyway, I’m over that hurtle, I’ve got a whole bunch of projects assigned, I’ve integrated Source Safe, and giving it an honest try.

What I like:

I like Snippets, especially after Mark’s tutorial. I like default code folding. I love Control+Shift+D (<cfdump> for those that haven’t used it). I love how much faster it is than Dreamweaver, especially working remotely. I love that the component explorer allows me to drop a fully written <cfinvoke> set down. (Well technically so does Dreamweaver, but CFEclipse does it much faster.)

What Surprised Me:

I’ve gone ANT crazy. It’s not really within the scope of CFEclipse, but now that I get ANT, I love it. It’s so much easier to run build tasks now.

What I don’t like:

I still wish the aforementioned difficulties with UNC paths weren’t there. Other than a few “I’m used to doing a different way” problems that are just learning curve issue, I only have one other concrete issue. I wish I could color the background of comments to the bright yellow I’ve gotten used to in Dreamweaver. (I know, it’s coming. )

I think between the speed, the integration with ANT, and the general direction of the community, I might stick with CFEclipse this time around.

CFLdap, Active Directory, and Group Membership

A question popped up on CF-Talk today about adding users to an Exchange Distribution list using <CFLdap>. I figured I would share my solution in case it could help anyone else.

The easiest way to do this is to add the user to the list of members of the group, as opposed to adding the group to the user. (I’m not 100% sure, but I think that you technically can’t add a group membership to the user.) You also need to do all modifications to ldap objects through their distinguished names, not their username, group name or as Microsoft likes to call it, “samAccountName.”

So you find out the distinguished name for the user, the distinguished name for the group, then add the user to the group. The code for doing so is in the extended version.

Update: My initial attempt to post this code caused my server to barf. Evidently my code displayer didn’t like it. So I’m just linking to it.

Ldap.cfc with add user to group function.

Whoa

You want people to find every problem with your code and publicly point them out? I’m not talking about code reviews again; I’m talking about releasing Squidhead as Open Source on RIAForge. I haven’t been this panicked about updates for awhile.

Not that I’m complaining. Every comment has been a move towards making it a better product, but I was unprepared for it. I missed a whole bunch of dumb things. (Dumb that I missed them, not that people want them.)

Thanks to everyone that downloaded it, and everyone who commented. I’ve made pretty much every recommendation, and fixed every bug report to date. With one exception that is. I haven’t made any movement on a MySQL version. I want to get it to work right in MS SQL before switching to another database. Good news is that errors are being found at a good clip.

On Code Reviews

I know I said in a previous post, that enough has been said about code reviews, but I’m writing about them. I may have to do more code reviews in the near future, so it was a good time for me to gather myself and think of all the principles I should keep in mind. Also, if anyone else has any thoughts on the matter, I would love to hear them.

Define Your Goals

This seems a little weird at first. “Our goal is to write good code.” Well yes and no. The group that I manage is in charge of administering the SQL, ColdFusion and IIS boxes. My personal goal with code reviews is to ensure I don’t get paged at 2am because our servers are down. I primarily look for performance and security issues. Another member of the code review team might manage a team of programmers; they might be looking at compliance with an accepted set of conventions, because their goal is to make sure that when changes need to be made, anyone on the team can quickly make them. Still another person on the code review team might be focused on usability as their goal is to comply with government regulations.

It’s okay that there might be more than one goal. Just figure out what your organization’s goals are, and shape your team’s goals accordingly. My team’s goals are:

  1. To protect shared resources from performance problems due to inefficient code.
  2. To show off new and interesting techniques
  3. To learn from each other’s experiences

Define Standards

Now that you know what your goals are you need to come up with what the rules are. I start with the Adobe CFMX Coding Guidelines. I look at performance and security issues, and then start building out rules from there. Then I collect tidbits from other online sources, and start lumping them all together.

I need to say, before I started any of this, I read my copies of the ColdFusion MX 7 Web Application Construction Kit and Advanced ColdFusion MX 7 Application Development. These are so fundamentally important to writing good ColdFusion, that we don’t even bother telling people to read them. You start working for us, you get handed copies of them.

Publish Them

This seems to be a no brainer, but people really get annoyed when they come to a code review and are told they’ve violated our super secret standards. Now in our mind, they’re never secret. Everybody who is reading the blogs know what techniques are out of favor now right? Well no, because not everyone who codes in your organization keeps up to date with the ColdFusion blogosphere. So you need to tell them what they standards are. We do this by including a blog in our development center that has a category named “Best Practices.” We add to it as techniques or situations come up. We then force our developers to see the blog, because the rest of our development tools are on the same site.

Give Directions

We very tell people the following:

  • Make sure your application conforms to current best practices
  • Prepare CFML, HTML, CSS
    • Make a local copy of your code. Feel free to include stylesheets, but don’t bother with images.
    • Remove database, or other passwords from code.
    • Remove any unused templates
    • Clean any commented code out of your applications
    • Remove development diagnostic code like <cftimer> or <cfdump>
    • Remove database, or other passwords from code.
    • In short, code should be ready to go to production when reviewed.
  • Prepare SQL
    • All SQL going against a database server must be called in a stored procedure.
    • Use Query Analyzer to properly index tables. [Link to tutorial]
    • Use Enterprise Manager to generate scripts for all tables, including indexes. [Link to tutorial]
    • Use Enterprise Manager to generate scripts for all stored procedures. [Link to tutorial]
  • Prepare Flow Chart
    • Use Visio or some comparable program to chart the flow of your application.
    • Visio can be obtained from [Link to Central Installs location]
  • Zip up all the collected files.

You may require other things. But make sure people are told what those things are.

Read the code before the review

Nothing irritates me quite as much as a reviewer who insists on not reading the code ahead of time. To force others to wait because you say “hold on” as you flip through pages is incredibly disrespectful to you co-workers.

Some people print out all of the code, and review directly on the paper. With the size of applications these days, this is becoming more and more unwieldy. I’ve taken to using my two monitors and putting up code in one window, and Microsoft One Note in the other. That way I can just record my thoughts, or copy and paste code. Additionally, I don’t waste paper.

Make clear and concise recommendations with references to specific lines of code. Here is a sample from one of my reviews:

Game

Application.cfc

Line224

Why do you raise the logout action to an application variable? Is there a good reason for doing so?

Application_security.cfc

Line 319-326

I really like this bit of logic.

effHistroyFunctions.cfc

Line 61

This is a bit confusing: either the object you are creating either exists throughout the entire CFC (which is only one function for now, but could grow at some point.) so it should be in the variables scope and init when the cfc init’s. OR it only exists in this function in which case it should initialized with a var.

Error_exception.cfm

Line 22

CompareNoCase is prefered over eq

1 eq 1 will always be true. So this conditional will always be true so get rid of it.

Error_request.cfm

Line 23

Using the error.mailto is preferred over using a hardcoded address.

Frontier.cfc

Function frontier_calc

I feel like this function might be a little hard to maintain and troubleshoot.

Additionally it has explicit steps within it. It could be encapsulated a little further to make troubleshooting and debugging easier.

Legend

  • Must Change
  • Suggested Change
  • Stylistic Tip
  • Curiosity, Not Criticism
  • Comment

Notice also that we make allowances for several levels of severity. There are things that must be changed. But we also place an appropriate priority on less important changes so developers against a deadline know what they have to do, and what they can negotiate with us over.

The Review

The developer presents their application. They tell us what its purpose is, any specific challenges they faced, or what problem they are trying to solve. Then we usually go through the code technology by technology. (So Flex code, then ColdFusion code, then SQL, then XHTML/CSS etc.) The team gives our feedback, and then discuss any points of contention. (I think something is the best way to do it, but another review disagrees, and the developer has a specific reason for choosing to do it in a way other then what we think is “best.”)

Keep it courteous. Keep it respectful. And don’t forget to praise the good things you find.

Aftermath

The developer should make changes to their code based on the review. The reviewers aren’t done yet though. Was anything “widely accepted” as best practices new to a developer? Then it should be posted with your best practices; even if you have to repost it. You may also have to sit down with your fellow developer and help them learn a new technique.

Conclusion

Code reviews are a necessary part of running a good programming shop. No one should be exempt; even the makers of the standards. They can be painful, and ego bruising, but with a little preparation, the negatives can be downplayed, and the positives allowed to shine through.