4. Explain Yourself in Code
Explain Yourself in Code
There are certainly times when code makes a poor vehic
There are certainly times when code makes a poor vehicle for this to mean that code is
many programmers have taken explanation. Unfortunately,
코드로 의도를 표현하라!! This:
many programmers have taken this to This thatpatently false. Which would you rath
explanation. mean is code is seldom, if ever, a good means for
explanation. This is patently false. Which would you rather see?
// Check to see if the employee is eligible for
// Check to see if theif ((employee.flags & HOURLY_FLAG) &&
employee is eligible for full benefits
if ((employee.flags & HOURLY_FLAG) &&
(employee.age > 65))
(employee.age > 65))
Or this?
Or this?
if (employee.isEligibleForFullBenefits())
if (employee.isEligibleForFullBenefits())
It takes only a few seconds of thought to explain mo
It takes only a few seconds of thought to explain most of your intent in code. In many
cases it’s simply a matter of creating a function that say
cases it’s simply a matter of creating a function that says the same thing as the comment
you want to write.
you want to write.
Good Comments
Good Comments
5. Legal Comments
into the comment.
Informativeour corporate coding standards force us to write certain comments for legal
Sometimes Comments
은 is sometimes into a comment하는authorshipsource file. arewith a comment. For example, c
It
주석to(글자값을provide basic information necessary and reasonable
reasons. For example, copyright and
주석)statements
things put useful to at the star t of each
sider this Here, for example,explains the return value of an abstract method: of
comment that is the standard comment header that we put at the beginning
법적인 주석
every source file in FitNesse. I am happy to say that our IDE hides this comment from act-
// Returns an instance of the Responder being tested.
ing as clutter by automatically collapsing it.
protected abstract Responder responderInstance();
A comment Copyright (C) 2003,2004,2005 bybe useful, butInc.is better to use the name of the fu
// like this can sometimes Object Mentor, it All rights reserved.
// Released under the terms of the GNU General Public License version 2 or later.
tion to convey the information where possible. For example, in this case the comm
could be made redundant by renaming the function: responderBeingTested .
정보를case
Here’s a 제공하는 주석
Good Comments that’s a bit better: 57
// format matched kk:mm:ss EEE, MMM dd, yyyy
Pattern timeMatcher = Pattern.compile(
String text = "'''bold text'''"; w* d*, d*");
"d*:d*:d* w*,
In this casenew BoldWidget(new= MockWidgetRoot(), that the regular expression is intended to matc
ParentWidget parent
the comment lets us know "'''bold text'''");
의도를 설명하는 주석(결정에 깔린 의도를 설명한다)
time and AtomicBoolean were formatted with the SimpleDateFormat.format function using
date that failFlag = new AtomicBoolean();
specified failFlag.set(false);
format string. Still, it might have been better, and clearer, if this code had b
moved to a special class that converted the formats of dates and times. Then the comm
//This is our best attempt to get a race condition
would likely have been superfluous.
//by creating large number of threads.
for (int i = 0; i < 25000; i++) {
Explanation of Intent
WidgetBuilderThread widgetBuilderThread =
new WidgetBuilderThread(widgetBuilder, text, parent, failFlag);
Sometimes Thread thread = goes beyond just useful information about the implementation a
a comment new Thread(widgetBuilderThread);
thread.start();
provides the intent behind a decision. In the following case we see an interesting decis
}
assertEquals(false, failFlag.get());
documented by a comment. When comparing two objects, the author decided that
6. code that// Don't run unless you then a helpful clarifying comment can be useful.
you cannot alter,
// have some time to kill.
public void _testWithReallyBigFile()
public void testCompareTo() throws Exception
{
은 주석(글자값을 하는 주석)
{ writeLinesToFile(10000000);
WikiPagePath a = PathParser.parse("PageA");
WikiPagePath ab = PathParser.parse("PageA.PageB");
response.setBody(testFile);
WikiPagePath b = PathParser.parse("PageB");
response.readyToSend(this);
WikiPagePath aa == PathParser.parse("PageA.PageA");
String responseString output.toString();
의미를 명료하게 밝히는 주석
WikiPagePath bb = PathParser.parse("PageB.PageB");
assertSubString("Content-Length: 1000000000", responseString);
WikiPagePath ba = 1000000000);
assertTrue(bytesSent > PathParser.parse("PageB.PageA");
}
assertTrue(a.compareTo(a) == 0); // a == a
Nowadays, of course, we’d turn off the test case by using// @Ignore b
assertTrue(a.compareTo(b) != 0); the a != attribute with an
appropriate explanatory string. @Ignore("Takes too long to // ab But back in the days
assertTrue(ab.compareTo(ab) == 0); run"). == ab
before JUnit 4, putting an underscore in front of the method namea < abcommon conven-
assertTrue(a.compareTo(b) == -1); // was
assertTrue(aa.compareTo(ab) == -1); // aa < ab
tion. The comment, while flippant, makes the point pretty well. ba < bb
결과를 경고하는 주석
assertTrue(ba.compareTo(bb) == -1); //
Here’s another, more poignant example: == 1);
assertTrue(b.compareTo(a) // b > a
assertTrue(ab.compareTo(aa) == 1); // ab > aa
public static SimpleDateFormat makeStandardHttpDateFormat()> ba
assertTrue(bb.compareTo(ba) == 1); // bb
} {
//SimpleDateFormat is not thread safe,
There //so a substantial risk,instance independently.a clarifying comment is incorrect. Go
is we need to create each of course, that
through the previous example and see how difficult it is to HH:mm:ss that they are correct. This
SimpleDateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy verify z");
df.setTimeZone(TimeZone.getTimeZone("GMT"));
explains both why the clarification is necessary and why it’s risky. So before writing com-
return df;
ments like this, take care that there is no better way, and then take even more care that they
}
TODO 주석(나쁜 코드를 남기는 핑계가 되어서는 안된다
are accurate.
You might complain that there are better ways to solve this problem. I might agree with
you. But the comment, as given here, is perfectly reasonable. It will prevent some overly
eager programmer from using a static initializer in the name of efficiency.
공개 API에서 JavaDocs
TODO Comments
It is sometimes reasonable to leave “To do” notes in the form of //TODO comments. In the
following case, the TODO comment explains why the function has a degenerate implementa-
7. 나쁜 주석
허술한 코드를 지탱하거나
엉성한 코드를 변명하거나
미숙한 결정을 합리화하는 등
프로그래머가 주절거리는 독
해당하는 대부분의 주석들!!
8. 주석을 달기로 결정했는가?
충분한 시간을 들여 최고의
주석을 달도록 노력해야 한다
의무감/프로세스에 의해 마지못
주석을 달다면 시간낭비일 뿐이
9. comment has failed to communicate to you and is not worth the bits it consumes.
나쁜 주석function with a header comment that is completely redundant.
Redundant Comments
Listing 4-1 shows a simple
The comment probably takes longer to read than the code itself.
같은 이야기를 중복하는 주석
Listing 4-1
waitForClose
// Utility method that returns when this.closed is true. Throws an exception
// if the timeout is reached.
public synchronized void waitForClose(final long timeoutMillis)
throws Exception
{
if(!closed)
{
wait(timeoutMillis);
if(!closed)
throw new Exception("MockResponseSender could not be closed");
}
}
주석이 같은 코드의 내용을 그대로 중복한다
코드보다 주석을 읽는 시간이 더 오래 걸린다
10. 나쁜 주석
64 Chapter 4: Comments
이력을 기록하는 주석
* Changes (from 11-Oct-2001)
* --------------------------
* 11-Oct-2001 : Re-organised the class and moved it to new package
* com.jrefinery.date (DG);
* 05-Nov-2001 : Added a getDescription() method, and eliminated NotableDate
* class (DG);
* 12-Nov-2001 : IBD requires setDescription() method, now that NotableDate
* class is gone (DG); Changed getPreviousDayOfWeek(),
* getFollowingDayOfWeek() and getNearestDayOfWeek() to correct
*
*
과거에는 필요했을지 모르지만
bugs (DG);
05-Dec-2001 : Fixed bug in SpreadsheetDate class (DG);
이제는 코드 관리 시스템으로 관리할 수 있다
* 29-May-2002 : Moved the month constants into a separate interface
* (MonthConstants) (DG);
* 27-Aug-2002 : Fixed bug in addMonths() method, thanks to N???levka Petr (DG);
* 03-Oct-2002 : Fixed errors reported by Checkstyle (DG);
* 13-Mar-2003 : Implemented Serializable (DG);
* 29-May-2003 : Fixed bug in addMonths method (DG);
* 04-Sep-2003 : Implemented Comparable. Updated the isInRange javadocs (DG);
* 05-Jan-2005 : Fixed bug in addYears() method (1096282) (DG);
Long ago there was a good reason to create and maintain these log entries at the start
of every module. We didn’t have source code control systems that did it for us. Nowadays,
however, these long journals are just more clutter to obfuscate the module. They should be
11. however, these long journals are just more clutter to obfuscate the module. They should be
completely removed.
나쁜Comments
Noise
주석
있으나 마나한 주석
Sometimes you see comments that are nothing but noise. They restate the obvious and
provide no new information.
/**
* Default constructor.
*/
protected AnnualDateRule() {
}
No, really? Or how about this:
/** The day of the month. */
주석이 지나친 참견이라 주석을 무시하게 된다
private int dayOfMonth;
코드를 읽으면서 자동을 주석을 건너뛴다
And then there’s this paragon of redundancy:
/**
코드가 바뀌면서 주석은 거짓말로 변한다.
* Returns the day of the month.
*
* @return the day of the month.
*/
public int getDayOfMonth() {
return dayOfMonth;
}
12. wc.java
while ((line = in.readLine()) != null) {
lineCount++;
나쁜 주석 charCount += line.length();
String words[] = line.split("W");
wordCount += words.length;
} //while
닫는 괄호에 다는 주석System.out.println("wordCount = " + wordCount);
System.out.println("lineCount = " + lineCount);
System.out.println("charCount = " + charCount);
} // try
catch (IOException e) {
System.err.println("Error:" + e.getMessage());
} //catch
} //main
}
Attributions 의미가 있을
and Bylines 수도 있지만, 작고 캡슐화된
함수에는 잡음일 뿐이다.
/* Added by Rick */
Source code control systems are very good at remembering who added what, when.
There is no need to pollute the code with little bylines. 달아야 겠다면
닫는 괄호에 주석을 You might think that such com-
ments would be useful in order to help others know who to talk to about the code. But the
reality is that they tend to stay 줄이려고and years, getting less and less accurate
함수를 around for years 시도해 봐라.
and relevant.
Again, the source code control system is a better place for this kind of information.
Commented-Out Code
13. ments would be useful in order to help others know who to talk to about the code. But the
reality is that they tend to stay around for years and years, getting less and less accurate
나쁜 주석 control system is a better place for this kind of information.
and relevant.
Again, the source code
Commented-Out Code
주석으로 처리한 코드들 / 저자를 표시하는 주석
Few practices are as odious as commenting-out code. Don’t do this!
InputStreamResponse response = new InputStreamResponse();
response.setBody(formatter.getResultStream(), formatter.getByteCount());
// InputStream resultsStream = formatter.getResultStream();
// StreamReader reader = new StreamReader(resultsStream);
// response.setContent(reader.read(formatter.getByteCount()));
Others who see that commented-out code won’t have the courage to delete it. They’ll think
주석으로 처리된 코드는 다른사람이 지우기를
it is there for a reason and is too important to delete. So commented-out code gathers like
dregs at the bottom of a bad bottle of wine.
이유가 있어 남겨놓았을 것이다. 중요하니까 지
Consider this from apache commons:
this.bytePos = writeBytes(pngIdBytes, 0);
//hdrPos = bytePos; 쓸모 없는 코드가 점차 쌓여간다.
그래서
writeHeader();
코드 관리 시스템을 통해서 모두 관리 가능하다
writeResolution();
//dataPos = bytePos;
if (writeImageData()) {
그냥 삭제해라. 잃어버릴 염려는 없다!
writeEnd();
this.pngBytes = resizeByteArray(this.pngBytes, this.maxPos);
}
14. 나쁜 주석
HTML 주석, 너무나 많은 정보를 담는 주석,
주석과 코드의 설명이 명백하지 않은 모호한 주석,
짧은 함수에 긴 설명 주석,
비공개코드의 JAvaDocs........