良好的代码风格能提高代码可读性及可维护性,程序员都应该遵守基本的代码排版规范、代码命名规范。
首先看看以下三张图,在没有代码的情况下能猜猜各是什么开发语言。
---------------------------------------------------------------
[img]http://dl2.iteye.com/upload/attachment/0126/3650/477bea72-5cfe-3f8e-aa4c-0e74e860af74.png[/img]
---------------------------------------------------------------
[img]http://dl2.iteye.com/upload/attachment/0126/3652/da3fd3c0-1f4b-360e-a557-7119bed26dbd.png[/img]
---------------------------------------------------------------
[img]http://dl2.iteye.com/upload/attachment/0126/3654/1500cb7e-fb2e-3e5a-9b74-f44e9e89da07.png[/img]
第一张图是CSS,可以看到清晰的选择器和属性键值对。
第二张图是HTML,可以看到清晰的head和body定义。
第三张图是Java,可以看到头部imports,类定义,成员变量,构造函数以及其他方法。
图片来自:https://schneide.wordpress.com/2015/04/26/the-typography-of-source-code/
各个语言都有自己的规范,开发所用的各种IDE也都内置了代码格式化工具,比如Eclipse对Java和JavaScript代码的标准格式化定义:
[img]http://dl2.iteye.com/upload/attachment/0126/3656/a2a9284b-0091-3365-8709-55ceeb9b2575.png[/img]
[img]http://dl2.iteye.com/upload/attachment/0126/3658/495299e4-737d-3407-8000-753eddc5bd76.png[/img]
也可以通过 [url=http://checkstyle.sourceforge.net/]Checkstyle[/url] 检查Java代码的规范性。
这里罗列几个最有争议的。
[b](1)缩进 [/b]
使用Tab 还是空格?2个空格还是4个空格?具体关于这个网上的争论太多了,但是需要特别注意的是像Python和CoffeeScript等是通过缩进来控制代码逻辑。
[img]http://dl2.iteye.com/upload/attachment/0126/3660/b19d8aa3-d5a0-3808-8b6e-154ec798b89c.jpeg[/img]
https://softwareengineering.stackexchange.com/questions/57/tabs-versus-spaces-what-is-the-proper-indentation-character-for-everything-in-e
https://medium.com/@hoffa/400-000-github-repositories-1-billion-files-14-terabytes-of-code-spaces-or-tabs-7cfe0b5dd7fd
[b](2)换行[/b]
大括号是否应该换行?
https://softwareengineering.stackexchange.com/questions/2715/should-curly-braces-appear-on-their-own-line
[b]大括号是否应该省略?[/b]
https://stackoverflow.com/questions/8020228/is-it-ok-if-i-omit-curly-braces-in-java
[b](3)对齐[/b]
[b]赋值等号对齐[/b]
[b]注释对齐[/b]
[b]参数对齐[/b]
[b]链式方法对齐[/b]
[b](4)空行[/b]
合理的利用空行来区分代码块。
[b](5)命名[/b]
违反命名规范的例子有很多,这里列2个:
[b]非驼峰命名[/b]
[b]连续编号[/b]
再列举一些代码书写上的其他Style。
[b](1)多层嵌套 还是 中途退出?[/b]
[b](2)常量放在左侧还是右侧?[/b]
https://stackoverflow.com/questions/2369226/object-null-or-null-object
[b](3)定义接口类型还是实现类型?[/b]
[b](4)标准for循环还是增强for循环?[/b]
[b](5)变量是否需要先定义为null?[/b]
*** 成员变量有默认值不需要赋值null,本地变量没有默认值需要赋值null。
[b](6)通过class还是interface定义全局常量?[/b]
还有这么定义的:
这些都是常见的,还有很多。
首先看看以下三张图,在没有代码的情况下能猜猜各是什么开发语言。
---------------------------------------------------------------
[img]http://dl2.iteye.com/upload/attachment/0126/3650/477bea72-5cfe-3f8e-aa4c-0e74e860af74.png[/img]
---------------------------------------------------------------
[img]http://dl2.iteye.com/upload/attachment/0126/3652/da3fd3c0-1f4b-360e-a557-7119bed26dbd.png[/img]
---------------------------------------------------------------
[img]http://dl2.iteye.com/upload/attachment/0126/3654/1500cb7e-fb2e-3e5a-9b74-f44e9e89da07.png[/img]
第一张图是CSS,可以看到清晰的选择器和属性键值对。
第二张图是HTML,可以看到清晰的head和body定义。
第三张图是Java,可以看到头部imports,类定义,成员变量,构造函数以及其他方法。
图片来自:https://schneide.wordpress.com/2015/04/26/the-typography-of-source-code/
各个语言都有自己的规范,开发所用的各种IDE也都内置了代码格式化工具,比如Eclipse对Java和JavaScript代码的标准格式化定义:
[img]http://dl2.iteye.com/upload/attachment/0126/3656/a2a9284b-0091-3365-8709-55ceeb9b2575.png[/img]
[img]http://dl2.iteye.com/upload/attachment/0126/3658/495299e4-737d-3407-8000-753eddc5bd76.png[/img]
也可以通过 [url=http://checkstyle.sourceforge.net/]Checkstyle[/url] 检查Java代码的规范性。
这里罗列几个最有争议的。
[b](1)缩进 [/b]
使用Tab 还是空格?2个空格还是4个空格?具体关于这个网上的争论太多了,但是需要特别注意的是像Python和CoffeeScript等是通过缩进来控制代码逻辑。
[img]http://dl2.iteye.com/upload/attachment/0126/3660/b19d8aa3-d5a0-3808-8b6e-154ec798b89c.jpeg[/img]
https://softwareengineering.stackexchange.com/questions/57/tabs-versus-spaces-what-is-the-proper-indentation-character-for-everything-in-e
https://medium.com/@hoffa/400-000-github-repositories-1-billion-files-14-terabytes-of-code-spaces-or-tabs-7cfe0b5dd7fd
[b](2)换行[/b]
大括号是否应该换行?
if (you.hasAnswer()) {
you.postAnswer();
} else {
you.doSomething();
}
if (you.hasAnswer())
{
you.postAnswer();
}
else
{
you.doSomething();
}
if (you.hasAnswer())
you.postAnswer();
else
you.doSomething();
https://softwareengineering.stackexchange.com/questions/2715/should-curly-braces-appear-on-their-own-line
[b]大括号是否应该省略?[/b]
for (int i = 0; i < size; i++) {
a += b;
}
for (int i = 0; i < size; i++)
a += b;
for (int i = 0; i < size; i++) a += b;
https://stackoverflow.com/questions/8020228/is-it-ok-if-i-omit-curly-braces-in-java
[b](3)对齐[/b]
[b]赋值等号对齐[/b]
int a_variable = 1;
int another_variable = 2;
int yet_another_variable = 3;
[b]注释对齐[/b]
// whole line comment
int linePointer; // inline comment
BufferredReader br = new BufferredReader(); // inline comment
File f = new File(); // inline comment
[b]参数对齐[/b]
int some_call_result = some_object.a_method(
with,
quite_long,
list_of,
parameters
);
[b]链式方法对齐[/b]
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**", "/signup", "/about").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
.anyRequest().authenticated()
.and()
.formLogin();
}
[b](4)空行[/b]
合理的利用空行来区分代码块。
/**
* Initialize this servlet. Most of the processing has been factored
* into support methods so that you can override particular functionality
* at a fairly granular level.
*
* @throws ServletException if we cannot configure ourselves correctly
*/
public void init() throws ServletException {
final String configPrefix = "config/";
final int configPrefixLength = configPrefix.length() - 1;
// Wraps the entire initialization in a try/catch to better handle
// unexpected exceptions and errors to provide better feedback
// to the developer
try {
initInternal();
initOther();
initServlet();
initChain();
getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this);
initModuleConfigFactory();
// Initialize modules as needed
ModuleConfig moduleConfig = initModuleConfig("", config);
initModuleMessageResources(moduleConfig);
initModulePlugIns(moduleConfig);
initModuleFormBeans(moduleConfig);
initModuleForwards(moduleConfig);
initModuleExceptionConfigs(moduleConfig);
initModuleActions(moduleConfig);
moduleConfig.freeze();
Enumeration names = getServletConfig().getInitParameterNames();
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
if (!name.startsWith(configPrefix)) {
continue;
}
String prefix = name.substring(configPrefixLength);
moduleConfig =
initModuleConfig(prefix,
getServletConfig().getInitParameter(name));
initModuleMessageResources(moduleConfig);
initModulePlugIns(moduleConfig);
initModuleFormBeans(moduleConfig);
initModuleForwards(moduleConfig);
initModuleExceptionConfigs(moduleConfig);
initModuleActions(moduleConfig);
moduleConfig.freeze();
}
this.initModulePrefixes(this.getServletContext());
this.destroyConfigDigester();
} catch (UnavailableException ex) {
throw ex;
} catch (Throwable t) {
// The follow error message is not retrieved from internal message
// resources as they may not have been able to have been
// initialized
log.error("Unable to initialize Struts ActionServlet due to an "
+ "unexpected exception or error thrown, so marking the "
+ "servlet as unavailable. Most likely, this is due to an "
+ "incorrect or missing library dependency.", t);
throw new UnavailableException(t.getMessage());
}
}
[b](5)命名[/b]
违反命名规范的例子有很多,这里列2个:
[b]非驼峰命名[/b]
package com.test.EC_shop;
public class db_manager {
private String connection_url;
public void Init() {
// ...
}
}
[b]连续编号[/b]
public class UC8010 extends CMN0101 {
private String FLD0001;
public int MTD0001() {
// ...
}
}
publi class UC8020 extends CMN0101 {
private String FLD0001;
public int MTD0001() {
// ...
}
}
再列举一些代码书写上的其他Style。
[b](1)多层嵌套 还是 中途退出?[/b]
public String getInsuranceName(Employee employee) {
if (employee != null) {
Car car = employee.getCar();
if (car != null) {
Insurance insurance = car.getInsurance();
if (insurance != null) {
return insurance.getName();
}
}
}
return "UNKNOWN";
}
public String getInsuranceName(Employee employee) {
if (employee == null) {
return "UNKNOWN";
}
Car car = employee.getCar();
if (car == null) {
return "UNKNOWN";
}
Insurance insurance = car.getInsurance();
if (insurance == null) {
return "UNKNOWN";
}
return insurance.getName();
}
[b](2)常量放在左侧还是右侧?[/b]
if (currentValue == 5) {
// do work
}
if (5 == currentValue) {
// do work
}
if (obj == null) {
}
if (null == obj) {
}
if (obj = null) { // 赋值运算、NPE异常
}
if (null = obj) { // 编译错误
}
https://stackoverflow.com/questions/2369226/object-null-or-null-object
[b](3)定义接口类型还是实现类型?[/b]
List<Integer> sampleList = new ArrayList<Integer>();
ArrayList<Integer> sampleList = new ArrayList<Integer>();
[b](4)标准for循环还是增强for循环?[/b]
for (int i = 0; i < peopleList.size(); i++) {
People p = peopleList.get(i);
// ..
}
for (People p : peopleList) {
// ...
}
[b](5)变量是否需要先定义为null?[/b]
Object localVariableObj2 = null;
localVariableObj2 = new Object();
Object localVariableObj2 = new Object();
*** 成员变量有默认值不需要赋值null,本地变量没有默认值需要赋值null。
[b](6)通过class还是interface定义全局常量?[/b]
public final class Constants {
public static final int PI = 3.14;
}
public interface Constants {
int PI = 3.14;
}
还有这么定义的:
public interface Constants {
public static final String TOAST = "toast";
}
这些都是常见的,还有很多。