<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>生活记忆[Uncle Li&#039;s Blog] ——专注Web开发</title>
	<atom:link href="http://www.uncleli.cn/feed" rel="self" type="application/rss+xml" />
	<link>http://www.uncleli.cn</link>
	<description>编程是一种艺术,我在欣赏这种艺术,却无法表演,但我也是一路走来的.</description>
	<lastBuildDate>Thu, 05 Aug 2010 00:57:13 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>网站用户体验的五大分类</title>
		<link>http://www.uncleli.cn/archives/557.html</link>
		<comments>http://www.uncleli.cn/archives/557.html#comments</comments>
		<pubDate>Thu, 05 Aug 2010 00:57:13 +0000</pubDate>
		<dc:creator>Uncle Li (黎 叔)</dc:creator>
				<category><![CDATA[前端技术]]></category>
		<category><![CDATA[网站体验]]></category>

		<guid isPermaLink="false">http://www.uncleli.cn/?p=557</guid>
		<description><![CDATA[每个人对网站的使用习惯不一样，功能要求也不一样，要做到最好的用户体验只能是照顾最主要目标受众的需求，因此要实现用户体验的优化，前提之 一是必须对自己的目标受众了如指掌。因此，要有一个详细的背景调查，分析目标受众的属性，分析他们的需求和行为特征，这样才能有的放矢，实现网站用户体验优化的目的。
现在很多互联网行业的从业人员动不动就提“用户体验”，但是在看了很多同行的网站后，发现很多的网站不仅没有把用户体验这个最重要的部分处理好，并 且对用户体验的概念都比较模糊，更不知道从何下手，尤其对于电子商务网站而言，直接的后果就是网站的转化率提不上去，销售额无法突破。每个人对网站的使用 习惯不一样，功能要求也不一样，要做到最好的用户体验只能是照顾最主要目标受众的需求，因此要实现用户体验的优化，前提之一是必须对自己的目标受众了如指 掌。因此，要有一个详细的背景调查，分析目标受众的属性，分析他们的需求和行为特征，这样才能有的放矢，实现网站用户体验优化的目的。
了解完用户之后，还是要回到从哪些方面或角度来进行网站用户体验优化这个问题上来，今天有感而发，总结了用户体验的76个要素，同行以及相关朋友可以参考下：
网站用户体验的分类
1、感官体验：呈现给用户视听上的体验，强调舒适性。
2、交互体验：呈现给用户操作上的体验，强调易用/可用性。
3、情感体验：呈现给用户心理上的体验，强调友好性。
4、浏览体验：呈现给用户浏览上的体验，强调吸引性。
5、信任体验：呈现给用户的信任体验，强调可靠性。
网站用户体验的76个要素
一、感官体验：呈现给用户视听上的体验，强调舒适性
1. 设计风格：符合目标客户的审美习惯，并具有一定的引导性。网站在设计之前，必须明确目标客户群体，并针对目标客户的审美喜好，进行分析，从而确定网站的总体设计风格。
2. 网站LOGO：确保logo的保护空间，确保品牌的清晰展示而又不占据过分空间。
3. 页面速度：正常情况下,尽量确保页面在5秒内打开。如果是大 型门户网站，必须考虑南北互通问题，进行必要的压力测试。
4. 页面布局：重点突出，主次分明，图文并茂。与企业的营销目标相结合，将目标客户最感兴趣的，最具有销售力的信息放置在最重要的位置。
5. 页面色彩：与品牌整体形象相统一，主色调+辅助色不超过三种颜色。以恰当的色彩明度和亮度，确保浏览者的浏览舒适度。
6. 动画效果：与主画面相协调，打开速度快，动画效果节奏适中，不干扰主画面浏览。
7. 页面导航：导航条清晰明了、突出，层级分明。
8. 页面大小：适合多数浏览器浏览(以15寸及17寸显示器为主)。
9. 图片展示：比例协调、不变形，图片清晰。图片排列既不过于密集，也不会过于疏远。
10. 图标使用：简洁、明了、易懂、准确，与页面整体风格统一。
11. 广告位：避免干扰视线，广告图片符合整体风格，避免喧宾夺主。
12. 背景音乐：与整体网站主题统一，文件要小，不能干扰阅读。要设置开关按钮及音量控制按钮。
二、交互体验：呈现给用户操作上的体验，强调易用/可用性
13. 会员申请：介绍清晰的会员权责，并提示用户确认已阅读条款。
14. 会员注册：流程清晰、简洁。待会员注册成功后，再详细完善资料。
15. 表单填写：尽量采用下拉选择，需填写部分需注明要填写内容，并对必填字段作出限制。(如手机位数、邮编等等，避免无效信息)
16. 表单提交：表单填写后需输入验证码，防止注水。提交成功后，应显示感谢提示。
17. 按钮设置：对于交互性的按钮必须清晰突出，以确保用户可以清楚地点击。
18. 点击提示：点击浏览过的信息颜色需要显示为不同的颜色，以区分于未阅读内容，避免重复阅读。
19. 错误提示：若表单填写错误，应指明填写错误之处，并保存原有填写内容，减少重复工作。
20. 在线问答：用户提问后后台要及时反馈，后台显示有新提问以确保回复及时。
21. 意见反馈：当用户在使用中发生任何问题，都可随时提供反馈意见。
22. 在线调查：为用户关注的问题设置调查，并显示调查结果，提高用户的参与度。
23. 在线搜索：搜索提交后，显示清晰列表，并对该搜索结果中的相关字符以不同颜色加以区分。
24. 页面刷新：尽量采用无刷新(AJAX)技术，以减少页面的刷新率。Ajax是新兴的网络开发技术的象征。它将JavaScript和XML技术结合在一起，用户每次调用新数据时，无需反复向服务器发出请求，而是在浏览器的缓存区预先获取下次可能用到的数据，界面的响应速度因此得到了显著提升。
25. 新开窗口：尽量减少新开的窗口，以避免开过多的无效窗口，设置弹出窗口的关闭功能。
26. 资料安全：确保资料的安全保密，对于客户密码和资料进行加密保存。
27. 显示路径：无论用户浏览到哪一个层级，哪一个页面，都可以清楚知道看到该页面的路径。
三、浏览体验：呈现给用户浏览上的体验，强调吸引性
28. 栏目的命名：与栏目内容准确相关，简洁清晰，不宜过于深奥。
29. 栏目的层级：最多不超过三层，导航清晰，运用JAVAscrip等技术使得层级之间伸缩便利。
30. 内容的分类：同一栏目下，不同分类区隔清晰，不要互相包含或混淆。
31. 内容的丰富性：每一个栏目应确保足够的信息量，避免栏目无内容情况出现。
32. 内容的原创性：尽量多采用原创性内容，以确保内容的可读性。
33. 信息的更新频率：确保稳定的更新频率，以吸引浏览者经常浏览。
34. 信息的编写方式：段落标题加粗，以区别于内文。采用倒金字塔结构。
35. 新文章的标记：为新文章提供不同标识(如new)，吸引浏览者查看。
36. 文章导读：为重要内容在首页设立导读，使得浏览者可以了解到所需信息。文字截取字数准确，避免断章取义。
37. 精彩内容的推荐：在频道首页或文章左右侧，提供精彩内容推荐，吸引浏览者浏览。
38. 相关内容的推荐：在用户浏览文章的左右侧或下部，提供相关内容推荐，吸引浏览者浏览。
39. 收藏夹的设置：为会员设置收藏夹，对于喜爱的产品或信息，可进行收藏。
40. 栏目的订阅：提供Rss或邮件订阅功能
41. 信息的搜索：在页面的醒目位置，提供信息搜索框，便于查找到所需内容。
42. 页面打印：允许用户打印该页资料，以便于保存。
43. 文字排列：标题与正文明显区隔，段落清晰。
44. 文字字体：采用易于阅读的字体，避免文字过小或过密造成的阅读障碍。可对字体进行大中小设置，以满足不同的浏览习惯。
45. 页面底色：不能干扰主体页面的阅读。
46. 页面的长度：设置一定的页面长度，避免页面过长而影响阅读。
47. 分页浏览：对于长篇文章 进行分页浏览。
48. 语言版本：为面向不同国家的客户提供不同的浏览版本。
49. [...]]]></description>
			<content:encoded><![CDATA[<p>每个人对网站的使用习惯不一样，功能要求也不一样，要做到最好的用户体验只能是照顾最主要目标受众的需求，因此要实现用户体验的优化，前提之 一是必须对自己的目标受众了如指掌。因此，要有一个详细的背景调查，分析目标受众的属性，分析他们的需求和行为特征，这样才能有的放矢，实现网站用户体验优化的目的。</p>
<p>现在很多互联网行业的从业人员动不动就提“用户体验”，但是在看了很多同行的网站后，发现很多的网站不仅没有把用户体验这个最重要的部分处理好，并 且对用户体验的概念都比较模糊，更不知道从何下手，尤其对于电子商务网站而言，直接的后果就是网站的转化率提不上去，销售额无法突破。每个人对网站的使用 习惯不一样，功能要求也不一样，要做到最好的用户体验只能是照顾最主要目标受众的需求，因此要实现用户体验的优化，前提之一是必须对自己的目标受众了如指 掌。因此，要有一个详细的背景调查，分析目标受众的属性，分析他们的需求和行为特征，这样才能有的放矢，实现网站用户体验优化的目的。</p>
<p>了解完用户之后，还是要回到从哪些方面或角度来进行网站用户体验优化这个问题上来，今天有感而发，总结了用户体验的76个要素，同行以及相关朋友可以参考下：</p>
<p>网站用户体验的分类<br />
1、感官体验：呈现给用户视听上的体验，强调舒适性。<br />
2、交互体验：呈现给用户操作上的体验，强调易用/可用性。<br />
3、情感体验：呈现给用户心理上的体验，强调友好性。<br />
4、浏览体验：呈现给用户浏览上的体验，强调吸引性。<br />
5、信任体验：呈现给用户的信任体验，强调可靠性。</p>
<p>网站用户体验的76个要素<br />
一、感官体验：呈现给用户视听上的体验，强调舒适性<br />
1. 设计风格：符合目标客户的审美习惯，并具有一定的引导性。网站在设计之前，必须明确目标客户群体，并针对目标客户的审美喜好，进行分析，从而确定网站的总体设计风格。<br />
2. 网站LOGO：确保logo的保护空间，确保品牌的清晰展示而又不占据过分空间。<br />
3. 页面速度：正常情况下,尽量确保页面在5秒内打开。如果是大 型门户网站，必须考虑南北互通问题，进行必要的压力测试。<br />
4. 页面布局：重点突出，主次分明，图文并茂。与企业的营销目标相结合，将目标客户最感兴趣的，最具有销售力的信息放置在最重要的位置。<br />
5. 页面色彩：与品牌整体形象相统一，主色调+辅助色不超过三种颜色。以恰当的色彩明度和亮度，确保浏览者的浏览舒适度。<br />
6. 动画效果：与主画面相协调，打开速度快，动画效果节奏适中，不干扰主画面浏览。<br />
7. 页面导航：导航条清晰明了、突出，层级分明。<br />
8. 页面大小：适合多数浏览器浏览(以15寸及17寸显示器为主)。<br />
9. 图片展示：比例协调、不变形，图片清晰。图片排列既不过于密集，也不会过于疏远。<br />
10. 图标使用：简洁、明了、易懂、准确，与页面整体风格统一。<br />
11. 广告位：避免干扰视线，广告图片符合整体风格，避免喧宾夺主。<br />
12. 背景音乐：与整体网站主题统一，文件要小，不能干扰阅读。要设置开关按钮及音量控制按钮。</p>
<p>二、交互体验：呈现给用户操作上的体验，强调易用/可用性<br />
13. 会员申请：介绍清晰的会员权责，并提示用户确认已阅读条款。<br />
14. 会员注册：流程清晰、简洁。待会员注册成功后，再详细完善资料。<br />
15. 表单填写：尽量采用下拉选择，需填写部分需注明要填写内容，并对必填字段作出限制。(如手机位数、邮编等等，避免无效信息)<br />
16. 表单提交：表单填写后需输入验证码，防止注水。提交成功后，应显示感谢提示。<br />
17. 按钮设置：对于交互性的按钮必须清晰突出，以确保用户可以清楚地点击。<br />
18. 点击提示：点击浏览过的信息颜色需要显示为不同的颜色，以区分于未阅读内容，避免重复阅读。<br />
19. 错误提示：若表单填写错误，应指明填写错误之处，并保存原有填写内容，减少重复工作。<br />
20. 在线问答：用户提问后后台要及时反馈，后台显示有新提问以确保回复及时。<br />
21. 意见反馈：当用户在使用中发生任何问题，都可随时提供反馈意见。<br />
22. 在线调查：为用户关注的问题设置调查，并显示调查结果，提高用户的参与度。<br />
23. 在线搜索：搜索提交后，显示清晰列表，并对该搜索结果中的相关字符以不同颜色加以区分。<br />
24. 页面刷新：尽量采用无刷新(AJAX)技术，以减少页面的刷新率。Ajax是新兴的网络开发技术的象征。它将JavaScript和XML技术结合在一起，用户每次调用新数据时，无需反复向服务器发出请求，而是在浏览器的缓存区预先获取下次可能用到的数据，界面的响应速度因此得到了显著提升。<br />
25. 新开窗口：尽量减少新开的窗口，以避免开过多的无效窗口，设置弹出窗口的关闭功能。<br />
26. 资料安全：确保资料的安全保密，对于客户密码和资料进行加密保存。<br />
27. 显示路径：无论用户浏览到哪一个层级，哪一个页面，都可以清楚知道看到该页面的路径。</p>
<p>三、浏览体验：呈现给用户浏览上的体验，强调吸引性<br />
28. 栏目的命名：与栏目内容准确相关，简洁清晰，不宜过于深奥。<br />
29. 栏目的层级：最多不超过三层，导航清晰，运用JAVAscrip等技术使得层级之间伸缩便利。<br />
30. 内容的分类：同一栏目下，不同分类区隔清晰，不要互相包含或混淆。<br />
31. 内容的丰富性：每一个栏目应确保足够的信息量，避免栏目无内容情况出现。<br />
32. 内容的原创性：尽量多采用原创性内容，以确保内容的可读性。<br />
33. 信息的更新频率：确保稳定的更新频率，以吸引浏览者经常浏览。<br />
34. 信息的编写方式：段落标题加粗，以区别于内文。采用倒金字塔结构。<br />
35. 新文章的标记：为新文章提供不同标识(如new)，吸引浏览者查看。<br />
36. 文章导读：为重要内容在首页设立导读，使得浏览者可以了解到所需信息。文字截取字数准确，避免断章取义。<br />
37. 精彩内容的推荐：在频道首页或文章左右侧，提供精彩内容推荐，吸引浏览者浏览。<br />
38. 相关内容的推荐：在用户浏览文章的左右侧或下部，提供相关内容推荐，吸引浏览者浏览。<br />
39. 收藏夹的设置：为会员设置收藏夹，对于喜爱的产品或信息，可进行收藏。<br />
40. 栏目的订阅：提供Rss或邮件订阅功能<br />
41. 信息的搜索：在页面的醒目位置，提供信息搜索框，便于查找到所需内容。<br />
42. 页面打印：允许用户打印该页资料，以便于保存。<br />
43. 文字排列：标题与正文明显区隔，段落清晰。<br />
44. 文字字体：采用易于阅读的字体，避免文字过小或过密造成的阅读障碍。可对字体进行大中小设置，以满足不同的浏览习惯。<br />
45. 页面底色：不能干扰主体页面的阅读。<br />
46. 页面的长度：设置一定的页面长度，避免页面过长而影响阅读。<br />
47. 分页浏览：对于长篇文章 进行分页浏览。<br />
48. 语言版本：为面向不同国家的客户提供不同的浏览版本。<br />
49. 快速通道：为有明确目的的用户提供快速入口。</p>
<p>四、情感体验：呈现给用户心理上的体验，强调友好性<br />
50. 客户分类：将不同的浏览者进行划分(如消费者、经销商、内部员工)，为客户提供不同的服务。<br />
51. 友好提示：对于每一个操作进行友好提示，以增加浏览者的亲和度。<br />
52. 会员交流：提供便利的会员交流功能(如论坛)，增进会员感情。<br />
53. 售后反馈：定期进行售后的反馈跟踪，提高客户满意度。<br />
54. 会员优惠：定期举办会员优惠活动，让会员感觉到实实在在的利益。<br />
55. 会员推荐：根据会员资料及购买习惯，为其推荐适合的产品或服务。<br />
56. 鼓励用户参与：提供用户评论、投票等功能，让会员更多地参与进来。<br />
57. 会员活动：定期举办网上会员活动，提供会员网下交流机会。<br />
58. 专家答疑：为用户提出的疑问进行专业解答。<br />
59. 邮件/短信问候：针对不同客户，为客户定期提供邮件/短信问候，增进与客户间感情。<br />
60. 好友推荐：提供邮件推荐功能。<br />
61. 网站地图：为用户提供清晰的网站指引。</p>
<p>五、信任体验：呈现给用户的信任体验，强调可靠性<br />
62. 搜索引擎：查找相关内容可以显示在搜索引擎前列。<br />
63. 公司介绍：真实可靠的信息发布，包括公司规模、发展状况、公司资质等。<br />
64. 投资者关系：上市公司需为股民提供真实准确的年报，财务信息等。<br />
65. 服务保障：将公司的服务保障清晰列出，增强客户信任。<br />
66. 页面标题：准确地描述公司名称及相关内容。<br />
67. 文章来源：为摘引的文章标注摘引来源，避免版权纠纷。<br />
68. 文章编辑作者：为原创性文章注明编辑或作者，以提高文章的可信度。<br />
69. 联系方式：准确有效的地址、电话等联系方式，便于查找。<br />
70. 服务热线：将公司的服务热线列在醒目的地方，便于客户查找。<br />
71. 有效的投诉途径：为客户提供投诉或建议邮箱或在线反馈。<br />
72. 安全及隐私条款：对于交互式网站，注明安全及隐私条款可以减少客户顾虑，避免纠纷。<br />
73. 法律声明：对于网站法律条款的声明可以避免企业陷入不必要的纠纷中。<br />
74. 网站备案：让浏览者确认网站的合法性。<br />
75. 相关链接：对于集团企业及相关企业的链接，应该具有相关性。<br />
76. 帮助中心：对于流程较复杂的服务，必须具备帮助中心进行服务介绍。</p>
<p>其实对一个网站做一次用户体验分析是很细很累的活，但是意义却很大，尤其对年销售额上千万级的电子商务网站而言，用户体验做好了，转化率能增加千分之一那就能促进数百上千万的销售额，你说用户体验重不重要?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.uncleli.cn/archives/557.html/feed</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>关于谷歌中国的最新声明</title>
		<link>http://www.uncleli.cn/archives/555.html</link>
		<comments>http://www.uncleli.cn/archives/555.html#comments</comments>
		<pubDate>Tue, 29 Jun 2010 08:59:56 +0000</pubDate>
		<dc:creator>Uncle Li (黎 叔)</dc:creator>
				<category><![CDATA[杂七杂八]]></category>
		<category><![CDATA[google]]></category>

		<guid isPermaLink="false">http://www.uncleli.cn/?p=555</guid>
		<description><![CDATA[关于谷歌中国的最新声明
2010 年 6 月 28 日 
David Drummond, SVP, Corporate Development and Chief Legal Officer 
自从为中国大陆用户推出 Google.cn 这个 搜索引擎以来，我们一直在尽最大的努力来提高用户对信息的访问，同时遵守中国法律。做到这样的平衡并不容易，尤其是我们在今年1月份宣布不愿意继续在 Google.cn 上对搜索结果进行审查。 
当前，我们把所有访问 Google.cn 的用户自动指向了我们香港的搜索引擎 Google.com.hk，通过这种方法，我们可以提供未经审查的简体中文 搜索结果。目前这种方法无论对用户还是对 Google 都运行良好。然而，在与中国有关部门的沟通中我们明确获知：自动指向的做法是不可接受的。如果我们继 续进行自动指向，我们的 ICP 牌照将无法通过年检（年检截止时间是6月30日）。没有 ICP 牌照，我们将不能在中国运营 Google.cn 这样的商业网站——这意味着 Google.cn 将不能被访问。 
那是许多 Google 中国用户所担忧的结果，因为他们都清楚表明了希望 Google.cn 继续运营的愿望。为此，我们开始寻找其他可能的替代办法，我们开始为一小部分用户提供一个新的 google.cn 访问页面，该页面与 Google.com.hk 链接，在那里，用户可以进行搜索，或继续使用在 google.cn 上的音乐搜索（Music Search）和文本翻译（Translate）等不涉及内容审查的服务。这个新做法确保 Google.cn 不对搜索结果进行审查的承诺，同时让用户可以在一个页面上访问我们所有的服务。 
未来几天，我们将全部停止自动指向，让所有中国用户都直接访问这个新页面——今天，基于这样一个新页面，我们重新提交了 ICP 牌照年检申请。 
作为一家公司，我们的追求是让用户随时随地访问到他们所需的信息，包括中国的用户。这就是为什么我们一直在努力地保持 [...]]]></description>
			<content:encoded><![CDATA[<p>关于谷歌中国的最新声明<br />
2010 年 6 月 28 日 </p>
<p>David Drummond, SVP, Corporate Development and Chief Legal Officer </p>
<p>自从为中国大陆用户推出 Google.cn 这个 搜索引擎以来，我们一直在尽最大的努力来提高用户对信息的访问，同时遵守中国法律。做到这样的平衡并不容易，尤其是我们在今年1月份宣布不愿意继续在 Google.cn 上对搜索结果进行审查。 </p>
<p>当前，我们把所有访问 Google.cn 的用户自动指向了我们香港的搜索引擎 Google.com.hk，通过这种方法，我们可以提供未经审查的简体中文 搜索结果。目前这种方法无论对用户还是对 Google 都运行良好。然而，在与中国有关部门的沟通中我们明确获知：自动指向的做法是不可接受的。如果我们继 续进行自动指向，我们的 ICP 牌照将无法通过年检（年检截止时间是6月30日）。没有 ICP 牌照，我们将不能在中国运营 Google.cn 这样的商业网站——这意味着 Google.cn 将不能被访问。 </p>
<p>那是许多 Google 中国用户所担忧的结果，因为他们都清楚表明了希望 Google.cn 继续运营的愿望。为此，我们开始寻找其他可能的替代办法，我们开始为一小部分用户提供一个新的 google.cn 访问页面，该页面与 Google.com.hk 链接，在那里，用户可以进行搜索，或继续使用在 google.cn 上的音乐搜索（Music Search）和文本翻译（Translate）等不涉及内容审查的服务。这个新做法确保 Google.cn 不对搜索结果进行审查的承诺，同时让用户可以在一个页面上访问我们所有的服务。 </p>
<p>未来几天，我们将全部停止自动指向，让所有中国用户都直接访问这个新页面——今天，基于这样一个新页面，我们重新提交了 ICP 牌照年检申请。 </p>
<p>作为一家公司，我们的追求是让用户随时随地访问到他们所需的信息，包括中国的用户。这就是为什么我们一直在努力地保持 Google.cn 的运营，以及继续我们在中国的研发工作。这个新做法确保了 Google.cn 不对搜索结果进行审查的承诺，并且，我们相信，符合中国法律。因此我们希望能够通过 ICP 牌照年检，让我们可以继续通过 Google.cn 为中国用户提供服务。 </p>
<p>http://www.google.com/press/new-approach-to-china/update_0610.html</p>
]]></content:encoded>
			<wfw:commentRss>http://www.uncleli.cn/archives/555.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>如何看懂源代码&#8211;(分析源代码方法)</title>
		<link>http://www.uncleli.cn/archives/553.html</link>
		<comments>http://www.uncleli.cn/archives/553.html#comments</comments>
		<pubDate>Thu, 24 Jun 2010 08:15:05 +0000</pubDate>
		<dc:creator>Uncle Li (黎 叔)</dc:creator>
				<category><![CDATA[网络收藏]]></category>

		<guid isPermaLink="false">http://www.uncleli.cn/?p=553</guid>
		<description><![CDATA[我们在写程式时，有不少时间都是在看别人的代码。
例如看小组的代码，看小组整合的守则，若一开始没规划怎么看，
就会“噜看噜苦（台语） ” 
不管是参考也好，从开源抓下来研究也好，为了了解箇中含意，在有限的时间下，不免会对庞大的源代码解读感到压力。
网路上有一篇关于分析看代码的方法，做为程式设计师的您，不妨参考看看，
换个角度来分析。 也能更有效率的解读你想要的程式码片段。 
六个章节：
（ 1 ）读懂程式码，使心法皆为我所用。
（ 2 ）摸清架构，便可轻松掌握全貌。
（ 3 ）优质工具在手，读懂程式非难事。
（ 4 ）望文生义，进而推敲组件的作用。
（ 5 ）找到程式入口，再由上而下抽丝剥茧。
（ 6 ）阅读的乐趣，透过程式码认识作者。 
阅读他人的程式码（ 1 ） &#8212;读懂程式码，使心法皆为我所用 
程式码是别人写的，只有原作者才真的了解程式码的用途及涵义。许多程式人心里都有一种不自觉的恐惧感，深怕被迫去碰触其他人所写的程式码。但是，与其抗拒接收别人的程式码，不如彻底了解相关的语言和惯例，当成是培养自我实力的基石。
对大多数的程式人来说，撰写程式码或许是令人开心的一件事情，但我相信，有更多人视阅读他人所写成的程式码为畏途。许多人宁可自己重新写过一遍程式码，也不愿意接收别人的程式码，进而修正错误，维护它们，甚至加强功能。 
这其中的关键究竟在何处呢？若是一语道破，其实也很简单，程式码是别人写的，只有原作者才真的了解程式码的用途及涵义。许多程式人心里都有一种不自觉的恐惧感，深怕被迫去碰触其他人所写的程式码。这是来自于人类内心深处对于陌生事物的原始恐惧。 
读懂别人写的程式码，让你收获满满
不过，基于许多现实的原因，程式人时常受迫要去接收别人的程式码。例如，同事离职了，必须接手他遗留下来的工作，也有可能你是刚进部门的菜鸟，而同事经验值够了，升级了，风水轮流转，一代菜鸟换菜鸟。甚至，你的公司所承接的专案，必须接手或是整合客户前一个厂商所遗留下来的系统，你们手上只有那套系统的原始码（运气好时，还有数量不等的文件） 。 
诸如此类的故事，其实时常在程式人身边或身上持续上演着。许多程式人都将接手他人的程式码，当做一件悲惨的事情。每个人都不想接手别人所撰写的程式码，因为不想花时间去探索，宁可将生产力花在产生新的程式码，而不是耗费在了解这些程式码上。 
很遗憾的是，上述的情况对程式人来说很难避免。我们总是必须碰触到其他人所写成的程式码，甚至必须了解它，加以修改。对于这项需求，在现今开放原始码的风气如此盛行的今日，正如之前的“程式设计2.0 ”文中所提到的，你可以透过开放原始码学习到新的技术，学习到高手的架构设计，大幅提高学习的效率及效果。你甚至可以直接自开放原始码专案中抽取，提炼出自己所需的程式码，站在巨人的肩膀上，直接由彼端获得所需的生产力。从这个观点来看，读懂别人所写的程式码，就不再只是从负面观点的“被迫接收” ，而是极具正面价值的“汲取养份。 ” 
先了解系统架构与行为模式，再细读
倘若撰写程式码是程式人的重要技艺之一，那么读懂别人的程式码，接着加以修改，也势必是另一个重要的技艺。 
如果你不能熟悉这项工作，不仅在遭逢你所不愿面对的局面时，无法解决眼前接手他人程式码的难题，更重要的是，当你看着眼前现成的程式码，却不知如何从中撷取自己所需，导致最后只能入宝山空手回，望之兴叹。 
接触他人的程式码，大致上可以分为三种程度：一，了解，二，修改，扩充，三，抽取，提炼。了解别人的程式码是最基础的工作，倘若不能了解自己要处理的程式码，就甭论修改或扩充，更不可能去芜存菁，从中萃取出自己所需，回收再利用别人所撰写的程式码。虽说是“阅读” ，但程式码并不像文章或小说一样，透过这种做法，便能够获得一定程度的了解。阅读文章或小说时，几乎都是循序地阅读，你只消翻开第一页，一行行阅读下去即可。但是，有许多程式人在试着阅读其他人的程式码时，却往往有不知如何读起的困难。 
或许找到系统的第一页（也就是程式码执行的启始点）并不难，但是复杂度高的系统，有时十分庞大，有时千头万绪。 
从程式码的启始点开始读起，一来要循序读完所有的程式码旷日费时，二来透过这种方式来了解系统，很难在脑中构建出系统的面貌，进而了解到系统真正的行为。所以，阅读程式码的重点，不在于读完每一行程式码，而是在于有效率地透过探索及阅读，从而了解系统的架构及行为模式。以便在你需要了解任何片段的细节实作时，能够很快在脑上对映到具体的程式码位置，直到那一刻，才是细读的时机。 
熟悉沟通语言与惯例用语
不论如何，有些基本的准备，是阅读他人程式码时必须要有的。 
首先，你最好得了解程式码写成的程式语言。想要读懂法文写成的小说，总不能连法文都不懂吧。有些情况则很特殊。我们虽然不懂该程式码撰写所用的语言，但是因为现代语言的高阶化，而且流行的程式语言多半都是血统相近，所以即使不那么熟悉，有时也可勉力为之。 
除了认识所用语言之外，再来就是要先确认程式码所用的命名惯例（命名惯例） 。了解命名惯例很重要，不同的程式人或开发团队，差异可能很大。
这命名惯例涵盖的范围通常包括了变数的名称，函式的名称，类别（如果是物件导向的话）的名称，原始码档案，甚至是专案建构目录的名称。倘若使用了像设计模式之类的方法，这些名称更有一些具体的表述方式。 
命名惯例有点像是程式人在程式语言之上，另行建构的一组沟通行话。程式人会透过共通约束，遵守的命名惯例，来表达一些较高阶的概念。例如，有名的匈牙利式命名法，便将变数名称以属性，型别，说明合并在一起描述。对程式人来说，这种方式能够提供更丰富的资讯，以了解该变数的作用及性质。 
对程式码阅读来说，熟悉这个做法之所以重要，是因为当你了解整个系统所采用的惯例时，你便能试着以他们所共同操用的语汇来进行理解。倘若，不能了解其所用的惯例，那么这些额外提供的资讯，就无法为你所用。像以设计模式写成的程式码，同样处处充满着模式的名称，诸如：工厂，门面，代理等等。以这些名称指涉的类别，也直接透过名称，表达了它们自身的作用。对于懂得这命名惯例的读者来说，不需要深入探索，也能很快捕捉到这些类别的意义。 
当你拿到一套必须阅读的程式码时，最好先取得命名惯例的说明文件。然而，并不是每套程式码都附有此类的说明文件。另一个方式，就是自己到程式码中，大略浏览一遍，有经验的程式人可以轻易发掘出该系统所用的命名惯例。 
常见的命名方式不脱那几类，这时候经验就很重要，倘若你知道的惯例越多，就越能轻易识别他人所用的惯例。如果运气很糟，程式码所用的惯例是前所未见的，那么你也得花点时间归纳，凭自己的力量找出这程式码命名上的规则。 
掌握程式码撰写者的心态与习惯
大多数的程式码，基本上都依循一致的命名惯例。不过运气更差的时候，一套系统中可能会充斥着多套命名惯例。这有可能是因为开发团队由多组人马所构成，每组人马都有不同的文化，而在专案开发管理又没有管控得宜所造成。最糟的情况，程式码完全没有明显的惯例可言，这时候阅读的难度就更高了。 
想要阅读程式码，得先试着体会程式码作者的“心” 。想要这么做，就得多了解对方所使用的语言，以及惯常运用的语汇。在下一回中，我们将继续探讨阅读程式码的相关议题。 
阅读他人的程式码（ 2 ） -摸清架构，便可轻松掌握全貌
在本文中，我们的重点放在：要了解一个系统，最好是采取由上至下的方式。先试着捕捉系统架构性的观念，不要过早钻进细节，因为那通常对于你了解全貌，没有多大的帮助。阅读程式码不需要从第一行读起，我们的目的并不是在于读遍每一段程式码。
基于许多原因，程式人需要阅读其他人所写成的程式码。而对程式设计2.0时代的程式人来说，最正面的价值在于，能读懂别人程式的人，才有能力从中萃取自己所需的程式，借以提高生产力。 
阅读程式码的目的，在于了解全貌而非细节
想要读懂别人程式码的根本基础，便是了解对方所用的程式语言及命名惯例。有了这个基础之后，才算是具备了基本的阅读能力。正如我之前提到的─ ─想要读懂法文写成的小说，总不能连法文都不懂吧。阅读程式码和阅读文学作品，都需要了解撰写所用的语言及作者习用的语汇。 
但我们在阅读文学作品通常是采循序的方式，也就是从第一页开始，一行一行地读下去，依循作者为你铺陈的步调，逐渐进到他为你准备好的世界里。阅读程式码却大大不同。我们很少从第一行开始读起，因为除非它是很简单的单执行绪程式，否则很少这么做。因为要是这么做，就很难了解整个系统的全貌。是的，我们这边提到了一个重点，阅读程式码的目的在于了解系统的全貌，而不是在于只是为了地毯式的读遍每一段程式码。 
就拿物件导向程式语言所写成的系统来说，整个系统被拆解，分析成为一个个独立的类别。阅读个别类别的程式码，或许可以明白每项类别物件个别的行为。但对于各类别物件之间如何交互影响，如何协同工作，又很容易陷入盲人摸象的困境。这是因为各类别的程式码，只描述个别物件的行为，而片段的阅读就只能造就片面的认识。 [...]]]></description>
			<content:encoded><![CDATA[<p>我们在写程式时，有不少时间都是在看别人的代码。<br />
例如看小组的代码，看小组整合的守则，若一开始没规划怎么看，<br />
就会“噜看噜苦（台语） ” </p>
<p>不管是参考也好，从开源抓下来研究也好，为了了解箇中含意，在有限的时间下，不免会对庞大的源代码解读感到压力。<br />
网路上有一篇关于分析看代码的方法，做为程式设计师的您，不妨参考看看，<br />
换个角度来分析。 也能更有效率的解读你想要的程式码片段。 </p>
<p>六个章节：<br />
（ 1 ）读懂程式码，使心法皆为我所用。<br />
（ 2 ）摸清架构，便可轻松掌握全貌。<br />
（ 3 ）优质工具在手，读懂程式非难事。<br />
（ 4 ）望文生义，进而推敲组件的作用。<br />
（ 5 ）找到程式入口，再由上而下抽丝剥茧。<br />
（ 6 ）阅读的乐趣，透过程式码认识作者。 </p>
<p>阅读他人的程式码（ 1 ） &#8212;读懂程式码，使心法皆为我所用 </p>
<p>程式码是别人写的，只有原作者才真的了解程式码的用途及涵义。许多程式人心里都有一种不自觉的恐惧感，深怕被迫去碰触其他人所写的程式码。但是，与其抗拒接收别人的程式码，不如彻底了解相关的语言和惯例，当成是培养自我实力的基石。</p>
<p>对大多数的程式人来说，撰写程式码或许是令人开心的一件事情，但我相信，有更多人视阅读他人所写成的程式码为畏途。许多人宁可自己重新写过一遍程式码，也不愿意接收别人的程式码，进而修正错误，维护它们，甚至加强功能。 </p>
<p>这其中的关键究竟在何处呢？若是一语道破，其实也很简单，程式码是别人写的，只有原作者才真的了解程式码的用途及涵义。许多程式人心里都有一种不自觉的恐惧感，深怕被迫去碰触其他人所写的程式码。这是来自于人类内心深处对于陌生事物的原始恐惧。 </p>
<p>读懂别人写的程式码，让你收获满满<br />
不过，基于许多现实的原因，程式人时常受迫要去接收别人的程式码。例如，同事离职了，必须接手他遗留下来的工作，也有可能你是刚进部门的菜鸟，而同事经验值够了，升级了，风水轮流转，一代菜鸟换菜鸟。甚至，你的公司所承接的专案，必须接手或是整合客户前一个厂商所遗留下来的系统，你们手上只有那套系统的原始码（运气好时，还有数量不等的文件） 。 </p>
<p>诸如此类的故事，其实时常在程式人身边或身上持续上演着。许多程式人都将接手他人的程式码，当做一件悲惨的事情。每个人都不想接手别人所撰写的程式码，因为不想花时间去探索，宁可将生产力花在产生新的程式码，而不是耗费在了解这些程式码上。 </p>
<p>很遗憾的是，上述的情况对程式人来说很难避免。我们总是必须碰触到其他人所写成的程式码，甚至必须了解它，加以修改。对于这项需求，在现今开放原始码的风气如此盛行的今日，正如之前的“程式设计2.0 ”文中所提到的，你可以透过开放原始码学习到新的技术，学习到高手的架构设计，大幅提高学习的效率及效果。你甚至可以直接自开放原始码专案中抽取，提炼出自己所需的程式码，站在巨人的肩膀上，直接由彼端获得所需的生产力。从这个观点来看，读懂别人所写的程式码，就不再只是从负面观点的“被迫接收” ，而是极具正面价值的“汲取养份。 ” </p>
<p>先了解系统架构与行为模式，再细读<br />
倘若撰写程式码是程式人的重要技艺之一，那么读懂别人的程式码，接着加以修改，也势必是另一个重要的技艺。 </p>
<p>如果你不能熟悉这项工作，不仅在遭逢你所不愿面对的局面时，无法解决眼前接手他人程式码的难题，更重要的是，当你看着眼前现成的程式码，却不知如何从中撷取自己所需，导致最后只能入宝山空手回，望之兴叹。 </p>
<p>接触他人的程式码，大致上可以分为三种程度：一，了解，二，修改，扩充，三，抽取，提炼。了解别人的程式码是最基础的工作，倘若不能了解自己要处理的程式码，就甭论修改或扩充，更不可能去芜存菁，从中萃取出自己所需，回收再利用别人所撰写的程式码。虽说是“阅读” ，但程式码并不像文章或小说一样，透过这种做法，便能够获得一定程度的了解。阅读文章或小说时，几乎都是循序地阅读，你只消翻开第一页，一行行阅读下去即可。但是，有许多程式人在试着阅读其他人的程式码时，却往往有不知如何读起的困难。 </p>
<p>或许找到系统的第一页（也就是程式码执行的启始点）并不难，但是复杂度高的系统，有时十分庞大，有时千头万绪。 </p>
<p>从程式码的启始点开始读起，一来要循序读完所有的程式码旷日费时，二来透过这种方式来了解系统，很难在脑中构建出系统的面貌，进而了解到系统真正的行为。所以，阅读程式码的重点，不在于读完每一行程式码，而是在于有效率地透过探索及阅读，从而了解系统的架构及行为模式。以便在你需要了解任何片段的细节实作时，能够很快在脑上对映到具体的程式码位置，直到那一刻，才是细读的时机。 </p>
<p>熟悉沟通语言与惯例用语<br />
不论如何，有些基本的准备，是阅读他人程式码时必须要有的。 </p>
<p>首先，你最好得了解程式码写成的程式语言。想要读懂法文写成的小说，总不能连法文都不懂吧。有些情况则很特殊。我们虽然不懂该程式码撰写所用的语言，但是因为现代语言的高阶化，而且流行的程式语言多半都是血统相近，所以即使不那么熟悉，有时也可勉力为之。 </p>
<p>除了认识所用语言之外，再来就是要先确认程式码所用的命名惯例（命名惯例） 。了解命名惯例很重要，不同的程式人或开发团队，差异可能很大。<br />
这命名惯例涵盖的范围通常包括了变数的名称，函式的名称，类别（如果是物件导向的话）的名称，原始码档案，甚至是专案建构目录的名称。倘若使用了像设计模式之类的方法，这些名称更有一些具体的表述方式。 </p>
<p>命名惯例有点像是程式人在程式语言之上，另行建构的一组沟通行话。程式人会透过共通约束，遵守的命名惯例，来表达一些较高阶的概念。例如，有名的匈牙利式命名法，便将变数名称以属性，型别，说明合并在一起描述。对程式人来说，这种方式能够提供更丰富的资讯，以了解该变数的作用及性质。 </p>
<p>对程式码阅读来说，熟悉这个做法之所以重要，是因为当你了解整个系统所采用的惯例时，你便能试着以他们所共同操用的语汇来进行理解。倘若，不能了解其所用的惯例，那么这些额外提供的资讯，就无法为你所用。像以设计模式写成的程式码，同样处处充满着模式的名称，诸如：工厂，门面，代理等等。以这些名称指涉的类别，也直接透过名称，表达了它们自身的作用。对于懂得这命名惯例的读者来说，不需要深入探索，也能很快捕捉到这些类别的意义。 </p>
<p>当你拿到一套必须阅读的程式码时，最好先取得命名惯例的说明文件。然而，并不是每套程式码都附有此类的说明文件。另一个方式，就是自己到程式码中，大略浏览一遍，有经验的程式人可以轻易发掘出该系统所用的命名惯例。 </p>
<p>常见的命名方式不脱那几类，这时候经验就很重要，倘若你知道的惯例越多，就越能轻易识别他人所用的惯例。如果运气很糟，程式码所用的惯例是前所未见的，那么你也得花点时间归纳，凭自己的力量找出这程式码命名上的规则。 </p>
<p>掌握程式码撰写者的心态与习惯<br />
大多数的程式码，基本上都依循一致的命名惯例。不过运气更差的时候，一套系统中可能会充斥着多套命名惯例。这有可能是因为开发团队由多组人马所构成，每组人马都有不同的文化，而在专案开发管理又没有管控得宜所造成。最糟的情况，程式码完全没有明显的惯例可言，这时候阅读的难度就更高了。 </p>
<p>想要阅读程式码，得先试着体会程式码作者的“心” 。想要这么做，就得多了解对方所使用的语言，以及惯常运用的语汇。在下一回中，我们将继续探讨阅读程式码的相关议题。 </p>
<p>阅读他人的程式码（ 2 ） -摸清架构，便可轻松掌握全貌</p>
<p>在本文中，我们的重点放在：要了解一个系统，最好是采取由上至下的方式。先试着捕捉系统架构性的观念，不要过早钻进细节，因为那通常对于你了解全貌，没有多大的帮助。阅读程式码不需要从第一行读起，我们的目的并不是在于读遍每一段程式码。</p>
<p>基于许多原因，程式人需要阅读其他人所写成的程式码。而对程式设计2.0时代的程式人来说，最正面的价值在于，能读懂别人程式的人，才有能力从中萃取自己所需的程式，借以提高生产力。 </p>
<p>阅读程式码的目的，在于了解全貌而非细节<br />
想要读懂别人程式码的根本基础，便是了解对方所用的程式语言及命名惯例。有了这个基础之后，才算是具备了基本的阅读能力。正如我之前提到的─ ─想要读懂法文写成的小说，总不能连法文都不懂吧。阅读程式码和阅读文学作品，都需要了解撰写所用的语言及作者习用的语汇。 </p>
<p>但我们在阅读文学作品通常是采循序的方式，也就是从第一页开始，一行一行地读下去，依循作者为你铺陈的步调，逐渐进到他为你准备好的世界里。阅读程式码却大大不同。我们很少从第一行开始读起，因为除非它是很简单的单执行绪程式，否则很少这么做。因为要是这么做，就很难了解整个系统的全貌。是的，我们这边提到了一个重点，阅读程式码的目的在于了解系统的全貌，而不是在于只是为了地毯式的读遍每一段程式码。 </p>
<p>就拿物件导向程式语言所写成的系统来说，整个系统被拆解，分析成为一个个独立的类别。阅读个别类别的程式码，或许可以明白每项类别物件个别的行为。但对于各类别物件之间如何交互影响，如何协同工作，又很容易陷入盲人摸象的困境。这是因为各类别的程式码，只描述个别物件的行为，而片段的阅读就只能造就片面的认识。 </p>
<p>由上而下厘清架构后，便可轻易理解组成关系<br />
如果你想要跳脱困境，不想浪费大量时间阅读程式码，却始终只能捕捉到对系统片段认识，就必须转换到另一种观点来看待系统。从个别的类别行为着手，是由下至上（自下而上）的方法;在阅读程式码时，却应该先采由上至下（自上而下）的方式。对程式码的阅读来说，由上至下意谓着，你得先了解整个系统架构。 </p>
<p>系统的架构是整个系统的骨干，支柱。它表现出系统最突出的特征。知道系统架构究竟属于那一种类型，通常大大有益于了解系统的个别组成之间的静态及动态关系。有些系统因为所用的技术或框架的关系，决定了最上层的架构。例如，采用的Java Servlet的/ JSP的技术的应用系统，最外层的架构便是以J2EE的（或起码的J2EE中的Web容器）为根本。 </p>
<p>使用的Java Servlet的/ JSP的技术时，决定了某些组成之间的关系。例如， Web容器依据web.xml中的内容载入所有的Servlets ，听众，以及过滤器。每当语境发生事件（例如初始化）时，它便会通知监听类别。每当它收到来自客户端的请求时，便会依循设定的所有过滤器链，让每个过滤器都有机会检查并处理此一请求，最后再将请求导至用来处理该请求的Servlet的。 </p>
<p>当我们明白某个系统采用这样的架构时，便可以很容易地知道各个组成之间的关系。即使我们还不知道究竟有多少Servlets ，但我们会知道，每当收到一个请求时，总是会有个相对应的服务器来处理它。当想要关注某个请求如何处理时，我应该去找出这个请求对应的服务器。 </p>
<p>了解架构，必须要加上层次感<br />
同样的，以爪哇写成的网页应用程式中，也许会应用诸如Struts的之类的的MVC框架，以及像Hibernate的这样的资料存取框架。它们都可以视为最主要的架构下的较次级架构。而各个应用系统，甚至有可能在Struts的及休眠之下，建立自有的更次级的架构。 </p>
<p>也就是说，当我们谈到“架构”这样的观念时，必须要有层次感。而不论是那一层级的架构，都会定义出各自的角色，以及角色间的关系。对阅读者来说，相较于直接切入最细微的单一角色行为，不如了解某个特定的架构中，究竟存在多少角色，以及这些角色之间的互动模式，比较能够帮助我们了解整个系统的运作方式。 </p>
<p>这是一个很重要的关键，当你试着进到最细节处之前，应该先试着找出参与的角色，及他们之间的关系。例如，对事件驱动式的架构而言，有3个很重要的角色。一个是事件处理的分派器（事件调度） ，一个是事件产生者（事件发生器） ，另一个则是事件处理器（事件处理程序） 。 </p>
<p>事件产生器产生事件，并送至事件分派器，而事件分派器负责找出各事件相对应的事件处理器，并且转交该事件，并命令事件处理器加以处理。像的图形用户界面的Windows应用程式，便是采用事件驱动式的架构。 </p>
<p>当你知道此类的应用程式皆为事件驱动式的架构时，你便可以进一步得知，在这样的架构下会有3种主要的角色。虽然也许还不清楚整个系统中，究竟会需要处理多少事件的类型，但对你而言，已经建立了对系统全貌最概观的认识。 </p>
<p>虽然你还不清楚所有的细节，但诸如确切会有那些事件类型之类的资讯，在此刻还不重要─ ─不要忘了，我们采取的是由上而下的方式，要先摸清楚主建筑结构，至于壁纸的花色怎么处理，那是到了尾声时才会做的事。 </p>
<p>探索架构的第一件事：找出系统如何初始化<br />
有经验的程式人，对于时常被运用的架构都很熟悉。常常只需要瞧上几眼，就能明白一个系统所用的架构，自然就能够直接联想到其中会存在的角色，以及角色间的关系。然而，并不是每个系统所用的架构，都是大众所熟悉，或是一眼能够望穿的。这时候，你需要探索。目标同样要放在界定其中的角色，以及角色间的静态，动态关系。 </p>
<p>不论某个系统所采用的架构是否为大部分人所熟知的，在试着探索一个系统的长相时，我们应该找出来几个答案，了解在它所用的架构下，下列这件事是如何被完成的：一，系统如何初始化，二，与这个系统相接的其他系统（或使用者）有那些，而相接的介面又是什么;三，系统如何反应各种事件，四，系统如何处理各种异常及错误。 </p>
<p>系统如何初始化是很重要的一件事，因为初始化是为了接下来的所有事物而做的准备。从初始化的方式，内容，能知道系统做了什么准备，对于系统会有什么行为展现，也就能得窥一二了。之所以要了解与系统相接的其他系统（或使用者） ，为的是要界定出系统的边界。其他的系统可能会提供输入给我们所探索的系统，也可能接收来自这系统的输出，了解这边界所在，才能确定系统的外观。 </p>
<p>而系统所反应的事件类型，以及如何反应，基本上就代表着系统本身的主要行为模式。最后，我们必须了解系统处理异常及错误的方式，这同样也是系统的重要行为，但容易被忽略。之前，我们提到必须先具备一个系统的语言基础，才能够进一步加以阅读，而在本文中，我们的重点放在：要了解一个系统，最好是采取由上至下的方式。先试着捕捉系统架构性的观念，不要过早钻进细节，因为那通常对于你了解全貌，没有多大的帮助。</p>
<p>阅读他人的程式码（ 3 ） -优质工具在手，读懂程式非难事</p>
<p>系统的复杂度往往超过人脑的负荷。阅读程式码的时候，你会需要更多工具提供协助。使用好的整合式开发环境（ IDE ）的或文字编辑器，就能提供最基本的帮助。</p>
<p>阅读程式码的动作，可以是很原始的，利用最简单的文字编辑器，逐一开启原始码，然后凭借着一己的组织能力，在不同的程式码间跳跃，拼凑出脑中想要构建的图像。<br />
不过，系统的复杂度往往超过人脑的负荷。阅读程式码的时候，你会需要更多工具提供协助。使用好的整合式开发环境（ IDE ）的或文字编辑器，就能提供最基本的帮助。 </p>
<p>善用文字编辑器或IDE中，加速解读程式码<br />
许多文字编辑器提供了常见程式语言的语法及关键字标示功能。这对于阅读来说，绝对能够起很大的作用。有些文字编辑器（例如我常用的编辑器及偶而使用的记事本+ + ） ，甚至能够自动列出某个原始档中所有定义的函式清单，更允许你直接从清单中选择函式，直接跳跃到该函式的定义位置。这对于阅读程式码的人来说，就提供了极佳的便利性。 </p>
<p>因为在阅读程式码时，最常做的事，就是随着程式中的某个控制流，将阅读的重心，从某个函式移至它所呼叫的另一个函式。所以对程式人来说，阅读程式码时最常做的事之一就是：找出某个函式位在那一个原始档里，接着找到该函式所在的位置。 </p>
<p>好的的IDE能够提供的协助就更多了。有些能够自动呈现一些额外的资讯，最有用的莫过于函式的原型宣告了。例如，有些的IDE支援当游标停留在某函式名称上一段时间后，它会以提示的方式显示该函式的原型宣告。 </p>
<p>对阅读程式码的人来说，在看到程式码中呼叫到某个函式时，可以直接利用这样的支援，立即取得和这个函式有关的原型资讯，马上就能知道呼叫该函式所传入的各个引数的意义，而不必等到将该函式的定义位置找出后，才能明白这件事。 </p>
<p>grep按（读者：推荐来源透视）是一个基本而极为有用的工具<br />
除了选用好的文字编辑器或的IDE之外，还有一个基本，但却极为有用的工具，它就是grep按。熟悉的Unix作业系统的程式人，对grep按这个公用程式多半都不陌生。 grep按最大的用途，在于它允许我们搜寻某个目录（包括递回进入所有子目录）中所有指定档案，是否有符合指定条件（常数字串或正规表示式）档案。 </p>
<p>倘若有的话，则能帮你指出所在的位置。这在阅读程式码时的作用极大。当我们随着阅读的脚步，遇上了任何一个不认识，但自认为重要的类别，函式，资料结构定义或变数，我们就得找出它究竟位在这茫茫程式码海中的何处，才能将这个图块从未知变为已知。<br />
grep按之所以好用，就是在于当我们发现某个未知的事物时，可以轻易地利用它找出这个未知的事物究竟位在何方。此外，虽说grep按是Unix系统的标准公用程式之一，但是像视窗这样子的平台，也有各种类型的grep按程式。对于在视窗环境工作的程式人来说，可以自行选用觉得称手的工具。 </p>
<p>gtags可建立索引，让搜寻更有效率<br />
grep按虽然好用，但是仍然有一些不足之处。第一个缺点在于它并不会为所搜寻的原始码档案索引。每当你搜寻时，它都会逐一地找出所有的档案，并且读取其中的所有内容，过滤出满足指定条件的档案。当专案的原始码数量太大时，就会产生搜寻效率不高的问题。 </p>
<p>第二个缺点是它只是一个单纯的文字档搜寻工具，本身并不会剖析原始码所对应的语言语法。当我们只想针对“函式”名称进行搜寻时，它有可能将注解中含有该名称的原始码，也一并找了出来。 </p>
<p>针对grep按的缺点，打算阅读他人程式码的程式人，可以考虑使用像是gtags这样子的工具。 gtags是源代码的GNU全局标记系统，它不只搜寻文字层次，而且因为具备了各种语言的语法剖析器，所以在搜寻时，可以只针对和语言有关的元素，例如类别名称，函式名称等。 </p>
<p>而且，它能针对原始码的内容进行索引，这意谓一旦建好索引之后，每次搜寻的动作，都毋需重新读取所有原始码的内容并逐一搜寻。只需要以现成的索引结构为基础，即可有效率的寻找关键段落。 </p>
<p>gtags提供了基于命令列的程式，让你指定原始码所在的目录执行建立索引的动作。它同时也提供程式让你得如同操作grep按一般，针对索引结构进行搜寻及检索。它提供了许多有用的检索方式，例如找出专案中定义某个资料结构的档案及定义所在的行号，或者是找出专案中所有引用某资料结构的档案，以及引用处的行号。 </p>
<p>这么一来，你就可以轻易地针对阅读程式码时的需求予以检索。相较于grep按所能提供的支援， gtags这样的工具，简直是强大许多。 </p>
<p>再搭配htags制作的HTML文件，更是如虎添翼<br />
还有一个绝对需要一提的工具。这个叫做htags的工具，能够帮你将已制作完成的索引结构，制作成为一组相互参考的的HTML文件。基本上，利用这样的的HTML文件阅读程式码，比起单纯地直接阅读原始码，来得更有结构。原因是阅读程式码时，这样的的HTML文件，已经为你建立起在各个原始码档案片段间跳跃的链结。例如，图一是针对一个有名的开放原始码专案ffmpeg ，由gtags所产生出来的的HTML文件首页的一部分。 </p>
<p>htags工具首先为你找出所有定义的Main （ ）函式的档案，并且列出所在的函式。找出的Main （ ）函式，时常是阅读程式码的第一步，因为主要（ ）函式是程式的主要入口点，所有的动作皆由此启动，它是一切事物的源头。<br />
凭借htags制作的的HTML文件，你可以轻易地点击超连结，直接进到的Main （ ）函式所在的程式码片段，如图二。 </p>
<p>当我们检视上述原始码时，发现av_register_all （ ）是个陌生，无法了解的事物，而想要搞懂它究竟是什么，可以再继续点击这个函式，如图三。这真是太方便了！阅读至此，你会猛然发现， gtags仿佛就是为了阅读程式码而专门量身打造的利器。 </p>
<p>阅读他人的程式码（ 4 ） -望文生义，进而推敲组件的作用</p>
<p>先建立系统的架构性认识，然后透过名称及命名惯例，就可以推测出各组件的作用。例如：当AOL的Winamp尝试着初始化一个插件时，它会呼叫这个结构中的初始化函式，以便让每个插件程式有机会初始化自己。当AOL的Winamp打算结束自己或结束某个插件的执行时，便会呼叫退出函式。</p>
<p>在阅读程式码的细节之前，我们应先试着捕捉系统的运作情境。在采取由上至下的方式时，系统性的架构是最顶端的层次，而系统的运作情境，则是在它之下的另一个层次。</p>
<p>好的说明文件难求，拼凑故事的能力很重要<br />
有些系统提供良善的说明文件，也许还利用UML的充分描述系统的运作情境。那么对于阅读者来说，从系统的分析及设计文件着手，便是快速了解系统运作情境的一个途径。<br />
但是，并不是每个软体专案都伴随着良好的系统文件，而许多极具价值的开放原始码专案，也时常不具备此类的文件。对此，阅读者必须尝试自行捕捉，并适度地记录捕捉到的运作情境。 </p>
<p>我喜欢将系统的运作情境，比拟成系统会上演的故事情节。在阅读细节性质的程式码前，先知道系统究竟会发生那些故事，是必备的基本功课。你可以利用熟悉或者自己发明的表示工具，描述你所找到的情境。甚至可以只利用简单的列表，直接将它们列出。只要能够达到记录的目的，对程式码阅读来说，都能够提供帮助。或者，你也可以利用基于UML中的类别图，合作图，循序图之类的表示方法，做出更详细的描述。<br />
当你能够列出系统可能会有的情境，表示你对系统所具备的功能，以及在各种情况下的反应，都具备概括性的认识。以此为基础，便可在任何需要的时候，钻进细节处深入了解。 </p>
<p>探索架构的第一步─ ─找到程式的入口<br />
在之前，我们在一个开发专案中，曾经需要将系统所得到的的MP3音讯档，放至iPod的这个极受欢迎的播放设备中。 </p>
<p>虽然iPod的本身也可以做为可移动式的储存设备，但并不是单纯地将MP3播放档案放到中的iPod ，就可以让苹果的播放器认得这个档案，甚至能够加以播放。<br />
这是因为苹果利用一个特殊的档案结构（ iTunes的数据库） ，记录播放器中可供播放的乐曲，播放清单以及乐曲资讯（例如专辑名称，乐曲长度，演唱者等） 。为了了解并且试着重复使用既有的程式码，我们找到了一个AOL的Winamp的iPod的外挂程式（插件） 。 </p>
<p>AOL的Winamp是个人电脑上极受欢迎的播放软体，而我们找到的外挂程式，能让的软件直接显示连接至电脑的的iPod中的歌曲资讯，并且允许的软件直接播放。 </p>
<p>我们追踪与阅读这个外挂程式的思路及步骤如下，首先，我们要先了解外挂程式的系统架构。很明显的，大概浏览过原始码后，我们注意到它依循着AOL的Winamp为插件程式所制定的规范，也就是说，它是实作成的Windows上的DLL的，并且透过一个叫做winampGetMediaLibraryPlugin的DLL的函式，提供一个名为winampMediaLibraryPlugin的结构。<br />
当我们不清楚系统的架构究竟为何时，我们会试着探索，而第一步，便是找到程式的入口。如何找到呢？这会依程式的性质不同而有所差别。<br />
对一个本身就是可独立执行的程式来说，我们会找启动程式的主要函式，例如对的C / C + +来说就是主要（ ） ，而对爪哇来说，便是静无效的main （ ） 。在找到入口后，再逐一追踪，摸索出系统的架构。<br />
但有时，我们所欲阅读的程式码是类别库或函式库，它只是用来提供多个类别或函式供用户端程式（客户程序）使用，本身并不具单一入口，此类的程式码具有多重的入口─ ─每个允许用户端程式呼叫的函式或类别，都是它可能的入口。 </p>
<p>例如，对AOL的Winamp的iPod的插件来说，它是一个动态链接库形式的函式库，所以当我们想了解它的架构时，必须要先找出它对外提供的函式，而对的Windows的DLL来说，对外提供的函式，皆会以dllexport这个关键字来修饰。所以，不论是利用grep按或gtags之类的工具，我们可以很快从原始码中，找到它只有一个DLL的函式（这对我们而言，真是一个好消息） ，而这个函式便是上述的winampGetMediaLibraryPlugin 。 </p>
<p>系统多会采用相同的架构处理插件程式<br />
如果经验不够的话，也许无法直接猜出这个函式的作用。<br />
不过，如果你是个有经验的程式人，多半能从函式所回传的结构，猜出这个函式实际的用途。而事实上，当你已经知道它是一个插件程式时，就应该要明白，它可能采用的，就是许多系统都采用的相同架构处理插件程式。 </p>
<p>当一个系统采用所谓插件形式的架构时，它通常不会知道它的插件究竟会怎么实作，实作什么功能。它只会规范插件程式需要满足某个特定介面。当系统初始化时，所有的插件都可以依循相同的方式，向系统注册，合法宣示自己的存在。 </p>
<p>虽然系统并不确切知道插件会有什么行为展现，但是因为它制定了一个标准的介面，所以系统仍然可以预期每个插件能够处理的动作类型。这些动作具体上怎么执行，对系统来说并不重要。这也正是物件导向程式设计中的“多型”观念。 </p>
<p>随着实务经验，归纳常见的架构模式<br />
我想表达的重点，是当你“涉世越深”之后，所接触的架构越多，就越能触类旁通。只需要瞧上几眼，就能明白系统所用的架构，自然就能够直接联想到其中可能存在的角色，以及角色间的关系。 </p>
<p>像上述的插件程式手法，时常可以在许多允许“外挂”程式码的系统中看到。所以，有经验的阅读者，多半能够立即反应，知道像这样的系统的软件，应该是让每个插件程式，都写成DLL的函式库。 </p>
<p>而每个插件的DLL的函式库中，都必须提供winampGetMediaLibraryPlugin （ ）这个函式（如果你熟悉的Windows的程式设计，你会知道这是利用加载（ ）和GetProcAddress （ ）来达成的一种多型手法） 。如果你熟悉设计模式，你更会知道这是简单工厂方法这个设计模式的运用。<br />
winampGetMediaLibraryPlugin （ ）所回传的winampMediaLibraryPlugin结构，正好就描述了每个AOL的Winamp插件的实作内容。 </p>
<p>善用名称可加速了解<br />
利用gtags这个工具，我们立即发现，这个插件它所定义的初始化，退出， PluginMessageProc这三个名称，都是函式名称。这暗示在多型的作用下，它们都是在某些时间点，会由AOL的Winamp核心本体呼叫的函式。 </p>
<p>名称及命名惯例是很重要的。看到“初始化” ，我们会知道它的作用多半是进行初始化的动作，而“退出”大概就是结束时处理函式，而PluginMessageProc多半就是各种讯息的处理常式（过程通常是程序的简写，所以PluginMessageProc意指插件讯息程序）了。 </p>
<p>“望文生义”很重要，我们看到函式的名称，就可以猜想到它所代表的作用，例如：当AOL的Winamp尝试着初始化一个插件时，它会呼叫这个结构中的初始化函式，以便让每个插件程式有机会初始化自己;当AOL的Winamp打算结束自己或结束某个插件的执行时，便会呼叫退出函式。当AOL的Winamp要和插件程式沟通时，它会发送各种不同的讯息至插件，而插件程式必须对此做出回应。 </p>
<p>我们甚至不需要检视这几个函式的内容，就可以做出推测，而这样的假设，事实上也是正确的。</p>
<p>阅读他人的程式码（ 5 ） -找到程式入口，再由上而下抽丝剥茧</p>
<p>根据需要决定展开的层数，或展开特定节点，并记录树状结构，然后适度忽略不需要了解的细节─这是一个很重要的态度。因为你不会一次就需要所有的细节，阅读都是有目的的，每次的阅读也许都在探索程式中不同的区域。</p>
<p>探索系统架构的第一步，就是找到程式的入口点。找到入口点后，多半采取由上而下（自上而下）的方式，由最外层的结构，一层一层逐渐探索越来越多的细节。<br />
我们的开发团队曾针对AOL的Winamp的iPod的插件进行阅读及探索，不仅找到入口点，也找出，并理解它最根本的基础架构。从这个入口点，可以往下再展开一层，分别找到三个重要的组成及其意义：<br />
●的init （ ） ：初始化动作<br />
     ●退出（ ） ：终止化动作<br />
     ● PluginMessageProc （ ） ：以讯息的方式处理程式所必须处理的各种事件</p>
<p>展开的同时，随手记录树状结构<br />
当我们从一个入口点找到三个分支后，可以顺着每个分支再展开一层，所以分别继续阅读的init ，退出，以及PluginMessageProc的内容，并试着再展开一层。阅读的同时，你可以在文件中试着记录展开的树状结构。<br />
●的init （ ） ：初始化动作<br />
     ● itunesdb_init_cc （ ） ：建立存取iTunes的数据库的同步物件<br />
     ●初始化资料结构<br />
     ●初始化的GUI元素<br />
     ●载入设定<br />
     ●建立日志档<br />
     ● autoDetectIpod （ ） ：侦测的iPod插入的执行绪<br />
     ●退出（ ） ：终止化动作<br />
     ● itunesdb_del_cc （ ） ：终止存取iTunes的数据库的同步物件<br />
     ●关闭日志档<br />
     ●终止化图形用户界面元素<br />
     ● PluginMessageProc （ ） ：以讯息的方式处理程式所必须面临的各种事件<br />
     ●执行所连接之苹果的MessageProc （ ） </p>
<p>这部分必须要留意几个重点。首先，应该一边阅读，一边记录文件。因为人的记忆力通常有限，对于陌生的事物更是容易遗忘，因此边阅读边记录，是很好的辅助。<br />
再者，因为我们采取由上而下的方式，从一个点再分支出去成为多个点，因此，通常也会以树状的方式记录。除此之外，每次只试着往下探索一层。从的init （ ）来看你便会明白。 </p>
<p>以下试着摘要的init （ ）的内容：<br />
诠释的init （ ） （<br />
itunesdb_init_cc （ ） ;<br />
currentiPod =空;<br />
苹果=新C_ItemList ;<br />
&#8230;略<br />
conf_file = （字符* ） SendMessage<br />
（ plugin.hwndWinampParent ， WM_WA_IPC ， 0 ， IPC_GETINIFILE ） ;<br />
m_treeview = GetDlgItem （ plugin.hwnd LibraryParent ， 0&#215;3fd ） ;<br />
/ /这个数字实际上是魔术： ）<br />
&#8230;略<br />
g_detectAll = GetPrivateProfileInt （ “ ml_ipod ” ， “ detectAll ” ， 0 ， conf_file ） ！ = 0 ;<br />
&#8230;略<br />
g_log = GetPrivateProfileInt （ “ ml_ipod ” ， “日志” ， 0 ， conf_file ） ！ = 0 ;<br />
&#8230;略<br />
g_logfile =打开（ g_logfilepath ，有“ A ” ） ;<br />
&#8230;略<br />
autoDetectIpod （ ） ;<br />
返回0 ;<br />
） </p>
<p>因为我们只试着多探索一层，而目的是希望发掘出下一层的子动作。所以在的init （ ）中看到像“ itunesdb_init_cc （ ） ; ”这样的函式呼叫动作时，我们知道它是在初始化（ ）之下的一个独立子动作，所以可以直接将它列入。但是当看到如下的程式行：<br />
currentiPod =空;<br />
苹果=新C_ItemList ; </p>
<p>我们并不会将它视为的init （ ）下的一个独立的子动作。因为好几行程式，才构成一个具有独立抽象意义的子动作。例如以上这两行构成了一个独立的抽象意义，也就是初始化所需的资料结构。 </p>
<p>理论上，原来的程式撰写者，有可能撰写一个叫做init_data_structure （ ）的函式，包含这两行程式码。这样做可读性更高，然而基于种种理由，原作者并没有这么做。身为阅读者，必须自行解读，将这几行合并成单一个子动作，并赋予它一个独立的意义─ ─初始化资料结构。 </p>
<p>无法望文生义的函式，先试着预看一层<br />
对于某些不明作用的函式叫用，不是望其文便能生其义的。当我们看到“ itunesdb_init_cc （ ） ”这个名称时，我们或许能从“ itunesdb_init ”的字眼意识到这个函式和苹果所采用的的iTunes数据库的初始化有关，但“循环”却实在令人费解。为了理解这一层某个子动作的真实意义，有时免不了要往前多看一层。 </p>
<p>原来它是用来初始化同步化机制用的物件。作用在于这程式一定是用了某个内部的资料结构来储存的iTunes数据库，而这资料结构有可能被多执行绪存取，所以必须以同步物件（此处是视窗的临界区）加以保护。 </p>
<p>所以说，当我们试着以树状的方式，逐一展开每个动作的子动作时，有时必须多看一层，才能真正了解子动作的意义。因为有了这样的动作，我们可以在展开树状结构中，为itunesdb_init_cc （ ）附上补充说明：建立存取iTunes的数据库的同步物件。这么一来，当我们在检视自己所写下的树状结构时，就能轻易一目了然的理解每个子动作的真正作用。 </p>
<p>根据需要了解的粒度，决定展开的层数<br />
我们究竟需要展开多少层呢？这个问题和阅读程式码时所需的“粒度（粒度） ”有关。如果我们只是需要概括性的了解，那么也许展开两层或三层，就能够对程式有基础的认识。倘若需要更深入的了解，就会需要展开更多的层次才行。 </p>
<p>有时候，你并不是一视同仁地针对每个动作，都展开到相同深度的层次。也许，你会基于特殊的需求，专门针对特定的动作展开至深层。例如，我们阅读AOL的Winamp的iPod插件的程式目录，其实是想从中了解究竟应该如何存取的iPod上的iTunes的数据库，使我们能够将MP3播放歌曲或播放清单加至此数据库中，并于的iPod中播放。 </p>
<p>当我们层层探索与分解之后，找到了parseIpodDb （ ） ，从函式名称判断它是我们想要的。因为它代表的正是剖析iPod的数据库，正是我们此次阅读的重点，也就达成阅读这程式码的目的。 </p>
<p>我们强调一种不同的做法：在阅读程式码时，多半采取由上而下的方式，而本文建议了一种记录阅读的方式，就是试着记录探索追踪时层层展开的树状结构。你可以视自己需要，了解的深入程度，再决定要展开的层数。你更可以依据特殊的需要，只展开某个特定的节点，以探索特定的细目。 </p>
<p>适度地忽略不需要了解的细节，是一个很重要的态度，因为你不会一次就需要所有的细节，阅读都是有目的的。每次的阅读也许都在探索程式中不同的区域;而每次探索时，你都可以增补树状结构中的某个子结构。渐渐地，你就会对这个程式更加的了解。</p>
<p>阅读他人的程式码（ 6 ） -阅读的乐趣：透过程式码认识作者</p>
<p>即便每个人的写作模式多半受到他人的影响，程式人通常还是会融合多种风格，而成为自己独有的特色，如果你知道作者程式设计的偏好，阅读他的程式码就更得心应手。</p>
<p>阅读程式码时，多半会采取由上而下，抽丝剥茧的方式。透过记录层层展开的树状结构，程式人可以逐步地建立起对系统的架构观，而且可以依照需要的粒度（粒度） ，决定展开的层次及精致程度。 </p>
<p>建立架构观点的认识是最重要的事情。虽然这一系列的文章前提为“阅读他人的程式码” ，但我们真正想做的工作，并不在于彻底地详读每一行程式码的细节，而是想要透过重点式的程式码“摘读” ，达到对系统所需程度的了解。每个人在阅读程式码的动机不尽相同，需要了解的程度也就有深浅的分别。只有极为少数的情况下，你才会需要细读每一行程式码。 </p>
<p>阅读程式码是新时代程式人必备的重要技能<br />
这一系列的文章至此已近尾声，回顾曾探讨的主题，我们首先研究了阅读程式码的动机。尤其在开放原始码的风气如此之盛的情况下，妥善利用开放原始码所提供的资源，不仅能够更快学习到新的技术，同时在原始码版权合适时，还可以直接利用现成的程式码，大幅地提高开发阶段的生产力。所以，阅读程式码俨然成为了新时代程式人必备的重要技能之一。<br />
接着，我们提到了阅读程式码前的必要准备，包括了对程式语言，命名惯例的了解等等。在此之后，我们反覆提起了“由上而下”的阅读方向的重要性。<br />
由上而下的阅读方式，是因为我们重视架构更胜于细节。从最外层的架构逐一向内探索，每往内探索一层，我们了解系统的粒度就增加了一个等级。当你识别出系统所用的架构时，便能够轻易了解在这个架构下会有的角色，以及它们之间的动态及静态的关系。如此一来，许多资讯便不言可喻，毋需额外花费力气，便能够快速理解。 </p>
<p>好的名称能够摘要性地点出实体的作用<br />
追踪原始码时，固然可以用本来的方式，利用编辑器开启所需的档案，然后利用编辑器提供的机制阅读，但是倘若能够善用工具，阅读程式码的效率及品质都能大大提升。在本系列文章中，我们介绍了一些工具，或许你还可以在坊间找到其他更有用的工具。<br />
我在这一系列的文章中，实际带着大家阅读，追踪了一个名为ml_pod的开放原始码专案。它是一个AOL的Winamp的iPod的外挂程式。在追踪的过程中，我们试着印证这一系列文中所提到的观念及方法。我们采用逐渐开展的树状结构来记录追踪的过程，并借以建立起对系统的概观认识。 </p>
<p>就原始码的阅读来说，之前的讨论涉及了工具面及技巧面。但还有一些主题不在这两个范畴之内，例如，善用名称赋予你的提示。名称做为隐喻（隐喻）的作用很大，好的名称能够摘要性地点出实体的作用，例如我们看到autoDetectIpod （ ） ，自然而然能够想像它的作用在于自动（自动）侦测（检测）的iPod的存在。 </p>
<p>我们在展开树状结构时，有时候需要预看一层，有时却不需要这么做，便可得到印证。程式人都会有惯用的名称以及组合名称的方法，倘若能够从名称上理解，便毋需钻进细节，可以省去相当多的时间。例如，当我们看到parseIpodDb （ ）时，便可以轻易了解它是剖析（解析）的iPod的资料库（ DB ）的，因此便不需要立即钻进parseIpodDb （ ）中查看底细。 </p>
<p>尽管如此，能否理解程式人命名的用意，和自身的经验以及是否了解原作者的文化背景，是息息相关的。 </p>
<p>命名本身就是一种文化产物。不同的程式人文化，就会衍生出不同的命名文化。当你自己的经验丰富，看过及接触过的程式码也多时，对于名称的感受及联想的能力自然会有不同。 </p>
<p>这种感受和联想的能力，究竟应该如何精进，很难具体描述。就我个人的经验，多观察不同命名体系的差异，并且尝试归纳彼此之间的异同，有助于更快地提升对名称的感受及联想力。 </p>
<p>转换立场，理解作者的思考方式<br />
除了工具及技巧之外， “想要阅读程式码，得先试着阅读写这个程式码的程式人的心。 ”这句话说来十分抽象，或许也令人难以理解。 </p>
<p>当你在阅读一段程式码时，或许可以试着转换自己的立场，从旁观者的角度转换成为写作者的心态，揣摩原作者的心理及处境。当你试着设身处地站在他的立场，透过他的思考方式来阅读，追踪他所写下的程式码，将会感觉更加流畅。 </p>
<p>许多软体专案，都不是由单一程式人所独力完成。因此，在这样的专案中，便有可能呈现多种不同的风格。 </p>
<p>许多专案会由架构师决定主体的架构及运作，有既定实施的命名惯例，及程式设计需要遵守方针。在多人开发的模式下，越是好的软体专案，越看不出某程式码片段究竟是由谁所写下的。 </p>
<p>不过，有些开放原始码的专案，往往又整合了其他开放原始码的专案。有的时候，也很难求风格的统一，便会出现混杂的情况。好比之前提到的ml_pod专案，因为程式码中混合了不同的来源，而呈现风格不一致的情况。 </p>
<p>我在阅读非自己所写的程式码时，会观察原作者写作的习惯，借以对应到脑中所记忆的多种写作模型。在阅读的过程中，读完几行程式码，我会试着猜想原作者在写下这段程式码时的心境。他写下这段程式码的用意是什么？为什么他会采取这样的写法？顺着原作者的思考理路阅读，自己的思考才能更贴近对方写作当时的想法。 </p>
<p>当你短暂化身为原作者时，才能更轻易的理解他所写下的程式码。<br />
如果你能知道原作者的背景，程式设计时的偏好，阅读他的程式码，就更能得心应手了。 </p>
<p>从程式码着手认识作者独有的风格，进而见贤思齐<br />
我在阅读别人写下的程式码时，我会试着猜想，原作者究竟是属于那一种“流派”呢？每个人都有自己独特的写作模式，即便每个人的写作模式多半受到他人的影响─ ─不论是书籍的作者，学习过程中的指导者，或一同参与专案的同侪，但每个程式人通常会融合多种风格，而成为自己独有的风格。 </p>
<p>物件导向的基本教义派，总是会以他心中觉得最优雅的物件导向方式来撰写程式。而阅读惯用，善用设计模式的程式人所写下的程式码时，不难推想出他会在各种常见的应用情境下，套用哪些模式。 </p>
<p>有些时候，在阅读之初，你并不知道原作者的习性跟喜好，甚至你也不知道他的功力。但是，在阅读之后，你会慢慢地从一个程式人所写下的程式码，开始认识他。 </p>
<p>你或许会在阅读他人的程式码时，发现令人拍案叫绝的技巧或设计。你也有可能在阅读的同时，发现原作者所留下的缺失或写作时的缺点，而暗自警惕于心。这也算是阅读他人程式码时的一项乐趣。 </p>
<p>当你从视阅读他人的程式码为畏途，转变成为可以从中获取乐趣的时候，我想，你又进到了另一个境界。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.uncleli.cn/archives/553.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[转]华中科技大学校长李培根在2010届毕业典礼上的致辞</title>
		<link>http://www.uncleli.cn/archives/551.html</link>
		<comments>http://www.uncleli.cn/archives/551.html#comments</comments>
		<pubDate>Thu, 24 Jun 2010 01:25:23 +0000</pubDate>
		<dc:creator>Uncle Li (黎 叔)</dc:creator>
				<category><![CDATA[网络收藏]]></category>

		<guid isPermaLink="false">http://www.uncleli.cn/?p=551</guid>
		<description><![CDATA[　　亲爱的2010届毕业生同学们：
　　你们好！
　　首先，为你们完成学业并即将踏上新的征途送上最美好的祝愿。
　　同学们，在华中科技大学的这几年里，你们一定有很多珍贵的记忆！
　　你们真幸运，国家的盛世如此集中相伴在你们大学的记忆中。08奥运留下的记忆，不仅是金牌数的第一，不仅是开幕式的华丽，更是中华文化的魅力和民族向心力的显示；六十年大庆留下的记忆，不仅是领袖的挥手，不仅是自主研制的先进武器，不仅是女兵的微笑，不仅是队伍的威武整齐，更是改革开放的历史和旗帜的威力；世博会留下的记忆，不仅是世博之夜水火相容的神奇，不仅是中国馆的宏伟，不仅是异国场馆的浪漫，更是中华的崛起，世界的惊异；你们一定记得某国总统的傲慢与无礼，你们也让他记忆了你们的不屑与蔑视；同学们，伴随着你们大学记忆的一定还有“什锦八宝饭”等新词，它将永远成为世界新的记忆。
　　近几年，国家频发的灾难一定给你们留下深刻的记忆。汶川的颤抖，没能抖落中国人民的坚强与刚毅；玉树的摇动，没能撼动汉藏人民的齐心与合力。留给你们记忆的不仅是大悲的哭泣，更是大爱的洗礼；西南的干旱或许使你们一样感受渴与饥，留给你们记忆的，不仅是大地的喘息，更是自然需要和谐、发展需要科学的道理。
　　在华中大的这几年，你们会留下一生中特殊的记忆。你一定记得刚进大学的那几分稚气，父母亲人送你报到时的历历情景；你或许记得“考前突击而带着忐忑不安的心情走向考场时的悲壮”，你也会记得取得好成绩时的欣喜；你或许记得这所并无悠久历史的学校不断追求卓越的故事；你或许记得裘法祖院士所代表的同济传奇以及大师离去时同济校园中弥漫的悲痛与凝重气息；你或许记得人文素质讲堂的拥挤，也记得在社团中的奔放与随意；你一定记得骑车登上“绝望坡”的喘息与快意；你也许记得青年园中令你陶醉的发香和桂香，眼睛湖畔令你流连忘返的圣洁或妖娆；你或许记得“向喜欢的女孩表白被拒时内心的煎熬”，也一定记得那初吻时的如醉如痴。
　　可是，你是否还记得强磁场和光电国家实验室的建立？是否记得创新研究院和启明学院的耸起？是否记得为你们领航的党旗？是否记得人文讲坛上精神矍铄的先生叔子？是否记得倾听你们诉说的在线的“张妈妈”？是否记得告诉你们捡起路上树枝的刘玉老师？是否记得应立新老师为你们修改过的简历，但愿它能成为你们进入职场的最初记忆。同学们，华中大校园里，太多的人和事需要你们记忆。
　　请相信我，日后你们或许会改变今天的某些记忆。瑜园的梧桐，年年飞絮成“雨”，今天或许让你觉得如淫雨霏霏，使你心情烦躁、郁闷。日后，你会觉得如果没有梧桐之“雨”，瑜园将缺少滋润，若没有梧桐的遮盖，华中大似乎缺少前辈的庇荫，更少了历史的沉积。你们一定还记得，学校的排名下降使你们生气，未来或许你会觉得“不为排名所累”更体现华中大的自信与定力。
　　我知道，你们还有一些特别的记忆。你们一定记住了“俯卧撑”、“躲猫猫”、“喝开水”，从热闹和愚蠢中，你们记忆了正义；你们记住了“打酱油”和“妈妈喊你回家吃饭”，从麻木和好笑中，你们记忆了责任和良知；你们一定记住了姐的狂放，哥的犀利。未来有一天，或许当年的记忆会让你们问自己，曾经是姐的娱乐，还是哥的寂寞？
　　亲爱的同学们，你们在华中科技大学的几年给我留下了永恒的记忆。我记得你们为烈士寻亲千里，记得你们在公德长征路上的经历；我记得你们在各种社团的骄人成绩；我记得你们时而感到“无语”时而表现都焦虑，记得你们为中国的“常青藤”学校中无华中大一席而灰心丧气；我记得某些同学为“学位门”、为光谷同济医院的选址而愤激；我记得你们刚刚对我的呼喊：“根叔，你为我们做了什么？”——是啊，我也得时时拷问自己的良心，到底为你们做了什么？还能为华中大学子做什么？
　　我记得，你们都是小青年。我记得“吉丫头”，那么平凡，却格外美丽；我记得你们中间的胡政在国际权威期刊上发表多篇高水平论文，创造了本科生参与研究的奇迹；我记得“校歌男”，记得“选修课王子”，同样是可爱的孩子。我记得沉迷于网络游戏甚至频临退学的学生与我聊天时目光中透出的茫然与无助，他们还是华中大的孩子，他们更成为我心中抹不去的记忆。
　　我记得你们的自行车和热水瓶常常被偷，记得你们为抢占座位而付出的艰辛；记得你们在寒冷的冬天手脚冰凉，记得你们在炎热的夏季彻夜难眠；记得食堂常常让你们生气，我当然更记得自己说过的话：“我们绝不赚学生一分钱”，也记得你们对此言并不满意；但愿华中大尤其要有关于校园丑陋的记忆。只要我们共同记忆那些丑陋，总有一天，我们能将丑陋转化成美丽。
　　同学们，你们中的大多数人，即将背上你们的行李，甚至远离。请记住，最好不要再让你们的父母为你们送行。“面对岁月的侵蚀，你们的烦恼可能会越来越多，考虑的问题也可能会越来越现实，角色的转换可能会让你们感觉到有些措手不及。”也许你会选择“胶囊公寓”，或者不得不蜗居，成为蚁族之一员。没关系，成功更容易光顾磨难和艰辛，正如只有经过泥泞的道路才会留下脚印。请记住，未来你们大概不再有批评上级的随意，同事之间大概也不会有如同学之间简单的关系；请记住，别太多地抱怨，成功永远不属于整天抱怨的人，抱怨也无济于事；请记住，别沉迷于世界的虚拟，还得回到社会的现实；请记住，“敢于竞争，善于转化”，这是华中大的精神风貌，也许是你们未来成功的真谛；请记住，华中大，你的母校。“什么是母校？就是那个你一天骂她八遍却不许别人骂的地方”。
　　亲爱的同学们，也许你们难以有那么多的记忆。如果问你们关于一个字的记忆，那一定是“被”。我知道，你们不喜欢“被就业”、“被坚强”，那就挺直你们的脊梁，挺起你们的胸膛，自己去就业，坚强而勇敢地到社会中去闯荡。
　　亲爱的同学们，也许你们难以有那么多的记忆，也许你们很快就会忘记根叔的唠叨与琐细。尽管你们不喜欢“被”，根叔还是想强加给你们一个“被”：你们的未来“被”华中大记忆！
]]></description>
			<content:encoded><![CDATA[<p>　　亲爱的2010届毕业生同学们：</p>
<p>　　你们好！</p>
<p>　　首先，为你们完成学业并即将踏上新的征途送上最美好的祝愿。</p>
<p>　　同学们，在华中科技大学的这几年里，你们一定有很多珍贵的记忆！</p>
<p>　　你们真幸运，国家的盛世如此集中相伴在你们大学的记忆中。08奥运留下的记忆，不仅是金牌数的第一，不仅是开幕式的华丽，更是中华文化的魅力和民族向心力的显示；六十年大庆留下的记忆，不仅是领袖的挥手，不仅是自主研制的先进武器，不仅是女兵的微笑，不仅是队伍的威武整齐，更是改革开放的历史和旗帜的威力；世博会留下的记忆，不仅是世博之夜水火相容的神奇，不仅是中国馆的宏伟，不仅是异国场馆的浪漫，更是中华的崛起，世界的惊异；你们一定记得某国总统的傲慢与无礼，你们也让他记忆了你们的不屑与蔑视；同学们，伴随着你们大学记忆的一定还有“什锦八宝饭”等新词，它将永远成为世界新的记忆。</p>
<p>　　近几年，国家频发的灾难一定给你们留下深刻的记忆。汶川的颤抖，没能抖落中国人民的坚强与刚毅；玉树的摇动，没能撼动汉藏人民的齐心与合力。留给你们记忆的不仅是大悲的哭泣，更是大爱的洗礼；西南的干旱或许使你们一样感受渴与饥，留给你们记忆的，不仅是大地的喘息，更是自然需要和谐、发展需要科学的道理。</p>
<p>　　在华中大的这几年，你们会留下一生中特殊的记忆。你一定记得刚进大学的那几分稚气，父母亲人送你报到时的历历情景；你或许记得“考前突击而带着忐忑不安的心情走向考场时的悲壮”，你也会记得取得好成绩时的欣喜；你或许记得这所并无悠久历史的学校不断追求卓越的故事；你或许记得裘法祖院士所代表的同济传奇以及大师离去时同济校园中弥漫的悲痛与凝重气息；你或许记得人文素质讲堂的拥挤，也记得在社团中的奔放与随意；你一定记得骑车登上“绝望坡”的喘息与快意；你也许记得青年园中令你陶醉的发香和桂香，眼睛湖畔令你流连忘返的圣洁或妖娆；你或许记得“向喜欢的女孩表白被拒时内心的煎熬”，也一定记得那初吻时的如醉如痴。</p>
<p>　　可是，你是否还记得强磁场和光电国家实验室的建立？是否记得创新研究院和启明学院的耸起？是否记得为你们领航的党旗？是否记得人文讲坛上精神矍铄的先生叔子？是否记得倾听你们诉说的在线的“张妈妈”？是否记得告诉你们捡起路上树枝的刘玉老师？是否记得应立新老师为你们修改过的简历，但愿它能成为你们进入职场的最初记忆。同学们，华中大校园里，太多的人和事需要你们记忆。</p>
<p>　　请相信我，日后你们或许会改变今天的某些记忆。瑜园的梧桐，年年飞絮成“雨”，今天或许让你觉得如淫雨霏霏，使你心情烦躁、郁闷。日后，你会觉得如果没有梧桐之“雨”，瑜园将缺少滋润，若没有梧桐的遮盖，华中大似乎缺少前辈的庇荫，更少了历史的沉积。你们一定还记得，学校的排名下降使你们生气，未来或许你会觉得“不为排名所累”更体现华中大的自信与定力。</p>
<p>　　我知道，你们还有一些特别的记忆。你们一定记住了“俯卧撑”、“躲猫猫”、“喝开水”，从热闹和愚蠢中，你们记忆了正义；你们记住了“打酱油”和“妈妈喊你回家吃饭”，从麻木和好笑中，你们记忆了责任和良知；你们一定记住了姐的狂放，哥的犀利。未来有一天，或许当年的记忆会让你们问自己，曾经是姐的娱乐，还是哥的寂寞？</p>
<p>　　亲爱的同学们，你们在华中科技大学的几年给我留下了永恒的记忆。我记得你们为烈士寻亲千里，记得你们在公德长征路上的经历；我记得你们在各种社团的骄人成绩；我记得你们时而感到“无语”时而表现都焦虑，记得你们为中国的“常青藤”学校中无华中大一席而灰心丧气；我记得某些同学为“学位门”、为光谷同济医院的选址而愤激；我记得你们刚刚对我的呼喊：“根叔，你为我们做了什么？”——是啊，我也得时时拷问自己的良心，到底为你们做了什么？还能为华中大学子做什么？</p>
<p>　　我记得，你们都是小青年。我记得“吉丫头”，那么平凡，却格外美丽；我记得你们中间的胡政在国际权威期刊上发表多篇高水平论文，创造了本科生参与研究的奇迹；我记得“校歌男”，记得“选修课王子”，同样是可爱的孩子。我记得沉迷于网络游戏甚至频临退学的学生与我聊天时目光中透出的茫然与无助，他们还是华中大的孩子，他们更成为我心中抹不去的记忆。</p>
<p>　　我记得你们的自行车和热水瓶常常被偷，记得你们为抢占座位而付出的艰辛；记得你们在寒冷的冬天手脚冰凉，记得你们在炎热的夏季彻夜难眠；记得食堂常常让你们生气，我当然更记得自己说过的话：“我们绝不赚学生一分钱”，也记得你们对此言并不满意；但愿华中大尤其要有关于校园丑陋的记忆。只要我们共同记忆那些丑陋，总有一天，我们能将丑陋转化成美丽。</p>
<p>　　同学们，你们中的大多数人，即将背上你们的行李，甚至远离。请记住，最好不要再让你们的父母为你们送行。“面对岁月的侵蚀，你们的烦恼可能会越来越多，考虑的问题也可能会越来越现实，角色的转换可能会让你们感觉到有些措手不及。”也许你会选择“胶囊公寓”，或者不得不蜗居，成为蚁族之一员。没关系，成功更容易光顾磨难和艰辛，正如只有经过泥泞的道路才会留下脚印。请记住，未来你们大概不再有批评上级的随意，同事之间大概也不会有如同学之间简单的关系；请记住，别太多地抱怨，成功永远不属于整天抱怨的人，抱怨也无济于事；请记住，别沉迷于世界的虚拟，还得回到社会的现实；请记住，“敢于竞争，善于转化”，这是华中大的精神风貌，也许是你们未来成功的真谛；请记住，华中大，你的母校。“什么是母校？就是那个你一天骂她八遍却不许别人骂的地方”。</p>
<p>　　亲爱的同学们，也许你们难以有那么多的记忆。如果问你们关于一个字的记忆，那一定是“被”。我知道，你们不喜欢“被就业”、“被坚强”，那就挺直你们的脊梁，挺起你们的胸膛，自己去就业，坚强而勇敢地到社会中去闯荡。</p>
<p>　　亲爱的同学们，也许你们难以有那么多的记忆，也许你们很快就会忘记根叔的唠叨与琐细。尽管你们不喜欢“被”，根叔还是想强加给你们一个“被”：你们的未来“被”华中大记忆！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.uncleli.cn/archives/551.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android 打包签名 从生成keystore到完成签名</title>
		<link>http://www.uncleli.cn/archives/549.html</link>
		<comments>http://www.uncleli.cn/archives/549.html#comments</comments>
		<pubDate>Wed, 23 Jun 2010 03:06:52 +0000</pubDate>
		<dc:creator>Uncle Li (黎 叔)</dc:creator>
				<category><![CDATA[Java相关]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[keystore]]></category>

		<guid isPermaLink="false">http://www.uncleli.cn/?p=549</guid>
		<description><![CDATA[首先,我们需要一个keystore,当然已经有了的话就不用这一步了:
cmd下:
进入到jdk的bin目录,这样的话,android.keystore文件就会生成在这个目录下,签名的时候我们需要这个文件
C:\Program Files\Java\jdk1.6.0_10\bin>keytool -genkey -alias android.keystore -keyalg RSA -validity 20000 -keystore android.keystore
输入keystore密码：
再次输入新密码：
您的名字与姓氏是什么？
  [Unknown]：  Lee
您的组织单位名称是什么？
  [Unknown]：  www.uncleli.cn
您的组织名称是什么？
  [Unknown]：  www.uncleli.cn
您所在的城市或区域名称是什么？
  [Unknown]：  nanchang
您所在的州或省份名称是什么？
  [Unknown]：  Jx
该单位的两字母国家代码是什么
  [Unknown]：  86
CN=Lee, OU=www.uncleli.cn, O=www.uncleli.cn, L=nc, ST=Jx, C=86 正确吗？
  [否]：  Y
输入的主密码（如果和 keystore 密码相同，按回车）：
其中参数-validity为证书有效天数，这里我们写的大些10000天。还有在输入密码时没有回显(尽管输就是啦) 并且 退格,tab等都属于密码内容，这个密码在给.apk文件签名的时候需要.
然后签名:
Eclipse中,右击需要签名的工程&#8211;>android tools&#8211;>export signed application package&#8230;
出现下面对话框,选择需要签名的工程
next,选择上面生成的android.keystore文件位置和设置的密码
next
next,选择签名生成文件的位置和名称
finish,搞定啦&#8230;
]]></description>
			<content:encoded><![CDATA[<p>首先,我们需要一个keystore,当然已经有了的话就不用这一步了:<br />
cmd下:<br />
进入到jdk的bin目录,这样的话,android.keystore文件就会生成在这个目录下,签名的时候我们需要这个文件<br />
C:\Program Files\Java\jdk1.6.0_10\bin>keytool -genkey -alias android.keystore -keyalg RSA -validity 20000 -keystore android.keystore<br />
输入keystore密码：<br />
再次输入新密码：<br />
您的名字与姓氏是什么？<br />
  [Unknown]：  Lee<br />
您的组织单位名称是什么？<br />
  [Unknown]：  www.uncleli.cn<br />
您的组织名称是什么？<br />
  [Unknown]：  www.uncleli.cn<br />
您所在的城市或区域名称是什么？<br />
  [Unknown]：  nanchang<br />
您所在的州或省份名称是什么？<br />
  [Unknown]：  Jx<br />
该单位的两字母国家代码是什么<br />
  [Unknown]：  86<br />
CN=Lee, OU=www.uncleli.cn, O=www.uncleli.cn, L=nc, ST=Jx, C=86 正确吗？<br />
  [否]：  Y<br />
输入<android.keystore>的主密码（如果和 keystore 密码相同，按回车）：</p>
<p>其中参数-validity为证书有效天数，这里我们写的大些10000天。还有在输入密码时没有回显(尽管输就是啦) 并且 退格,tab等都属于密码内容，这个密码在给.apk文件签名的时候需要.</p>
<p>然后签名:<br />
Eclipse中,右击需要签名的工程&#8211;>android tools&#8211;>export signed application package&#8230;<br />
出现下面对话框,选择需要签名的工程</p>
<p>next,选择上面生成的android.keystore文件位置和设置的密码</p>
<p>next</p>
<p>next,选择签名生成文件的位置和名称</p>
<p>finish,搞定啦&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.uncleli.cn/archives/549.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Word行号设置方法</title>
		<link>http://www.uncleli.cn/archives/546.html</link>
		<comments>http://www.uncleli.cn/archives/546.html#comments</comments>
		<pubDate>Tue, 22 Jun 2010 06:24:29 +0000</pubDate>
		<dc:creator>Uncle Li (黎 叔)</dc:creator>
				<category><![CDATA[互联网资讯]]></category>
		<category><![CDATA[杂七杂八]]></category>
		<category><![CDATA[word]]></category>
		<category><![CDATA[网格]]></category>
		<category><![CDATA[行号]]></category>

		<guid isPermaLink="false">http://www.uncleli.cn/?p=546</guid>
		<description><![CDATA[最近弄文档要求要行号，转载文章一段：
　　我们怎样知道word文档中每页有多少行呢?这就要靠word行号帮忙了。Word中的行号可以自动计算文件中的行数，然后在各行文字旁显示适当的行号。
　　在出版物中，有些类型的文档，如果在正文的侧面添加行号，会增强文档的易读性。比如许多英文教材，法律文书、名人手稿等，显然人工添加是不现实的，我们就可以使用添加行号来实现。添加行号这个技巧对于老师给学生打印阅读材料，程序员打印程序都很实用。
　　word 如何添加行号呢？方法如下：
　　第一步，打开Word文档，选择“视图”→“页面”命令把当前文档设置为页面模式。这一点很重要，其他模式是看不到这个效果的。
　　第二步，在打开的Word文档中用鼠标选中要添加行号的段落。
　　注：如果要给整篇文章加上行号，或者希望在文章输入过程中自动添加行号，则无需此步骤。
　　第三步，选择“文件”菜单下“页面设置”命令，打开“页面设置”对话框，并单击“版式”标签。
　　第四步，在“版式”选项卡中找到最下面的“预览”设置部分，在“应用于”选项根据自己的要求选择“整篇文档”或“所选文字”。
　　注：如果没有在文档中选择任何文字，则不会出现“所选文字”项。
　　第五步，单击下面的“行号”按钮，出现“行号”设置对话框。首先选中“添加行号”复选框，然后根据自己的要求设置“起始编号”和“行号间隔”。其中“距正文”用来设置行号与其正文之间的距离；“编号方式”中选择是“每页重新编号”、“每节重新编号”还是“连续编号”；最后单击“确认”按钮退出“行号”设置。
　　第六步，单击“确认”按钮退出“页面”设置。此时你就会看到行号出现在正文的左边。
　　如果Word中已经添加了行号，不使用了，需要取消，可以将“添加行号”前面的对勾取消掉就可以了。
]]></description>
			<content:encoded><![CDATA[<p>最近弄文档要求要行号，转载文章一段：<br />
　　我们怎样知道word文档中每页有多少行呢?这就要靠word行号帮忙了。Word中的行号可以自动计算文件中的行数，然后在各行文字旁显示适当的行号。</p>
<p>　　在出版物中，有些类型的文档，如果在正文的侧面添加行号，会增强文档的易读性。比如许多英文教材，法律文书、名人手稿等，显然人工添加是不现实的，我们就可以使用添加行号来实现。添加行号这个技巧对于老师给学生打印阅读材料，程序员打印程序都很实用。</p>
<p>　　word 如何添加行号呢？方法如下：</p>
<p>　　第一步，打开Word文档，选择“视图”→“页面”命令把当前文档设置为页面模式。这一点很重要，其他模式是看不到这个效果的。</p>
<p>　　第二步，在打开的Word文档中用鼠标选中要添加行号的段落。<br />
　　注：如果要给整篇文章加上行号，或者希望在文章输入过程中自动添加行号，则无需此步骤。</p>
<p>　　第三步，选择“文件”菜单下“页面设置”命令，打开“页面设置”对话框，并单击“版式”标签。</p>
<p>　　第四步，在“版式”选项卡中找到最下面的“预览”设置部分，在“应用于”选项根据自己的要求选择“整篇文档”或“所选文字”。<br />
　　注：如果没有在文档中选择任何文字，则不会出现“所选文字”项。</p>
<p>　　第五步，单击下面的“行号”按钮，出现“行号”设置对话框。首先选中“添加行号”复选框，然后根据自己的要求设置“起始编号”和“行号间隔”。其中“距正文”用来设置行号与其正文之间的距离；“编号方式”中选择是“每页重新编号”、“每节重新编号”还是“连续编号”；最后单击“确认”按钮退出“行号”设置。</p>
<p>　　第六步，单击“确认”按钮退出“页面”设置。此时你就会看到行号出现在正文的左边。</p>
<p>　　如果Word中已经添加了行号，不使用了，需要取消，可以将“添加行号”前面的对勾取消掉就可以了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.uncleli.cn/archives/546.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>网页设计师是怎样下地狱的!</title>
		<link>http://www.uncleli.cn/archives/544.html</link>
		<comments>http://www.uncleli.cn/archives/544.html#comments</comments>
		<pubDate>Wed, 09 Jun 2010 12:46:37 +0000</pubDate>
		<dc:creator>Uncle Li (黎 叔)</dc:creator>
				<category><![CDATA[前端技术]]></category>
		<category><![CDATA[网页设计师]]></category>

		<guid isPermaLink="false">http://www.uncleli.cn/archives/544.html</guid>
		<description><![CDATA[把这个送给曾经接过活的设计师，或者有过类似经历的设计师们。阿门。
刚开始的时候，一切都很棒。客户提出他们的需求，你也满怀期望。充满激情和兴奋感。
客户：新的网站一定会很棒。
设计师：岂止很棒？肯定会难以置信地棒。它会像遨游在外太空的雄鹰一般不可思议。
客户给你看他们现在的网站，你们一起嘲笑它是如此糟糕。
客户：哈哈，这都是什么烂玩意！我们上次请的设计师简直是个白痴。
设计师：是啊！怎么可能做成这样？！简直就是在对全人类犯罪。
于是，你重新设计了网站。新网站看上去美观，用起来也很好。这简直就是完美设计的最佳范例。
设计师：噔噔噔噔！看！
客户：我喜欢！看上去太棒了！我都想跟它做爱了！但是……
还需要做些“小”调整
客户（想）：这个设计很完美，但我作为CEO，有责任提点改正意见来让自己感觉自己的工作做到位了。同时，我得用“用户体验”，“转化导向”这样的术语来显得自己聪明些，尽管我几乎都不大会用电脑。
客户：你能设计得更“跳”一点么？它需要更“鲜明”些。看上去感觉好像不太对。
（作者注：客户确实跟我说过这样的话。直到今天，我还是不太理解在网页设计上“跳”和“鲜明”到底是什么意思。我也不知道怎样以他人的感受来设计网页）
所谓的小调整开始变多，很快就变成不那么小了。
客户：我想了一下，决定把字体调回Comic Sans. 另外，你能搞一个镜头光晕效果么？它们看上去非常Web2.0. 另外，这个网站绝对不能太“线条化”了。当我看这个网站的时候，我看到的都是一行一行的。你能处理一下么？
（作者注：确实有个客户这么对我说过。这个设计里绝对没有任何水平标尺或者线条之类的东西。事实上他说的是
啊
啊之类的代码生成的矩形区域）
客户让别的人参与了进来。
“看上去不错，不过我还想听到更多的意见，朋友，同事，叔叔甚至是我的宠物仓鼠”
客户：我让我母亲也加入讨论。她在1982年设计过一张面包促销宣传单，所以你可以说她也是有设计的眼光。
客户母亲：你排的这个设计需要点亮色，看上去太暗了。加点粉色怎样？再放上一只小猫。人人都爱小猫。
（作者注：我确实曾经遇到一个客户让他的母亲也参与到设计流程里，好让她提出批评和建议）
所有希望都破灭了。
你开始幻想别的职业，比如靠挖沟来生存或者给老人搓澡。
客户：好的。现在是这样，我的狗Miffles可是个关键人物。它可以说是我生命中最重要的部分。我希望你能加上狗的“意识流”，这样看上去就像是Miffles在和来访的用户说话。我会给你几页Miffles可能会说的话，比如“我喜欢美食”，还有“嗨！欢迎访问我的网站，我是一只小狗，你可以和我握手^^”
(作者注：这绝对不是我编的。就有一个客户这样要求过。我还从来没有像那会一样那么想用车用蓄电池敲一个人的头)
你再也不是一名网页设计师。
你现在变成了一只绘图程序里的鼠标，而你的客户可以通过语音，email或者聊天软件来直接控制你。
（作者注：我曾经遇到一个客户拿走我的设计稿后，自己直接在Photoshop上进行修改，然后把改过后觉得是他们想要的效果再发给我。在我收到他的第13个修正版后，我炒掉了他。）
怨念就此诞生。
客户完全忘了，他们是雇佣了你，网页设计师，来帮他们设计一个好产品。想象一下，如果你是一个设计商业飞机涡轮的工程师，他们还敢掺和进来么？
客户：现在这个设计终于称得上是“跳”出来了！
设计师：饶了我吧……
]]></description>
			<content:encoded><![CDATA[<p>把这个送给曾经接过活的设计师，或者有过类似经历的设计师们。阿门。</p>
<p>刚开始的时候，一切都很棒。客户提出他们的需求，你也满怀期望。充满激情和兴奋感。</p>
<p>客户：新的网站一定会很棒。</p>
<p>设计师：岂止很棒？肯定会难以置信地棒。它会像遨游在外太空的雄鹰一般不可思议。</p>
<p>客户给你看他们现在的网站，你们一起嘲笑它是如此糟糕。</p>
<p>客户：哈哈，这都是什么烂玩意！我们上次请的设计师简直是个白痴。</p>
<p>设计师：是啊！怎么可能做成这样？！简直就是在对全人类犯罪。</p>
<p>于是，你重新设计了网站。新网站看上去美观，用起来也很好。这简直就是完美设计的最佳范例。</p>
<p>设计师：噔噔噔噔！看！</p>
<p>客户：我喜欢！看上去太棒了！我都想跟它做爱了！但是……</p>
<p>还需要做些“小”调整</p>
<p>客户（想）：这个设计很完美，但我作为CEO，有责任提点改正意见来让自己感觉自己的工作做到位了。同时，我得用“用户体验”，“转化导向”这样的术语来显得自己聪明些，尽管我几乎都不大会用电脑。</p>
<p>客户：你能设计得更“跳”一点么？它需要更“鲜明”些。看上去感觉好像不太对。</p>
<p>（作者注：客户确实跟我说过这样的话。直到今天，我还是不太理解在网页设计上“跳”和“鲜明”到底是什么意思。我也不知道怎样以他人的感受来设计网页）</p>
<p>所谓的小调整开始变多，很快就变成不那么小了。</p>
<p>客户：我想了一下，决定把字体调回Comic Sans. 另外，你能搞一个镜头光晕效果么？它们看上去非常Web2.0. 另外，这个网站绝对不能太“线条化”了。当我看这个网站的时候，我看到的都是一行一行的。你能处理一下么？</p>
<p>（作者注：确实有个客户这么对我说过。这个设计里绝对没有任何水平标尺或者线条之类的东西。事实上他说的是
<div>啊
<p>啊之类的代码生成的矩形区域）</p>
<p>客户让别的人参与了进来。</p>
<p>“看上去不错，不过我还想听到更多的意见，朋友，同事，叔叔甚至是我的宠物仓鼠”</p>
<p>客户：我让我母亲也加入讨论。她在1982年设计过一张面包促销宣传单，所以你可以说她也是有设计的眼光。</p>
<p>客户母亲：你排的这个设计需要点亮色，看上去太暗了。加点粉色怎样？再放上一只小猫。人人都爱小猫。</p>
<p>（作者注：我确实曾经遇到一个客户让他的母亲也参与到设计流程里，好让她提出批评和建议）</p>
<p>所有希望都破灭了。</p>
<p>你开始幻想别的职业，比如靠挖沟来生存或者给老人搓澡。</p>
<p>客户：好的。现在是这样，我的狗Miffles可是个关键人物。它可以说是我生命中最重要的部分。我希望你能加上狗的“意识流”，这样看上去就像是Miffles在和来访的用户说话。我会给你几页Miffles可能会说的话，比如“我喜欢美食”，还有“嗨！欢迎访问我的网站，我是一只小狗，你可以和我握手^^”</p>
<p>(作者注：这绝对不是我编的。就有一个客户这样要求过。我还从来没有像那会一样那么想用车用蓄电池敲一个人的头)</p>
<p>你再也不是一名网页设计师。</p>
<p>你现在变成了一只绘图程序里的鼠标，而你的客户可以通过语音，email或者聊天软件来直接控制你。</p>
<p>（作者注：我曾经遇到一个客户拿走我的设计稿后，自己直接在Photoshop上进行修改，然后把改过后觉得是他们想要的效果再发给我。在我收到他的第13个修正版后，我炒掉了他。）</p>
<p>怨念就此诞生。</p>
<p>客户完全忘了，他们是雇佣了你，网页设计师，来帮他们设计一个好产品。想象一下，如果你是一个设计商业飞机涡轮的工程师，他们还敢掺和进来么？</p>
<p>客户：现在这个设计终于称得上是“跳”出来了！</p>
<p>设计师：饶了我吧……</p>
]]></content:encoded>
			<wfw:commentRss>http://www.uncleli.cn/archives/544.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>网页中flash wmode属性</title>
		<link>http://www.uncleli.cn/archives/542.html</link>
		<comments>http://www.uncleli.cn/archives/542.html#comments</comments>
		<pubDate>Wed, 09 Jun 2010 12:40:41 +0000</pubDate>
		<dc:creator>Uncle Li (黎 叔)</dc:creator>
				<category><![CDATA[前端技术]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[wmode]]></category>

		<guid isPermaLink="false">http://www.uncleli.cn/?p=542</guid>
		<description><![CDATA[在flash标签中

&#8220;Window&#8221; 在 Web 页上用影片自己的矩形窗口来播放应用程序，并且始终位于最顶层。
&#8220;Opaque&#8221; 显示页面上位于它后面的内容。
&#8220;Transparent&#8221;使 HTML 页的背景可以透过应用程序的所有透明部分显示出来，并且可能会降低动画性能。
注：&#8221;Opaque&#8221;和&#8221;Transparent&#8221;都可与 HTML 层交互，从而允许 SWF 文件上方的层遮蔽应用程序。这两种选项之间的差异在于&#8221;Transparent&#8221;允许透明，因此，如果 SWF 文件的某一部分是透明的，则 SWF 文件下方的 HTML 层可以透过该部分显示出来，而&#8221;opaque&#8221;则不会显示。
也就是如果发生FLASH遮盖DIV层的情况，就必须要改wmode属性为“Transparent”
在做web开发中可能会遇到flash遮挡页面中元素的情况，无论怎么设置flash容器和层的深度(z-index)也无济于事，现有的解决方案是在插入flash的embed或object标签中加入”wmode”属性并设置为wmode=“transparent”或”opaque”，但wmode属性到底是什么意义，为什么可以解决这个问题呢？
window mode(wmode)
wmode即窗口模式总共有三种，看看当年Macromedia官方的说法：
Window: Use the Window value to play a Flash Player movie in its own rectangular window on a web page. This is the default value for wmode and it works the way the classic Flash Player works. This [...]]]></description>
			<content:encoded><![CDATA[<p>在flash标签中</p>
<param name=”wmode" value="xxxx">
<p>&#8220;Window&#8221; 在 Web 页上用影片自己的矩形窗口来播放应用程序，并且始终位于最顶层。</p>
<p>&#8220;Opaque&#8221; 显示页面上位于它后面的内容。</p>
<p>&#8220;Transparent&#8221;使 HTML 页的背景可以透过应用程序的所有透明部分显示出来，并且可能会降低动画性能。</p>
<p>注：&#8221;Opaque&#8221;和&#8221;Transparent&#8221;都可与 HTML 层交互，从而允许 SWF 文件上方的层遮蔽应用程序。这两种选项之间的差异在于&#8221;Transparent&#8221;允许透明，因此，如果 SWF 文件的某一部分是透明的，则 SWF 文件下方的 HTML 层可以透过该部分显示出来，而&#8221;opaque&#8221;则不会显示。</p>
<p>也就是如果发生FLASH遮盖DIV层的情况，就必须要改wmode属性为“Transparent”</p>
<p>在做web开发中可能会遇到flash遮挡页面中元素的情况，无论怎么设置flash容器和层的深度(z-index)也无济于事，现有的解决方案是在插入flash的embed或object标签中加入”wmode”属性并设置为wmode=“transparent”或”opaque”，但wmode属性到底是什么意义，为什么可以解决这个问题呢？</p>
<p>window mode(wmode)</p>
<p>wmode即窗口模式总共有三种，看看当年Macromedia官方的说法：</p>
<p>Window: Use the Window value to play a Flash Player movie in its own rectangular window on a web page. This is the default value for wmode and it works the way the classic Flash Player works. This normally provides the fastest animation performance.<br />
Opaque: By using the Opaque value you can use JavaScript to move or resize movies that don’t need a transparent background. Opaque mode makes the movie hide everything behind it on the page. Additionally, opaque mode moves elements behind Flash movies (for example, with dynamic HTML) to prevent them from showing through.<br />
Transparent: Transparent mode allows the background of the HTML page, or the DHTML layer underneath the Flash movie or layer, to show through all the transparent portions of the movie. This allows you to overlap the movie with other elements of the HTML page. Animation performance might be slower when you use this value.<br />
window 模式</p>
<p>默认情况下的显示模式，在这种模式下flash player有自己的窗口句柄，这就意味着flash影片是存在于Windows中的一个显示实例，并且是在浏览器核心显示窗口之上的，所以flash只是貌似显示在浏览器中，但这也是flash最快最有效率的渲染模式。由于他是独立于浏览器的HTML渲染表面，这就导致默认显示方式下flash总是会遮住位置与他重合的所有DHTML层。</p>
<p>但是大多数苹果电脑浏览器会允许DHTML层显示在flash之上，但当flash影片播放时会出现比较诡异的现象，比如DHTML层像被flash刮掉一块一样显示异常。</p>
<p>Opaque 模式</p>
<p>这是一种无窗口模式，在这种情况下flash player没有自己的窗口句柄，这就需要浏览器需要告诉flash player在浏览器的渲染表面绘制的时间和位置。这时flash影片就不会在高于浏览器HTML渲染表面而是与其他元素一样在同一个页面上,因此你就可以使用z-index值来控制DHTML元素是遮盖flash或者被遮盖。</p>
<p>Transparent 模式</p>
<p>透明模式，在这种模式下flash player会将stage的背景色alpha值将为0并且只会绘制stage上真实可见的对象，同样你也可以使用z-index来控制flash影片的深度值，但是与Opaque模式不同的是这样做会降低flash影片的回放效果，而且在9.0.115之前的flash player版本设置wmode=”opaque”或”transparent”会导致全屏模式失效。</p>
<p>了解了各种模式的实现方式和意义在以后的开发中就可以按照具体情况选择设置wmode属性的值了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.uncleli.cn/archives/542.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ubuntu开启root用户及其它登录问题的解决</title>
		<link>http://www.uncleli.cn/archives/538.html</link>
		<comments>http://www.uncleli.cn/archives/538.html#comments</comments>
		<pubDate>Tue, 01 Jun 2010 03:48:26 +0000</pubDate>
		<dc:creator>Uncle Li (黎 叔)</dc:creator>
				<category><![CDATA[程序人生]]></category>
		<category><![CDATA[root]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.uncleli.cn/?p=538</guid>
		<description><![CDATA[Ubuntu安装后，root用户默认是被锁定了的，不允许登录，也不允许“su”到 root。有人说这是个不好的实践，特别是对于服务器来说。我觉得对于桌面用户来说，这样安全性更高一些，是应该的；但对于服务器可以设置成“允许 su 到root，但不允许root用户直接登录”。
而我为了开发时的方便，则在桌面和服务器上都采用这种方式。
　　允许 su 到 root
　　非常简单，下面是设置的方法：
　　me@tipfoo:~$ sudo passwd
　　Password: ]]></description>
			<content:encoded><![CDATA[<p>Ubuntu安装后，root用户默认是被锁定了的，不允许登录，也不允许“su”到 root。有人说这是个不好的实践，特别是对于服务器来说。我觉得对于桌面用户来说，这样安全性更高一些，是应该的；但对于服务器可以设置成“允许 su 到root，但不允许root用户直接登录”。</p>
<p>而我为了开发时的方便，则在桌面和服务器上都采用这种方式。</p>
<p>　　允许 su 到 root</p>
<p>　　非常简单，下面是设置的方法：</p>
<p>　　me@tipfoo:~$ sudo passwd</p>
<p>　　Password: <—— 输入安装时那个用户的密码</p>
<p>　　Enter new UNIX password: <—— 新的Root用户密码</p>
<p>　　Retype new UNIX password: <—— 重复新的Root用户密码</p>
<p>　　passwd：已成功更新密码</p>
<p>　　允许root登录</p>
<p>　　如果要允许root登录（不推荐），则这样操作：</p>
<p>　　me@tipfoo:~$ gksu /usr/sbin/gdmsetup</p>
<p>　　（或者使用桌面菜单：系统＞系统管理＞登录窗口）</p>
<p>　　点“安全”选项页，选择“允许本地管理员登录”。</p>
<p>　　注：这一步依赖上一步</p>
<p>　　不输入密码直接登录</p>
<p>　　在论坛上也看见有人抱怨，家中的Ubuntu不能像Window$那样──不用输入密码就能登录。其实同样能做到：</p>
<p>　　就在上一步的“安全”选项页中，勾选：</p>
<p>　　“启用自动登录”，“用户”选择（如：“me”）;</p>
<p>　　注意：公共用的计算机千万不能这么设置！</p>
<p>　　SSH登录远程服务器</p>
<p>　　如果远程服务器只允许root用户SSH到服务器时，在Ubuntu下，必须“su 到root”用户才能登录成功(具体是看服务器端的配置)。</p>
<p>　　首先，复制密钥到“/root/.ssh/”目录，</p>
<p>　　me@tipfoo:~$ su</p>
<p>　　Password:</p>
<p>　　root@tipfoo:/home/me# chmod 600 -R /root/.ssh/</p>
<p>　　root@tipfoo:/home/me# ssh -p 27482 11.22.33.44</p>
<p>　　Enter passphrase for key &#8216;/root/.ssh/id_rsa&#8217;:</p>
<p>　　Last login: Thu Jun 21 14:29:00 2007 from 11.22.33.45</p>
]]></content:encoded>
			<wfw:commentRss>http://www.uncleli.cn/archives/538.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>mysql alter 语句用法,添加、修改、删除字段等</title>
		<link>http://www.uncleli.cn/archives/535.html</link>
		<comments>http://www.uncleli.cn/archives/535.html#comments</comments>
		<pubDate>Sat, 29 May 2010 10:02:08 +0000</pubDate>
		<dc:creator>Uncle Li (黎 叔)</dc:creator>
				<category><![CDATA[数据库相关]]></category>

		<guid isPermaLink="false">http://www.uncleli.cn/?p=535</guid>
		<description><![CDATA[//主键
   alter table tabelname add new_field_id int(5) unsigned default 0 not null auto_increment ,add primary key (new_field_id);
//增加一个新列
   alter table t2 add d timestamp;
alter table infos add ex tinyint not null default &#8216;0&#8242;;
//删除列
   alter table t2 drop column c;
//重命名列
   alter table t1 change a b integer;
//改变列的类型
   [...]]]></description>
			<content:encoded><![CDATA[<p>//主键</p>
<p>   alter table tabelname add new_field_id int(5) unsigned default 0 not null auto_increment ,add primary key (new_field_id);<br />
//增加一个新列</p>
<p>   alter table t2 add d timestamp;<br />
alter table infos add ex tinyint not null default &#8216;0&#8242;;<br />
//删除列</p>
<p>   alter table t2 drop column c;<br />
//重命名列</p>
<p>   alter table t1 change a b integer;</p>
<p>//改变列的类型</p>
<p>   alter table t1 change b b bigint not null;<br />
alter table infos change list list tinyint not null default &#8216;0&#8242;;</p>
<p>//重命名表</p>
<p>   alter table t1 rename t2;<br />
加索引</p>
<p>   mysql> alter table tablename change depno depno int(5) not null;<br />
mysql> alter table tablename add index 索引名 (字段名1[，字段名2 …]);<br />
mysql> alter table tablename add index emp_name (name);<br />
加主关键字的索引</p>
<p>mysql> alter table tablename add primary key(id);<br />
加唯一限制条件的索引</p>
<p>  mysql> alter table tablename add unique emp_name2(cardnumber);<br />
删除某个索引</p>
<p>   mysql>alter table tablename drop index emp_name;<br />
修改表：</p>
<p>增加字段：</p>
<p>   mysql> ALTER TABLE table_name ADD field_name field_type;<br />
修改原字段名称及类型：</p>
<p>   mysql> ALTER TABLE table_name CHANGE old_field_name new_field_name field_type;<br />
删除字段：</p>
<p>   mysql> ALTER TABLE table_name DROP field_name; </p>
]]></content:encoded>
			<wfw:commentRss>http://www.uncleli.cn/archives/535.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
