代碼注釋的藝術,優(yōu)秀代碼真的不需要注釋嗎?
點擊上方“Java技術江湖”,選擇“設為星標”
回復”666“獲取全網(wǎng)最熱的Java核心知識點整理

前言
注釋的意義
; **************************************************************************; * RAMinit Release 2.0 *; * Copyright (c) 1989-1994 by Yellow Rose Software Co. *; * Written by Mr. Leijun *; * Press HotKey to remove all TSR program after this program *; **************************************************************************; Removed Softwares by RI:; SPDOS v6.0F, WPS v3.0F; Game Busters III, IV; NETX ( Novell 3.11 ); PC-CACHE; Norton Cache; Microsoft SmartDrv; SideKick 1.56A; MOUSE Driver; Crazy (Monochrome simulate CGA program); RAMBIOS v2.0; 386MAX Version 6.01
爭議與分歧
壞代碼的救命稻草
The proper use of comments is to compensate for our failure to express ourself in code.
-- Robert C. Martin 《Clean Code》
譯:注釋的恰當用法是彌補我們在用代碼表達意圖時遭遇的失敗
零注釋

糟糕的代碼加上完全不存在的注釋,我喜歡稱呼它們?yōu)椤何液蜕系壑g的秘密』,當然過2個月后也可以稱之為『上帝一個人的秘密』。
無用注釋
/*** returns the last day of the month* @return the last day of the month*/public Date getLastDayOfMonth(Date date) {Calendar calendar = new GregorianCalendar();calendar.setTime(date);calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));return calendar.getTime();}
代碼優(yōu)于注釋
"Comments Do Not Make Up for Bad Code"
-- Robert C.Martin 《Clean Code》
譯:注釋不能美化糟糕的代碼
// 判斷是否活躍用戶if((customer.getLastLoginTime().after(dateUtils.minusDays(new Date(),15)) && customer.getCommentsLast30Days() > 5)|| orderService.countRecentDaysByCustomer(customer,30) > 1)
if(customer.isActive())public synchronized void setFormatter(Formatter newFormatter) {checkPermission();// Check for a null pointernewFormatter.getClass();formatter = newFormatter;}
注釋否定論
"If our programming languages were expressive enough, or if we had the talent to subtly wield those languages to express our intent, we would not need comments very much—perhaps not at all."
-- Robert C.Martin 《Clean Code》
譯:若編程語言足夠有表達力,或者我們長于用這些語言來表達意圖,就不那么需要注釋--也許根本不需要
軟件設計的烏托邦
美麗的烏托邦
"'good code is self-documenting' is a delicious myth"
-- John Ousterhout《A Philosophy of Software Design》
譯:‘好的代碼自解釋’是一個美麗的謊言
好代碼的最佳僚機
You might think the purpose of commenting is to 'explain what the code does', but that is just a small part of it.The purpose of commenting is to help the reader know as much as the writer did.
譯:你可能以為注釋的目的是“解釋代碼做了什么”,但這只是其中很小一部分,注釋的目的是盡量幫助讀者了解得和作者一樣多
-- Dustin Boswell《The Art of Readable Code》
更精準表述
There are only two hard things in Computer Science: cache invalidation and naming things.
-- Phil Karlton
譯:計算機科學中只有兩個難題:緩存失效和命名
public class TheSilkRoadEconomicBeltAndThe21stCenturyMaritimeSilkRoad {}
/*** 一帶一路* 絲綢之路經(jīng)濟帶和21世紀海上絲綢之路*/public class OneBeltOneRoad {}
代碼層次切割
代碼層次切割
/*** 客戶列表查詢*/public List queryCustomerList(){// 查詢參數(shù)準備UserInfo userInfo = context.getLoginContext().getUserInfo();if(userInfo == null || StringUtils.isBlank(userInfo.getUserId())){return Collections.emptyList();}LoginDTO loginDTO = userInfoConvertor.convertUserInfo2LoginDTO(userInfo);// 查詢客戶信息List<CustomerSearchVO> customerSearchList = customerRemoteQueryService.query(loginDTO);Iterable<CustomerSearchVO> it = customerSearchList.iterator();// 排除不合規(guī)客戶while(it.hasNext()){CustomerSearchVO customerSearchVO = it.next();if(isInBlackList(customerSearchVO) || isLowQuality(customerSearchVO)){it.remove();}}// 補充客戶其他屬性信息batchFillCustomerPositionInfo(customerSearchList);batchFillCustomerAddressInfo(customerSearchList);}
母語的力量
TaskDispatch taskDispatch = TaskDispatchBuilder.newBuilder().withExceptionIgnore().build();taskDispatch// 外貿(mào)信息.join(new FillForeignTradeInfoTask(targetCustomer, sourceInfo))// 國民經(jīng)濟行業(yè)、電商平臺、注冊資本.join(new FillCustOutterInfoTask(targetCustomer, sourceInfo))// 客戶信息.join(new FillCustomerOriginAndCategoryTask(targetCustomer, sourceInfo))// 客戶擴展信息.join(new FillCustExtInfoTask(targetCustomer, sourceInfo))// 收藏屏蔽信息.join(new FillCollectStatusInfoTask(targetCustomer, sourceInfo, loginDTO()))// 詳情頁跳轉需要的標簽信息.join(new FillTagInstanceTask(targetCustomer, sourceInfo, loginDTO()))// 客戶信息完整度分數(shù).join(new FillCustomerScoreTask(targetCustomer, sourceInfo))// 潛客分層完整度.join(new FillCustomerSegmentationTask(targetCustomer, sourceInfo))// 填充操作信息.join(new FillOperationStatusTask(targetCustomer, sourceInfo, loginDTO))// 認證狀態(tài).join(new FillAvStatusTask(targetCustomer, loginDTO))// 客戶地址和組織.join(new FillCompanyAddressTask(targetCustomer, loginDTO))// 違規(guī)信息.join(new FillPunishInfoTask(targetCustomer, sourceInfo))// 填充客戶黑名單信息.join(new FillCustomerBlackStatusTask(targetCustomer, sourceInfo))// 填充客戶意愿度.join(new FillCustIntentionLevelTask(targetCustomer, sourceInfo));// 執(zhí)行.execute();
注釋的真正歸屬
復雜的業(yè)務邏輯
// Fail if we're already creating this bean instance:// We're assumably within a circular reference.if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// Check if bean definition exists in this factory.BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// Not found -> check parent.String nameToLookup = originalBeanName(name);if (args != null) {// Delegation to parent with explicit args.return parentBeanFactory.getBean(nameToLookup, args);}else {// No args -> delegate to standard getBean method.return parentBeanFactory.getBean(nameToLookup, requiredType);}}
截取自:
晦澀的算法公式
/*** Returns the value obtained by reversing the order of the bits in the* two's complement binary representation of the specified {@code long}* value.*/public static long reverse(long i) {// HD, Figure 7-1i = (i & 0x5555555555555555L) << 1 | (i >>> 1) & 0x5555555555555555L;i = (i & 0x3333333333333333L) << 2 | (i >>> 2) & 0x3333333333333333L;i = (i & 0x0f0f0f0f0f0f0f0fL) << 4 | (i >>> 4) & 0x0f0f0f0f0f0f0f0fL;i = (i & 0x00ff00ff00ff00ffL) << 8 | (i >>> 8) & 0x00ff00ff00ff00ffL;i = (i << 48) | ((i & 0xffff0000L) << 16) |((i >>> 16) & 0xffff0000L) | (i >>> 48);return i;}
截取自java.lang.Long#reverse
不明所以的常量
/*** The bin count threshold for using a tree rather than list for a* bin. Bins are converted to trees when adding an element to a* bin with at least this many nodes. The value must be greater* than 2 and should be at least 8 to mesh with assumptions in* tree removal about conversion back to plain bins upon* shrinkage.*/static final int TREEIFY_THRESHOLD = 8;
截取自java.util.HashMap#TREEIFY_THRESHOLD
意料之外的行為
for (int i = 0; i < 3; i++) {// if task running, invoke only check result ready or notResult result = bigDataQueryService.queryBySQL(sql, token);if (SUCCESS.equals(result.getStatus())) {return result.getValue();}Thread.sleep(5000);}
接口對外API
/*** <p>Checks if a CharSequence is empty (""), null or whitespace only.</p>* <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>* StringUtils.isBlank(null) = true* StringUtils.isBlank("") = true* StringUtils.isBlank(" ") = true* StringUtils.isBlank("bob") = false* StringUtils.isBlank(" bob ") = false** @param cs the CharSequence to check, may be null* @return {@code true} if the CharSequence is null, empty or whitespace only*/public static boolean isBlank(final CharSequence cs) {final int strLen = length(cs);if (strLen == 0) {return true;}for (int i = 0; i < strLen; i++) {if (!Character.isWhitespace(cs.charAt(i))) {return false;}}return true;}
截取自org.apache.commons.lang3.StringUtils#isBlank
法律文件信息
/** Licensed to the Apache Software Foundation (ASF) under one or more* contributor license agreements. See the NOTICE file distributed with* this work for additional information regarding copyright ownership.* The ASF licenses this file to You under the Apache License, Version 2.0* (the "License"); you may not use this file except in compliance with* the License. You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
寫在最后
《A Philosophy of Software Design》:https://www.amazon.com/-/zh/dp/173210221X/ref=sr_1_1

40 個 SpringBoot 常用注解:讓生產(chǎn)力爆表!

如果要存 IP 地址,用什么數(shù)據(jù)類型比較好?99%人都會答錯!

面試官:Java8 lambda 表達式 forEach 如何提前終止?
關注公眾號【Java技術江湖】后回復“PDF”即可領取200+頁的《Java工程師面試指南》
強烈推薦,幾乎涵蓋所有Java工程師必知必會的知識點,不管是復習還是面試,都很實用。

評論
圖片
表情
