C/C++编程-理论学习-考鼎录<解耦代码和数据>

解耦代码和数据的重要性

  1. 好处:
    1. 分开维护数据和代码(可维护性)
    2. 增加新的错误码,不需要修改代码(可维护性)
    3. 简化代码结构(代码质量)
    4. 提高执行效率(代码质量)
  2. 坏处
    1. 不太直观,降低可读性

结论:好代码是多次重构出来的!

注:工程师-发现问题,解决问题。设计东西。

手段

  1. 使用数组、枚举、宏定义等手段抽离、维护数据。(也可以索引值用枚举,字符串常量数据采用数组维护,数据也再次进行一次拆分)
  2. 为避免手误,或者程序、数据分离造成的两处更改不一致问题,使用编译器断言避免出现未有效维护的情形。

注:通常是更改数据,但是代码也需要更改,但是没有两者不对应,为了能保证两者对应采取的手段。

更复杂的情形

  1. 有如下格式的消息数据包
type:request
target:session/0
operation:create_plain_window
requestId:d56464ed464566d655s56544465dd644f
dataType:ejson
dataLen:<length of data in bytes>

{
	workspace: 3456789,
	name: "_current",
	title: "Hello, world!",
	class: "normal",
}
  1. 希望解析为如下的数据结构
typedef enum{
	PCRDR_MSG_TYPE_REQUEST = 0,
	PCRDR_MSG_TYPE_RESPONSE,
	PCRDR_MSG_TYPE_EVENT,
} pcrdr_msg_type;

typedef emum{
	PCRDR_MSG_TARGET_SESSION = 0,
	PCRDR_MSG_TARGET_WINDOW,
	PCRDR_MSG_TARGET_TAB,
	PCRDR_MSG_TARGET_DOM,
}pcrde_msg_target;

typedef enum{
PCRDR_MSG_ELEMENT_TYPE_VOID = 0,
PCRDR_MSG_ELEMENT_TYPE_CSS,
PCRDR_MSG_ELEMENT_TYPE_XPATH,
PCRDR_MSG_ELEMENT_TYPE_HANDLE,
}pcrdr_msg_element_type;

pcrdr_msg_type pcrdr_message_get_type(const pcrdr_msg *msg);

typedef enum{
	PCRDR_MSG_DATA_TYPE_VOID = 0,
	PCRDR_MSG_DATA_TYPE_EJSON,
	PCRDR_MSG_DATA_TYPE_TEXT,
}pcrdr_msg_data_type;

struct _pcrdr_msg{
	pcrdr_msg_type			type;
	pcrde_msg_target		target;
	pcrdr_msg_element_type	elementType;
	pcrdr_msg_data_type		dataType;
	unsigned int			retCode;

	uintptr_t				targetValue;
	char *					operation;
	char *					element;
	char *					property;
	char *					event;

	char *					requestId;

	size_t					dataLen;
	char *					data;
};

  1. 通过键值,返回特定数据类型
  2. 通过键值,索引函数指针
/* 构造方法和自己通常用的构造列表一样,前面索引值,后面函数指针 */

/**
* 优化
* 1. 使用二分查找法优化find_key_op 函数
* 2. 此方法也适用于稀疏整数集合
* 3. 通过sorted-array实现
* /
static key_op find_key_op(const char* key)
{
	/* 巧用static, 编译阶段计算出,赋值给static */
	static size_t max = sizeof(key_ops)/sizeof(key_ops[0]) -1;
	size_t low = 0,high = max, mid;
	while(low <= high)
	{
		int cmp;
		mid = (low +high) / 2;
		cmp = strcasecmp(key, key_ops[mid].key)
		if (cmp == 0)
		{
			goto found; 
		}
		else{
			if (cmp < 0)
			{
				high = mid - 1;
			}
			else
			{
				low = mid + 1;
			}
		}
	}
	return NULL;

	found:
		return key_ops[mid].op;
}

终极大法

用脚本生成代码:

  1. 让程序处理大量的重复性编码工作,避免手工编写引入错误
  2. 处理字符串时,字符串较多时,二分查找性能不高,可以用哈希表;
  3. 用脚本,可以找到一个相对均衡的哈希算法
  4. 依赖构建系统自动维护代码的重新生成

一个例子

  • 如何快速获取CSS属性(如width、height、color)的内部属性信息?
  • 我们准备一个描述文件
  • 然后用python脚本处理这个文件并自动生成代码
/* 描述文件内容 */
background-attachment
	values: scroll fixed inherit
	initial: scroll
	inherited: no
background_color
	values: <color> inherit
	initial: transparent
	inherited: no
......
"""
Make CSS property value macros:
	1. Read 'propertylist.txt'file
	2. Generate CSS property identifier list(enum)
	3. Generate CSS property value keyword list(enum)
	4. Generate CSS property value macros
	5. Write code to 'csspropertyvalue.inc','cssdeclared.inc',and'cssinitial.cc'files 
"""
/**
* 生成的源文件
* 1. 样式的属性值定义
* 2. 样式属性操作函数
* 3. 样式的初始化
*/

/* 样式的属性值定义 */
typedef enum _CssPropertyIds {
// background-attachment
PID_BACKGROUND_ATTACHMENT,
// background-color
PID_BACKGROUND_COLOR

......
}

typedef enum _CssPropertyValueTypes {
PVT_NONE = 0,
PVT_KEYWORD,
......
}

/* 生成操作函数 */
bool setBackgroundIamge(Uint32 value ,HTInt data){
 return Css::setProperty (PID_BACKGROUND_IMAGE, value, data);
}
......

/* 初始化 */
#include "css/cssinitial.h"

namespace hfcl {
CssInitial* CssInitial::s_singleton = NULL;

CssInitial::CssInitial()
{
	memset(&m_data, 0 ,sizeof(m_data));
	memset(&m_arraysize, 0, sizeof(m_arraysize));
	//Initial value
	m_values[PID_BACKGROUND_ATTACHMENT] = MAKE_CSS_PPT_INITIAL_VALUE(CSS_PPT_VALUE_MARK_)
}

....

}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值