Vertical Formatting
1. Significant systems can be created with classes up to 200 lines long (maximum 500 lines).
(You can reach average values for some global projects in the book.)
2."Variable Declarations"
Local variables should appear a the top of each function.
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) {
}
}
}
|
3."Instance variables"
"The common convention in Java, however, is to put them all at the top of the class."
"The important thing is for the instance variables to be declared in one well-known place. Everybody should know where to go to see the declarations."
In the below example, you see two instance variables declared in the middle of the class. It is hard to realize where the declarations are.
public class public class TestSuite implements Test {
static public Test
createTest(Class<? extends TestCase> theClass, String name)
{
...
}
public static Constructor<?
extends TestCase>
getTestConstructor(Class<? extends TestCase> theClass)
throws NoSuchMethodException {
...
}
public static Test warning(final String message) {
...
}
private static String
exceptionToString(Throwable t) {
...
}
private String fName;
private Vector<Test>
fTests=
new
Vector<Test>(10);
public TestSuite() {
}
public TestSuite(final Class<? extends TestCase>
theClass) {
...
}
public TestSuite(Class<? extends TestCase>
theClass, String name) {
...
}
... ... ... ... ...
}
|
4."Dependent Functions."
"If one function calls another, they should be vertically close, and the caller should be above the callee, if at all possible.This gives the program a natural flow."
public class WikiPageResponder
implements SecureResponder
{
protected WikiPage page;
protected PageData pageData;
protected String pageTitle;
protected Request request;
protected PageCrawler
crawler;
public Response makeResponse(FitNesseContext
context, Request request)
throws Exception {
String pageName =
getPageNameOrDefault(request, "FrontPage");
loadPage(pageName, context);
if (page == null)
return notFoundResponse(context,
request);
else
return
makePageResponse(context);
}
private String getPageNameOrDefault(Request
request, String defaultPageName)
{
String pageName =
request.getResource();
if (StringUtil.isBlank(pageName))
pageName =
defaultPageName;
return pageName;
}
protected void loadPage(String
resource, FitNesseContext context)
throws Exception {
WikiPagePath path = PathParser.parse(resource);
crawler =
context.root.getPageCrawler();
crawler.setDeadEndStrategy(new VirtualEnabledPageCrawler());
page = crawler.getPage(context.root,
path);
if (page != null)
pageData = page.getData();
}
private Response notFoundResponse(FitNesseContext
context, Request request)
throws Exception {
return new NotFoundResponder().makeResponse(context,
request);
}
private SimpleResponse
makePageResponse(FitNesseContext context)
throws Exception {
pageTitle = PathParser.render(crawler.getFullPath(page));
String html = makeHtml(context);
SimpleResponse response =
new SimpleResponse();
response.setMaxAge(0);
response.setContent(html);
return response;
}
}
|
5."Conceptual Affinity."
"The stronger that affinity, the less vertical distance there should be between them."
The following functions call each other, so the closer to the vertical is better.
public class Assert {
static public void assertTrue(String
message, boolean condition) {
if (!condition)
fail(message);
}
static public void assertTrue(boolean condition) {
assertTrue(null, condition);
}
static public void assertFalse(String
message, boolean condition) {
assertTrue(message,
!condition);
}
static public void assertFalse(boolean condition) {
assertFalse(null, condition);
}
}
|
Horizontal Formatting
6. A good character limit on a line is 100-120.
"I used to follow the rule that you should never have to scroll to the right."
7."Horizontal Openness and Density"
Surround the assignment operators with white space.
Don't put spaces between the function and the parenthesis.
private void measureLine(String line) {
lineCount++;
int lineSize = line.length();
totalChars += lineSize;
lineWidthHistogram.addLine(lineSize, lineCount);
recordWidestLine(lineSize);
}
|
public static double root2(int a, int b, int c) {
|
8. "Horizontal Alignment"
The below kind of alignment is not useful.
public class FitNesseExpediter
implements ResponseSender
{
private Socket
socket;
private InputStream
input;
private OutputStream
output;
private Request
request;
private Response
response;
private FitNesseContext
context;
protected long requestParsingTimeLimit;
private long requestProgress;
private long requestParsingDeadline;
private boolean hasError;
public FitNesseExpediter(Socket
s,
FitNesseContext context) throws Exception
{
this.context = context;
socket = s;
input =
s.getInputStream();
output =
s.getOutputStream();
requestParsingTimeLimit = 10000;
|
9."Breaking Indentation."
USE:
public class CommentWidget
extends TextWidget {
public static final String REGEXP = "^#[^\r\n]*(?:(?:\r\n)|\n|\r)?";
public CommentWidget(ParentWidget
parent, String text) {
super(parent, text);
}
public String render() throws Exception {
return "";
}
}
INSTEAD OF:
public class CommentWidget
extends TextWidget
{
public static final String REGEXP = "^#[^\r\n]*(?:(?:\r\n)|\n|\r)?";
public CommentWidget(ParentWidget parent,
String text){super(parent,
text);}
public String render() throws Exception {return ""; }
}
|
References:
Robert C Martin - Clean Code: A Handbook of Agile Software Craftsmanship