Variables
What's in a name?
- Intention
- No cryptic names
- No abbreviations
- Rather have something longer, but clearer/obvious
- Be serious
- Funny comments etc
//Not clear
for(i=1; i<=ArrayLen(myArr); i++)
{
temp=myArr[i];
temp.update();
}
//More clear
for ( thisForm=1; thisForm <= ArrayLen( forms ); thisForm++ )
{
forms[thisForm].setDefaultValues();
}
Much more readable.
Doesn't like the use of i or j, k as it can get confusing in nested loops and isn't clear
Another side-by-side
v1 = new RCVal();
isDumb = v1.idiotCheck();
validator = new RemoteConnectionValidator();
isConnectionActive = validator.checkConnection();
Logic and Algorithms If / Else
If you can't look at a piece of code and tell what it can do in under 10 seconds, think about re-writing.
The following just gets too confusing. Try not to have so many conditions in one if statement, break it up.
if(currentUser.isActive()
&& Len(form.content)
&& isValid(form.email)
&& currentUser.isHappy()
)
{
//do something
}
Seperate out the code so you don't get lost in the if/else statments...
if (isMessageReady( form ) )
{
//20 lines of
// send email
//code
}
else if ( !isMessageReady ( form ) )
{
//20 more
//lines
//of code
}
Change to this..
if (isMessageReady( form ) )
{
sendMessage( form )
}
else if ( !isMessageReady ( form ) )
{
handleMessageError( form )
}
Switch / Case
Looping
for ( thisPreference in preferences )
{
if ( !thisPreference.isDefaultPreference() )
{
updatePreference.preferences( preferences[this] );
}
else
- Minimize use
- If possible, just don't use them
- Simple conditions
- Break it up
- Avoid nesting
- Don't assume a branch will run
If you can't look at a piece of code and tell what it can do in under 10 seconds, think about re-writing.
The following just gets too confusing. Try not to have so many conditions in one if statement, break it up.
if(currentUser.isActive()
&& Len(form.content)
&& isValid(form.email)
&& currentUser.isHappy()
)
{
//do something
}
Seperate out the code so you don't get lost in the if/else statments...
if (isMessageReady( form ) )
{
//20 lines of
// send email
//code
}
else if ( !isMessageReady ( form ) )
{
//20 more
//lines
//of code
}
Change to this..
if (isMessageReady( form ) )
{
sendMessage( form )
}
else if ( !isMessageReady ( form ) )
{
handleMessageError( form )
}
Switch / Case
- Minimize Use
- Breaking it up
- Avoid Nesting
- Don't assume a case will match
Looping
- Break up logic
- Avoid nesting
for ( thisPreference in preferences )
{
if ( !thisPreference.isDefaultPreference() )
{
updatePreference.preferences( preferences[this] );
}
else
{
updatePreference.preferences( preferences[this] );
}
}
for (thisPrefernce in preferences )
{
updatePreference.preferences( preferences[this] );
updatePreference.preferences( preferences[this] );
}
Basically, make the code you're writing more clear to read and handle extra stuff in their own methods..
Methods and Functions
Verb-oriented Names
Methods - Smaller = better
Focus!
Try not to argue
// 1+3^2 = 10 possible invocations
function loadContent ( url, isSSL=false, useCache=false, method='get' )
function loadContent ( LoaderSettings settings )
Where you're passing a cfc as an argument, if it makes things more clear of simple
Side Effects:
What just happened?
Error Codes
Classes (and CFCs)
Noun-Oriented Names
Rather have more smaller, cohesive cfcs vs really long ones
3-4 screens tall is really big..
Cohesive
Guard that Wall!
Comments
Don't Comment
If you HAVE to, make it count
Don't Comment Out Code
Joined at the Hip
Format and Layout
How do you lay the code out physically?
Adopt a Standard
Vertical Spacing
Put some spaces here and there to visually break things up..
Indentation
You Are Your Code
Conclusion
Clean Code Matters
Some reading:
Clean Code: A Handbook of Agile Software Craftsmanship
The Pragmatic Programmer
updatePreference.preferences( preferences[this] );
}
}
for (thisPrefernce in preferences )
{
updatePreference.preferences( preferences[this] );
updatePreference.preferences( preferences[this] );
}
Basically, make the code you're writing more clear to read and handle extra stuff in their own methods..
Methods and Functions
Verb-oriented Names
- updateRSSFeed()
- validate()
- trackShipment()
- authenticate()
- findRelatedProducts()
Methods - Smaller = better
- More cohesive
- Easier to test
- Easier to override
Focus!
- Sergeants and privates
- One public function that gets called from the outside (to a CFC for example), but within that its a bunch of private methods that get called.
- One level of abstraction
Try not to argue
- Avoid many arguments
- Best number is 0, then 1, then 2... After that it gets too many / too complicated
- Avoid optional arguments
- Add a class to encapsulate arguments
// 1+3^2 = 10 possible invocations
function loadContent ( url, isSSL=false, useCache=false, method='get' )
function loadContent ( LoaderSettings settings )
Where you're passing a cfc as an argument, if it makes things more clear of simple
Side Effects:
What just happened?
- Avoid side effects
- Return a value vs changing things
- Throwing things into a method and having it updating things, return things back to make it more clear
Error Codes
- Codes are evil
- Codes can change
- Exceptions are there for a reason!
Classes (and CFCs)
Noun-Oriented Names
- Shipment
- Attendee
- Permission
- UserGateway
- RemoteContentService
- InvoiceGenerator
Rather have more smaller, cohesive cfcs vs really long ones
3-4 screens tall is really big..
Cohesive
- Does one thing
- Simpler
- Easier to test
Guard that Wall!
- Encapsulate by convention, reveal by need
- Be paranoid up front, make all private and expose them as you need them..
- Limit external dependencies
- The more things something depends on, the more change a chance will occur and negatively affect things.
Comments
Don't Comment
- All comments are failures
- Code is not simple enough or the language is not useful enough to allow for you to be clear.
- Ask yourself WHY you think you need a comment
- Try to make the code simpler and more readable before using comments.
If you HAVE to, make it count
- Don't restate HOW the code works
- /* Loop over users query, then set firstName from db record */
- Explain WAHT the code is supposed to do
Don't Comment Out Code
- Comments should not be version control
- Nobody ever deletes it and will forget why its there for still..
- All it offers is confusion
Joined at the Hip
- Stale comments are far worse than no comments
- Obligated to freshness
- If you put a comment, you're obligated to keep that block of comment fresh and relevant.
- Again, try to make the code more useful first.
Format and Layout
How do you lay the code out physically?
Adopt a Standard
Vertical Spacing
- Make it easy to scan through
- Seperate methods
- Separate appropriate chunks of logic
- Litmus test for complexity
Put some spaces here and there to visually break things up..
Indentation
- Again, easy to read
- Easy to identify conditionals, loops etc
- Litmus test for complexity
- If it goes too far over, you'll start to know it may be getting too complex
You Are Your Code
Conclusion
Clean Code Matters
- Clean code is easier to read
- Clean code is easier to maintain
- Clean code encourages thoughtful design
Some reading:
Clean Code: A Handbook of Agile Software Craftsmanship
The Pragmatic Programmer