程序员心法三则

原创
2013/04/04 00:44
阅读数 2.9K

  本文不是介绍奇技淫巧,甚至本质上并不是技术,而是态度,心法。

1、抓住问题的本质,在源头解决问题

  简单地说,A 有八哥,B 依赖 A,所以导致依赖 B 的 C 出问题,您会通过修改 B 来解决问题吗?正常人都知道要先解决 A 的八哥,蛋似,稍微复杂、含蓄点的问题就有人迷糊了:

  一个浮动小窗体,不希望在任务栏上出现标签。

  UMU 见过有人使用了 ITaskbarList 对象的 DeleteTab 方法来删掉任务栏上的标签,很高端的做法。蛋似,不够本质,我们要的是不让它出现,而不是出现后擦掉……很早以前,explorer.exe 挂掉后,任务栏通知区域的 QQ 图标就消失了,因为当时 QQ 没有处理任务栏重建的通知消息 TaskbarCreated,重新添加图标。前面说的方法,有同样的问题,explorer.exe 重启后,标签又会出现,还要再删除一次。

  正确的主流做法有两个,看情况采用:(1)、WS_EX_TOOLWINDOW;(2)、指定一个隐藏窗体为自己的拥有者。

  另一个脱裤子放屁的例子:获得一个文本文件大小,然后 new 一个够大的 char 数组 p,把内容读到 p 上,最后 ::std::string str = p; delete[] p;,这个见太多次了,懒得喷了,::std::string 有 resize 方法,可以直接分配,不需要 new 一个临时数组,再 delete……

  《判断系统是不是 XPhttp://my.oschina.net/umu618/blog/98039,也包含了这一哲学,表面上看有好多函数可以获得系统信息,但要明白他们的本质其实有差别,不是都可以混用。

2、要有远见,没有?至少不要不见棺材不落泪!

  Y2K 已经过去了,但还有一个 Y2K38,又称 Unix Millennium Bug,历史原因 Unix 时间戳是一个 32 位整数,记录从 1970 年 01 月 01 日开始的秒数,它所能保存的最大时间长度大概是 68.1 年,2038 年 1 月 19 日 03:14:07 之后。
 
    以前硬盘容量小,也不看高清,很多代码都认为文件大小用 32 位表示就够了,结果后来出现很多 ISO、高清电影,都超过 4G……还见过有人采集流量用 32 位整形表示,时间跑久了就溢出了。

    远见未必人人都有,退一步说,UMU 敢保证,有很多人即使知道 32 位不够用,还是继续用着,明知道 IPv6 已经出现了很久,还是各种硬编码,认为 IP 地址一定是 IPv4 的地址。态度问题!

3、不要姑息养奸

    遇到不合理的情况,UMU 认为应该给力地告诉该知道的人。比如,函数不希望入参是某指,可是调用者偏偏就输入了那个值,怎么办?打印调试信息?不够给力,容易被忽视,应该中断一下,告诉开发者。

    配置文件字段被改错,怎么办?如果这个文件是技术人员维护的,应该抛出异常,死给修改配置文件的人看;如果是一般的最终用户,那应该弹出界面,友好提示哪里、怎么错了。

    早期,很多程序员为了避免头文件被重复包含,就用了以下代码:

#ifndef XXX
#define XXX
// 各种语句
#endif

 

    后来,大家喜欢用 #pragma once,省事,又不容易漏掉最后的 #endif。但是这样做之后会……姑息养奸,对严谨的人来说,重复包含是不应该的!所以应该这样:

#ifdef XXX
#error "您不严谨了!"
#endif
#define XXX
// 各种语句

    有重复包含立刻告警,而且都是集中在开头,不存在漏掉 #endif 的问题。

    态度问题!这里只是举几个简单的例子~

展开阅读全文
打赏
0
72 收藏
分享
加载中
UMU博主

引用来自“郭煜”的评论

引用来自“UMU”的评论

引用来自“郭煜”的评论

引用来自“UMU”的评论

引用来自“郭煜”的评论

比如一个功能table要用到list,然后又有个功能要给table做一个list。实现这个功能的时候为了避免重复包含,所以要去了解table的实现部分细节,然后等要给这个table的list再做一个list的时候,又要倒回去了解前面两者的部分细节。等项目大了之后,为了不重复包含,要增加很多不必要的工作,而语言本身提供了这个功能。

我怎么觉得没有您说的这样的情况呢?您在两个 cpp 里写了一样的包含语句,这并不是重复包含。

项目还不够复杂吧。不是cpp就是头文件。

即使都写在hpp里,您都已经知道这些功能的包含关系了,就应该知道怎么包含最少的h了,不小心多包含没必要的,刚好会提醒,这能帮助您搞明白设计。如果关系是乱网状的,说明设计不够清晰,或者不适合hpp,还是改为cpp好。

不可能所有模块都完全分层,最明显的是工具类的代码,经常穿插在各个地方被使用。

这个有道理,是有很多现有的工具类如此,不过我自己写的都按这个规范来,真没有遇到什么麻烦,这个规范也是和github上的高手学的,不过必须承认,我做的项目没有需要写像stdio这样基础的工具类。
这个规范应该是合适比较高层次的模块,太基础的不适合。
2013/04/10 23:54
回复
举报

引用来自“UMU”的评论

引用来自“郭煜”的评论

引用来自“UMU”的评论

引用来自“郭煜”的评论

比如一个功能table要用到list,然后又有个功能要给table做一个list。实现这个功能的时候为了避免重复包含,所以要去了解table的实现部分细节,然后等要给这个table的list再做一个list的时候,又要倒回去了解前面两者的部分细节。等项目大了之后,为了不重复包含,要增加很多不必要的工作,而语言本身提供了这个功能。

我怎么觉得没有您说的这样的情况呢?您在两个 cpp 里写了一样的包含语句,这并不是重复包含。

项目还不够复杂吧。不是cpp就是头文件。

即使都写在hpp里,您都已经知道这些功能的包含关系了,就应该知道怎么包含最少的h了,不小心多包含没必要的,刚好会提醒,这能帮助您搞明白设计。如果关系是乱网状的,说明设计不够清晰,或者不适合hpp,还是改为cpp好。

不可能所有模块都完全分层,最明显的是工具类的代码,经常穿插在各个地方被使用。
2013/04/10 19:17
回复
举报

引用来自“UMU”的评论

引用来自“郭煜”的评论

引用来自“UMU”的评论

引用来自“郭煜”的评论

比如一个功能table要用到list,然后又有个功能要给table做一个list。实现这个功能的时候为了避免重复包含,所以要去了解table的实现部分细节,然后等要给这个table的list再做一个list的时候,又要倒回去了解前面两者的部分细节。等项目大了之后,为了不重复包含,要增加很多不必要的工作,而语言本身提供了这个功能。

我怎么觉得没有您说的这样的情况呢?您在两个 cpp 里写了一样的包含语句,这并不是重复包含。

项目还不够复杂吧。不是cpp就是头文件。

即使都写在hpp里,您都已经知道这些功能的包含关系了,就应该知道怎么包含最少的h了,不小心多包含没必要的,刚好会提醒,这能帮助您搞明白设计。如果关系是乱网状的,说明设计不够清晰,或者不适合hpp,还是改为cpp好。

等规模到一定程度,合作的时候照着案例写代码就够了,非要去了解所有的调用细节有时候会比较浪费时间。最简单的例子,参考stdio.h和stdlib.h。
2013/04/10 19:15
回复
举报
UMU博主

引用来自“郭煜”的评论

引用来自“UMU”的评论

引用来自“郭煜”的评论

比如一个功能table要用到list,然后又有个功能要给table做一个list。实现这个功能的时候为了避免重复包含,所以要去了解table的实现部分细节,然后等要给这个table的list再做一个list的时候,又要倒回去了解前面两者的部分细节。等项目大了之后,为了不重复包含,要增加很多不必要的工作,而语言本身提供了这个功能。

我怎么觉得没有您说的这样的情况呢?您在两个 cpp 里写了一样的包含语句,这并不是重复包含。

项目还不够复杂吧。不是cpp就是头文件。

即使都写在hpp里,您都已经知道这些功能的包含关系了,就应该知道怎么包含最少的h了,不小心多包含没必要的,刚好会提醒,这能帮助您搞明白设计。如果关系是乱网状的,说明设计不够清晰,或者不适合hpp,还是改为cpp好。
2013/04/09 23:27
回复
举报

引用来自“UMU”的评论

引用来自“郭煜”的评论

比如一个功能table要用到list,然后又有个功能要给table做一个list。实现这个功能的时候为了避免重复包含,所以要去了解table的实现部分细节,然后等要给这个table的list再做一个list的时候,又要倒回去了解前面两者的部分细节。等项目大了之后,为了不重复包含,要增加很多不必要的工作,而语言本身提供了这个功能。

我怎么觉得没有您说的这样的情况呢?您在两个 cpp 里写了一样的包含语句,这并不是重复包含。

项目还不够复杂吧。不是cpp就是头文件。
2013/04/08 21:33
回复
举报
UMU博主

引用来自“郭煜”的评论

比如一个功能table要用到list,然后又有个功能要给table做一个list。实现这个功能的时候为了避免重复包含,所以要去了解table的实现部分细节,然后等要给这个table的list再做一个list的时候,又要倒回去了解前面两者的部分细节。等项目大了之后,为了不重复包含,要增加很多不必要的工作,而语言本身提供了这个功能。

我怎么觉得没有您说的这样的情况呢?您在两个 cpp 里写了一样的包含语句,这并不是重复包含。
2013/04/08 10:19
回复
举报
比如一个功能table要用到list,然后又有个功能要给table做一个list。实现这个功能的时候为了避免重复包含,所以要去了解table的实现部分细节,然后等要给这个table的list再做一个list的时候,又要倒回去了解前面两者的部分细节。等项目大了之后,为了不重复包含,要增加很多不必要的工作,而语言本身提供了这个功能。
2013/04/07 22:51
回复
举报
UMU博主

引用来自“郭煜”的评论

引用来自“UMU”的评论

引用来自“郭煜”的评论

重复包含是必须要被支持的。

看情况了,要和一个项目组约好,大家一起执行就是。看这个例子:
https://github.com/webcoyote/coho/blob/master/Base/List.h
和我现在遵守的规范一样,不允许重复包含

除了您说的“不严谨”,重复包含会产生什么问题?

对程序没有。很多朋友都告诉我这个东西没用,我也这么觉得,但我提出来,是要告诉大家,我们是一个什么样的公司,这是一种情怀。
2013/04/06 22:28
回复
举报

引用来自“UMU”的评论

引用来自“郭煜”的评论

重复包含是必须要被支持的。

看情况了,要和一个项目组约好,大家一起执行就是。看这个例子:
https://github.com/webcoyote/coho/blob/master/Base/List.h
和我现在遵守的规范一样,不允许重复包含

除了您说的“不严谨”,重复包含会产生什么问题?
2013/04/06 20:52
回复
举报
UMU博主

引用来自“郭煜”的评论

重复包含是必须要被支持的。

看情况了,要和一个项目组约好,大家一起执行就是。看这个例子:
https://github.com/webcoyote/coho/blob/master/Base/List.h
和我现在遵守的规范一样,不允许重复包含
2013/04/06 19:28
回复
举报
更多评论
打赏
15 评论
72 收藏
0
分享
返回顶部
顶部