代码注释的艺术,代码真的不需要注释吗?
前言
注释的意义
; **************************************************************************
; * 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》
译:注释的恰当用法是弥补我们在用代码表达意图时遭遇的失败
零注释
糟糕的代码加上完全不存在的注释,我喜欢称呼它们为『我和上帝之间的秘密』,当然过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();
}
代码优于注释
"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 pointer
newFormatter.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 {
}
/**
* 一带一路
* 丝绸之路经济带和21世纪海上丝绸之路
*/
public class OneBeltOneRoad {
}
代码层次切割
代码层次切割
/**
* 客户列表查询
*/
public List queryCustomerList(){
// 查询参数准备
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();
// 排除不合规客户
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
// 外贸信息
.join(new FillForeignTradeInfoTask(targetCustomer, sourceInfo))
// 国民经济行业、电商平台、注册资本
.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()))
// 客户信息完整度分数
.join(new FillCustomerScoreTask(targetCustomer, sourceInfo))
// 潜客分层完整度
.join(new FillCustomerSegmentationTask(targetCustomer, sourceInfo))
// 填充操作信息
.join(new FillOperationStatusTask(targetCustomer, sourceInfo, loginDTO))
// 认证状态
.join(new FillAvStatusTask(targetCustomer, loginDTO))
// 客户地址和组织
.join(new FillCompanyAddressTask(targetCustomer, loginDTO))
// 违规信息
.join(new FillPunishInfoTask(targetCustomer, sourceInfo))
// 填充客户黑名单信息
.join(new FillCustomerBlackStatusTask(targetCustomer, sourceInfo))
// 填充客户意愿度
.join(new FillCustIntentionLevelTask(targetCustomer, sourceInfo));
// 执行
.execute();
注释的真正归属
复杂的业务逻辑
// 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-1
i = (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 = ; i < 3; i++) {
// if task running, invoke only check result ready or not
Result 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 == ) {
return true;
}
for (int i = ; 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.
*/
写在后
相关文章