代码规范中常见问题举例说明

1、背景说明

虽然不止一次说明代码规范的问题,但是在协同作战的时候,代码规范这问题总是被遗忘,希望大家能够引以为戒。协同作战的时候,如果不能遵守代码规范,很容易出现各种问题,而且不知道从何处入手解决,消耗时间成本。

实际上,对于代码规范这种问题,应该有人专门来审核代码的,但是公司小,项目也不大,参与的人员也不多的情况下,绝大多数公司都没有这种机制,尤其是在移动端编程上面 ,这就需要开发人员自我监督,避免出现不必要的麻烦。

本文就举例说明,在近期笔者所带领的团队协作中,出现的一些问题。

2、命名

2.1 控件名称

笔者在合并代码的过程中,看到如下的一段代码,大家注意看看id命名:

<TextView
        android:id="@+id/zongnumber"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="0dp"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="6dp"/>

这种id的命名方式,是不被认可的,程序会报错,但是不符合我们约定俗成的规范,建议的规范是:模块名_控件简称_功能名

2.2 实体名称

看到一个实体类的命名为:

Part_3_JsonBean

看到这个,我也是醉了。首先,类名要使用驼峰标识,中间不要出现下划线;其次,除了to可以用2,for可以用4表示,一律不允许使用数字在类中表示;第三,part加上数字这种命名没有任何的实际标识意义,看到这个类也很茫然,尽量不要使用。

jinriremen_gridview.xml

这样的xml文件命名方式,也是不符合规范的,看半天,才意识到这说的是“今日热门”,凡事有直接英文翻译的,简单的单词,统统使用英文命名,today,hot这都很简单呀,单词之间全部用下划线分开,不然读起来很困难。

getExit();

这个是一个方法的命名,实际表示的意义,是退出程序。好吧,set和get方法,只能用在赋值和获取值这种方法上,其他方法,一律不要使用!!!其次,这种意思是说调用何种方法的方法名,或者使用go,或者使用on,不要使用get。

3 代码要简洁

代码要简介,意思是说,能够一句话写完,就不要分开成两句话,那么我们看看,如下两个例子:

3.1 不够简洁

这里提供一段代码,如下所示:

Intent intent = new Intent();
intent.putExtra("detail", detail.getText().toString());
intent.setClass(mActivity, NewestActivity.class);
startActivity(intent);

我们再看看,这段代码如何简化:

Intent intent = new Intent(getActivity(), NewestActivity.class);
intent.putExtra("detail", detail.getText().toString());
startActivity(intent);

从API文档中,很明显得知这个方法有构造方法,那么尽量优先使用构造方法,这样出错的可能性更小。这是规范性问题。

3.2 乱用简洁

有时候,程序员误以为,简洁就是所有代码都写在一行,所有的同类项都可以合并,这是不对的,我们举例如下:

public static class ViewHolder {
	public ImageView remen_gallery_img;
	public TextView title, zongnumber, canyu, shenyu, detail;
	public ProgressBar progressBar;
}

这段代码中,我们的程序员将TextView的多个控件写在一行上,这是不科学的。每一个控件都表示的不同含义,严格来说,字段都需要添加doc注释。所以,除了表示同一个含义的字段,可以使用集合或者数组表示之外,其它的都需要单独声明。

4、字段注释

这里就不过多解释了,上面已经说了,严格来说需要使用doc注释。先上一个反例:

public class JsonBean {
	private String already = null; // 以参与人数
	private String thumb = null;
	private String title = null;
	private String detail = null;
	private String total = null;// 总参与人数
	private String remaining = null;// 剩余人数
	private String issue = null;// 期数

	public JsonBean() {
		// TODO Auto-generated constructor stub
	}
}

这种在后面添加注释,不能说错,但是不那么严格。这里提供的是一个实体对象,那么这个对象除了字段之外,只有get和set方法了,我们在外部调用的时候,需要将鼠标移动在这个字段上,就知道字段表示什么含义,这里,给出一个规范:

public class UserBean {

	/** 参与次数 */
	private int count;
	/** 用户名 */
	private String username;
	/** 开奖时间 */
	private String publish_time;
	/** 用户ID */
	private String user_id;
	/** 幸运号码 */
	private String luck_num;
	/** ip地址 */
	private String ip;
	/** 头像 */
	private String head_picture;
	/** 抢单时间 */
	private String create_time;

	public UserBean() {
		// TODO Auto-generated constructor stub
	}
}

最后说明一点,字段前面的修饰符,一律使用private,这里是封装的特性体现。其次,一定要添加默认的构造方法,不能只写一个有参数构造方法,编译器如果识别到有参构造方法,不会再提供默认构造方法。有很多时候,我们传递参数的时候,是允许缺省的,所以一定要提供默认构造方法。

5、方法模块化

一个方法里面,尽可能只做一件事情,不要同时执行了很多不同的事情,尤其是不要再一个方法,嵌套多层的网络请求,案例如下:

/**
 * 请求json数据
 * **/
private void setJson(){

	new Thread(new Runnable() {

		@Override
		public void run() {
			try {
				String json = HttpRequestUtils.doGet(PublicUtils.EG_URL + "/index");
				JSONObject response = new JSONObject(json);
				String msg = response.optString("msg");
				JSONObject object = new JSONObject(msg);
				String part_1 = object.optString("part_1");
				String part_2 = object.optString("part_2");
				String part_3 = object.optString("part_3");
				JSONArray array2 = new JSONArray(part_1);
				JSONArray array3 = new JSONArray(part_2);
				JSONArray array4 = new JSONArray(part_3);
				lists1 = new ArrayList<Part_1_JsonBean>();
				lists2 = new ArrayList<Part_2_JsonBean>();
				lists3 = new ArrayList<Part_3_JsonBean>();
				/** 解析part_1数据 **/
				for (int j = 0; j < array2.length(); j++) {
					// 代码省略
				}

				Message message = new Message();
				message.what = 200;
				handler.sendMessage(message);

				/** 解析part_2数据 **/
				for (int j = 0; j < array3.length(); j++) {
					// 代码省略
				}
				Message message2 = new Message();
				message2.what = 201;
				handler.sendMessage(message2);

				/** 解析part_3数据 **/
				for (int j = 0; j < array4.length(); j++) {
					// 代码省略
				}
				Message message3 = new Message();
				message3.what = 202;
				handler.sendMessage(message3);

			} catch (JSONException e) {
				e.printStackTrace();
			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}).start();
}

这段代码中,是说的设置json字符串,但是先要开启网络请求,网络请求也是非常耗时的,应该单独开线程。等得到返回的json字符串之后,再用一个线程处理设置数据,而这个方法就将两者合并在一起了,这样的编程习惯就不是那么好了。

修正案例如下:

/** handler消息处理机制 */
private Handler handler = new Handler() {
	public void handleMessage(android.os.Message msg) {
		switch (msg.what) {
		case ConstantValues.GET_NET_SUCCEED:
			jsonString = (String) msg.obj;
			if (jsonString != null && !jsonString.equals("")) {
				new DelJsonThread().start();
			} else {
				Logger.ii(TAG, "There is no data");
			}
			break;
		case ConstantValues.GET_NET_FAILED:
			// 获取网络失败
			break;
		case ConstantValues.DEL_RESULT_SUCCEED:
			listView.setAdapter(new HistoryListAdaptet(list,
					HistoryActivity.this));
			break;
		case ConstantValues.DEL_RESULT_FAILED:
			// 字符串处理失败
			Logger.ii(TAG, "del result failed");
			break;
		default:
			break;
		}
	}

};

if (!StringUtils.isEmpty(url)) {
	HttpGetThread httpGetThread = new HttpGetThread(handler, url);
	new Thread(httpGetThread).start();
}

网络请求代码,和处理返回json的线程类DelJsonThread()这里就不在提供了。

6、逻辑处理

在代码规范中,逻辑处理也是比较难遵守的,因为在测试的时候很难出现。这里的逻辑问题,主要是空指针这样的问题,主要有以下几个方面:

6.1 异步加载图片

这里使用的是开源组件,如果url为空的时候,会在后台提示异常。

ImageLoader.getInstance().displayImage(url,holder.remen_gallery_img, options);

if (!StringUtils.isEmpty(url)) {
	ImageLoader.getInstance().displayImage(url,holder.remen_gallery_img, options);
}

6.2 从上一个界面获取数据

我们从一个Activity跳转到另一个Activity的时候,会使用如下方法获取数据,这里都需要做判断:

String url = getIntent().getStringExtra("history");
if (!StringUtils.isEmpty(url)) {
	HttpGetThread httpGetThread = new HttpGetThread(handler, url);
	new Thread(httpGetThread).start();
}else{
	handler.sendEmptyMessage(ConstantValues.THE_URL_ERROR);
}

6.3 处理JSON字符串

当我们向服务器发出请求,服务器返回一段字符串,这个时候,我们需要先判断一下数据是否正确:

if (jsonString != null && !jsonString.equals("")) {
	new DelJsonThread().start();
} else {
	Logger.ii(TAG, "There is no data");
}

空指针异常还有许多情况,逻辑判断也有其它很多情况,比如,有了if,最好要添加else;在try-catch中,不要直接返回总异常,而要得到网络请求异常,数据错误异常,端口连接异常等等情况,不要偷懒,不然程序运行的错误要找很久才会发现。

7、总结

程序开发的规范,是一个很考验程序员功力的问题,希望大家一开始就养成良好的习惯。

以上,是笔者在公司做指导开发的时候,发现的一些问题,从中截取了一些代码。这里只是提供一些说明,并不提供完整可运行的程序,希望读者自己注意。

时间: 2024-10-10 20:43:47

代码规范中常见问题举例说明的相关文章

解读阿里官方代码规范

2017年开春,阿里对外公布了「阿里巴巴Java开发手册」.作为一个13年经验的码农,从头到尾浏览了一遍这份手册之后,感觉很棒.虽然其中的某些观点笔者不能苟同,但大部分的规范还是值得绝大多数程序员学习和遵守的. 笔者将对这份代码规范中的一些细节做一些解读,包含笔者的观点和想法,可以作为这份代码规范的扩展阅读.对于规范中某些「显而易见」的条款,将不在解读范围之列(换言之,这都不懂,就说明你天赋不够,乘早别做程序员了). 当然,笔者在日常的编程过程中属于「代码洁癖偏执狂」,所以文中的某些观点仅代表个

代码规范及代码复审

1.对代码规范的讨论 编写一个程序是否需要代码规范?本人以为,规范当然得有,但也必须合理. 为什么我们需要代码规范?代码规范就是规定代码中某些格式必须遵守一定条件,比如缩进.变量命名.注释等.当制定了合理的规范后,不仅代码本身会显得美观,而且每个人都很容易读懂,代码的可维护性也大大增强.举个例子,甲程序里使用的变量名有input_msg,output_msg,decipher,每个符号之间均加了空格,而乙程序里则是随意地使用a,b,c等无意义的字母作为变量名,而且多个函数里重复使用相同名称的局部

个人博客作业2 - 代码规范讨论与个人项目代码审查

对于是否需要有代码规范,请考虑下列论点并反驳/支持: 这些规范都是官僚制度下产生的浪费大家的编程时间.影响人们开发效率, 浪费时间的东西. 我是个艺术家,手艺人,我有自己的规范和原则. 规范不能强求一律,应该允许很多例外. 我擅长制定编码规范,你们听我的就好了. 对于论点1,我认为是不正确的.对于一个独立的开发者来说,代码风格可以完全遵从个人意愿,代码规范也没有存在的必要,强调代码规范可能睡些许降低个人的开发效率.但是现代软件工程中,一个开发团队往往少则几个人,多则数百人,一个项目需要多个人同时

JavaScript必备:Google发布的JS代码规范(转)

[翻译]关于Google发布的JS代码规范,你需要了解什么? 翻译 | WhiteYin 译文 | https://github.com/WhiteYin/translation/issues/10 Google为了那些还不熟悉代码规范的人发布了一个JS代码规范.其中列出了编写简洁易懂的代码所应该做的最佳实践. 代码规范并不是一种编写正确JavaScript代码的规则,而是为了保持源代码编写模式一致的一种选择.对于JavaScript语言尤其如此,因为它灵活并且约束较少,允许开发者使用许多不同的

从任正非公开信说起,谈代码规范的重要性!

最近的1月2号,任正非发布了题为<全面提升软件工程能力与实践,打造可信的高质量产品>致全体员工信,这也是今年华为总裁办签发的2019年001号文件.在信中,任正非强调了高质量软件产品的关键特性,呼吁各软件工程师理解架构的核心要素.重视代码质量.遵循业界共识的标准和规范,并计划用5年时间投入20亿美元全面提升华为软件质量. 任正非的公开信 在我的印象中,关于某某公司宣布重金投入一个领域.一个产品的新闻有很多,比如某度和某米的all in:但华为这次却很不一样,20亿美元的投入点居然单纯是冲着软件

go语言代码规范指南

本规范旨在为日常Go项目开发提供一个代码的规范指导,方便团队形成一个统一的代码风格,提高代码的可读性,规范性和统一性.本规范将从命名规范,注释规范,代码风格和 Go 语言提供的常用的工具这几个方面做一个说明.该规范参考了 go 语言官方代码的风格制定. 一. 命名规范 命名是代码规范中很重要的一部分,统一的命名规则有利于提高的代码的可读性,好的命名仅仅通过命名就可以获取到足够多的信息. Go在命名时以字母a到Z或a到Z或下划线开头,后面跟着零或更多的字母.下划线和数字(0到9).Go不允许在命名

【Android 应用开发】 Android 相关代码规范 更新中 ...

. 简介 : Android 常用的代码结构, 包括包的规范, 测试用例规范, 数据库模块常用编写规范; 参考 : 之前写的一篇博客 [Android 应用开发] Application 使用分析 ; -- Application 分析 : Application 概念, 声明周期, 组件间传递数据作用, 数据缓存作用; -- 源码分析 : 分析 Application 结构接口源码; -- 使用示例 : 自定义 Application 注册, 保存崩溃日志到文件, 监听Activity声明周期

iOS中书写代码规范

1.精简代码, 返回最后一句的值,这个方法有一个优点,所有的变量都在代码块中,也就是只在代码块的区域中有效,这意味着可以减少对其他作用域的命名污染.但缺点是可读性比较差 NSURL *url = ({ NSString *urlString = [NSString stringWithFormat:@"%@/%@", baseURLString, endpoint]; [NSURL URLWithString:urlString]; }); 2.关于编译器:关闭警告: #pragma

opp思想、代码规范、单例模式、php中引号问题以及include用法

关于OPP(Object Oriented Programming(此内容参照百度百科)): 面向对象程序设计不同于面向过程程序设计,它将一件复杂的事情拆分成一个一个的块对象,然后对块进行分析,实现块级的动作.最后把一个一个的块像搭积木一样组成复杂的事件.可以说,OPP大大地降低了软件开发的难度. OPP达到了软件工程的三个主要目标:重用性.灵活性和扩展性. OPP的主要特性: **抽象性 -- 程序有能力忽略正在处理的信息某些方面的能力.也就是说对信息某些主要方面关注,次要方面忽略. 信息封装