How Many Zeros In A Million

This blog hit over a million total views today. Well, I think it was today, I can't be sure.

Last week I noticed the page count was somewhere near 990k and I wanted to get a screen shot of when the site rolled over to a cool million. It looks like I missed it by a few hundred. Oh well, I guess I can try to pay better attention when I hit a billion. (Heh.)

So thanks to those who come and read articles from nodans.com. I hope you found them as helpful to you as they were to me when I wrote them.

So you wanna learn Regex? - Part 5

Welcome to So You Wanna Learn Regex? Part 5. This is our last part of this series, mostly because I don't know a whole lot more than this. If you want more tutorials about regex, go bug Ben. He knows more about this than I ever will and I hear he has a blog...

In our last exercise, we looked at a simple way to add cfqueryparam to a bunch of queries. This was accomplished by making a pattern consisting of 3 groups then using one of the groups to populate a literal string.

In this exercise, we are going to clean up some data scripts. Let's suppose you are generating database scripts and your script generator puts the primary key in there. For whatever reason, you want to remove this.

Assume this set of declarations:

INSERT INTO `memberchallenge` VALUES ('11', '1', '19', null, '2008-11-14 14:07:59', '2008-11-14 14:07:59', '1', '2008-11-14 14:07:59', '0');
INSERT INTO `memberchallenge` VALUES ('12', '2', '19', null, '2008-11-14 15:40:51', '2008-11-14 15:40:51', '1', '2008-11-14 15:40:51', '0');
INSERT INTO `memberchallenge` VALUES ('14', '5', '19', null, '2008-11-14 20:14:26', '2008-11-14 20:14:26', '5', '2008-11-14 20:14:26', '0');
INSERT INTO `memberchallenge` VALUES ('15', '1', '20', null, '2008-11-23 18:19:31', '2008-11-23 18:19:31', '1', '2008-11-23 18:19:30', '0');
INSERT INTO `memberchallenge` VALUES ('16', '2', '20', null, '2008-11-23 18:20:09', '2008-11-23 18:20:09', '1', '2008-11-23 18:20:09', '0');
INSERT INTO `memberchallenge` VALUES ('17', '1', '21', null, '2008-11-25 20:32:44', '2008-11-25 20:32:44', '1', '2008-11-25 20:32:44', '0');
INSERT INTO `memberchallenge` VALUES ('18', '2', '21', null, '2008-11-25 20:33:01', '2008-11-25 20:33:01', '1', '2008-11-25 20:33:01', '0');

What we want, is to turn:INSERT INTO `memberchallenge` VALUES ('11', '1', '19', null, '2008-11-14 14:07:59', '2008-11-14 14:07:59', '1', '2008-11-14 14:07:59', '0'); into: INSERT INTO `memberchallenge` VALUES ('1', '19', null, '2008-11-14 14:07:59', '2008-11-14 14:07:59', '1', '2008-11-14 14:07:59', '0');

Note the first value in the VALUES statement has vanished.. this would be the primary key in our dataload script.

So as you know, we define this pattern in the gobbledegook of regular expressions. When read one chunk at a time, these actually make sense. We'll go through the exercise, then look at why it worked.

In Eclipse, perform the following:

[More]

How to resolve svn: Error setting property 'log':

I was trying to check in some changes on the Model-Glue framework and kept getting this error:

view plain print about
1update D:/webroot/ModelGlueTrunk/ModelGlue/gesture -r HEAD --force
2 At revision 184.
3commit -m "Removed potential recursion in this functionality..." D:/webroot/ModelGlueTrunk/ModelGlue/gesture/helper/HelperInjector.cfc D:/webroot/ModelGlueTrunk/ModelGlue/gesture/helper/IncludeHelperShell.cfc
4 Failed to execute WebDAV PROPPATCH
5svn: Commit failed (details follow):
6svn: At least one property change failed; repository is unchanged
7RA layer request failed
8svn: Error setting property 'log':
9Could not execute PROPPATCH.

I updated from SVN, thinking it to be a synchronization error, but I still got the same error.

I used the 'cleanup' or SVN:clean functionality to maybe get the .svn files and such back in to the right condition, but that didn't help either.

The original SVN Comment I used was:

view plain print about
1Removed potential recursion in this functionality
2Also removed useless cfdump when a helper is attempted to be included but doesn't have a cfc or cfm extension

Can you spot the issue? I can't either. What fixed the error:

view plain print about
1Failed to execute WebDAV PROPPATCH
2svn: Commit failed (details follow):
3svn: At least one property change failed; repository is unchanged
4RA layer request failed
5svn: Error setting property 'log':
6Could not execute PROPPATCH.

Was changing the multi-line comment to a single line comment. Once the comment was a single line, there was no issue checking it in. I'm not sure what I learned here, but I hope SVN doesn't REALLY have a problem with multi-line comments, after all, we need those to keep details on what changed!

So you wanna learn Regex? - Part 4

Welcome to So You Wanna Learn Regex? Part 4. In our last exercise, we looked at a simple way to clean a whole bunch of strings. This was accomplished by making a pattern, then removing everything according to that pattern. This time we are going to add cfqueryparam to a query. Say for example, that you have a junior developer who has been turned loose on her first application and she's done a good job, except for she didn't use cfqueryparam. You just found this out and the site has to go live in 10 minutes and you have 200 queries to fix. Do you:

  • a) Download the code to your laptop then pull the fire alarm to stall for time?
  • b) Start blasting your resume out on Monster.com?
  • c) Take a fistfull of aspirin, knowing your forearms will ache in the morning?

If you answered d) none of the above, please keep reading.

Assume this set of declarations:

UPDATE plant
	SET 	Symbol = '#form.symbol#',
			SynonymSymbol = '#form.SynonymSymbol#',
     		ScientificNameWithAuthor = '#form.ScientificNameWithAuthor#',
     		CommonName = '#CommonName#',
     		Family = '#Family#'
WHERE PlantCode = '#form.plantCode#'

What we want, is to turn: '#form.symbol#' into: <cfqueryparam value="#form.symbol#" cfsqltype="cf_sql_varchar">

So as you know, we define this pattern in the gobbledegook of regular expressions. When read one chunk at a time, these actually make sense. We'll go through the exercise, then look at why it worked.

In Eclipse, perform the following:

[More]

So you wanna learn Regex? - Part 3

Welcome to So You Wanna Learn Regex? Part 3.

In our last exercise, we looked at a simple way to wrap a function argument inside a new function. This was accomplished by making a pattern, defining a group and using a back reference. This time we will look at how to clean some strings.

Say for example, that you run a website called The Health Challenge and say for example, you wanted to use some of your fine tax dollar funded research to deliver motivating messages to the members.

Well, you could just happen across Small Steps and just use their content. After all, it is in the public domain. So you happily cut a LARGE chunk of these from the web site, but now you have to clean them.

Assume this set of declarations:

(# 11)  	Avoid food portions larger than your fist.
(# 12) 	Mow lawn with push mower.
(# 13) 	Increase the fiber in your diet.
(# 17) 	Join an exercise group.
(# 20) 	Do yard work.
(# 24) 	Skip seconds.
(# 25) 	Work around the house.
(# 26) 	Skip buffets.
(# 29) 	Take dog to the park.
(# 30) 	Ask your doctor about taking a multi-vitamin.
....( 700 more lines)

What we want, is to turn: (# 11) Avoid food portions larger than your fist. into: Avoid food portions larger than your fist. See, we like the content, we don't like the parentheticals nor the whitespace. Do we flex our forearms in preparation for a copy/paste session? Do we call KeyboardsAreUs.com and have 2 fresh keyboards airdropped, knowing we'll wear out some keys? (if you said yes, please delete your hard drive and apply at KFC.) Regular expressions are our friends. A Regex is a pattern matcher, and it can do stuff. We can see our code is repetitive and the pattern we want is: Get rid of the parentheticals and the extra whitespace. (Same stuff we'd do over and over via cut/paste/etc, isn't it? Though in a copy paste, you are talking about 5 keystrokes per line times 700 lines. That is 3500 keystrokes, unless you type like me, in which case it would be nearly 4 million.)

So as you know, we define this pattern in the gobbledegook of regular expressions. When read one chunk at a time, these actually make sense. We'll go through the exercise, then look at why it worked.

In Eclipse, perform the following:

[More]

So you wanna learn Regex? - Part 2

Welcome to So You Wanna Learn Regex? Part 2. In our last exercise, we looked at a simple way to add a new attribute to an HTML tag. This was accomplished by making a pattern, defining a group and using a back reference. This time we will look at a slightly more complicated use case.

Assume this set of declarations:

product.setColor(arguments.color);
product.setSize(arguments.size);
product.setCondition(arguments.condition);
product.setRating(arguments.rating);
product.setReliability(arguments.reliability);
product.setNeedsBatteries(arguments.needsBatteries);

What we want, is to turn: product.setColor(arguments.color); into: product.setColor( htmlEditFormat(arguments.color) );

Normally, this would be a forearm/wrist fatiguing flail on the keyboard, furiously cutting/pasting and generally flapping about. Not so with Regular Expressions. A Regex is a pattern matcher, and it can do stuff. We can see our code is repetitive and the pattern we want is: Take Everything Inside The Parenthesis, and Wrap It In A htmlEditFormat() Function. (Same stuff we'd do over and over via cut/paste/etc, isn't it?)

We can define this pattern in the gobbledegook defining a regular expression. When read one chunk at a time, these actually make sense. We'll go through the exercise, then look at why it worked.

In Eclipse, perform the following:

[More]

So you wanna learn Regex? - Part 1

I've had a set of blog posts stewing in my brain for a while. Steve Nelson, last year, helped me out with a Regular Expression (Regex) and I made it a point to practice my Regex skills more. This series will show how to use Regular Expressions in Eclipse and we'll learn some helpful tips along the way. This series is for you if you are the kind of developer that reads Ben Nadel's blog posts containing Regular Expressions, and has no idea what the heck he is talking about. Seriously Ben, this is unintelligible to us mere mortals:

<cfset blogContent = reReplace( blogContent, "</?\w+(\s*[\w:]+\s*=\s*(""[^""]*""|'[^']*'))*\s*/?>", " ", "all" ) />
(It looks like a catnip crazed kitty went for a prance on a keyboard, doesn't it?) Enough guffaws and such. On with the learning.

Editors Note:

Simply reading these blog posts aren't going to help you. Open eclipse, and copy/paste this stuff into your find/replace dialog. You'll learn more, or your money back!

So, firstly we need a use case. Let's pretend we are going through some old code and looking to add HTMLEditFormat around some arguments so that the forms won't break if there are quotes.

Assume this set of declarations:

<input name="fred" value="willy" />
<input name="bill" value="mickey" />
<input name="erin" value="harry" />
<input name="baz" value="pissette" />

What we want, is to turn: <input name="fred" value="willy" /> into: <input name="fred" id="fred" value="willy" /> Normally, this would be a forearm/wrist fatiguing flail on the keyboard, furiously cutting/pasting and generally flapping about. Not so with Regular Expressions. A Regex is a pattern matcher, and it can do stuff. We can see our code is repetitive and the pattern we want is: make a new attribute called 'id' and populate it with the value from the attribute 'name'... which is what we'd do over and over via cut/paste/etc. We can define this pattern in the gobbledegook defining a regular expression, of course, else I'd be writing this post about Cute LOLCats, not Cute Regexes., wouldn't I? We'll go through the exercise, then look at why it worked.

In Eclipse, perform the following:

[More]

Adobe Max Sessions Filling Up Fast!

I registered for Adobe Max a few weeks ago but never actually put my session schedule together. I'm not the biggest fan of the way Max handles it's sessions. Most of the conferences I go to do not have badge nazi's at the door banning anyone without prior registration, Max does. While I can understand logistical circumstances, I still don't like it. So, after a reminder from the blogosphere I logged in today to schedule my sessions.

Max, for me, is all about the hands-on stuff. I don't mind paying the price especially knowing I'm going to get hands-on training. Matter of fact, I sell professional training and when compared with my bill rates Max is a bargain :) !

So, if you haven't registered for Max, hurry up. If you've registered and not scheduled your sessions, you REALLY need to hurry up. I'm attaching my Max schedule to this article in case you want to see where I'm spending my time.

See you @ Max!

DW

Download Download

Win a ColdFusion Dude Camera

Registration for the CFinNC conference is filling up fast. Even though we are a free conference, space is limited so get your registrations in very soon!

The illustrious Simon Free is running a promotional conference to help not only CFinNC, but bFlex/bFusion and RIA Unleashed. You could win a limited edition, one of a kind, never to be seen again, amazingly creative, yet awesomely useful custom CF Dude Flip video camera by simply registering and Submit, in 100 words or less, why you love ColdFusion or why you are excited to learn ColdFusion!

Win a CF Dude Camera - 3 great conferences, 3 Chances to Win

Usability and Error Messages

I often consider usability when using web applications, especially when I am the user. Our lovely state of North Carolina, is very tech savvy and has a lot of online resources and help. Did you know that North Carolina was one of the first states to have it's own data center?

Today, I went online to change my address on my Driver License. Apparently there is some complication with my particular license (hopefully not a warrant out for my arrest :-) ) in the system and I need to go into a physical office for human assistance. As an application architect, I can see this is probably some poorly handled data condition. I can dig that, a computer can't handle EVERYTHING...

What prompted this post was a bit of musing on proper error messages. When humans interact with computers, by definition there is a depersonalization to the process. This depersonalization can add a level of harshness or friction into the equation, altering the perception of the organization to the user. Allow me to pontificate...

I often stay at nice hotels. Nice hotels always have extremely polite front desk staff to help check guests in. The check-in phase of the hotel stay sets the stage for perception. If the registration desk is nicely furnished, elegant and staffed with ultra-polite staff, guests perceive the hotel as a nicely furnished, elegant and ultra-polite and this perception sticks with them the entire trip. If there is some reason why a request can not be accommodated, say I ask for a room on the top floor and the top floor has already been booked, the registration staff apologize effusively and find a suitable arrangement. Even if I asked for something impossible, like a helicopter to take my bags to my room, the staff would politely and softly apologize that such a service was not available, then offer the services of a bellman for bag delivery.

Hotels definitely understand the human touch. Computers do not. Nor do the engineers that create applications. See, it was perfectly acceptable for some reason or another not to provide algorithms suitable for handling an address change with my specific type of license. The engineer probably had a meeting discussing just such an occurrence and it was deemed not critical for the application. So the engineer dutifully put in code to catch such an occurrence and then added an error message to halt the flow of the application. The engineer considered the application from the perspective of the application and this is what was implemented:


Ouch. Nothing like a BIG RED STOP SIGN.

STOP! It says.. The text, actually, isn't half bad because it attempts to explain the issue, "...Multiple Address Records..." and offer to help me find the nearest office. But, I reeled from the impact of that stop sign.

To stick with the hotel analogy, it was as if I approached the registration desk, asked for a room with a King Sized bed, and the clerk said, "We have no king beds" then slapped me across the face, WACK!

I'm sure all of this seemed rather normal for the Application Engineer, who had undoubtedly seen this error page hundreds of times before during testing and was desensitized to it. Me, however, expecting to see a helpful page allowing me to change my address, was a little taken aback by the HONKING BIG RED STOP SIGN OF DOOM CLUBBING ME LIKE A BABY SEAL.

So, I mused a little bit this morning and made a decision to pay a little more attention to the human factor and to usability. I challenge you to do the same in your applications.

Do you have a screenshot example of a ridiculously insulting error message? Submit a link of the image to me and I'll post it here for the amusement of others...