2012年6月21日星期四

资源的拥有权


资源的拥有权
     -- C++程序申请与释放资源小结

开篇先引用一下,《Effective C++》的条款16:成对使用new和delete时要采取相同形式。简单的示例就是下面这样的,如下:

  example 1.
     type* ptr = new type;
     ...
     delete ptr;


  example 2.   
     type* ptr = new[10] type;
     ...
     delete[] ptr;

 
  还有C语言的版本,如下:
example 3.
     type* ptr = (type*) malloc(sizeof(type));
     ...
     free(ptr);   
      
一条编程实践的经验条款,经如上的简单示例显得很简单,浅显易懂。类似地,我想在此延伸到另一点:在哪里申请资源,最后就在哪里释放资源吧。
PS. 这里提到的“哪里”,其实理解了模块更好一些。若缩小了(作用域)范围如函数显然不妥,做不到在函数A申请资源,又在函数A释放资源,毕竟资源是要提供给对外使用的。若“哪里”理解成类型,好像还可以如某工厂类,其负责对象的创建和析构。

比如说,在模块A申请资源R,资源R属于多模块B,C,D等共享的,那么最后应该同样在模块A释放资源R。
虽然,一般情况下你在其它模块最后使用完资源R之后即完成释放,不会出现什么问题,但是这样的逻辑看着也令人觉得也不合理乎。“某女人生的孩子,日子过着过着,结果孩子长大成人了,却客死他乡了。”多么令人遗憾,心生不妥啊。(额,我承认举得例子太言重,恐怖了)

某些情况下,这种做法(在其它模块是否资源R)明显会出现程序异常情况,如释放资源导致程序崩溃。

什么情况下呢?
答:当其它模块如B,C,D模块编译链接时候所使用的运行时库与模块A的不同,如VC++编译器的不同运行时库包括如下:
多线程 (/MT)
多线程调试 (/MTd)
多线程 DLL (/MD)
单线程 (/ML)
单线程调试 (/MLd)



还有另一种情况,更可能导致程序异常,模块A与其他模块使用着不同的内存分配器

所以,你应该(或必须)做到在同一模块申请和释放内存资源。如模块A存在这样成对接口:
resource* allocate_resourse(...);
void release_resourse(resource* res);

这样,不管模块A,或其他模块B,C,D若需要新的resource,即通过模块A接口allocate_resourse申请;若最后用完了resource,即通过模块A接口release_resourse完成释放。逻辑也足够简单。


忌讳、痛恨那种在模块A申请资源,却在其他模块做释放资源的。很可能,最后你(程序)怎么死的都不知道。
好吧,最后总结一句,资源的拥有权始终保持唯一性。

(完)

2012-06-18/ Junkun Huang.



2012年6月16日星期六

被入室盗窃的事记


被入室盗窃的事记
     -- 生活故事之2012-06 被入室盗窃


2012-06-01,由于那件令人费心费神的房屋租赁纠纷的事情,而且其过程还甚是漫长(去年10份开始算起),吾与同学共三人一同到法院去与那位‘无敌极品’房东继续对簿公堂。额,这件事情足以长篇大论一番,在此就不多详述了(已整理一大部分),待日后事情了结再完成吧。
诶,2012年六月份第一天,主要新闻如上,貌似挺友好的。还亏当天是六一儿童节啊!


可惜,没过几天后面的故事更加令人‘瞠目结舌’,生活常常会有一些事情出现让你措手不及啊,而且是那种你不喜欢碰到的不愿面对的……说到这点上,不禁让我想起以前的听过有意思的那么一句话,“生活总是有趣的,又很好玩的,而且常常喜欢玩(弄)我。”。好吧,转发我的两条微博,开始我的一段生活故事,如下:

晚上下班回家,发现家里遭贼了啊,丢失笔记本一台,一部G1手机,义雄和我是受害者!。报警能有用吗?报了。

报完警,被警察接到派出所备完案,然后再回家拍照取证等,折腾完都半夜十二点多快一点了,'惨不忍睹' 洗洗睡觉睡觉。困- - !

--------- 分割线 --------- 分割线 --------- 分割线 --------- 分割线 --------- 分割线 ---------

至此,什么样的故事应该大致清楚了吧,够杯具乎,不,餐具也!家里被入室盗窃了,主要损失即一台Thinkpad笔记本,一部智能手机。

零零碎碎地整理着描述一下吧,如下:
诶,这几天事情多费心费神的,各种折腾各种坎坷啊。
还有什么比家里遭贼了,被入室盗窃的,更坑爹的吗。


同学三人白天都上班,晚上下班,那天九点多到家我最早了,一会儿雄也回家了,然后才发现家里遭贼了。他的thinkpad笔记本连带电池,鼠标一套不见了(尼玛的,不这么谈心会死啊),然后我才发现我的那部落在家里的手机也不见了,被入室盗窃了……
奇怪的是,我的电脑竟然幸免了。唯一可以接受的原因就是,该小偷不敢或是不便一下子偷了带走两台笔记本,害怕容易暴露被发现、怀疑。可以继续推测,该小偷不是专业小偷,只是一个生活无赖的小偷。但他懂得同学的thinkpad比起我的acer高级,就选择了thinkpad,诶!

当天晚上果断出去找师傅换锁了。犹豫了会儿后还是报了警察(虽然心知此举在该国度效果不明显但还是报了吧算是寻求一点点心里慰藉),接着,跟同学又去了趟附近派出所录了笔供,再接着,与两位民警一同回家拍了照取了证。

种种迹象看来,那小偷有钥匙开门进来,入室盗窃的。门锁没有发现没撬动痕迹。
而且,那天早上我是最后一个出门上班的,清清楚楚记得自己反锁了两扇大门……刚好那天要带着垃圾出去丢了,出门时先放下垃圾袋在大门一旁然后锁门锁门……晚上回家时候,奇怪的发现两扇大门都没有发现,当时我没有在意以为同学先回家了吧。直到(上面描述情况)……发现情况不妙。

……

之前租房时候,雄问房东门锁是否安全,房东说已更换过了,当时他就这样算过去了。
(我也是事发之后,问起门锁安全吗,才听雄这么说起的 - -!唉。)
然后我们就匆匆忙忙地搬进来入住,当时没心思留意更换门锁这点,后来也忘了……直到被入室盗窃那天,都住了两个多月。

这次的租房,我当时各种忙碌没时间所以都让雄去操心租房的事情了,现在想想觉得我有点后悔与愧疚,当时我应该分担一些,多考虑些安全问题。

第二天早上,我询问隔壁的大妈,他们一大家子都住在隔壁一般都有人在家,问问道些情况,或许可以了解到线索。不料大妈说到情况,“昨天下午三点多我们家里灯亮着,外门关着,内门留着小缝隙而开着。”,“好像是09年还是10年时候,以前也是你们这件间屋子503遭贼被盗过笔记本和手机 …… ”

我当时听着有些恐怖毛骨悚然的感觉,照情况看来这小偷十成八九有着钥匙的,真的为之前两个月的日子捏了把冷汗啊,完全没安全感了!即使现在换好锁了安全感也大打折扣啊。


有朋友提醒,会不会你们房东自己安排干着的这趟事啊。不会,应该不会吧,但愿不会吧,否则我等完全败了!

虽然门锁已更换好了,但自身的安全感被严重打击受损了,所以这几天上班都开始背着本子一块上下班的,还好并不怎么重。估计还要持续背包上下班一段时间吧,至少把自己放心下来,安稳些日子吧。

这等糟糕的事情既然发生了,也报了警(中间虽然犹豫了会儿,知道后面也需要麻烦配合警方工作)。发了条微博说“……报警有用吗?报了。” 好多朋友纷纷回复,都质疑了报警的有效性。
少数的几个朋友表示理解,报了警可以为自己受损的心理图个小小的慰藉,或曰小小的希望吧。

其实,我就是这么个想法才报了警,暂且图个心理慰藉吧。Good luck!

20120606 / Junkun Huang.



(201206016 更新)

刚好这周六不必上班,所以跟附近警务室管理监控录像的工作人员预约了时间上午10点,到时我过去查看录像。唉,可惜的是盯着监控屏幕看到中午12点半,仍然未果,那些已有的监控录像实在是没法令人看出个啥毛线(锁)啊。虽然楼下安装了三个摄像头,但是那些都是楼房负责人私人安装的,警察那边问了负责人,话说录像没有保持了。擦,难道那几个摄像头是假的,忽悠人的吗!

上周六,同学雄已看了那些监控录像内容,未果。听着监控录像的工作人员说,请示警察去获取其他更有线索的监控录像资料,俺们就抱有希望警务人员能够联系到楼房负责人,获取到楼下最近摄像头的监控录像。额,这两天竟然说那三摄像头的监控录像都没保存。鸟啊!

而警察安装的那几个摄像头,倒是均有监控录像保持下来,可供查看。但是但是最最狗血的是,最靠近我们楼房的那个摄像头那天正好被某大妈晾的衣服给挡住了,我勒了个去啊,监控录像画面大部分被一件白色T恤挡住了,唉。所以,只能对着其他摄像头的监控录像查看了,而且只有一个靠谱一点,另外的真是相隔太远了。

至今天,之前心里对于警察办案抱有那一丝希望也抹灭去了。
洗洗去了啊,早点睡觉!

“生活总是有趣的,又很好玩的,而且常常喜欢玩(弄)我。” 

20120616 / Junkun Huang.

(完)


删接口,哥以后惹不起了。


# 删接口,哥以后惹不起了。 
     -- 越是稳定的产品项目,其接口越不予改动。

# 背景

今天遇到一件比较尴尬的工作上事情,虽然有些后悔,但也没有啥不好意思的。所以就想在此描述聊聊,吐吐内心里的小小“憋屈”。
其实,只是涉及一个小小的程序改动,不过故事倒是不短。那开始讲起……

最近工作上都挺忙的,事情多需要经常多线程切换操作,这边事情那边事情的:
负责日常项目管理事务(项目计划安排,组织开会讨论等),负责版本控制安排(版本统一编译,提测,配合打包等),负责项目开发工作,负责配合测试的工作(撰写需求、设计文档,梳理、解释、讨论设计逻辑等),负责解决问题(包括测试发现的问题,关注崩溃系统问题,用户反馈诡异问题等)。
(故事背景,当是讲故事前奏预热吧☺)

# 故事

前一阵子,某项目涉及一个接口的修改,而该接口为异步返回结果,描述如下:
原来,调用者不需要关心其返回结果。一个简单接口可以满足,
int set_xxx_func ( ... );

现在,新的需求决定调用者要关心其返回结果,调用之后调用者需要以轮循的方式查询结果。此时需要两个接口得以满足:
int submit_set_xxx_func ( ... );
int query_set_xxx_func ( ... );

PS. 至于这里为啥是轮循方式查询?在这里不是重点不需关心☺,具体的系统设计决定了这样的形式吧,不过当然是callback机制的效率高于一筹了!不再多说了,否则离题了。

说到这里还没有说到重点呢,改接口。后来因这样的新需求决定如上描述修改了该接口。记得在过(讨论)详细设计方案时候,开发测试四人(包括YJ,JL,SY还有我)都提到了是否保留原来接口set_xxx_func的问题,讨论中确认了已经没有其他产品,其他模块在使用该接口了,而且差不多已一年的时间没有使用到了吧,最后大家均同意了去掉该接口吧,直接上新的接口吧。因为该接口的模块一直都是跟着另一接口层模块DK一起发布的(该点是问题的所在),只要保证到时DK模块一块更新新的接口就万事大吉了。

好吧,那就果断去掉吧,我当然乐意了。作为开发人员,我已经难受很久那些“无用久已”的接口了,看着就觉得接口资源浪费在那儿,一个dll导出了四百多接口不少了吧,而且也碍着程序猿们查看代码啊。注意,这里带着当初一时比较重的个人感情色彩。汗。。

修改过程,与DK模块一并更新了新的接口设计,后面也完成了开发与测试,提测顺利完毕了。没出啥接口方面的问题,就不再关心了,以为没事就放心了。

差不多过了三周的时间吧。突然在今天下午,兄弟部门某同事突然报了一个问题到了欧爷(My TL)那边,转给了我。查了原因,他竟然使用了旧版的DK模块,Check不到老接口set_xxx_func了,囧,然后程序刻意做就地崩溃下来了。

这时,欧爷大怒了(可能夸张了点,其实情况还好吧)。痛批,“ Too simple,too stupid!,你们怎能去掉老接口呢,甚低级错误也“。

虽然某同事使用接口不当,但崩溃这种不良情况确实发生了,我有点愣住了,必须无条件承认自己过错了。奇怪,当初我们四人咋都同意了如此做法了呢。即使留着旧接口吧,也不崩溃。回想揣摩一下,”该接口的模块一直都是跟着另一接口层模块DK一起发布的“ 其实,这只是一条”一直以来都这样“的常识判断,而不是某确定的发布方案。

# 结果

情况还好,产品版本未发布,还在测试改错阶段。尽快恢复老接口,修补该问题即可。
越是稳定的产品项目,其接口越不予改动。

……
好吧,故事就讲到此吧。
所以,删接口,哥以后惹不起了。谨记!

晚安好梦。

(完)

20120615 / Junkun Huang.


2012年6月14日星期四

代码风格杂谈

代码风格杂谈


在此,想随便说说几句关于C++程序代码风格的话题。

以前,我所在的项目大组(下载库)的程序代码,基本都是C++代码,一直沿袭的代码风格大致情况描述,如下:

1,内部逻辑
Linux风格,统一小写字符配合下划线。该风格规范为内部使用的代码命名风格。

2,对外接口
驼峰风格,大小写字符配合,单词首字符大写。该风格规范为对外接口使用的代码命名风格。详细参考驼峰式大小写(维基)

大驼峰式命名法(upper camel case):
每一个单字的首字母都采用大写字母,例如:FirstName、LastName、CamelCase,也被称为Pascal命名法。


其实,我一直赞成,推崇这样的代码风格规范。关键一点,其做到了内部逻辑与对外接口之间的明显区分。

--------- 在此分割吧 ---------

现在(其实是去年九月份就开始制定了规则),我们所有涉及的新项目有关于C++代码,其风格均采用统一的“驼峰风格”。

不管内部逻辑与对外接口,函数命名规则均采用大驼峰式命名法
变量命名规则统一为,匈牙利命名法。


相比“以前”和“现在”,个人感觉“现在”不好的地方在于:
(程序的函数)不能从代码命名规则层次上,快速地区分出代码逻辑属于内部处理或对外暴露的。

话说回来了,既然当时讨论会议上,多数同事支持了“现在”的风格,规则已定下,那就安分遵循吧。

其实嘛,只要你在命名规则上做些善意的“手脚”,还是可帮助你较快地区分出其所属的内外逻辑,如:

void InnerFunc1();
void OutterFunc2();

如下示例只是简单说明情况,具体安排设计依具体情况而定。

     / 2012-06-10/ Junkun Huang.
--

最后,推荐良好的代码风格可参考,列表如下:








2012年6月11日星期一

盖茨将被历史铭记,乔布斯会被忘却?

盖茨将被历史铭记,乔布斯会被忘却?


文章最后总结的那一点,如下:
“他们并非有道德的领导者。如果他们是有道德的领导者,那么就不会成为伟大的商人。因此,当一名商人同时也是伟大的有道德的领导者时,那是因为他们保持着独立于公司业务以外的道德心。”
原来,慈善威武的地方正是如此,最终还是盖茨明智啊!

(转载如下)

纽约客:盖茨将被历史铭记 乔布斯会被忘却?


腾讯科技讯(童云)北京时间6月8日消息,《纽约客》杂志专职作家、曾是《华盛顿邮报》商务科学专栏作家的马尔科姆·格拉德威尔(Malcolm Gladwell)最近参加了在多伦多公共图书馆召开的苹果沙龙,他对美国文化中的企业家精神有一些有趣的深刻见解。
“在我们的文化中,我们尊敬企业家。”格拉德威尔说道。“他们是我们新的先知。让我们一个字一个字的来说吧:我们尊敬他们。如果你正在读有关伟大企业家的文学作品,那么可能会把它们当做‘肖像学’或是‘圣徒言行录’来读吧。”
那么,这些企业家是否值得这种高度的尊敬呢?格拉德威尔并不这样以为。
到最后,企业家受人尊敬的原因是他们如何帮助人类,而并非其大量赚钱的能力。他对传奇企业家比尔·盖茨(Bill Gates)和史蒂夫·乔布斯(Steve Jobs)进行了对比,以此作为一个例子:
“盖茨是最无情的资本家,然后有一天他起床后对自己说:‘够了。’然后他辞职,拿走了属于他的钱。”
“我鉴定地相信,在从现在算起的五十年以后,盖茨将因他在慈善事业方面所做的工作而被人铭记,而那时甚至没人会记得微软是什么。”
“而作为这一时代中的伟大企业家,乔布斯则将被人们忘却。谁是乔布斯?而盖茨的雕像则遍及整个第三世界。”
那么,象乔布斯这样的企业家为何不值得被偶像化呢?格拉德威尔指出,所有伟大的企业家都有一件事情是共通的。
“最伟大的企业家都是不分是非的。这并不是说他们是不道德的,而是说他们超越了是非。”他解释道。在2011年为《纽约客》撰写的一篇有关欧莱雅与纳粹德国之间交易的文章中,他曾说过这个问题。
“他们都是彻头彻尾的单细胞,着魔般的集中致力于他们企业的健康性。”格拉德威尔说道。“那让他们擅长建设企业,但也正因如此,他们才不值得受到这种程度的尊崇。”
“因此,当我们崇拜企业家时,我们需要搞清楚我们崇拜的是什么。”格拉德威尔说道。“他们并非有道德的领导者。如果他们是有道德的领导者,那么就不会成为伟大的商人。因此,当一名商人同时也是伟大的有道德的领导者时,那是因为他们保持着独立于公司业务以外的道德心。”

转载自这里

下载与上传速度计算的总结


下载与上传速度计算的总结
     -- 从良好的用户体验出发,速度计算乃一门艺术活儿。


# 背景说明

首先,背景说明一下,这里要探讨的速度涉及到两部分,一个下载速度,一个上传速度。

前段时间从事的一个项目开发,正好涉及到计算速度,要求在界面提供有速度的显示。刚开始认为要显示速度应该很简单的逻辑,计算公式如下:
download_speed = download_bytes / tick_time_count;
upload_speed = upload_bytes / tick_time_count;


照此,若要计算每秒的即时速度,只需获取每秒的流量差值结果即可,足够简单吧☺。
# 情况描述

但是,我们上面涉及的问题很单纯,忽略了产品设计细节上的很多东西,复杂的元素。
有必要先说明清楚我们产品的在统计速度方面,大致流程是怎么设计的,如下:
--
为了方便描述逻辑,在此先定义我们产品的两进程p1和p2,说明,p1负责具体的下载逻辑,p2负责下载展示与用户交互。
-- 1,p1进程实时更新流量统计值download_bytes,upload_bytes 。
     在系统应用层,毕竟下载与上传逻辑都是在p1进程直接处理,足以做到实时更新,提供准确信息。
  
2,p2与p1的通信均为异步-轮循机制。所以p2投递异步请求获取流量统计值,然后轮循尝试获取结果。
     两进程通信是单方面,只有p2向p1投递请求,而p2获取请求结果需要以定时轮循方式得以获取。
  
3,p2获到统计值download_bytes,upload_bytes ,与上次获取的流量统计值download_bytes’,upload_bytes ‘相比得到差值
 diff_download_bytes,diff_upload_bytes 。

4,p2同时取得p1返回流量时的时间戳tick_time_count,与上次的时间戳tick_time_count‘,相比得到差值diff_tick_time_count。

5, 差值与时间代入以上速度计算公式,最后得到速度值。
     download_speed = diff_download_bytes / diff_tick_time_count;
     upload_speed = diff_upload_bytes / diff_tick_time_count;

6,界面显示的速度值为6秒的平均速度,作为平滑效果的处理。
# 问题剖析

那么,产品上面具体的复杂细节在哪里?个人的总结可能不太全面,描述如下:

1,统计流量的地方与显示速度地方不在同一进程。
     p1负责流量统计而不涉及具体的速度计算,该点主要从逻辑分层方面考虑,一个属于功能逻辑,一个属于具体的业务逻辑。
     p2可以周期从p1获取流量统计值,根据具体场合计算所需的速度。

2,两进程通信为异步交互,存在堵塞导致延迟。
     由于下载与上传涉及逻辑诸多,p1进程需要处理的请求可能很多很多,导致p2获取流量的请求等到一段时间才得以处理返回,出现延迟现象。这样,请求时刻与计算速度的时刻出现较大的时差。
     其实,第二点是由第一点而引起的。

    

# 歇后语

像以上的情况,要想进程间的尽量同步(准确)显示速度,的确是一件考验的事情啊。

如同事振振所说的,”公司单独安排一同事负责这方面工作的研究,设计好速度显示的用户体验,也不为过。”

所以,从良好的用户体验出发,速度计算乃一门艺术活儿。



2012年6月7日星期四

生活玩你的故事(微博)

生活玩你的故事(微博)
 -- 201206 转自我的微博

故事零零散散碎碎,心情凄凄惨惨戚戚,围观如下:



报完警,被警察接到派出所备完案,然后再回家拍照取证等,折腾完都半夜十二点多快一点了,'惨不忍睹' 洗洗睡觉睡觉。困- - !

[图片]

-- 分割线 --
晚上下班回家,发现家里遭贼了啊,丢失笔记本一台,一部G1手机,义雄和我是受害者!。报警能有用吗?报了。
-- 分割线 --
Today,某故事又暂时告一段落,诶。不断“修身”淡然加明智,克制冲动与愤慨,在深圳与一’无敌极品‘房东的漫长而艰辛的故事。 #深圳中级法院#

Bless me,good luck!

(完)