2009年6月21日
2009年6月的一天,我在甲方办公室加班调试程序,笔记本的屏幕只有12英寸,我得不停地在调试器和编辑器之间切换,观察断点的执行情况,发现代码中的问题。在那一刻,我突然觉得所做的完全是
低水平重复工作。
1. 对业务流程不熟悉,对自己的代码不熟悉,编译运行后不能预测结果。
2. 做管理软件,重复性工作太多。
3. 技术视野有限,不能从一个更广的角度去看待问题。
对于第一个问题,首要要求在写完代码后做review,把代码详细读一遍想一遍,确认无误后才编译。review要随时地做,写完一个函数完成一个功能块,都要检查,想一想这段代码在整个业务流程中的位置。对代码做到心中有数,而不至于不停的开调试器(调试器是一个效率低下的缘由之一)。
重复性工作多,这个是管理软件固有属性,能否将重复性的工作抽离出来?在之前的项目中,做了很多这方面的尝试。有一定成效。但另一方面,由于经验不足,强扭地将一些个性化的东西抽离出来,最后代码组织结构混乱。要达到重用,有很多条路可以达到,但由于技术的积累不够,看到一条路就以为这条路是最好的,一往无前地闯过去。其实还有很多更好的选择,只是因为技术积累不够,而工期紧张,没得选了。
视野有限,所看到仅仅是所写的,而不能引发更加广度的联想。比如说在asp.net中的master页面,自定义控件,管理软件三层架构的优势,mvc等等。没有深刻地了解和实际的体验,在项目中自然无法联想到。所以只能做一些简单的重复工作。
posted @
2009-06-21 20:18 ronliu 阅读(313) |
评论 (0) |
编辑 收藏
2009年3月11日
在日常生活中,经常有大量的文本需要处理,正则表达式正是基于此提出的。本文将结合一些具体的实例来解释它。虽然在不同的语言环境中,正则表达式有不同的语法规则,但其基本语义却是一致的。http://en.wikipedia.org/wiki/Regular_expression。这将是一个系列教程。本节只是一个开胃菜:)
某一次同学很无聊,然后问我电脑上有无小说。这是显然的,我是网络小说迷嘛!从起点down下无数小说存在电脑上,名字都懒得改,都是以数字打头,然后以“.txt”结尾,比如23432.txt之类的。当然,文件查找还是得用Everything,要不然电脑上的上百万个文件,手会抽筋的。
(注:我以为Everything是史上最快的文件查找工具,强烈推荐!)
先用"*.txt"尝试一下,:(,给出一大堆文本文件呀。范围太广。还是得用正则表达式来。
^[0-9]*\.txt
Yes!给出了我电脑上存储的所有小说了。
解释一下:
^[0-9]表示文件名以0-9之间的数字开头,^是开头的意思($结尾)
*表示它前面的字符(这里是数字)要重复若干次(>=0)
\.匹配139869.txt中的那个小数点。因为正则表达式中,‘.’被占用了,表示任意字符,所以要转义一下
txt,这就不说了,紧接着小数点的是‘txt’三个字符。
Everything只支持部分正则表达式, | () ? * + . [] [^] ^ $ {m,n} 不过已经完全够用了。
http://xbeta.info/everything/faq.htm#How_do_I_use_regex
考虑这样一个问题:项目组在验收的时候,被指出代码的注释量不够,需要达到至少30%才行,也就是至少需要添加6500行注释。此时老师提出,要将所有的函数加上注释,函数的名称、功能、参数、返回值。这个时候,考虑能不能用正则表达式,提取源代码中的函数信息,然后自动生成注释模板?比如:
int foo(int x, int y);
替换为:
/**
* @method foo
* @para x
* @para y
* @return
*/
int foo(int x, int y);
注意到,这个函数参数的个数和类型可以是变动的,返回值限定符的个数和类型也是变动的,比如static类型函数,有两个限定符,而构造函数,则没有限定符,还有部分virtual类型函数。
posted @
2009-03-11 20:01 ronliu 阅读(627) |
评论 (1) |
编辑 收藏
2009年3月8日
本例学习QDialog。预期目的:1. 组织多个窗体。2. 学习Dialog的相关属性。3. 学习一些widget。
1. 本例中,定义了3个不同的PageWidget,都是从QWidget中派生。用户在左侧list更换后,切换到不同的配置页。
2. QStackedWidget提供一组widget,但一次只能有一个显示。将这个widget添加到layout中。
3. 在layout设置中,一般为MainWindow设置一个layout,然后向这个layout中添加不同的widget,layout。
4. 一个窗体是Window或者Dialog,向这个窗体中添加其他的Widget,这些Widget可以使系统提供的,也可以是用户自己定义的。
5. 本例中使用两次QListWidget。一次为图文,一次为文字。setViewMode(),设置ListWidget为图标模式。通过setIcon(),设置Item的图标。configButton->setIcon(QIcon(":/images/config.png"));
6. 定义QListWidgetItem的父类为QListWidget,设置QListWidget的项。或者使用addWidget()之类的方法。
7. 左侧select切换时,if(!current) current = previous;防止current为0的意外情况。
8. 自定义了一个slot,用来处理contentList被选中项切换时,相应的处理方法。也就是设置stackedWidget的被选中项。通过contentlist的row()确定index,然后设置第index项为当前item。
posted @
2009-03-08 22:20 ronliu 阅读(764) |
评论 (0) |
编辑 收藏
2009年2月26日
2008.2.27 by RonLiu
方法一:使用tr()函数
QT中,用QString存储所有可见得文本/字符串,使用tr()将各种字符编码的文本转化为QString,然后既可以将他们设置为控件的显示文本。
在Widget的构造函数中加入:
QTextCodec::setCodecForTr(QTextCodec::codecForName("gbk"));
QFont font1("Times", 12, QFont::Normal, FALSE);
this->setFont(font1);
这样在该窗体的其他位置,可以使用tr()设置控件的内容,他们均可以显示为中文了。
setWindowTitle(tr("消息嗅探器"));
注意:这种方式设置的中文显示对于整个控件,以及它们的子控件都生效。如果在子控件中另外设置了setFont(),那么全局的字体方案将会失效。
方法二:使用translate()转换
先将需要显示的中文转化为gbk编码的unicode,然后将unicode转化为QByteArray,在将只转化为char指针,并传递给translate()函数。
注意:这种方法显示中文时,会出现失效的情况。譬如在菜单栏中可以显示中文,但是在Label或者Button中却无法显示中文。
另外,这种方法仅仅建议只有少数按钮显示中文时选用,否则,代码写得也麻烦呀。
如果使用QDesigner生成的ui文件,后创建的界面类,一般都有一个retranslateUI,就是做这个用的。
const char * stringToUnicode(const char *str)
{
static QTextCodec *codec = QTextCodec::codecForName("gbk");
QByteArray qba = (codec->toUnicode(str)).toLocal8Bit();
const char * c_str = qba.data();
return c_str;
}
menuFile->setTitle(QApplication::translate("MainWindow", stringToUnicode("文件"), 0, QApplication::CodecForTr));
QTextCodeC用于在不同的编码方案之间进行转换。
方法三:使用Linguist
这是QT自带的用于软件本地化的软件的工具。没仔细研究过。
这种方式可以用于外文软件的本地化,那么相比于前两者方式,处于更高的层次。
延生一:编写多语言版本的QT程序
(本部分内容参考QT手册Internationalization一节)
在方法一和方法二种,仍然是一个程序对应一个语言。如果希望QT程序针对不同的语言,有不同的版本,该如何操作?
准备一个.pro文件,如:
HEADERS = funnydialog.h \
wackywidget.h
SOURCES = funnydialog.cpp \
main.cpp \
wackywidget.cpp
FORMS = fancybox.ui
TRANSLATIONS = superapp_dk.ts \
superapp_fi.ts \
superapp_no.ts \
superapp_se.ts
1. 使用lupdate,从QT程序中抽取可转换的文本,生成一个ts文件。
2. 使用Linguist工具,在原始文本间转换。ts文件以xml格式保存,可以手动修改。
3. 运行lrelease,生成轻量级的qm格式的消息文件。这种文件可以在程序中使用。
4. In your application, you must QTranslator::load() the translation files appropriate for the user's language, and install them using QCoreApplication::installTranslator().
posted @
2009-02-26 20:09 ronliu 阅读(819) |
评论 (0) |
编辑 收藏
2009年2月20日
1. 为什么使用Eclipse进行C++的开发。
因为Eclipse的IDE支持多种语言,如Java、Python、C++,也支持不同的操作系统。这样不管换到什么环境,或者换一种语言,熟悉的环境不会变化。
2. 安装和设置Eclipse/CDT的环境。
a. mingw的安装与配置。http://www.cppblog.com/romangol/archive/2008/04/19/47595.html。(PATH,C_INCLUDEPATH,CPLUS_INCLUDE_PATH, LIBRARY_PATH)
b. Java虚拟机的安装与设置。(PATH)
c. Eclipse/CDT的下载与安装。http://www.ibm.com/developerworks/cn/linux/opensource/os-ecc/index.html
3. toolchain设置
新建一个自带makefile的helloworld程序,build可以通过。但点击运行时,提示找不到可执行文件。原因在于,新建项目时,没有选择合适的toolchain。如果是下载后解压后得到的CDT,那么toolchain已经内置在其中了。但如果是update的方式获取,则需要手动下载。
我安装的是mingw的编译环境,但选择cygwin,却仍然可以生成可执行的程序。奇怪的事情。获取是因为,设置configuration时,通过检查环境变量来获取实际调用的编译器?
4. 何为toolchain?
A toolchain is a set of tools (such as a compiler, linker, and assembler) intended to build your project. Additional tools, such as a debugger, can be associated with a toolchain. There can be several toolchains available, depending on the compilers installed on your system.
5. 有哪些toolchain可供选择?
Cygwin,通过支持GNU libc运行库,它完全实现gun toolchain,使用dll向上提供Windows的兼容层。
mingw。windows平台下gnu toolchain的入口,它直接使用windows c运行库,不需要兼容层,但可移植性要差一些。
6. Eclipse如何使用这些toolchain? TODO
The CDT is designed to provide an extensible architecture, that will provide support for integration of tools provided by Independent Software Vendors。
附:
Eclipse 平台只是用于开发者工具的一个框架,它不直接支持 C/C++;它使用外部插件来提供支持。CDT 是完全用 Java 实现的开放源码项目(根据 Common Public License 特许的),它作为 Eclipse SDK 平台的一组插件。这些插件将 C/C++ 透视图添加到 Eclipse 工作台(Workbench)中,现在后者可以用许多视图和向导以及高级编辑和调试支持来支持 C/C++ 开发。
下面是 CDT 插件/组件的完整列表:
- 主 CDT 插件(Primary CDT plug-in)是“框架”CDT 插件。
- CDT 功能 Eclipse(CDT Feature Eclipse)是 CDT 功能组件(Feature Component)。
- CDT 核心(CDT Core)提供了核心模型(Core Model)、CDOM 和核心组件(Core Component)。
- CDT UI是核心 UI、视图、编辑器和向导。
- CDT 启动(CDT Launch)为诸如编译器和调试器之类的外部工具提供了启动机制。
- CDT 调试核心(CDT Debug Core)提供了调试功能。
- CDT 调试 UI(CDT Debug UI)为 CDT 调试编辑器、视图和向导提供了用户界面。
- CDT 调试 MI(CDT Debug MI)是用于与 MI 兼容的调试器的应用程序连接器。
posted @
2009-02-20 14:15 ronliu 阅读(7610) |
评论 (0) |
编辑 收藏
2009年2月16日
对于QT的学习,一直处于半懂不懂的状态,看文档也只处于“貌似”的境界,导致真正碰到问题时就个屁掉。这次阅读basiclayout的demo说明,甚感惭愧,之前学得太肤浅。
1. 设计一个窗体,安排好它的函数和属性。
2. 基本的layout包括四类,QHBoxLayout,QVBoxLayout,QGridLayout,QFormLayout。前两个将widget水平或竖直防止,grid将widget以格子的形式放置,formlayout将widget以row的形式放置。
3. layout的使用方法是,先定一个layout,再向这个layout中添加widget,然后使用父类中的setlayout(),设置这个widget的layout。
4. layout有一个setMenubar,可以使得Dialog也可以设置菜单栏。
5. 在定义类时,定义一个enum,之后就可以直接使用这个enum中的元素。
6. QT赋参数的方法为tr("Button %1").arg(i + 1)。
7. QGridLayout有setColumnStretch(int, int)方法,用于设置grid中格子的伸长因子,也就是能够占用多大的空间。
8. QDialogButtonBox指用于确定/退出的button组。它是这两类常用button的一个box组合。
9. 本例中涉及到的其它widget包括:
a. QTextEdit,文本编辑框,支持plain text和html text
b. QPushButton,按钮
c. QGroupBox,将widget以box的形式组织在一起
d. QLineEdit,行编辑框
e. QComboBox,下拉框
f. QSpinBox,spin框,提供数值选择。
posted @
2009-02-16 22:28 ronliu 阅读(9601) |
评论 (3) |
编辑 收藏
2009年2月11日
cppblog提供了metablog接口,供用户使用一些桌面工具操作blog。MetaBlogAPI是一个XML-RPC Service。它可以让用户远程调用Blog程序提供的接口来完成一些功能,比如发布新的文章,查看最新文章的列表等。http://dudu.cnblogs.com/articles/411388.html
先看cppblog的一个接口:
metaWeblog.getCategories()的参数
返回结构体
下面介绍使用Python来操作metablog接口。既然metablog是一个xml-rpc接口,那么就使用Python的xmlrpc库吧,好消息是这个库Python已经提供了,就是xmlrpclib。
代码如下:
import xmlrpclib
user = 'ronliu'
pass = '123'
url = 'http://www.cppblog.com/ronliu/services/metaweblog.aspx'
server = xmlrpclib.Server(url)
cata = server.metaWeblog.getCategories('', user, pass) #典型的rpc调用
for e in cata:
print e['categoryid'], e['title']
操作结果:
使用xmlrpclib的Server()方法,可以创建一个rpc服务器的代理,然后通过这个代理访问远程的方法。可以使用Python提供的调试功能查看rpc的执行过程:
import httplib
httplib.HTTPConnection.debuglevel = 1
posted @
2009-02-11 22:36 ronliu 阅读(457) |
评论 (0) |
编辑 收藏
使用这些api,即使一个门外汉也可以为自己的网站添加地图。
下面的代码,将会创建一个简单的地图网页。如:
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>地图测试</title>
<script language="javascript" src="http://api.51ditu.com/js/maps.js "></script>
</head>
<body>
<form id="form1" runat="server">
<div id="myMap" style="position:relative; width:400px; height:300px;"></div>
<script language="javascript">
var maps = new LTMaps( "myMap" ); //LTMaps类有一个参数,是该地图所在div的name
maps.cityNameAndZoom( "beijing" , 5 );
var c = new LTSmallMapControl(); //简单的放大缩小条
maps.addControl(c);
var point = new LTPoint( 11640969 , 3989945 );//北京
var marker = new LTMarker( point ); //一个标记
maps.addOverLay( marker ); //将标记覆盖到地图涂层上
var text = new LTMapText( marker );
text.setLabel( "我的位置" );
maps.addOverLay( text );
</script>
</form>
</body>
</html>
详细的API说明在http://api.51ditu.com/docs/index.html可以查询。
51API架构
posted @
2009-02-11 20:25 ronliu 阅读(363) |
评论 (0) |
编辑 收藏
2009年1月6日
现象:服务器端意外退出后马上重启,提示端口绑定错误,端口正在使用中。稍等一会后再次重启,可以正常运行。
可以设置socket的选项为SO_REUSEADDR,使其允许完全重复的绑定。
int rc = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc));
bind(fd, (struct sockaddr *) &addr, sizeof(addr));
setsockopt的函数原型为:
int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen);
int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen);
其中optval为选项的开关标志符,例如我使用rc=1开启SO_REUSEADDR。
fcntl 文件控制,file control,譬如控制socket为非阻塞IO,信号驱动IO等。类似的有ioctl
posted @
2009-01-06 11:52 ronliu 阅读(1394) |
评论 (0) |
编辑 收藏
2009年1月4日
(一)感冒了,浑身发抖,头疼,胸口疼,胃疼。不注意保暖,以及严重的不规律饮食带来的。现在只想早些跑回去钻被窝加衣服。网络小说是不能看了,不规律的饮食很大程度与此有关,且影响学习状态。可以多读一些历史,政治,经济方面的书,比如世界通史之类。关注养生,病殃殃的状况实在难受,学会调养自己的身体。有条件的话,可以多锻炼一些。
(二)找工作期间,最遗憾的是,没有拿得出手的技能,以及拿得出手的成果。在找完工作之后,就开始急于求成,一心想作一个东西出来,但经常是想了却不做,做时半途而废,然后又开始新的想法。很浮躁,急于求成。在今后的三个月,可以多作技能方面的锻炼。比如编程语言,能否作到精通?需要锻炼的技能包括:
甲。语言是表达思想的工具,语言说不好,不精通,再好的思想也表达不出来。反过来,语言学得好了,会促进思维的成长。然后,掌握一门专精的语言,也是将来安身立命,向更深层次的架构师成长的根本。但就目前,有什么语言是真正拿的出手的?C++是最熟悉的,却仍然谈不上精通。在今后的三个月,对C++的深入锻炼,是重点。
乙。在平常的编程中,算法用的似乎并不多,但对培养计算机的思维,培养设计能力,很有好处。更高层的,如设计模式之类。可以将语言的学习和算法,设计模式的学习结合起来。
(三)新的一年,增大一岁。不知不觉,二十好几。回头看时,什么也没有做成。感情上,学业上,以及和家人的关系,都不如意。这是浮躁的根本原因。但这些问题,却不是一蹴而就的,需要时间的积累,需要精力的积累,不是随想就有的。就像Scott信中的那位技术总监,没有5年甚至5年以上的技术沉淀,能够将技术玩到如指臂使?淡然,做好自己该做的。清风抚山岗,明月照大江。高三毕业那年,能够坐在河边,对广场上人来人往充耳不闻,和尚念经般默诵这两句话,心中淡然。年龄增大,考虑增多,却越来越浮躁了。在浮躁和淡然之间,需要有一个平衡。
(四)做好接下来的三个月!
posted @
2009-01-04 11:13 ronliu 阅读(326) |
评论 (0) |
编辑 收藏