Code Wants to be Stoopid

October 27, 2010 by

Clever code never did no-one nay but no good.  Not know-how, not no-way.

Yeah, I’m not sure what I just said either.  I do know that “clever” and “slick” are words that I don’t care to hear about code, or a coding solution to a given problem.  Code needs to be simple.  How simple?  As simple as possible [but no simpler, yadda yadda yadda].  “But my code IS simple” you say.  I’m done.

Cool.

…just one more thing.  Do all your methods only do one, and only one, thing?  Yes, I said all.

Every method (or function) should accomplish only what it’s name says it does.  If you have a method “saveThing” it should only save that thing.  It should not check for something else, optionally set a flag, make any other call, then save that thing, and return the price of tea.  It should only save the thing.  This means you will have many very small methods.

At a high level this will lead to something really powerful:  Readable code.  You see, as your fine granularity builds upwards you are essentially utilizing the ‘composition design pattern’ in a micro-economy.

What are some signs that you may have code that can be refactored into it’s own method?

  • Length.  If a method is growing beyond 10 lines, take a close look and make sure it’s still doing only one job.  As methods grow they want to do more than they should.  You can’t convince me that 1,000 line method is as small as it can get.
  • Unused parameters or only using one or two variables off an object.  Too much data will lead to putting process in the wrong place.  If you don’t have the data you can’t do the wrong thing with it.  Don’t pass in a few extra objects just in case.  If you don’t need them pull them out.  Use static analysis to remove unused and dead parameters (and code blocks).  If you really only need to do work on a username… just pass in the string, and not the whole user object.
  • Comments.  If you feel the need to explain a section of code inline, it should be it’s own function with a well suited name.  You either use too many comments (rare, and not cool but that’s another topic) or you use one or two in confusing places.  That’s the tingly feeling you’re trying to learn that says “put this code in it’s own method”.

This is the path to better code.  Code that does what it says it does, nothing more and nothing less.  It sounds so simple, but is the essence of a truly powerful system.  Keep your code dumb, you’ll thank me for it.

P.S.  I know it’s spelled “stupid”.  😉

BFusion/BFlex 2010

October 18, 2010 by

Last month, 16 Web Monkeys with Laserbeams went to BFusion/BFlex 2010.  What a cool little gem of a conference.  There were some truly world class presenters there.  One even shed new light on a sore spot of mine that made me reconsider my entire belief system.

Well, my entire belief system on Unit Testing.

Hi.  My name is Jim.  …and I’ve been abused by bad Unit Tests.

I’m sure to talk more about that eventually.  For now let me say that Michael Labriola over at Digital Primates is a fantastic guy with a solid view on writing solid apps.  He introduced the idea that separation of concerns is what’s key to unit tests.  The issue with tests is that they can’t test the code cause it’s untestable.  A method should do only one thing which makes for easier testing.

I like it.  I like it a lot.

Our very own Doug Smith spoke about RESTful services as well.  Yeah, I’ve been a POST-heavy addict as well.  It seems I’ve got issues.  REST makes sense.  Almost too much sense.

You have to catch these guys talk.  They’re really top notch!  Keep your eyes on next years Bfusion/Bflex conference.  It’s hot, and you’re sure to learn something and have a great time!

Investing In ColdFusion

August 18, 2010 by

If you listen to Dave Ramsey at all, you know he’s all about wise investing. The daveramsey.com development team has made a significant investment in a new RESTful service layer. We’ve invested time in building it so that our site can continue to scale and grow to reach millions more with the message of Financial Peace. And, we’ve invested in the Mach-II framework by writing the code for the new REST Endpoint for version 1.9, so that simple and powerful RESTful services are available to the entire ColdFusion developer community.

Not only that, we’re investing in an upcoming ColdFusion conference, BFusion ’10. I’ll be presenting a session titled “Building a RESTful Service Layer in ColdFusion“. Well over a dozen Dave Ramsey developers will be making the trek from Nashville to beautiful Bloomington, IN for BFusion/BFlex this year. The facilities, speakers, content, and networking opportunities are very valuable. It’s a smaller conference so it’s easy to connect with industry leaders and really dig in to learn some new things. If you’re doing anything with ColdFusion or Flex, or think you might want to get started, this conference is well worth your time.

Automated testing and dynamic ID’s

May 5, 2010 by

First off, if you’ve never used the testing tools Selenium or WebTest, you should give them a try.  Each of these tools is used to generate and run scripted interaction with your Web site (i.e. Web app functional testing).

As I built a regression test for a bug I found, I needed to automate selecting an option from a drop-down. Usually the test recorders handle this for me, and I give it no thought.  The catch is, the ‘id’ of the select element could be different on any given test run.  What I really needed was to choose a select element based on its label rather than its ‘id.’

Consider this (dynamically generated) HTML fragment:

<label for="arbitraryElementId">Product</label>
<select name="productX_another_arbitrary_id" id="arbitraryElementId">
   <option>foo</option>
   <option>fizzle</option>
</select>

<label for="somethingElse">Qty</label>
<select name="qtyX_another_arbitrary_id" id="somethingElse">
   <option>10</option>
   <option>20</option>
</select>

How can I locate the correct select element without referencing them by ID?

//select[@id='???']

That would work great if I knew the ID ahead of time.  That’s where the ‘for’ attribute comes in handy:

//label[text()='Product']/@for

That will get me the for attribute of the “Product” label.  Putting it all together, it looks like this:

//select[@id=//label[text()='Product']/@for]

A Java/Ruby Developer Appreciates ColdFusion?

May 4, 2010 by

When I moved my family 2,500 miles to join Dave Ramsey’s web team two years ago, I joined because of my passion to help Dave reach more financially distressed people through technology. I didn’t join because his web site used ColdFusion. With more than 15 years of development experience, primarily as a Java, ActionScript, and Ruby developer, I had a relatively low opinion of ColdFusion.

However, as a member of Dave’s web team and the ColdFusion developer community, I’ve seen the truly world-class work that is being done with ColdFusion. I’ve come to appreciate ColdFusion as a worthy peer of other modern development platforms.

What changed my mind? Here are some of the contributing factors:

  • Results. As a very practical person, I observed our very successful website. It serves more than 1M unique visitors, with over 10M page views per month. A company of nearly 300 team members generates a large amount of its income from our site. As a Java developer with my nose in the air, I had never worked on a site that had even close to this much of an impact.
  • Java. ColdFusion applications compile down to Java and run as a standard Java web-app, deployable as a .war file on any Java app server. All of the scalability, flexibility, and power I was used to in my Java web-app development is available in a well-executed ColdFusion app.
  • Mach-II. We have been a Mach-II shop for several years, but we recently rebuilt our primary web site, daveramsey.com, into a 50 module Mach-II 1.8 application. We’ve found Mach-II to be an extremely powerful Model-View-Controller framework that enables us to support our growing number of users. It provides a foundation we can build on that has helped us to roll out new features quickly, without compromising a strong MVC design. (I also had the honor of meeting team Mach-II at BFusion, and found Peter, Kurt, and Matt to be an outstanding group of committed, brilliant developers. We reviewed their work on Mach-II 1.8 while we were developing our new website, and found their code to be among the best ColdFusion code around. They set the bar for outstanding quality and community support.)
  • Libraries. ColdFusion 9 added Hibernate, providing access to the same proven ORM used by leading Java and Groovy apps. The ColdSpring framework provides IoC support on par with Spring. Several automated testing libraries are available; we use MxUnit. RiaForge has 700+ additional open source ColdFusion projects. And, since ColdFusion is Java, thousands more Java libraries are available. We used the Java Topology Suite for a large internal Flex/CF/Java Map mashup application.
  • Productivity. ColdFusion is a dynamic language that runs on a JVM, offering productivity improvements over traditional Java development. From simple things like cffile, cfhttp, cfquery, and cfdump (!), to integration with the frameworks I mentioned above, I’ve found ColdFusion development to be more agile than Struts or Spring MVC.
  • Competition. I’m a huge fan of the Railo and Open BlueDragon efforts, because they provide very healthy competition to Adobe and encourage innovation. They also open CFML up to the open source community, so that developers can deploy ColdFusion applications on a completely open stack. We don’t use them here yet, but may in the future.

ColdFusion isn’t perfect — any experienced developer knows that there is no such thing. Every technology has pluses and minuses. However: real, enterprise-class, powerful, and successful applications are being built on ColdFusion. If you are like I was a couple years ago, and have a low opinion of ColdFusion based on poorly written apps or experience years ago, I’d encourage you to take a second look. You may be pleasantly surprised by what you find.

Country Music Marathon: Web Dev Represented!

April 27, 2010 by

When Nashville’s Country Music Marathon comes around every spring, you can be sure that you’ll see many of our Dave Ramsey team members scattered throughout the field of runners.  We are very proud to say quite a few of our own web developers participated this year in the half marathon!  The conversion of this distance into Imperial units is approximately — not exactly — 13.10938 miles.  Way to go team!  We hope this will inspire others to get out there and accomplish something that’s not easy, yet rewarding for their health!  Maybe you can join us next year!  Here’s some of the teams’ thoughts on the marathon experience.  Enjoy!

“Having people come up to me before the marathon and ask if I worked for Dave was actually pretty cool. They were so excited and encouraged by what we do that they took the time to talk to me about it. One lady leads an FPU class in Macon, GA and said “you’re so lucky to get to work for Dave.” I agree. My wife and I also had people run by us at the beginning and ask if we were debt-free, to which we enthusiastically responded “yes.” Running as part of Team Ramsey was a blast.”

–  Kevin | Web Programmer/User Interface


“At Lampo, running is contagious. Before the half marathon, I was not much of a runner, but I was inspired and encouraged by many team members to participate. I’m so glad that I did! Not only did I accomplish something I thought I never would, but I am more excited about exercising and staying in shape. I will definitely be back next year!”

–  Andrew | User Experience/Interface Developer


“To be honest, I really don’t like this race. For me it’s too big … 30,000+ participants. It’s pretty well organized but just because of the shear mass of people you have to be there waiting to start for at least an hour maybe two. Then it takes almost as long to get back to your vehicle, out of the parking lot, and on your way home. That said this is the third time I’ve done it and I plan to do it next year. For me running is about getting into shape, being healthy, and trying to be a good steward with the gifts God has blessed me. Having a target like a ½ marathon gives motivation to train and doing it with a bunch of your peers gives even more. So since Dave is willing to pay the entry fee and even supply team shirts, there’s no reason not to take advantage of it. I didn’t hit my goal time but I did knock 40 minutes off the previous year’s time and I recovered much faster so I’m satisfied. I also got to see Moses (or maybe he was supposed to be a kung fu master. I’m not really sure) running the race. Next week I start training for my first sprint triathlon.”

–  Jon | Senior Web Programmer


“Two things about the half marathon stood out to me.  One was the incredible sense of camaraderie and encouragement I got from seeing fellow Team Ramsey members out running and cheering along the course.  Sometimes one doesn’t realize the power of unity until it gives him the strength to push himself harder than he normally could.  Secondly, a few times during the race someone would see my shirt and say, “Hey!  Dave Ramsey!” with a big smile on their face.  To know that what we do is having an impact out in the community and to see the faces of those who have had their lives changed and probably visited the very site we work on was uplifting not just for the race, but even when I came into work on Monday.”

Ty | Web Programmer


“This is a huge race – over 30,000 folks run, and there are loads of spectators. It really is a big event, and it feels like it. About 70 folks from our team ran or walked this year. We all wore bright yellow “Team Ramsey” shirts for the run, which has people shouting out encouragement along the way, and saying things like “Dave Ramsey saved my life!” It’s incredibly inspiring, especially when you’re pushing through some tough miles.”

– Ron | Marketing Web Programmer

“This is the second year I have run the half marathon, and I finished this year 22 minutes faster than last year, finishing in 1:58, just over a 9-minute mile.  It took every ounce of energy to finish.  I really enjoyed seeing all the yellow Lampo shirts out on the course (as runners or supporters).  I ran with my brother-in-law and even he was impressed with how many people from Lampo were there – even Dave came to cheer!  Running the half marathon is a great example of the type of people that Lampo works with: goal setters that are go-getters, positive attitudes that have fun during training and on the race day, diligence and dedication to finish strong, and providing hope and encouragement to the tired and weary.  There is a genuine sense of family support for each other.  I am blessed.”

– Jim | ELP Team Lead


We’re Debt FREE!!!

March 1, 2010 by

Two members of our team this past Friday made their own celebratory call into Dave’s radio program to exclaim with their spouse, “We’re Debt FREEEEEEEE!!!”

Michael, our Financial Literacy Programmer, paid off $126,000!  This took him and his wife Tracy, 3 1/2 years; knocking out a car payment and completely paying off their house.  Amazing!   At the age of 41, Michael and his wife are completely free of the strangle hold of debt and live in a house fully paid for!  WOW!

Next was a phone call in from Kevin, one of our ELP Web Programmers, and his wife Sara.  They paid off a total of $28,000 in only 21 months!  What was their debt from you ask?  That crabby old lady Sallie Mae!  They paid off all their student loans with a gazelle intense speed and are now, at the young age of 26, ready to live their lives DEBT FREE!

We are very proud of our team members Michael and Kevin. We even had the privilege of joining them in their debt free scream!  We wish them the very best as they continue to live out their lives debt free! 🙂

WAY TO GO GUYS!

Michael and his wife Tracy calling in to Dave's Friday radio program to yell, "We're Debt FREE!!!"

Kevin and his wife Sara ready to start their debt free life at the young age of 26!

Custom Dynamic POIs in Flex 3.5 & MapQuest API

February 23, 2010 by

Recently, I had a fun problem to work on with our homegrown mapping application.  I wanted to create a POI that would bring multiple images together to create an icon on-the-fly so we didn’t have to make two or three dozen of them.  Normally you just embed a custom image to use as an POI icon.  Well, with all the type of things we might add to an icon it could cause the swf to get very large and the icons to become unmanageable.  You can think of it as if you were going to show a radio station on your map.  Perhaps you want to have a pretty little FM or AM graphic on it depending on the type of station.  Well you would have to make two or three graphics to make sure you get all the combinations traditionally.  Then embed those graphics into the system.  This way we have three seperate graphics and they are smaller in file size so they don’t add as much weight to the application.  In short, think of it Photoshopping with code.

So here comes the How-to. It seems pretty simple now that I am writing it, but it was a little bit of a pain to figure it out. In English what I want to do is bring in the image as a class, turn it into a Bitmap then get the Bitmap-Data out of it. Call Merge on Bitmap data and pass in the proper information and get back some new Bitmap data. We will then turn that into a Bitmap and put is into a Map Icon.

/*We can set this as a class/global variable so the functions know what kind of multiplier we need. This is just a number to know how much the merge should combine the two images*/

private var mult:uint = 0xff; //
private function createPoiBitmap(mainPoi:Bitmap,initials:String,fontSize:Number = 10):Bitmap
{
//this is the main graphic for the POI that I need to get.
var bmdMainPoi:BitmapData = mainPoi.bitmapData;
//this is the bitmap that will house the whole picture.
var holder:BitmapData = new BitmapData(45, 34, true, 0X00000000);
//this is the main POI that got pulled

//this is the rectangle placement and size it will pull from the bitmap

var rectItm:Rectangle = new Rectangle(3, 4, bmdMainPoi.width - 7, bmdMainPoi.height);

var ptItm:Point = new Point(8, 9);//this is the point at which the merged item will be placed.

if(initials.length > 0)

{

//this is initial badge that we need to put on

var bmdBadge:BitmapData = getBadgeWithText(initials,fontSize).bitmapData;

//this is the name badge that was made. //this is the rectangle placement and size it will pull from the bitmap

var rectBadge:Rectangle = new Rectangle(0, 0, bmdBadge.width -1, bmdBadge.height - 1);

var ptBadge:Point = new Point(13, 0);//this is the point at which the merged item will be placed.

//add the new items to the holder image

holder.merge(bmdBadge,rectBadge,ptBadge,mult,mult,mult,mult);

}

holder.merge(bmdMainPoi,rectItm,ptItm,mult,mult,mult,mult); //make the holder image a bitmap and add it to the screen var bm1:Bitmap = new Bitmap(holder); return bm1; }
The following piece of code is actually adding the Text into the image. It is going to load up an object that I am caching so it doesn’t have to build it every time. I took out that if statement so you could see how it works.

private function getBadgeWithText(initials:String,fontSize:Number = 10):Bitmap
{
var object = getMyObject(); //this gets me a custom object so i can get and set bitmaps
var bmdInitbadge:BitmapData = object.getEmptyBadge().bitmapData;
var textitm:BitmapData = new BitmapData(10, 30, true, object.getBackgroundColor());
var txtFrmt:TextFormat = new TextFormat('Arial',fontSize,0xFFFFFF);
var uit:UITextField = new UITextField();
uit.background = true;
uit.backgroundColor = object.getBackgroundColor();
uit.text = object.getInitials();
uit.setTextFormat(txtFrmt);
var textBitmapData:BitmapData = ImageSnapshot.captureBitmapData(uit);
var rectText:Rectangle = new Rectangle(3, 3, 14, 10);
var ptText:Point = new Point(8, 7);//this is the point at which the merged item will be placed.
textitm.merge(textBitmapData,rectText,ptText,mult,mult,mult,mult);
bmdInitbadge.merge(textBitmapData,rectText,ptText,mult,mult,mult,mult);
var bmReturn:Bitmap = new Bitmap(bmdInitbadge);
object.setCompletedBadge(bmReturn);
return object.getCompletedBadge();
}

At this Point another function that called all this can set the Bitmap into the MapIcon

var icn:MapIcon = new MapIcon();
icn.setImage(createPoiBitmap(getMainIcn(),"ME",10));

Cygwin and SVN—friends at last

February 23, 2010 by

I’m kind of a CLI junky. Ironically, I prefer command line over GUI for its simplicity (that and I haven’t found a pointing device I care to use). In a Windows world, short of setting up an ssh server, this pretty much leaves me with Cygwin or PuTTYcyg (no, cmd.exe doesn’t count for anything).

The problem

When we upgraded to Subversion 1.5 (and now 1.6), I started running into problems with the new interactive conflict management. I prefer not to use it, but occasionally forget to add the --non-interactive flag to my commands.

The Dos emulator handled this just fine, but Cygwin would lock up. With PuTTYcyg, I can ctrl-C to at least get my prompt back. Then I have to svn cleanup. Sometimes this can bork your svn meta data beyond what ‘cleanup’ can fix. There are few things more frustrating than spending good development time on fixing your development environment.

The Solution

It turns out, you can disable interactive-conflicts by default by modifying your Subversion client’s config file. On Windows, this is %APPDATA%\Subversion\config (“$APPDATA/Subversion/config” for PuTTYcyg users).

Because I started with svn 1.1, the commented options in my config were outdated so I did the following to get a fresh one:

rm "$APPDATA/Subversion/config"
svn --version

Any subversion command will (re-)create a default config file.
Finally, I just uncommented the following line:

# interactive-conflicts = no

Now I can run SVN in my CLI of choice with no worries of losing time to repairing my local code check-out.

UPDATE: svn/cygwin now happily interactive

A colleague of mine suggested simply installing svn through the cygwin package management (i.e. re-run cygwin’s setup.exe). After doing so, I can interact with svn through local puttcyg just as I would through normal ssh. (Among other things, I no longer have to worry about my credentials being echoed when svn prompts me for authentication!)

What a Year

December 22, 2009 by

Our existing website was about 5 years old. After 5 years and uncounted utterances of  “Hey! We have a great new product that needs exclusive top billing on our website!” our web presence was… a bit busy.

We took our time, did our homework, researched, discussed, and planned a long project. In March, Right after we started into what became thousands of man hours, we had ANOTHER cool idea. Right in the middle of a season of economic uncertainty Dave led the team to do an event giving reasons to be hopeful. In early March we had a full workload and an unrelated idea. 2 months later on April 23rd, we had a fully functional website serving 1,000,000 people watching streamed video at 6,000 volunteer locations.

Of course that means that we pushed back launching the main site… right? Well,  no.  Did we work a ton of overtime? Well, we did some but it wasn’t 2 months worth. The new website is now up at www.daveramsey.com, and the side idea is up at www.townhallforhope.com.

I love that we did all of it without staying at the office so much that we forgot who our kids are. It’s been a great year. I’m excited to see what comes next!