Archive for the ‘ Code Smell ’ Category

Open/Closed Principle

The entities within your software (classes, functions, etc.) should be open for extension (and parameterisation), but closed for modification.  Extension in this context means adding/changing behaviour.

You should structure your application so that you can add new functionality with minimal changes to existing code.  Interfaces are your friend along with the Single Responsibility principle.

If the entities within your software only do one thing you will move towards achieving true Open/Closed nirvana.  Each of your classes should implement a cohesive set of related functions.  If you find functionality within a class that does not fit the name of the class consider moving it to another class.

If you are creating abstractions, don’t let the consumer of your abstraction depend on anything but the public contract you provide for the abstraction.

Two things to watch out for that indicate you aren’t following the Open/Closed Principle are:

  • A class that uses another class and embeds knowledge about the internal workings of its dependency (making assumptions about what is returned from methods).
  • A class that uses an abstraction has to downcast to a specific subclass in one section.

Think of Open/Closed as a direction rather than as an end goal of your design.  As you head down this path constantly check that you are still meeting the other principles such as KISS and YAGNI.

There is a caveat in that the more a class is used the more the Open/Closed principle applies.

The more a class is reused in the code base, the more stable it becomes.  As a class becomes more stable it becomes safer to depend on it leading to it being used more.  The more a class is reused throughout the codebase, the more important it becomes that the class adheres to the Open/Closed Principle so that small changes don’t have large impacts across the codebase.  Libraries, component based software, frameworks and APIs get lots of value from having classes adhere to the Open/Closed Principle.

References

http://www.artima.com/weblogs/viewpost.jsp?thread=331531

http://msdn.microsoft.com/en-us/magazine/cc546578.aspx

http://joelabrahamsson.com/entry/the-open-closed-principle-a-real-world-example

http://c2.com/cgi/wiki?OpenClosedPrinciple

You Aren’t Going To Need It (YAGNI)

This is from extreme programming – don’t add functionality until you need it.  Resist the urge to add things that you might need in the future.  Only implement things when you actually need them, never when you are only foreseeing the need for them.

Usually if you start adding things you don’t need at this point in time it is a sign that your focus has drifted from the actual problem you are trying to solve.

Remember that your time is a precious resource, to add the unnecessary feature you are going to need to take time away from the functionality that you need to be implementing.

This directly impacts the quality of your solution, increases code bloat, makes refactoring harder, and can in some cases restrict your ability to implement a necessary feature in the future.

From a testing point of view, until a feature is actually needed it is difficult to define what it should do and how it should be tested.  It might not even be needed at all or the actual feature needed might be completely different to what you implemented.

Then you have the worst case, adding the new feature leads to thinking of more new features that should be added, which are then added, creating a snowball effect also referred to as creeping featurism.

One of the benefits of only implementing new features when you need them is that your code remains simpler and simpler code is easier to maintain and refactor.

Remember that if you need to implement the feature in the future, provided you are following the appropriate practices, it should be just as easy to add it in the future when it is needed as it would be to add it now when it isn’t needed.

References

http://www.artima.com/weblogs/viewpost.jsp?thread=331531

http://en.wikipedia.org/wiki/You_ain’t_gonna_need_it

http://c2.com/xp/YouArentGonnaNeedIt.html

Keep It Simple, Stupid! K.I.S.S.

This principle is self descriptive.  As a software developer, reducing complexity and providing the simplest solution should always be a key goal.  Simple code is easier to test, faster to write, has fewer bugs and is generally easier to modify and understand.

This principle can be found represented in other statements throughout history:

  • Occam’s Razor: “simpler explanations are, other things being equal, generally better than more complex ones”
  • Albert Einstein: “everything should be made as simple as possible, but no simpler”
  • Leonardo Da Vinci: “Simplicity is the ultimate sophistication”
  • Antoine de Saint-Exupery: “It seems that perfection is reached not when there is nothing left to add, but when there is nothing left to take away”

Some examples of KISS not being followed in Software development are

  • Instruction Creep: This occurs when instructions increase over time in both size and number until they are unmanageable.  An example of this is a class file which is 5000 lines long or a single method which is 500 lines long but only started out at 30 lines of code.
  • Function Creep: Occurs when parts of the software designed for a specific purpose end up serving another purpose for which that code was never intended to perform.
  • Feature Creep: The ongoing addition of new features to a product that go beyond the basic function of the product resulting in over-complication.

How can you keep your software simple? Break problems down into the smallest possible pieces and then develop those pieces.  If you find yourself writing lots of exception cases when implementing a piece then probably you need to break that piece down further still.

Here are some things you might notice happening if you apply KISS to your day to day coding

  • Your code quality will be higher
  • You will be solving problems faster
  • Complex problems will be solved in fewer lines of code.
  • Your code should be easier to maintain
  • It will be easier for others to pick up your code and understand exactly what it does.

To start applying KISS to your day to day development, here are some steps that you can take

  • Break each task down into smaller tasks no more than 1 days effort, ideally a half day.
  • Take each problem and break it down into smaller problems.
  • Method size should be at most 30 to 40 lines.  Each method should be solving a single small problem (only have one purpose).
  • If a method contains many conditions refactor those out into smaller methods.
  • Each class should only have a single responsibility (this is its own principle).  Look at each method in a class and ask yourself “does it belong in this class? or should it be in its own class?”
  • First solve the problem and then implement the solution.  If you need to play with code to come up with a solution that is fine – writing unit test is a good way to think through a problem with the “how would I test this?” question.
  • Learn to love deleting code and refactoring.  You will send a lot of time refactoring while distilling your solution down to the simplest possible solution.

For more information on the benefits of KISS and ways to include it in your day to day development Richy Gerard has publish an interesting article on iwannabeageek.com.

References

http://www.artima.com/weblogs/viewpost.jsp?thread=331531

http://en.wikipedia.org/wiki/KISS_principle

http://en.wikipedia.org/wiki/Scope_creep

http://techcrunch.com/2009/04/28/keep-it-simple-stupid/

http://www.iwannabeageek.com/posts/kiss-keep-it-simple-stupid

Abstraction Principle

This principle goes with the DRY principle.  Within the application, each piece of functionality should be implemented in only in a single place.  Where similar functions are performed by disparate pieces of code it is better to have a single implementation and abstract out the differences.  The DRY principle is actually a generalisation of the Abstraction Principle.

Abstraction is the suppression of detail and a focus on concept.  The emphasis is placed on what an object is or does rather than the implementation.  This makes abstraction the primary means for managing complexity in large programs.

One of caveats of using Abstractions is do not introduce an abstraction unless you are going to use it more than once.  Do the simplest thing first.

One thing I have picked up from designing API’s that applies to abstractions in general is that you won’t iron out the majority of the issues with your abstraction until you have used it in anger in at least three different scenarios.

A common way to achieve reuse of an abstraction is to parameterise the implementation making use of interfaces to allow you to apply the abstraction to different implementations.

To explain Abstraction in one sentence just remember it allows you to answer “how is this done” with “I don’t care”.

Well this is a topic I will need to come back and redo once I’ve gotten better at getting past the 250 word barrier on my blog posts.  It has been a challenge stretching this topic past 250 words and in the end I only got there by talking about how hard it was to stretch the topic to 250 words. 😉

Hopefully the topic I chose tomorrow isn’t as hard to get past 250 words with. 🙂

References

http://www.artima.com/weblogs/viewpost.jsp?thread=331531

http://en.wikipedia.org/wiki/Abstraction_principle_(programming)

http://www.codeproject.com/KB/architecture/OOP_Concepts_and_manymore.aspx

DRY – Don’t Repeat Yourself

Also known as Duplication Is Evil (DIE)

This is the basis of all good programming, if you find yourself repeating code or concepts it is time to think about creating a new abstraction.

How does duplicate code come into existance?

Here are some ways that spring to mind:

  • Copy and paste.  The developer is on a tight deadline and needs xyz functionality in the new widget and its already in an existing widget.  The fast path to the result is copy and paste. Sometimes with a TODO to come back later and clean it up.
  • Easy and Fast.  It isn’t intellectually taxing to identify code that already does what you want, copy it, alter it slightly to suit the situation and then move onto the next task.  Duplicating existing code is the path of least resistance.
  • Didn’t realise the functionality already existed.  This could be two developers working on different features or one developer not realising they implemented the feature already several months back.
  • Boilerplate. Some frameworks and APIs, both in house and third party, require boilerplate code to be repeatedly re-written for each use of the framework/API.  This also falls under Copy and Paste.
  • Identical Concept – slightly different implementation.  Instead of enhancing the original implementation to cater for more scenarios a duplicate but slightly different implementation is created.

I am sure that there are a lot of other reasons and justifications for duplicating code – if you can think of some feel free to add them in the comments.

What are the down sides of code duplication? Each line of duplicated code is an increase in technical debt through code size, ongoing maintenance cost, and an increase in the complexity of the software.

For example: the same bug might exist in a method that has been duplicated 3 times.  Three different developers fix the bug in slightly different ways introducing three different side effects.

On of the easiest ways to improve the quality of code and ease of maintenance is to refactor out duplicate code.

The challenge though is detecting the duplicate code.  A couple of tools which can do this for you are

There are many more tools out there – a quick Google search will turn up other alternative tools.

If you have an automated build process build the tooling into your process and regularly review the reports it generates.  Make it a point to regularly go through and clean up duplicated code.  Even if you don’t have an automated build process you can manually run the tools across your code base at regular intervals to highlight duplicate code that can be cleaned up.

You get bonus points if you catch the duplicate code as you are working on new features, fixing defects, or reviewing another developer’s code.  As these are some of the least expensive times to find the duplicate code.

References

http://en.wikipedia.org/wiki/Don%27t_repeat_yourself

http://www.artima.com/weblogs/viewpost.jsp?thread=331531

http://en.wikipedia.org/wiki/Duplicate_code#Detecting_duplicate_code

http://www.solidsourceit.com/blog/?tag=code-duplication