Class Name :
Classes and objects should have noun or noun phrase names like Customer, WikiPage, Account, and
AddressParser. Avoid words like Manager, Processor, Data, or Info in the name of a class. A class name
should not be a verb.
Method Name :
Methods should have verb or verb phrase names like postPayment, deletePage, or save. Accessors, mutators,
and predicates should be named for their value and prefixed with get, set, and is according to the javabean
standard.
Don't Be Cute :
If names are too clever, they will be memorable only to people who share the author’s sense of humor, and
only as long as these people remember the joke. Will they know what the function named HolyHandGrenade is
supposed to do? Sure, it’s cute, but maybe in this case DeleteItems might be a better name. Choose clarity
over entertainment value.
Say what you mean. Mean what you
say.
Final Words :
The hardest thing about choosing good names is that it requires good descriptive skills and shared cultural
background. This is a teaching issue rather than a technical, business, or management issue. As a result,
many people in this field don’t learn to do it very well.
Exercise-1 :
Read the below code snippet and honestly talk to yourself if you understood the working of the code.
public static String renderPageWithSetupsAndTeardowns( PageData pageData, boolean isSuite ) throws Exception { boolean isTestPage = pageData.hasAttribute("Test"); if (isTestPage) { WikiPage testPage = pageData.getWikiPage(); StringBuffer newPageContent = new StringBuffer(); includeSetupPages(testPage, newPageContent, isSuite); newPageContent.append(pageData.getContent()); includeTeardownPages(testPage, newPageContent, isSuite); pageData.setContent(newPageContent.toString()); } return pageData.getHtml(); } Listing 1.1
The above code is refactored code, priorly it was like depicted below, now read that too and take an honest opinion of yourself if you understanding it or not.
public static String testableHtml( PageData pageData, boolean includeSuiteSetup ) throws Exception { WikiPage wikiPage = pageData.getWikiPage(); StringBuffer buffer = new StringBuffer(); if (pageData.hasAttribute("Test")) { if (includeSuiteSetup) { WikiPage suiteSetup = PageCrawlerImpl.getInheritedPage( SuiteResponder.SUITE_SETUP_NAME, wikiPage ); if (suiteSetup != null) { WikiPagePath pagePath = suiteSetup.getPageCrawler().getFullPath(suiteSetup); String pagePathName = PathParser.render(pagePath); buffer.append("!include -setup .") .append(pagePathName) .append("\n"); } } WikiPage setup = PageCrawlerImpl.getInheritedPage("SetUp", wikiPage); if (setup != null) { WikiPagePath setupPath = wikiPage.getPageCrawler().getFullPath(setup); String setupPathName = PathParser.render(setupPath); buffer.append("!include -setup .") .append(setupPathName) .append("\n"); } } buffer.append(pageData.getContent()); if (pageData.hasAttribute("Test")) { WikiPage teardown = PageCrawlerImpl.getInheritedPage("TearDown", wikiPage); if (teardown != null) { WikiPagePath tearDownPath = wikiPage.getPageCrawler().getFullPath(teardown); String tearDownPathName = PathParser.render(tearDownPath); buffer.append("\n") .append("!include -teardown .") .append(tearDownPathName) .append("\n"); } if (includeSuiteSetup) { WikiPage suiteTeardown = PageCrawlerImpl.getInheritedPage( SuiteResponder.SUITE_TEARDOWN_NAME, wikiPage ); if (suiteTeardown != null) { WikiPagePath pagePath = suiteTeardown.getPageCrawler().getFullPath (suiteTeardown); String pagePathName = PathParser.render(pagePath); buffer.append("!include -teardown .") .append(pagePathName) .append("\n"); } } } pageData.setContent(buffer.toString()); return pageData.getHtml(); } Listing 1.2
The point I want to convey here is that this is the power of functions.
Small! :
The first rule of functions is that they should be small. The second rule of functions is that they should
be smaller than that. This is not an assertion that we can justify. The author has nearly 40 years of
experience in programming, who has written functions that are 3000 lines long and functions that are 20 to
30 lines long, Author says that from long trial and error I came to one conclusion that functions should be
very small. How short should your functions be? They should usually be shorter than Listing 1.1 Indeed,
Listing 1.1 should be shortened to Listing 1.3
public static String renderPageWithSetupsAndTeardowns( PageData pageData, boolean isSuite) throws Exception { if (isTestPage(pageData)) includeSetupAndTeardownPages(pageData, isSuite); return pageData.getHtml(); } Listing 1.3
Do One Thing :
It should be very clear that Listing 1.2 is doing lots more than one thing. It’s creating buffers, fetching
pages, searching for inherited pages, rendering paths, appending arcane strings, and generating HTML, among
other things. Listing 1.2 is very busy doing lots of different things. On the other hand, Listing 1.3 is
doing one simple thing. It’s including setups and teardowns into test pages. The following advice has
appeared in one form or another for 30 years or more.
FUNCTIONS SHOULD DO ONE THING. THEY SHOULD DO IT WELL. THEY SHOULD DO IT
ONLY.
Use Descriptive Names :
In Listing 1.1 I changed the name of our example function from testableHtml to SetupTeardownIncluder.render.
This is a far better name because it better describes what the function does. I also gave each of the
private methods an equally descriptive name such as isTestable or includeSetupAndTeardownPages. It is hard
to overestimate the value of good names. Remember Ward’s principle: “You know you are working on clean code
when each routine turns out to be pretty much what you expected.” Half the battle to achieving that
principle is choosing good names for small functions that do one thing. The smaller and more focused a
function is, the easier it is to choose a descriptive name.
Don’t be afraid to make a name long. A long descriptive name is better than a short enigmatic name. A long descriptive name is better than a long descriptive comment. Use a naming convention that allows multiple words to be easily read in the function names, and then make use of those multiple words to give the function a name that says what it does.
Function Arguments :
The ideal number of arguments for a function is zero (niladic). Next comes one (monadic), followed closely
by two (dyadic). Three arguments (triadic) should be avoided where possible. More than three (polyadic)
require very special justification—and then shouldn’t be used anyway.
Argument Objects :
When a function seems to need more than two or three arguments, some of those arguments likely ought to be
wrapped into a class of their own. Consider, for example, the difference between the two following
declarations:
Circle makeCircle(double x, double y, double radius); Circle makeCircle(Point center, double radius);Reducing the number of arguments by creating objects out of them may seem like cheating, but it’s not. When groups of variables are passed together, the way x and y are in the example above, they are likely part of a concept that deserves a name of its own.
Have No Side Effects :
Side effects are lies. Your function promises to do one thing, but it also does other hidden things.
Sometimes it will make unexpected changes to the variables of its class. Sometimes it will take them to the
parameters passed into the function or to system globals. In either case, they are devious and damaging
mistruths that often result in strange temporal couplings and order dependencies.
Consider, for example, the seemingly innocuous function in Listing 2.1. This function uses a standard
algorithm to match a userName to a password. It returns true if they match and false if anything goes wrong.
But it also has side effects. Can you spot it?
public class UserValidator { private Cryptographer cryptographer; public boolean checkPassword(String userName, String password) { User user = UserGateway.findByName(userName); if (user != User.NULL) { String codedPhrase = user.getPhraseEncodedByPassword(); String phrase = cryptographer.decrypt(codedPhrase, password); if ("Valid Password".equals(phrase)) { Session.initialize(); return true; } } return false; } } Listing 2.1
The side effect is the call to Session.initialize(), of course. The checkPassword function, by its name, says that it checks the password. The name does not imply that it initializes the session. So a caller who believes what the name of the function says runs the risk of erasing the existing session data when he or she decides to check the validity of the user.
This side effect creates a temporal coupling. That is, checkPassword can only be called at certain times (in other words, when it is safe to initialize the session). If it is called out of order, session data may be inadvertently lost. Temporal couplings are confusing, especially when hidden as a side effect. If you must have a temporal coupling, you should make it clear in the name of the function. In this case, we might rename the function checkPasswordAndInitializeSession, though that certainly violates “Do one thing.”
How do we write functions that people love? :
Writing software is like any other kind of writing. When you write a paper or an article, you get your
thoughts down first, then you massage it until it reads well. The first draft might be clumsy and
disorganized, so you wordsmith it and restructure it and refine it until it reads the way you want it to
read.
When I write functions, they come out long and complicated. They have lots of indenting and nested loops. They have long argument lists. The names are arbitrary, and there is duplicated code. But I also have a suite of unit tests that cover every one of those clumsy lines of code.
So then we should massage and refine that code, splitting out functions, changing names, eliminating duplication. We should shrink the methods and reorder them. Sometimes we break out whole classes, all the while keeping the tests passing. In the end, we wind up with functions that follow the rules I’ve laid down in this chapter. We don’t write them that way to start. We don’t think anyone could.
Source : Clean Code : A Handbook of Agile Software by Martin Fowler