Month: January 2011

Good practice check list for code

This is a reworking of a list I created a couple of years ago for a client. Hope you find it useful.

Contents

Object-orientation

DRY & Shy

Don’t repeat yourself (DRY)

An example of this is having setup and teardown code repeated in every method. This avoids a heavy maintenance load and ensures that the “cut and paste monster” does not create code that looks correct but references incorrect variables, or require fixes to be applied across many classes where they might not be implemented properly.

Don’t tell people about yourself (shy)

In object-oriented design this means that an object should not expose how it does things, it may expose a method that gives you a result saying that it did it. Outside of a class used to transport data around most classes should not expose their internal attributes to client classes.

Back to top

Tell don’t ask

Procedural code gets information then makes decisions. Object-oriented code tells objects to do things.
— Alec Sharp

Objects should be told what to do – not asked about their state and then the client object decides, procedural code uses state like this. This causes strong coupling between objects and makes testing and refactoring a nightmare. This also avoids the “train wreck” scenario where you end up with long strings of method calls, e.g.

project.client.calls.first.message

See the following links for more discussion on this:

Tell don’t ask

Mock objects and tell don’t ask

Back to top

The law of Demeter

This came out of a project on object-oriented design called Demeter, it is a more formal way of talking about tell don’t ask. It is also described as the principle of least knowledge. A caricature of this is to say that there should never be more than one ‘.’ in the string of method calls; of course common sense says this is a guideline rather than a hard and fast approach. In essence constructing helper methods to mask out long chains and make it clear what you are doing.

In summary:

More formally, the Law of Demeter for functions requires that a method M of an object O may only invoke the methods of the following kinds of objects:

1. itself
2. M’s parameters
3. any objects created/instantiated within M
4. O’s direct component objects

It is explained here

A common mistake is discussed here; one should endeavour to delegate behaviour not attributes

Back to top

Object Composition

It is often better to compose an object from others rather than extending something and giving it too much to do or overriding the default constructor and creating a hybrid object in a non-standard way.

Ruby-specific considerations

Reusability in Ruby is not just through inheritance. It also works through modules. You need to think hard about using modules or inheritance and be able to justify why you chose one over the other. There are no right answers but don’t just blindly do what you did last time. Sometimes modules can be hard to understand and debug, and even hard to find if they’re in, say, a library directory outside of the main code base.

Back to top

Replace case statement with behaviour

Long case statements are not true object code. Depending upon the circumstances there are several ways to refactor this:

  1. Use a Hash
  2. If an object needs to be instantiated or a method called then use the technique in 1 to call a lambda function (created using create_function if you’re a PHP head) that will return the object.
  3. Any long list, e.g. of return codes, should be held as a Hash and used to return the associated value directly.

A long case statement indicates the target object is not broken up into grouped behaviours correctly – the client object should be calling a method to do what it needs directly and the case statements would be unnecessary.

Testing code written this way is far easier. The dispatching array needs to be set up correctly and each single method can be tested independently. Testing a large case statement is almost impossible. The behaviour in each case needs to be put into its own method.

Back to top

Fat models, thin controllers in MVC

When using the Model/View/Controller architecture any complex work should be done by the model code. This encourages reuse and moves the controller to just controlling and dispatching.

Back to top

Short methods and classes

Methods should not be in excess of about 25 lines including comments. A class should have its responsibilities well-defined and not have more than ten or so methods.

Back to top

General points

Magic numbers

There should be no references to numbers or stages that aren’t given symbolic names to make the code clear. This also means method names, e.g. fred_12321 is not helpful.

Back to top

Let boolean be boolean

Consider the following

isMyNumber = (defined?(biff) && boff == 3) ? true : false;

There is no point in testing a boolean result to return a boolean. (I also have a personal dislike of the ternary operator, because it encourages this kind of sloppiness, think!).

Back to top

No surprises

If there is an accepted way of doing something, e.g. a class constructor calls the super class method, do not create non-standard ways of doing things. If something has to be done in a non-standard way there must be a comment to that effect.

Back to top

Meaningful comments

An example of a meaningless comment is:

-- Open cursor
open cursor x for ...

A comment that just says what the code is doing is a waste of time.

Another example is:

/**
 * Enter description here...
*/

Enter the description or remove the comment. I don’t care if your code generator puts it in, it’s garbage.

Back to top

Exceptions

try{
 someDodgyOperation() ;
} catch( e Exception ){
  return null ;
}

Just don’t, ok? Handle the exception, or at least log it somewhere to give the next poor soul a chance of finding where the problem is. In Java you’ll get a null pointer exception somewhere probably completely unrelated to where the problem actually is, same in Ruby or any language you care to name that has exceptions, just don’t do this.

Back to top

Databases

No filtering of result sets from the database

This involves getting the database to do the work – there should be no need to filter result sets. Retrieving more data than needed has several deleterious effects:

  1. Data sets need to be passed through several layers to get to the calling module – the less data that needs to be marshalled and transmitted the better.
  2. Retrieving large sets and filtering for a few records can easily cause locking and contention problems.
  3. Testing may be difficult because the PHP instance may run out of memory if the sets are not released quickly enough to be garbage collected.

In essence: make sure the database returns as little as possible and keys and relationships are properly policed.

Back to top

Generic database code

If the where clause changes but the columns selected do not, the where clause should be made into a something that can be set. This reuses the method and the return bindings, meaning they only have to be changed in one place

Back to top

Do not ‘select *’ from tables

Under no circumstances should * be selected from a table:

  1. All of the columns will be selected regardless of the need for them – see the discussion in in the above section about this.
  2. The values returned are dependent on the default order the columns appear in in the database and that is a function of how they were created. There is no guarantee that, for operational reasons, columns in your development and production environments were created in the same order, an RFC could have been applied in a different order – this will break and be very hard to debug.

Ruby on Rails Active Record fixes the ordering problem. But if you have several K of text you don’t use often, it won’t hurt to think about not retrieving it.

Back to top

HTML and CSS

HTML code should not use deprecated tag attributes, e.g. bgcolor, or valign. Styling should be done through CSS.

Sizes of elements, e.g. tables, should be done through CSS also. This allows a DRY approach to styling output.

CSS should not be in line but in its own sheets to promote reusablility and allow the web browser to cache it. It also allows restyling work to be done with a minimum of fuss.

HTML should be conforming, e.g. attributes should be inside double or single quotes and lower case as recommended by the W3C

HTML 5 may change the definition of conforming HTML, because there’s a lot less nonsense in there.

JavaScript

JavaScript should be in separate files, if it needs PHP then the web server will sort this out. If the script is less than twenty lines or so then inline is fine, otherwise it should be handled in its own file. This is to promote reusability of the scripts and allow the web browser the chance to cache the JavaScript.

Most of the comments about code in the above section also apply to Javascript.

Back to top

Recommendations for fixing “unstable” code

In order to change code you must be able to say that your changes have not broken any existing assumptions. This means that you need a reasonably complete test suite to begin with.

Creating such a test suite, and the culture that keeps it up to date, is a sound investment in future. When bugs are encountered then a new test should be created that exposes this error – then it is fixed. The whole suite running ensures that no new bugs have been introduced.

There is a good article (and book) explaining this in more depth

Back to top

Continuous testing

This does not require a large amount of resources and can be built up over time. It needs to be in place before any refactoring takes place. Normal practice is to keep the testing running and ensure that refactoring has not broken any existing functionality.

Deploys are automated and run the test suite against a test database before they happen. Any failure will stop deployment. (in my dreams)

Back to top

Review of Seth Godin’s Linchpin: Are You Indispensable?

Linchpin: Are You Indispensable?Linchpin: Are You Indispensable? by Seth Godin
My rating: 5 of 5 stars
Seriously, if you want to know why your children’s school seems to not be teaching them to think, if you want to know why you hate your job, read this book.
Our entire education system is built around creating good factory workers, who have no initiative and do what they’re told. You may sit in a call centre or push numbers into a computer all day – but it’s still a factory, think about it. Guess what – the factories are all gone or on their way, and cost-cutting means that you can’t compete with folk from other countries. The race to the cheapest is one you can’t win. The race to the most useful, caring, innovative – well, you’re competing with the cheapest, they’re going to lose.
Enter the linchpin – someone who adds value, who cares about doing a good job, who thinks about how to get things done more quickly and to a higher standard, a game changer. Your boss will employ a competent drone if no-one else is available, but would prefer a linchpin. Someone who is difficult to replace. If you don’t want to be easy to replace then read this book and follow Seth’s advice.
The latter half of the book gives a whistle-stop tour of the human brain and goes into some detail about how the “lizard brain” tends to sabotage the thinking brain and choose short term comfort over long term success. It needs to be tricked to get out of the way and allow you to succeed. Godin talks about how the lizard brain made him stop writing the book several times, because it was hard work. The paradox is the lizard brain likes comfort, but is scared of success.
Read this book if you want to escape the whole post-industrial “my job went to India” fear and find your way to a future where you enjoy what you do.
Just read it, it’s the 21st century equivalent to How to Win Friends & Influence People, (which you should read as well).

View all my reviews

Imported Comments:

ChuckJHardy

Reading this at the moment – really enjoying it, thanks for the review

Review of Tom Peters’ The Circle of Innovation: You Can’t Shrink Your Way to Greatness

The Circle of Innovation: You Can't Shrink Your Way to GreatnessThe Circle of Innovation: You Can’t Shrink Your Way to Greatness by Tom Peters
My rating: 5 of 5 stars
Had this book on tape and listened to it many times back in the early noughties. I was writing a blog post about “The Agile Heart” (http://goo.gl/aBCae) and quoted from it, so I got a second-hand copy from Amazon to verify the quote, my tape player having gone the way of all flesh a while ago. Still need to change the quote, but there you go.

Thing is, even now, nearly 15 years after it was first published, it’s a gem. The style is designed to look like his presentations, with a slide-like set of images setting up a proposition and then some discussion about the ideas. I’ve also been reading Linchpin: Are You Indispensable? and they cover a lot of similar ground. Peters’ take is more based on subverting the traditional workplace, “brand you”, “making everything a project”, “making where you work into a company in its own right”. Godin talks about the kinds of behaviour and attitude you need to make what Peters talks about become a reality. The two books complement each other. I think Linchpin is an essential read for anyone who cares about where we are today, but Peters’ book gives some historical context.

The subtitle you can’t shrink your way to greatness is a polemic with the late 90’s obsession with the bottom line: how big corporations were doing a slash and burn on their workforce and their working conditions to drive profit up. But if you race to the bottom you end up competing with people who are much poorer than you are and will do the same low-value work for less in a different country. You lose, the whole enterprise loses, and that’s it. This is also the theme of Linchpin. Two recessions later we are still learning the same lessons, funny that. Those lessons being that creativity and what Peters terms “emotional labour” (as in giving it some heart and caring about it) will keep you fed, but charging to the bottom won’t.

Both authors say that if you’re stuck somewhere you can’t do “emotional labour” or become a Linchpin – move on. Good advice.

View all my reviews