Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

[2012 02 03]clean_code 4장


Published on

Published in: Technology
  • Be the first to comment

  • Be the first to like this

[2012 02 03]clean_code 4장

  1. 1. Clean Code 4장 주석 2012 02. 03 원종필
  2. 2. 주석(Comment)코드로 의도를 표현하지 못해,실패를 만회하기 위해서 사용한다. 부정확한 주석은 아예 없는 주석보다 훨씬 더 나진실은 한곳에만 존재한다! 바로 코드(code). 주석을 엄격하게 관리하는 방향 보다는 코드를 깔끔하게 정리하여 주석이 필요없는
  3. 3. 주석을 달아야 겠다?? 코드를 정리해야 한다석은 나쁜 코드를 보완하지 못한다!!
  4. 4. Explain Yourself in CodeExplain Yourself in Code There are certainly times when code makes a poor vehicThere 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 forexplanation. 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 saycases it’s simply a matter of creating a function that says the same thing as the comment you want to want to write. Good CommentsGood Comments
  5. 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, 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. 6. code that// Dont 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. 7. 나쁜 주석 허술한 코드를 지탱하거나 엉성한 코드를 변명하거나 미숙한 결정을 합리화하는 등 프로그래머가 주절거리는 독 해당하는 대부분의 주석들!!
  8. 8. 주석을 달기로 결정했는가? 충분한 시간을 들여 최고의 주석을 달도록 노력해야 한다 의무감/프로세스에 의해 마지못 주석을 달다면 시간낭비일 뿐이
  9. 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. 10. 나쁜 주석 64 Chapter 4: Comments이력을 기록하는 주석 * Changes (from 11-Oct-2001) * -------------------------- * 11-Oct-2001 : Re-organised the class and moved it to new package * (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. 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. 12. 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 thereality 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. 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(; 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. 14. 나쁜 주석 HTML 주석, 너무나 많은 정보를 담는 주석, 주석과 코드의 설명이 명백하지 않은 모호한 주석, 짧은 함수에 긴 설명 주석, 비공개코드의 JAvaDocs........
  15. 15. Q/A
  16. 16. END