views:

276

answers:

6

Being a Java developer in an agile development cycle, I have learnt that it is essential to make sure I design my classes in a manner that I can refactor them easily without much of a pain. I want to know, what are the best practices that you follow in your daily design/development cycle that helps you to perform refactoring easily.
For example, I know that I should hide the implementation details behind an interface. So that event if I am changing the implementation tomorrow, I am not disturbing the client code which consumes this APIs. Similarly I should use “factory design pattern” wherever possible so that the change of implementation classes can be controlled from one factory class rather than find out all the places and change them.
Similarly I would like to know what all best practices that you are following which will help me.

+3  A: 

You should have a bunch of unit tests that can prove the codebase was not (inadvertantly) affected each time you refactor.

+13  A: 

Use TDD. Seriously. Writing tests while you write your classes forces you to think about how they will be used by others. You'll tend to write better abstractions when you do this.

Entire books have been written on this subject:

  • Code Complete
  • Working Effectively with Legacy Code
  • Clean Code
  • Refactoring
  • Refactoring to Patterns
  • Agile Principles, Patterns and Practices

Each one of these touches on this subject in its own unique way.

codeelegance
I would like to add TDD by Example from Kent Bach, and more up-to-date, Lasse Koskela's Test Driven. Even then, your list is a must.
Adeel Ansari
+1  A: 

Don't copy and paste (also known as DRY: Don't Repeat Yourself). When any given functionality is implemented in no more than one place, then it's easier to reimplement that functionality.

ChrisW
+1  A: 

My answer relates to what constitutes a good result after the refactoring.

Methods should be...

  • short - they should never be more than a screen full of code.
  • do at most one thing:
    • calculate a value
    • test and branch
    • log
    • guard and throw exception
  • have a single exit point - my reasoning..
    • If you later need to come back and do something to the return value, it all happens in one spot.
    • Easy to set a breakpoint and inspect the returned value...
    • Amounts to DRY.
mP
The single exit point should not be a hard and fast rule - see http://stackoverflow.com/questions/36707/should-a-function-have-only-one-return-statement
Tom Leys
And I tend to agree with Tom here.
Adeel Ansari
Ah - the if parameter fails or some other pre condition fails some test return... Well i dont have space here to elaborate my comments but thats prolly one of the few exceptions to the rule.
mP
Many of the samples given in 36707 dont exist if one uses exceptions etc - especially the 5-6+ levels of nested ifs and different error codes - or breaks up code into many smaller methods.
mP
I'm with Tom, too. Keeping your methods short obviates all of the reasons for a single exit point. When everything is ten lines or less, it's just not that hard to spot the returns. Logic that needs special end-processing should be wrapped up in an end-processing function, imnsho.
Carl Manaster
Multiple returns is a form of copy-and-paste. When one needs to adjust the return value and one has many returns, you are violating DRY.
mP
Exactly my thoughts. +1.
Christian Madsen
+1  A: 

I would recommend picking up two books if you're going to be doing a lot of java.

I'd recommend Effective Java and Design Patterns: Elements of Reusable Object-Oriented Software.

PSU_Kardi
+2  A: 

This may sound like a bit of circular reasoning but I find it to be true in my experience:

Refactor it a lot.

Many of the answers here (especially a strong test suite) are great advice and help a lot, so let me be clear in saying that I'm all for those pre-emptive measures as well.

At first, it's always easy to change (when it's small). Then, you generally have to go through a few bouts of tough refactoring before you have a breakthrough and get something that is really supple.

TM
I think it's apocryphal, but I've heard of a college math course that is its own prerequisite. This is something like that... But I agree with you. What keeps code malleable is refactoring.
Carl Manaster