三毛说过:基础是重要的东西,没有基础的人,将来走任何一条路都比基础深厚的人来得辛苦和单薄
当我们的开发Leader或者项目组需要我们编写符合各种规则的代码,我一直是一个不守规矩的“坏小孩”。我们一直强调我们的开发人员写短的方法,必须编写注释,我们甚至用各种工具去Check我们的小伙伴的代码,注释,命名规范,方法长度我们用尽了Check Style里面的定义。但是往往我们忘了了初衷,我们为什么要注释,我们为什么要命名规范,我们为什么要方法“短小而精干”。是的,为什么?为什么?为什么?
别给糟糕的代码加上注释----重新写吧!
不记得什么时候开始,我们有了这样的一个想法,糟糕的代码可以用完美的注释来弥补,真的真的是这样吗?糟糕的代码,就是糟糕的代码,不管用多么好的注释去弥补还是糟糕的,就像一个腐坏的食品,你在用什么华丽的包装去包装它,他还是坏的,必须扔掉,重新做。
什么也比不上放置良好的注释来的有用,什么也比不上乱七八糟的注释更加有能耐搞乱一个模块,什么也不会比陈旧,提供错误信息的注释要有更加的破坏性。
记得在做一个项目的时候,有一位高手就告诉我,假如你得编程语言有足够的表达力,或者我们擅长用这些语言来表达意图,就不那么需要注释,因为你的注释会将别人带入到沟里面。
是的带入到沟里面,当我的代码编写的越来越多,或者说,阅读的代码变多的时候,真的。我已经不知道多少次被人带入到沟里面了。
代码是一直会变的也在一直演变中,从这里迁移到那里,彼此分离,然后又和别的代码重新组合,变成一对,但是注释我们不会总是跟着代码在变动。
糟糕的代码,注释也没法弥补
用代码来阐述你的意图
//检查员工是否有资格获得免费的福利
if((employee.flags && HOURLY_FLAG)&&(employee.age>65))
if(employee.isEligibleForFullBenefits())
你会选择哪一个,让别人第一时间了解的意图,即使在不知道你的方法具体实现的时候,让阅读的人理解你的意图。
有时候,代码本身不足以解释其行为,不幸的消息是,许多开发人员常常认为代码很少,如果可以的话,能用注释做好解释工作。
好的注释,有一些注释必须要有的,也是有利的。不过要记住,唯一真正好的注释是你想办法不写注释。(但是我不完全认可这个)。
法律信息
在我们使用很多开源项目的时候,我们往往会看到以下注释
//Copyright (C) 2003,2004,2005 by Object Mentor,Inc,All rights reserved.
//Released under the terms of the GNU General Public License version 2 or laster.
提供信息注释
有时候,用注释来提供有用的信息也是恰其好处。比如
/**
* @return Responder Returns an instance of the Responder being tested.
**/
protected abstract Responder responderInstance();
//format matched kk:mm:ss EEE,MMM dd,yyyy
Pattern timMatcher = Pattern.compile("\\d*:\\d*:\\d* \\w* \\d* \\d*");
这个注释说明了,该正则表达式的作用在匹配一个经过SimleDateFormat方法格式化完的一个字符串的时间和日期。
对意图的解释
有时候,注释不仅提供了有关实现的具体说明,而且还提供了某个决定后面的意图。
例如我们在读取文件的时候,我们提供出来很多方法的时候,往往我们没有写在读写完文件的时候,告诉调用的人员,你需要关闭文件流,有人这时候会说,这些事程序猿肯定知道的。肯定知道的,不代表一定知道,或者一定遵守的。
比如
a.compareTo(b) == 0
a.compareTo(b)<0
a.compareTo(b)>0
这些其实我们不需要写注释的,但是往往我们还是会写,为什么,因为我们要强调。
a.compareTo(b) == 0 //a ==b
a.compareTo(b)<0 //a<b
a.compareTo(b)>0 //a>b
这时候,你会发现有时候好的注释,往往会让你“蛋疼”。
TODO注释
TODO,我想很多人已经用过了,TODO是一种程序猿认为应该做的,比如在某种情况下,目前我们可能还不需要完成某种工作,我们就必须使用TODO
公共API中的JavaDoc
如果你在做一些共通的东西的话,好的JavaDoc将会为你省下很多解释的时间。因为我们可以使用Javadoc生成很好的API文档提供给别人。这样的话,使用人员就可以很明确的明白你的意图,或者方法的作用
请不要喃喃自语
public void loadProperties(){
try{
String propertiesPath = propertiesLocation + "/" + PROPERTIES_FILE;
FileInputStream propertiesStream = new FileInputStream(propertiesPath);
loadedProperties.load(propertiesStream);
}catch(IOException ex){
//No Properties files means all defaults are loaded
}
}
谁能解释一下Catch里面注释的意义,这个可能是开发人员对于没有Properties文件的情况做的一个特殊处理,但是有没有阐述情况,因为在Catch里面只是空空的注释,别没有对这块做任何的操作,难道开发人员会在后面发现有问题的情况的时候补充代码吗?那么为什么我们不是用TODO呢?
循规蹈矩的注释
还记得我们循规蹈矩的注释吗?那些循规蹈矩的注释是否真的很有用呢?是不是只是为了保证我们的Check Style通过?好吧,是的。就是为了Check Style通过。但是那些注释的作用又有多少呢?我可以为是0.
/**
*
*@param title The title of the CD
*@param author The author of the CD
*@param track The number of tracks on the CD
*@param durationInMinutes The duration of the CD in minutes
*/
public void addCd(String title,String author,int tracks,int durationInMinutes){
.......
}
我们是否可以不需要这些我们为了Check Style通过,而编写这些废话的注释呢?
废话注释
废话注释,就是那些写的是废话的注释,没有任何营养的注释,说的再难听一点,就是,你写的那些事废话,没有任何价值,你在写那些的时候,就是浪费人月,浪费时间。
/**
* Default constructor.
**/
public AnnualDateRule(){
}
你告诉我,谁不知道这是默认构造函数,
还有更加规范的废话
/**
* Returns the day of the month.
*@return the day of the month .
public int getDayOfMonth(){
return this.dayOfMonth.
}
这样的规范注释,我们见得很多,有时候我们会纠结,要不要加这些废话的注释,但是当我们命名规范或者有含义的时候,我真的认为不需要了。除非,你想表达的更加清晰明朗。
还有更加废话的注释。
/**The name*/
private String name;
/**The Version*/
private String version;
妹的,想骂脏字了,难道我不知道这个是name,那个是version,要你说。
当我们思维达到一个边界的时候,我们往往会忘了初衷,难道不是吗?我们的规范,我们的要求,往往忘了为什么。
写了这么多,参考一下别人的注释吧!
/**
* Spring Boot 启动类,加载需要的Bean和设置启动时候Config扫描类.
*@author jiang_nan
*/
@Configuration
@Import({
DispatcherServletAutoConfiguration.class,
EmbeddedServletContainerAutoConfiguration.class,
ErrorMvcAutoConfiguration.class,
FreeMarkerAutoConfiguration.class,
HttpEncodingAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
JacksonAutoConfiguration.class,
MultipartAutoConfiguration.class,
PersistenceExceptionTranslationAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
RedisAutoConfiguration.class,
ServerPropertiesAutoConfiguration.class,
WebMvcAutoConfiguration.class,
WebSocketAutoConfiguration.class
})
@EnableTransactionManagement// 开启注解事务管理,等同于xml配置文件中的
@ComponentScan(basePackages={"com.msk.batch"})
public classApplicationimplementsTransactionManagementConfigurer {
@Resource
privateEnvironmentenvironment;
@Resource
privatePlatformTransactionManagerdataSourceTransactionManager;
@Bean
publicDataSourcedataSource(){
DruidDataSource dataSource =newDruidDataSource();
String url =environment.getProperty("spring.datasource.url");
dataSource.setUrl(url);
String userName =environment.getProperty("spring.datasource.username");
dataSource.setUsername(userName);
String password =environment.getProperty("spring.datasource.password");
dataSource.setPassword(password);
dataSource.setInitialSize(2);
dataSource.setMaxActive(20);
dataSource.setMinIdle(0);
dataSource.setMaxWait(60000);
dataSource.setValidationQuery("SELECT 1");
dataSource.setTestOnBorrow(false);
dataSource.setTestWhileIdle(true);
dataSource.setPoolPreparedStatements(false);
returndataSource;
}
@Bean
publicJdbcTemplatejdbcTemplate(){
return newJdbcTemplate(dataSource());
}
@Bean
publicPlatformTransactionManagertxManager(DataSource dataSource) {
return newDataSourceTransactionManager(dataSource);
}
@Override
publicPlatformTransactionManagerannotationDrivenTransactionManager() {
returndataSourceTransactionManager;
}
public static voidmain(String[] args)throwsException {
SpringApplication.run(Application.class,args);
}
}
没有一行多余的注释。
网友评论