Monday, 20 October 2008

Clean Code By Robert C. Martin - Part3

Couple of Days back i started reading Clean Code By Robert C. Martin

I wanted to share few important quotations i found from the next 2 chapters of the book (5-6).

1) Variable Declarations.
Variables should be declared as close to their usage as possible.Because our functions are very short, local variables should appear a the top of each function, as in this longish function from Junit4.3.1.


private static void readPreferences() {
InputStream is= null;
try {
is= new FileInputStream(getPreferencesFile());
setPreferences(new Properties(getPreferences()));
getPreferences().load(is);
} catch (IOException e) {
try {
if (is != null)
is.close();
} catch (IOException e1) {
}
}
}



Control variables for loops should usually be declared within the loop statement, as in this cute little function from the same source.

2) Instance variables, on the other hand, should be declared at the top of the class. This should not increase the vertical distance of these variables, because in a well-designed class, they are used by many, if not all, of the methods of the class.

3) Vertical Ordering

In general we want function call dependencies to point in the downward direction. That is,a function that is called should be below a function that does the calling.This creates a nice flow down the source code module from high level to low level.

4) The Law of Demeter

There is a well-known heuristic called the Law of Demeter that says a module should not know about the innards of the objects it manipulates. Objects hide their data and expose operations. This means that an object should not expose its internal structure through accessors because to do so is to expose, rather than to hide, its internal structure.

More precisely, the Law of Demeter says that a method f of a class C should only call the methods of these:

• C
• An object created by f
• An object passed as an argument to f
• An object held in an instance variable of C

The method should not invoke methods on objects that are returned by any of the allowed functions. In other words, talk to friends, not to strangers.

The following code appears to violate the Law of Demeter (among other things) because it calls the getScratchDir() function on the return value of getOptions() and then calls getAbsolutePath() on the return value of getScratchDir().


final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();


5) Train Wrecks

This kind of code is often called a train wreck because it look like a bunch of coupled train cars. Chains of calls like this are generally considered to be sloppy style and should be avoided. It is usually best to split them up as follows:

Options opts = ctxt.getOptions();
File scratchDir = opts.getScratchDir();
final String outputDir = scratchDir.getAbsolutePath();

Are these two snippets of code violations of the Law of Demeter? Certainly the containing module knows that the ctxt object contains options, which contain a scratch directory, which has an absolute path. That’s a lot of knowledge for one function to know. The calling function knows how to navigate through a lot of different objects.

Whether this is a violation of Demeter depends on whether or not ctxt, Options, and ScratchDir are objects or data structures. If they are objects, then their internal structure should be hidden rather than exposed, and so knowledge of their innards is a clear violation of the Law of Demeter. On the other hand, if ctxt, Options, and ScratchDir are just data structures with no behavior, then they naturally expose their internal structure, and so Demeter does not apply.

6) Objects expose behavior and hide data. This makes it easy to add new kinds of objects without changing existing behaviors. It also makes it hard to add new behaviors to existing objects. Data structures expose data and have no significant behavior. This makes it easy to add new behaviors to existing data structures but makes it hard to add new data structures to existing functions.

In any given system we will sometimes want the flexibility to add new data types, and so we prefer objects for that part of the system. Other times we will want the flexibility to add new behaviors, and so in that part of the system we prefer data types and procedures.Good software developers understand these issues without prejudice and choose the approach that is best for the job at hand.

About the Author

Robert C. Martin is a principal in a consulting firm named Object Mentor, based in Illinois. Object Mentor provides software leadership services to the global community. They use XP process improvement, OO design consulting, and the skills that come with experience to help companies get their projects done.

0 comments: