<?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"
	>

<channel>
	<title>北风技术专栏 &#187; 风风</title>
	<atom:link href="http://column.ibeifeng.com/wp-feed.php?author_name=allg0&#038;feed=feed" rel="self" type="application/rss+xml" />
	<link>http://column.ibeifeng.com</link>
	<description>用技术点亮生活中每个亮点</description>
	<pubDate>Sun, 25 Jul 2010 12:28:34 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.2</generator>
	<language>en</language>
			<item>
		<title>说说程序员与博客</title>
		<link>http://column.ibeifeng.com/allg0/20100725411.shtml</link>
		<comments>http://column.ibeifeng.com/allg0/20100725411.shtml#comments</comments>
		<pubDate>Sun, 25 Jul 2010 12:28:34 +0000</pubDate>
		<dc:creator>风风</dc:creator>
		
		<category><![CDATA[其他]]></category>

		<guid isPermaLink="false">http://column.ibeifeng.com/?p=411</guid>
		<description><![CDATA[开篇之前，先奉上几句好话，一来表扬下我的博客网站，二来感谢下在博客里认识的朋友。感谢那些网站提供这么好的一个地方让我尽情释放自己的涂鸦，感激阅读我文章的同僚们，有你们的支持，我的文章得到了很好的分享。哈哈。。。
　　为什么我今天想到“程序员与博客”这个立题，主要还是源于前几天自己的某个博客被封杀，当时很是纳闷。java眼居然说我的文章玷污他们的神地，我很纠结，很郁闷，很崩溃。写了这么久的博客，居然落得这步田地。纵然是文章烂，你也别封杀我啊，搞得我像凤姐一样——臭名昭著、丢人现眼。
　　牢骚发完，进入主题。我今天想说的是程序员与博客的那点事情，不为别的，只希望如我一般的程序员们，应该多写些博客，多散发下自己的内心。别一天尽是class，package，function，produrce，那样的生活多少有些枯燥、无味，时间一长，人也会变得呆滞难看，细想起来总是有些不值。世界本就如此精彩，何故一味地钟情code。
　　我也是最近爱上写博客，以前基本上不写，这样的转变主要还是源于空聊无寂的生活。一个人，孤孤单单生活在深圳这个大都市里——迷茫，渺小，无助。寂寞之于，我开始写博客。慢慢的，我发现写博客是一件令我愉悦的事情，既打发了那些空荡的时间，又能在博客中广交朋友，每每看见自己的文章获得别人的点击，赞同，短评，总是蹈足欢腾。写博客能到这样的程度，多少算是有点痴。
　　我从不敢妄想自己的文章是佳作，可终究都是自己的言语。拿出来不怕丑，秀一下不怕臊，显一下不怕鄙。
　　写了这段时间的博客，我今天只想把自己写博客的丁点想法奉献给大伙。奔着三个问题求证而来，好与不好，不吝赐教。
　　第一问，程序员为什么写博客
　　程序员为什么写博客?不为别的，只为感触生活、分享心得、丰富人生。
　　何为感触生活，说白点就是知道自己活在世上，我有很多同事，他们总是习惯于冥坐在电脑前，除了敲就是打，整天一门心思只有对技术的迷恋。有时真不知道他们这样子图个啥。古人云：以有限的生命，去追逐无限的知识，岂不可怜。这里告诉你，作为程序员的你我，别一味地除了代码还是代码，技术永无止境，生命稍纵即逝。何况写代码也并非易事，光勤不行，得有悟道。代码写乏了，提起笔，写篇博客发散下自己的感悟，畅快之于，可能你又可以领悟到另一种新知也未必，何乐不为之？
　　在程序的世界里摸爬滚打这些年，我们总会钟情于某个方面，沉迷于上，研究入深，久而久之，多少能知道些别人不解的东西。倘若如此，你千万别把它们看似宝贝的压箱底，其实知识也如人一样般，终有无用的一天，这样的宝贝收藏无益，何不拿出来和大伙分享。没准能得到高人指点，使其更上一层楼；又或者觅的知音，一同说道说道，也不枉今朝一时。
　　在前面的一篇文章中，我说程序员多少有些自闭，有人不同意。可就我看来，身边的很多同事每逢休息，总是一个人呆在家里，上网，聊天，游戏，就是这样的生活——单调，乏味，枯燥，腻！以其这样荒诞地打算青春，何不提起笔，刷刷两下，发泄出内心的牢骚，写写自己的工作，感悟下奋斗的人生。待到人老珠黄的那天，不时间拿出来看看瞧瞧，也会感慨一番——年少轻狂，此生无悔。
　　第二问，程序员该怎么写博客
　　“该怎么写？”，“想怎么写就怎么写”，这就是答案。博客本就是消遣娱乐之举，无须太多修饰，唯有朴实，纯真，有血有肉，足也。
　　好几次，博客里的朋友总是问我，为什么不喜欢写技术类的文章，我总是轻笑着答到，“不会写，写不好”。有时想想，在软件堆里混了这些年，皮了，累了，油了。技术对我来说已经变得无趣，无聊。所以我现在几乎不写技术类的文章，偶尔兴趣所致，也就是拿自己的框架，叨咕上两句，草草了事。也许你会笑我轻狂，无知，我不回避，因为我本就不是那类技术痴人，何故自欺欺人，捉弄自己。
　　想怎么写就怎么写，不要在乎别人如何看，如何品，哪怕就是一句简单的 System.out.println(“hello world”)，那也是自己的感，自己的误——真实，可信。
　　第三问，程序员博客写什么
　　喜欢写博，自然经常在各博客里面打转，就软件类专业博客，我喜欢去的无非就是csdn，java眼，以及现在喜欢的博客园，blogjava。不过这次java眼是让我很郁闷，所以我开始唾弃它，也就懒得去了。
　　相比之下，就博客内容而言，我觉得博客园相对好点，确切的说是专业些，不过我还是想提点意见，有时太过专业也未必是件好事。毕竟程序员是人，总是有七情六欲的，不能一味地要求大伙写的东西都往软件上靠，这样多少有点狭隘。在我看来，不管你是技术研讨，软件工程，项目管理，开源框架，文学小说，诗歌散文，都应该有权利，有机会发表。丰富方显多姿，聚类总能完美。
　　在博客园里，发表纵然是没问题，可推荐到首页就有点麻烦。前几天我的小说，就是被这样无情地抹杀了，虽不是什么好文，起码短短10分中就得到了500多的点击，况且严格来说它属于程序人生的范畴，发表到这里，总能有些共鸣。可无情的管理员还是把它从首页踢出了，有点伤心。鉴于我对博客园的一点好感，也默许了这样的结局。不过我最终还是希望管理员们思想开阔些，因为我们的程序员都是有血，有肉，有情，有感的正常人，自然时常也是会说，会笑，会哭，会跳。
　　“一篇好的文章应该如一坛佳酿，未偿已久醉于心；或如一壶好茶，品尝之间回味无穷；或如与心爱的人共进晚餐，仅餐秀色足以饱食。我不妄想自己的文章能惊世骇俗，但始终期待有‘和旋之音，击缶之伴’”，这是我的杜撰，很希望有同感的程序员们如此对待写博。平平淡淡，真真切切，写出真我。
]]></description>
			<content:encoded><![CDATA[<p>开篇之前，先奉上几句好话，一来表扬下我的博客网站，二来感谢下在博客里认识的朋友。感谢那些网站提供这么好的一个地方让我尽情释放自己的涂鸦，感激阅读我文章的同僚们，有你们的支持，我的文章得到了很好的分享。哈哈。。。</p>
<p>　　为什么我今天想到“程序员与博客”这个立题，主要还是源于前几天自己的某个博客被封杀，当时很是纳闷。java眼居然说我的文章玷污他们的神地，我很纠结，很郁闷，很崩溃。写了这么久的博客，居然落得这步田地。纵然是文章烂，你也别封杀我啊，搞得我像凤姐一样——臭名昭著、丢人现眼。<span id="more-411"></span></p>
<p>　　牢骚发完，进入主题。我今天想说的是程序员与博客的那点事情，不为别的，只希望如我一般的程序员们，应该多写些博客，多散发下自己的内心。别一天尽是class，package，function，produrce，那样的生活多少有些枯燥、无味，时间一长，人也会变得呆滞难看，细想起来总是有些不值。世界本就如此精彩，何故一味地钟情code。</p>
<p>　　我也是最近爱上写博客，以前基本上不写，这样的转变主要还是源于空聊无寂的生活。一个人，孤孤单单生活在深圳这个大都市里——迷茫，渺小，无助。寂寞之于，我开始写博客。慢慢的，我发现写博客是一件令我愉悦的事情，既打发了那些空荡的时间，又能在博客中广交朋友，每每看见自己的文章获得别人的点击，赞同，短评，总是蹈足欢腾。写博客能到这样的程度，多少算是有点痴。</p>
<p>　　我从不敢妄想自己的文章是佳作，可终究都是自己的言语。拿出来不怕丑，秀一下不怕臊，显一下不怕鄙。</p>
<p>　　写了这段时间的博客，我今天只想把自己写博客的丁点想法奉献给大伙。奔着三个问题求证而来，好与不好，不吝赐教。</p>
<p>　　第一问，程序员为什么写博客</p>
<p>　　程序员为什么写博客?不为别的，只为感触生活、分享心得、丰富人生。</p>
<p>　　何为感触生活，说白点就是知道自己活在世上，我有很多同事，他们总是习惯于冥坐在电脑前，除了敲就是打，整天一门心思只有对技术的迷恋。有时真不知道他们这样子图个啥。古人云：以有限的生命，去追逐无限的知识，岂不可怜。这里告诉你，作为程序员的你我，别一味地除了代码还是代码，技术永无止境，生命稍纵即逝。何况写代码也并非易事，光勤不行，得有悟道。代码写乏了，提起笔，写篇博客发散下自己的感悟，畅快之于，可能你又可以领悟到另一种新知也未必，何乐不为之？</p>
<p>　　在程序的世界里摸爬滚打这些年，我们总会钟情于某个方面，沉迷于上，研究入深，久而久之，多少能知道些别人不解的东西。倘若如此，你千万别把它们看似宝贝的压箱底，其实知识也如人一样般，终有无用的一天，这样的宝贝收藏无益，何不拿出来和大伙分享。没准能得到高人指点，使其更上一层楼；又或者觅的知音，一同说道说道，也不枉今朝一时。</p>
<p>　　在前面的一篇文章中，我说程序员多少有些自闭，有人不同意。可就我看来，身边的很多同事每逢休息，总是一个人呆在家里，上网，聊天，游戏，就是这样的生活——单调，乏味，枯燥，腻！以其这样荒诞地打算青春，何不提起笔，刷刷两下，发泄出内心的牢骚，写写自己的工作，感悟下奋斗的人生。待到人老珠黄的那天，不时间拿出来看看瞧瞧，也会感慨一番——年少轻狂，此生无悔。<br />
　　第二问，程序员该怎么写博客</p>
<p>　　“该怎么写？”，“想怎么写就怎么写”，这就是答案。博客本就是消遣娱乐之举，无须太多修饰，唯有朴实，纯真，有血有肉，足也。</p>
<p>　　好几次，博客里的朋友总是问我，为什么不喜欢写技术类的文章，我总是轻笑着答到，“不会写，写不好”。有时想想，在软件堆里混了这些年，皮了，累了，油了。技术对我来说已经变得无趣，无聊。所以我现在几乎不写技术类的文章，偶尔兴趣所致，也就是拿自己的框架，叨咕上两句，草草了事。也许你会笑我轻狂，无知，我不回避，因为我本就不是那类技术痴人，何故自欺欺人，捉弄自己。</p>
<p>　　想怎么写就怎么写，不要在乎别人如何看，如何品，哪怕就是一句简单的 System.out.println(“hello world”)，那也是自己的感，自己的误——真实，可信。<br />
　　第三问，程序员博客写什么<br />
　　喜欢写博，自然经常在各博客里面打转，就软件类专业博客，我喜欢去的无非就是csdn，java眼，以及现在喜欢的博客园，blogjava。不过这次java眼是让我很郁闷，所以我开始唾弃它，也就懒得去了。<br />
　　相比之下，就博客内容而言，我觉得博客园相对好点，确切的说是专业些，不过我还是想提点意见，有时太过专业也未必是件好事。毕竟程序员是人，总是有七情六欲的，不能一味地要求大伙写的东西都往软件上靠，这样多少有点狭隘。在我看来，不管你是技术研讨，软件工程，项目管理，开源框架，文学小说，诗歌散文，都应该有权利，有机会发表。丰富方显多姿，聚类总能完美。</p>
<p>　　在博客园里，发表纵然是没问题，可推荐到首页就有点麻烦。前几天我的小说，就是被这样无情地抹杀了，虽不是什么好文，起码短短10分中就得到了500多的点击，况且严格来说它属于程序人生的范畴，发表到这里，总能有些共鸣。可无情的管理员还是把它从首页踢出了，有点伤心。鉴于我对博客园的一点好感，也默许了这样的结局。不过我最终还是希望管理员们思想开阔些，因为我们的程序员都是有血，有肉，有情，有感的正常人，自然时常也是会说，会笑，会哭，会跳。</p>
<p>　　“一篇好的文章应该如一坛佳酿，未偿已久醉于心；或如一壶好茶，品尝之间回味无穷；或如与心爱的人共进晚餐，仅餐秀色足以饱食。我不妄想自己的文章能惊世骇俗，但始终期待有‘和旋之音，击缶之伴’”，这是我的杜撰，很希望有同感的程序员们如此对待写博。平平淡淡，真真切切，写出真我。</p>
]]></content:encoded>
			<wfw:commentRss>http://column.ibeifeng.com/allg0/20100725411.shtml/feed</wfw:commentRss>
		</item>
		<item>
		<title>基于MVC团队组合模式的系统开发</title>
		<link>http://column.ibeifeng.com/allg0/20100725409.shtml</link>
		<comments>http://column.ibeifeng.com/allg0/20100725409.shtml#comments</comments>
		<pubDate>Sun, 25 Jul 2010 12:25:12 +0000</pubDate>
		<dc:creator>风风</dc:creator>
		
		<category><![CDATA[其他]]></category>

		<guid isPermaLink="false">http://column.ibeifeng.com/?p=409</guid>
		<description><![CDATA[ MVC团队组合模式，主要源于J2EE中常说的MVC演变而来。确切地说这个东西是我自己杜撰出来的，但又经历过一些项目实践，今天拿出来在与大伙这里说说，一来弥补一下自己长期不写技术类文章的缺陷，不然很多人又说我作为一个软件人，在博客中连起码的技术东西都没有，很是惭愧。二来也想把自己经历过的丁点经验告诉大伙，至于是对是错，有用与否，那只有天晓得了，哈哈。。。。

　　 说到MVC团队组合模式，那就要说说我的框架WMframework，
　　 WMframework现阶段采用主要技术有：s2,ibtatis2,spring3，HTML，js， xml，ajax，整个技术框架也是自己杜撰出来的，一直自己在默默地喜欢着，改进着，这些年的程序员生涯也就剩余这点东西可以怀念下了。我向来不是吝啬的人，所以在后面的时间里我会逐步把自己的WMframework拿出来与大伙分享，希望有心的你可以期待，当然更梦想得到大伙的真知灼见。今天我主要说的东西还是我的团队中如何使用MVC团队组合模式进行软件开发。
　　 MVC团队组合模式？
　　何谓“MVC团队组合模式”，主要意思就是把一个团队里面的各成员按其个人综合技能进行分工协作，具体地说就是针对每个业务模块的开发，采用各成员进行分工协作完成的模式。一个模块，张三完成一部分，李四完成另一部分，王五又完成其他部分。这有别于大伙常见的由一个人承担某个模块的开发合作模式。
　　 先来说说我们常见的开发模式。大伙都知道，我们通常的软件系统开发中，很多时候都是这样的，先由项目经理或小组长做统一的任务分配，把具体的各功能点模块按人头分配给团队中的各程序员们。比如用户注册张三负责；组织机构管理李四负责；哪天哪天这个模块由谁完成，哪天哪天这部分由谁实现。整个编码计划就是这样指定下来，直到系统的所有功能模块都被分摊到相应的开发人员身上。等待我们的程序员把各模块都编码完成，大伙再把这些代码、功能进行系统的整合、集成、测试等，这就是大家常见的甘特图模式，也是我们通常碰见的开发模式。
　　 我提出的MVC团队组合模式，区别于上面最大的不同就是，我把任何一个业务模块开发任务分为3部分，由三类不同角色的人员来共同完成，这三类人员我称它们为MVC，即M_actor 模型执行者、V_actor 视图执行者、C_actor 控制器执行者。
　　 下面我给出这三者的主要描述：
　　 M: M_actor 模型执行者
　　 主要任务：后台业务处理模型，主要就是Dao，sqlmap的编写；（在WMframework中，我已经弱化了dao这层，因为在WMframework中我们的dao都是公共的，开发人员基本上不用写dao。）
　　 个人要求：要求开发人员对数据库操作能力强，对整体业务流程充分了解，保证其sqlmap编写的sql完成当前模块的业务需求。
　　这部分可以由擅长数据库开发人员和需求分析人员结合完成。
　　V：V_actor 视图执行者
　　主要任务：前台表单视图，主要就是jsp，html，js的编写；完成页面数据表单的设计、实现、业务数据的js校验、提交等。（在WMframework中，我对于页面表单数据提交、校验也是一个公用的自定义js前台框架，开发人员只需要写简短的几句js脚本调用即可。）
　　 个人要求：开发人员需要有很好的UI设计能力，可以更为人性化地实现页面操作，使其有更好的用户体验，知道些js语法和html标签使用即可。
　　 这部分由美工、UI技术人员和需求分析人员结合完成。
 
　　 C：C_actor 控制器执行者
　　主要任务：s1/s2中的action，业务层接口service的编写；
　　个人要求：开发人员熟悉常用的java开发模式，有很好的java开发能力，能很好地处理request请求，respronse返回响应等。（在WMframework中，我同样弱化了action的使用，很多时候对于多数页面请求只需要调用公用的action即可，开发人员基本上不用自己写）。
  　 这部分资深java开发人员完成。
 
　　 MVC团队组合模式优势
　　 通过我的介绍看出些好处没有？很明显，若采用MVC的开发模式来在组织团队人员，对不同类型的人员要求就不尽相同。
　　 C_actor 可以完成不用了解系统业务，他们只需要关心如何解析前台提交的请求数据，就WMframework而言就是完成从request里面读取xml转化为bean(这里说的bean也就是我们常说的pojo、vo、bo等)的实现；然后通过外部接口service转交给内部实现dao，最后在dao中完成持久层的相关操作；
　　 V_actor 可以完全不用了解什么叫j2EE，只需知道jsp的表头怎么写（其实很多时候不用写，因为我们都是include进来的嘛），合理地设计页面表单的布局，知道哪里该放button，哪里该用text，哪里摆个textarea，哪里该弄个select等，仅此而已；
　　 M_actor不需要关心用户界面如何设计，该怎么制作，用户数据以什么方式提交。他只需要清楚当前业务涉及那些数据模型，各数据表中相应的字段是否填上，哪些是必填项，数据类型是什么，数据大小如何定义，数据存储是否正确等。
　　 如果联系到公司人员配置问题，这里也有一点优势在里面。因为很多时候，很多公司，总会在项目来临一味扩招，项目结束一味削减，而最终能保留下来的也就是那么几个核心人物，当然我这里不是提倡这样的作法，毕竟多少有些凶残。如果你的公司，你的项目采用了我说的MVC团队组合模式开发，那很多时候，你的核心开发人员、业务人员依旧全力地支撑着整个项目，他们掌握着整个项目的核心，所以很多时候，你可以重点培养M_actor与C_actor，对于V_actor自然多少有些微不足道，弃之无妨。不过做人起码需要些厚道，尽管商场残酷，商人无情，终究我们都是人，应该多一点感情，多一点良知。实在不想要他们了，能最大限度给点补偿也不枉人家为你卖命一场。
　　 以上这些就是我能看到的基于MVC团队组合模式开发的优势，使用它可以让我们的开发人员减少许多需要关注和学习的东西，有时候闷头想来做一个合格的java web开发者，你最基本的可能需要知道这些：java、jsp、js、xml、css、sql、ide、html等，太杂，太多，太烦。但如果你使用如上所说的开发模式，让开发者专注于各自所特长的一方面，并进行很好地发挥，最后更好地完成自己的任务，做好自己喜欢的工作，那种感觉应该会好很多。起码是辛苦并快乐着，哈哈。。
　　 MVC团队组合模式劣势
　　 前面竟说了些好听的，下面我来说说MVC团队组合模式的弊端，最明显的一点就是，各类型成员间开发任务的同步性、顺序性、可用性测试、问题跟踪等。比如一个用户基本信息维护模块，如果某天客户需要增加一个用户生日的信息，必然会涉及 C_actor进行业务数据对象修改,M_actor修改sqlmap中的insert,select,update等语句，V_actor 修改表单jsp增加生日的输入框等。又或者用户基本信息业务模块出现异常（数据不正确，不能保存等）也必然需要C_actor、M_actor、V_actor来配合完成跟踪，这自然也就增加了当前任务消耗的资源。再或者用户基本信息业务模块不能在规定的项目计划时间完成，其最终的责任应该算在谁的头上。C_actor说用户表单没有设计，如何完成action的编写，V_actor抱怨数据模型没有给出如何知道页面元素类型，哪些应该必填，哪些应该选填，哪些应该下拉，哪些应该只读，我都不知道，叫我如何设计页面；M_actor呢，咆哮V_actor页面表单都没有，叫我如何知道业务模型需要那些字段，需要什么样的数据类型，需要多大长度。最终是个个推诿，人人有理，整天就是这样缠绕在彼此间借口的闭环中，周而复始、无穷无尽。哎，程序员，难啊。。。。。
　　 凡事皆有两面性，对于MVC团队组合模式我基本上说的差不多了。我曾经在一些项目中使用过它，有说好的当然也有暴跳骂娘的，终究是孰是孰非，谁对谁错，我也不得知晓，只待各位自己去想，去悟。
]]></description>
			<content:encoded><![CDATA[<p> MVC团队组合模式，主要源于J2EE中常说的MVC演变而来。确切地说这个东西是我自己杜撰出来的，但又经历过一些项目实践，今天拿出来在与大伙这里说说，一来弥补一下自己长期不写技术类文章的缺陷，不然很多人又说我作为一个软件人，在博客中连起码的技术东西都没有，很是惭愧。二来也想把自己经历过的丁点经验告诉大伙，至于是对是错，有用与否，那只有天晓得了，哈哈。。。。</p>
<p><span id="more-409"></span></p>
<p>　　 说到MVC团队组合模式，那就要说说我的框架WMframework，</p>
<p>　　 WMframework现阶段采用主要技术有：s2,ibtatis2,spring3，HTML，js， xml，ajax，整个技术框架也是自己杜撰出来的，一直自己在默默地喜欢着，改进着，这些年的程序员生涯也就剩余这点东西可以怀念下了。我向来不是吝啬的人，所以在后面的时间里我会逐步把自己的WMframework拿出来与大伙分享，希望有心的你可以期待，当然更梦想得到大伙的真知灼见。今天我主要说的东西还是我的团队中如何使用MVC团队组合模式进行软件开发。<br />
　　 MVC团队组合模式？<br />
　　何谓“MVC团队组合模式”，主要意思就是把一个团队里面的各成员按其个人综合技能进行分工协作，具体地说就是针对每个业务模块的开发，采用各成员进行分工协作完成的模式。一个模块，张三完成一部分，李四完成另一部分，王五又完成其他部分。这有别于大伙常见的由一个人承担某个模块的开发合作模式。</p>
<p>　　 先来说说我们常见的开发模式。大伙都知道，我们通常的软件系统开发中，很多时候都是这样的，先由项目经理或小组长做统一的任务分配，把具体的各功能点模块按人头分配给团队中的各程序员们。比如用户注册张三负责；组织机构管理李四负责；哪天哪天这个模块由谁完成，哪天哪天这部分由谁实现。整个编码计划就是这样指定下来，直到系统的所有功能模块都被分摊到相应的开发人员身上。等待我们的程序员把各模块都编码完成，大伙再把这些代码、功能进行系统的整合、集成、测试等，这就是大家常见的甘特图模式，也是我们通常碰见的开发模式。<br />
　　 我提出的MVC团队组合模式，区别于上面最大的不同就是，我把任何一个业务模块开发任务分为3部分，由三类不同角色的人员来共同完成，这三类人员我称它们为MVC，即M_actor 模型执行者、V_actor 视图执行者、C_actor 控制器执行者。</p>
<p>　　 下面我给出这三者的主要描述：</p>
<p>　　 M: M_actor 模型执行者</p>
<p>　　 主要任务：后台业务处理模型，主要就是Dao，sqlmap的编写；（在WMframework中，我已经弱化了dao这层，因为在WMframework中我们的dao都是公共的，开发人员基本上不用写dao。）</p>
<p>　　 个人要求：要求开发人员对数据库操作能力强，对整体业务流程充分了解，保证其sqlmap编写的sql完成当前模块的业务需求。</p>
<p>　　这部分可以由擅长数据库开发人员和需求分析人员结合完成。<br />
　　V：V_actor 视图执行者</p>
<p>　　主要任务：前台表单视图，主要就是jsp，html，js的编写；完成页面数据表单的设计、实现、业务数据的js校验、提交等。（在WMframework中，我对于页面表单数据提交、校验也是一个公用的自定义js前台框架，开发人员只需要写简短的几句js脚本调用即可。）</p>
<p>　　 个人要求：开发人员需要有很好的UI设计能力，可以更为人性化地实现页面操作，使其有更好的用户体验，知道些js语法和html标签使用即可。</p>
<p>　　 这部分由美工、UI技术人员和需求分析人员结合完成。</p>
<p> </p>
<p>　　 C：C_actor 控制器执行者</p>
<p>　　主要任务：s1/s2中的action，业务层接口service的编写；</p>
<p>　　个人要求：开发人员熟悉常用的java开发模式，有很好的java开发能力，能很好地处理request请求，respronse返回响应等。（在WMframework中，我同样弱化了action的使用，很多时候对于多数页面请求只需要调用公用的action即可，开发人员基本上不用自己写）。</p>
<p>  　 这部分资深java开发人员完成。</p>
<p> </p>
<p>　　 MVC团队组合模式优势</p>
<p>　　 通过我的介绍看出些好处没有？很明显，若采用MVC的开发模式来在组织团队人员，对不同类型的人员要求就不尽相同。<br />
　　 C_actor 可以完成不用了解系统业务，他们只需要关心如何解析前台提交的请求数据，就WMframework而言就是完成从request里面读取xml转化为bean(这里说的bean也就是我们常说的pojo、vo、bo等)的实现；然后通过外部接口service转交给内部实现dao，最后在dao中完成持久层的相关操作；<br />
　　 V_actor 可以完全不用了解什么叫j2EE，只需知道jsp的表头怎么写（其实很多时候不用写，因为我们都是include进来的嘛），合理地设计页面表单的布局，知道哪里该放button，哪里该用text，哪里摆个textarea，哪里该弄个select等，仅此而已；<br />
　　 M_actor不需要关心用户界面如何设计，该怎么制作，用户数据以什么方式提交。他只需要清楚当前业务涉及那些数据模型，各数据表中相应的字段是否填上，哪些是必填项，数据类型是什么，数据大小如何定义，数据存储是否正确等。<br />
　　 如果联系到公司人员配置问题，这里也有一点优势在里面。因为很多时候，很多公司，总会在项目来临一味扩招，项目结束一味削减，而最终能保留下来的也就是那么几个核心人物，当然我这里不是提倡这样的作法，毕竟多少有些凶残。如果你的公司，你的项目采用了我说的MVC团队组合模式开发，那很多时候，你的核心开发人员、业务人员依旧全力地支撑着整个项目，他们掌握着整个项目的核心，所以很多时候，你可以重点培养M_actor与C_actor，对于V_actor自然多少有些微不足道，弃之无妨。不过做人起码需要些厚道，尽管商场残酷，商人无情，终究我们都是人，应该多一点感情，多一点良知。实在不想要他们了，能最大限度给点补偿也不枉人家为你卖命一场。<br />
　　 以上这些就是我能看到的基于MVC团队组合模式开发的优势，使用它可以让我们的开发人员减少许多需要关注和学习的东西，有时候闷头想来做一个合格的java web开发者，你最基本的可能需要知道这些：java、jsp、js、xml、css、sql、ide、html等，太杂，太多，太烦。但如果你使用如上所说的开发模式，让开发者专注于各自所特长的一方面，并进行很好地发挥，最后更好地完成自己的任务，做好自己喜欢的工作，那种感觉应该会好很多。起码是辛苦并快乐着，哈哈。。<br />
　　 MVC团队组合模式劣势<br />
　　 前面竟说了些好听的，下面我来说说MVC团队组合模式的弊端，最明显的一点就是，各类型成员间开发任务的同步性、顺序性、可用性测试、问题跟踪等。比如一个用户基本信息维护模块，如果某天客户需要增加一个用户生日的信息，必然会涉及 C_actor进行业务数据对象修改,M_actor修改sqlmap中的insert,select,update等语句，V_actor 修改表单jsp增加生日的输入框等。又或者用户基本信息业务模块出现异常（数据不正确，不能保存等）也必然需要C_actor、M_actor、V_actor来配合完成跟踪，这自然也就增加了当前任务消耗的资源。再或者用户基本信息业务模块不能在规定的项目计划时间完成，其最终的责任应该算在谁的头上。C_actor说用户表单没有设计，如何完成action的编写，V_actor抱怨数据模型没有给出如何知道页面元素类型，哪些应该必填，哪些应该选填，哪些应该下拉，哪些应该只读，我都不知道，叫我如何设计页面；M_actor呢，咆哮V_actor页面表单都没有，叫我如何知道业务模型需要那些字段，需要什么样的数据类型，需要多大长度。最终是个个推诿，人人有理，整天就是这样缠绕在彼此间借口的闭环中，周而复始、无穷无尽。哎，程序员，难啊。。。。。</p>
<p>　　 凡事皆有两面性，对于MVC团队组合模式我基本上说的差不多了。我曾经在一些项目中使用过它，有说好的当然也有暴跳骂娘的，终究是孰是孰非，谁对谁错，我也不得知晓，只待各位自己去想，去悟。</p>
]]></content:encoded>
			<wfw:commentRss>http://column.ibeifeng.com/allg0/20100725409.shtml/feed</wfw:commentRss>
		</item>
		<item>
		<title>轻量级工作流引擎jBPM 4.4正式发布</title>
		<link>http://column.ibeifeng.com/allg0/20100725407.shtml</link>
		<comments>http://column.ibeifeng.com/allg0/20100725407.shtml#comments</comments>
		<pubDate>Sun, 25 Jul 2010 12:23:34 +0000</pubDate>
		<dc:creator>风风</dc:creator>
		
		<category><![CDATA[其他]]></category>

		<guid isPermaLink="false">http://column.ibeifeng.com/?p=407</guid>
		<description><![CDATA[jBPM 4是jBPM的最新一代产品，它提供的PVM（流程虚拟机）可以支持多种流程语言，默认支持的是jBPM自己的jPDL流程语言，从jBPM-4.3开始，又提供了对BPMN-2.0的支持（不过还不完全）。jBPM的发布包中提供了一键式安装的ant脚本，可以将jBPM流程引擎以及配套的管理控制台，流程设计器一次性安装到本机上运行使用。

安装配置的详细步骤可以参考官方的用户手册：http://www.family168.com/tutorial/jbpm4.0/html/installation.html
最新发布的jBPM-4.4中解决了108个issue，不过它距离上次发布也半年有余了，jBPM-4.3发布于2009年12月底。
jBPM-4.4是一个bug fix版本，并未对数据库有任何修改，使用之前版本的项目基本可以平滑升级。在进行升级时需要注意：
1.Activity和Transition两个接口从org.jbpm.pvm.internal.model包下移动到了 org.jbpm.api.model包下。
2.所有与el表达式相关的部分都替换为新加的org.jbpm.pvm.internal.el.Expression。
添加的几个重要功能：
1.for each支持动态的并发分支流程，会签和并发子流程都可以用它来实现了。
2.assign活动，可以对变量的值进行复制。
3.变量声明，可以在xml里声明变量。
4.修正了console在tomcat下找不到dataSource的问题（包括报表）。
详细的发布信息，请参考官方的JIRA：https://jira.jboss.org/secure/ReleaseNote.jspa?projectId=10052&#38;version=12314183
用Alejandro的话说，This makes 4.4 the most cat-friendly jBPM yet!下个版本会对数据库结构进行修改了，以便完善流程历史库的功能。
相关的发布下载与文档资源如下：
Subversion tag: http://anonsvn.jboss.org/repos/jbpm/jbpm4/tags/jbpm-4.4/
Maven artifact: http://repository.jboss.org/nexus/content/repositories/releases/org/jbpm/jbpm4/jbpm/4.4/
SourceForge file: https://downloads.sourceforge.net/project/jbpm/jBPM%204/jbpm-4.4/jbpm-4.4.zip
User Guide: http://docs.jboss.com/jbpm/v4/userguide/html_single/
Developer Guide: http://docs.jboss.com/jbpm/v4/devguide/html_single/
Maven Artifact: http://repository.jboss.org/nexus/content/repositories/releases/org/jbpm/jbpm4/jbpm/4.4/
另附我们翻译的用户手册和开发指南：
用户手册：http://www.family168.com/tutorial/jbpm4.0/html/index.html
开发指南：http://www.family168.com/tutorial/jbpm4devguide/html/index.html
]]></description>
			<content:encoded><![CDATA[<p>jBPM 4是jBPM的最新一代产品，它提供的PVM（流程虚拟机）可以支持多种流程语言，默认支持的是jBPM自己的jPDL流程语言，从jBPM-4.3开始，又提供了对BPMN-2.0的支持（不过还不完全）。jBPM的发布包中提供了一键式安装的ant脚本，可以将jBPM流程引擎以及配套的管理控制台，流程设计器一次性安装到本机上运行使用。</p>
<p><span id="more-407"></span></p>
<p>安装配置的详细步骤可以参考官方的用户手册：<a href="http://www.family168.com/tutorial/jbpm4.0/html/installation.html">http://www.family168.com/tutorial/jbpm4.0/html/installation.html</a></p>
<p>最新发布的jBPM-4.4中解决了108个issue，不过它距离上次发布也半年有余了，jBPM-4.3发布于2009年12月底。</p>
<p>jBPM-4.4是一个bug fix版本，并未对数据库有任何修改，使用之前版本的项目基本可以平滑升级。在进行升级时需要注意：</p>
<p>1.Activity和Transition两个接口从org.jbpm.pvm.internal.model包下移动到了 org.jbpm.api.model包下。<br />
2.所有与el表达式相关的部分都替换为新加的org.jbpm.pvm.internal.el.Expression。</p>
<p>添加的几个重要功能：<br />
1.for each支持动态的并发分支流程，会签和并发子流程都可以用它来实现了。<br />
2.assign活动，可以对变量的值进行复制。<br />
3.变量声明，可以在xml里声明变量。<br />
4.修正了console在tomcat下找不到dataSource的问题（包括报表）。</p>
<p>详细的发布信息，请参考官方的JIRA：<a href="https://jira.jboss.org/secure/ReleaseNote.jspa?projectId=10052&amp;version=12314183">https://jira.jboss.org/secure/ReleaseNote.jspa?projectId=10052&amp;version=12314183</a></p>
<p>用Alejandro的话说，This makes 4.4 the most cat-friendly jBPM yet!下个版本会对数据库结构进行修改了，以便完善流程历史库的功能。</p>
<p>相关的发布下载与文档资源如下：<br />
Subversion tag: <a href="http://anonsvn.jboss.org/repos/jbpm/jbpm4/tags/jbpm-4.4/">http://anonsvn.jboss.org/repos/jbpm/jbpm4/tags/jbpm-4.4/</a><br />
Maven artifact: <a href="http://repository.jboss.org/nexus/content/repositories/releases/org/jbpm/jbpm4/jbpm/4.4/">http://repository.jboss.org/nexus/content/repositories/releases/org/jbpm/jbpm4/jbpm/4.4/</a><br />
SourceForge file: <a href="https://downloads.sourceforge.net/project/jbpm/jBPM%204/jbpm-4.4/jbpm-4.4.zip">https://downloads.sourceforge.net/project/jbpm/jBPM%204/jbpm-4.4/jbpm-4.4.zip</a></p>
<p>User Guide: <a href="http://docs.jboss.com/jbpm/v4/userguide/html_single/">http://docs.jboss.com/jbpm/v4/userguide/html_single/</a><br />
Developer Guide: <a href="http://docs.jboss.com/jbpm/v4/devguide/html_single/">http://docs.jboss.com/jbpm/v4/devguide/html_single/</a><br />
Maven Artifact: <a href="http://repository.jboss.org/nexus/content/repositories/releases/org/jbpm/jbpm4/jbpm/4.4/">http://repository.jboss.org/nexus/content/repositories/releases/org/jbpm/jbpm4/jbpm/4.4/</a></p>
<p>另附我们翻译的用户手册和开发指南：<br />
用户手册：<a href="http://www.family168.com/tutorial/jbpm4.0/html/index.html">http://www.family168.com/tutorial/jbpm4.0/html/index.html</a><br />
开发指南：<a href="http://www.family168.com/tutorial/jbpm4devguide/html/index.html">http://www.family168.com/tutorial/jbpm4devguide/html/index.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://column.ibeifeng.com/allg0/20100725407.shtml/feed</wfw:commentRss>
		</item>
		<item>
		<title>如何优化SQL Server数据库性能之SQL语句篇</title>
		<link>http://column.ibeifeng.com/allg0/20100725405.shtml</link>
		<comments>http://column.ibeifeng.com/allg0/20100725405.shtml#comments</comments>
		<pubDate>Sun, 25 Jul 2010 12:20:56 +0000</pubDate>
		<dc:creator>风风</dc:creator>
		
		<category><![CDATA[数据库]]></category>

		<guid isPermaLink="false">http://column.ibeifeng.com/?p=405</guid>
		<description><![CDATA[近期项目需要，做了一段时间的SQL Server性能优化，遇到了一些问题，也积累了一些经验，现总结一下，与君共享。SQL Server性能优化涉及到许多方面，如良好的系统和数据库设计，优质的SQL编写，合适的数据表索引设计，甚至各种硬件因素：网络性能、服务器的性能、操作系统的性能，甚至网卡、交换机等。这篇文章主要讲到如何改善SQL语句，还将有另一篇讨论如何改善索引。

如何改善SQL语句的一些原则：
1. 按需索取字段，跟“SELECT *”说拜拜
字段的提取一定要按照“用多少提多少”的原则，避免使用“SELECT *”这样的操作。做了这样一个实验，表tblA有1000万数据：
select top 10000 c1, c2, c3, c4 from tblA order by c1 desc  用时：4673毫秒
select top 10000 c1, c2, c3 from tblA order by c1 desc用时：1376毫秒
select top 10000 c1, c2 from tblA order by c1 desc 用时：80毫秒
由此看来，我们每少提取一个字段，数据的提取速度就会有相应的提升。但提升的速度还要看您舍弃的字段的大小来判断。
另外，关于“SELECT *“的问题，可以参考这篇文章：
http://www.cnblogs.com:80/goodspeed/archive/2007/07/20/index_coverage.html
2. 字段名和表名要写规范，注意大小写
这一点要多注意，如果大小写写错的话，虽然SQL仍然能正常执行，但数据库系统会花一定的开销和时间先要把您写的规范成正确的，然后再执行SQL。写对的话，这个时间就省了。
正常的：    select top 10 dteTransaction, txtSystem_id from tblTransactionSystem
不小心的：select top 10 dtetransaction, txtsystem_id from [...]]]></description>
			<content:encoded><![CDATA[<p>近期项目需要，做了一段时间的SQL Server性能优化，遇到了一些问题，也积累了一些经验，现总结一下，与君共享。SQL Server性能优化涉及到许多方面，如良好的系统和数据库设计，优质的SQL编写，合适的数据表索引设计，甚至各种硬件因素：网络性能、服务器的性能、操作系统的性能，甚至网卡、交换机等。这篇文章主要讲到如何改善SQL语句，还将有另一篇讨论如何改善索引。</p>
<p><span id="more-405"></span><br />
如何改善SQL语句的一些原则：<br />
1. 按需索取字段，跟“SELECT *”说拜拜<br />
字段的提取一定要按照“用多少提多少”的原则，避免使用“SELECT *”这样的操作。做了这样一个实验，表tblA有1000万数据：<br />
select top 10000 c1, c2, c3, c4 from tblA order by c1 desc  用时：4673毫秒<br />
select top 10000 c1, c2, c3 from tblA order by c1 desc用时：1376毫秒<br />
select top 10000 c1, c2 from tblA order by c1 desc 用时：80毫秒<br />
由此看来，我们每少提取一个字段，数据的提取速度就会有相应的提升。但提升的速度还要看您舍弃的字段的大小来判断。<br />
另外，关于“SELECT *“的问题，可以参考这篇文章：<br />
<a href="http://www.cnblogs.com:80/goodspeed/archive/2007/07/20/index_coverage.html">http://www.cnblogs.com:80/goodspeed/archive/2007/07/20/index_coverage.html</a><br />
2. 字段名和表名要写规范，注意大小写<br />
这一点要多注意，如果大小写写错的话，虽然SQL仍然能正常执行，但数据库系统会花一定的开销和时间先要把您写的规范成正确的，然后再执行SQL。写对的话，这个时间就省了。<br />
正常的：    select top 10 dteTransaction, txtSystem_id from tblTransactionSystem<br />
不小心的：select top 10 dtetransaction, txtsystem_id from tbltransactionsystem<br />
3. 适当使用过渡表<br />
把表的一个子集进行排序并创建临时表，有时能加速查询。它有助于避免多重排序操作，而且在其他方面还能简化优化器的工作。例如：<br />
 SELECT   cust.name，rcvbles.balance，……other   columns    <br />
  FROM   cust，rcvbles    <br />
  WHERE   cust.customer_id   =   rcvlbes.customer_id    <br />
  AND   rcvblls.balance&gt;0    <br />
  AND   cust.postcode&gt;“98000”    <br />
  ORDER   BY   cust.name<br />
  如果这个查询要被执行多次而不止一次，可以把所有未付款的客户找出来放在一个临时文件中，并按客户的名字进行排序：    <br />
  SELECT   cust.name，rcvbles.balance，……other   columns    <br />
  INTO   temp_cust_with_balance    <br />
  FROM   cust，rcvbles    <br />
  WHERE   cust.customer_id   =   rcvlbes.customer_id    <br />
  AND   rcvblls.balance&gt;0    <br />
  ORDER   BY   cust.name    <br />
  然后以下面的方式在临时表中查询：    <br />
  SELECT   ＊   FROM   temp_cust_with_balance    <br />
  WHERE   postcode&gt;“98000”    <br />
临时表中的行要比主表中的行少，而且物理顺序就是所要求的顺序，减少了磁盘I/O，所以查询工作量可以得到大幅减少。注意：过渡临时表创建后不会反映主表的修改。在主表中数据频繁修改的情况下，注意不要丢失数据。<br />
4. 别在where条件中做函数计算<br />
这样做的后果是将在每个行上进行运算，这将导致该列的索引失效而触发全表扫描。如下SQL：<br />
select * from users where YEAR(dteCreated) &lt; 2007<br />
可以改成select * from users where dteCreated &lt;‘2007-01-01’，这样会使用针对dteCreated的索引，提高查询效率。<br />
5. IN（NOT IN）操作符与EXISTS（NOT EXISTS）操作符<br />
有时候会将一列和一系列值相比较。最简单的办法就是在where子句中使用子查询。在where子句中可以使用两种方式的子查询。如下：<br />
第一种方式使用IN操作符：<br />
Select a.id from tblA a where a.id in (select b.id from tblB b)<br />
第二种方式使用EXIST操作符：<br />
Select a.id from tblA a where exists (select 1 from tblB b where b.id = a.id);<br />
用IN写出来的SQL的优点是比较容易写及清晰易懂，这比较适合现代软件开发的风格。但是用IN的SQL性能总是比较低的，而第二种格式要远比第一种格式的效率高。从SQL执行的步骤来分析用IN的SQL与不用IN的SQL有以下区别：<br />
SQL试图将其转换成多个表的连接，如果转换不成功则先执行IN里面的子查询，再查询外层的表记录，如果转换成功则直接采用多个表的连接方式查询。由此可见用IN的SQL至少多了一个转换的过程。一般的SQL都可以转换成功，但对于含有分组统计等方面的SQL就不能转换了。<br />
第二种格式中，子查询以’select 1’开始。运用EXISTS子句不管子查询从表中抽取什么数据它只查看where子句。这样优化器就不必遍历整个表而仅根据索引就可完成工作（这里假定在where语句中使用的列存在索引）。相对于IN子句来说，EXISTS使用相连子查询，构造起来要比IN子查询困难一些。<br />
通过使用EXIST，数据库系统会首先检查主查询，然后运行子查询直到它找到第一个匹配项，这就节省了时间。数据库系统在执行IN子查询时，首先执行子查询，并将获得的结果列表存放在一个加了索引的临时表中。在执行子查询之前，系统先将主查询挂起，待子查询执行完毕，存放在临时表中以后再执行主查询。这也就是使用EXISTS比使用IN通常查询速度快的原因。<br />
同时应尽可能使用NOT EXISTS来代替NOT IN，尽管二者都使用了NOT（不能使用索引而降低速度），NOT EXISTS要比NOT IN查询效率更高。<br />
6. IS NULL 或 IS NOT NULL操作（判断字段是否为空）<br />
不能用null作索引，任何包含null值的列都将不会被包含在索引中，因为B树索引是不索引空值的。即使索引有多列这样的情况下，只要这些列中有一列含有null，该列就会从索引中排除。也就是说如果某列存在空值，即使对该列建索引也不会提高性能。<br />
任何在where子句中使用is null或is not null的语句优化器是不允许使用索引的。<br />
推荐方案：用其它相同功能的操作运算代替，如a is not null 改为 a&gt;0 或a&gt;’等。另外还设置字段不允许为空，而用一个缺省值代替空值，如一个datetime字段，可以将默认时间设为“1900-01-01”。<br />
7. &gt; 及 &lt; 操作符（大于或小于操作符）<br />
       大于或小于操作符一般情况下是不用调整的，因为它有索引就会采用索引查找，但有的情况下可以对它进行优化，如一个表有100万记录，一个数值型字段A，30 万记录的A=0，30万记录的A=1，39万记录的A=2，1万记录的A=3。那么执行A&gt;2与A&gt;=3的效果就有很大的区别了，因为 A&gt;2时sql会先找出为2的记录索引再进行比较，而A&gt;=3时sql则直接找到=3的记录索引。可结合非聚集索引一起考虑。<br />
8. LIKE操作符<br />
LIKE 操作符可以应用通配符查询，里面的通配符组合可能达到几乎是任意的查询，但是如果用得不好则会产生性能上的问题，如LIKE ‘%5400%’ 这种查询不会引用索引，而LIKE ‘X5400%’则会引用范围索引。因为索引的摆放是依据字段值升序或降序排列，like&#8217;%*&#8217;这种用法，不能利用有序的数据结构，利用二分法查找数据。一个实际例子：用YW_YHJBQK表中营业编号后面的户标识号可来查询营业编号 YY_BH LIKE ‘%5400%’ 这个条件会产生全表扫描，如果改成YY_BH LIKE ’X5400%’ OR YY_BH LIKE ’B5400%’ 则会利用YY_BH的索引进行两个范围的查询，性能肯定大大提高。<br />
9. 查询条件中的适当与不适当<br />
查询参数可以包含一下操作：=、&lt;、&gt;、&gt;=、&lt;=、BETWEEN、部分like。其中，like当这样使用时会用到索引：like &#8216;*%&#8217;,但like&#8217;%*&#8217;就用不到索引。<br />
不适当的查询参数有：NOT 、!= 、&lt;&gt;、 !&gt;、 !&lt; 、NOT EXISTS、 NOT IN 、NOT LIKE等，还有一些不当的用法，例如：对数据进行计算，负向查询、等号左边使用函数、使用OR。上述语法都不用不上索引，降低程序的效率。</p>
]]></content:encoded>
			<wfw:commentRss>http://column.ibeifeng.com/allg0/20100725405.shtml/feed</wfw:commentRss>
		</item>
		<item>
		<title>创新工厂面试经历</title>
		<link>http://column.ibeifeng.com/allg0/20100614363.shtml</link>
		<comments>http://column.ibeifeng.com/allg0/20100614363.shtml#comments</comments>
		<pubDate>Mon, 14 Jun 2010 11:53:41 +0000</pubDate>
		<dc:creator>风风</dc:creator>
		
		<category><![CDATA[其他]]></category>

		<guid isPermaLink="false">http://column.ibeifeng.com/?p=363</guid>
		<description><![CDATA[  周五接到创新工厂的面试电话，让周一过去。我原先是投的实习岗位，毕竟NOKIA离学校太远了，想找个离学校近点的地方。咨询过原本去面试过的同学，说起来题目都很简单，无非是折半查找什么的，面试个把小时就结束了。结果到我这：我12点50到那，跟一个面试我的工程师一直面对面的聊到2点半，活活面了1个半小时，悲惨~午饭都没吃。（面试完了，我才明白：那工程师以为我是来面正式员工的，所以~~）
      我以前也参加过几个公司的面试，但是这次面试的经历是最nice的！以前去朗讯面试，基本上过去做了张试卷然后和team中的四个工程师随便聊了20分钟就被告知：明天就可以来入职了，当时自己还一愣一愣的（后来因为种种原因没去，非常可惜）。这次在创新工厂面试和笔试不是分开的，工程师找了一张桌子，我们俩就像朋友一样一起坐那，然后开始聊天一样的面试。刚开始主要是问我一些：以前自己做过的项目的经历，从框架设计上，设计模式使用上，具体问题解决上~~基本上都要巨细无遗的询问，我觉得：除非你真的有大的工程项目经验，否则真的蒙不过去。 面试官还让我举出在项目中间我认为最难得一个问题，以及如何解决的，  我举了一个关于多线程之间冲突的解决方法：用的二维映射表来处理彼此之间的冲突。

      我觉得让我不太好回答的问题是：你觉得所做项目的Bug-list中：你自己的问题所占比例有多少~  呵呵，这个我确实不知道该如何回答是好，最后勉勉强强说了个1/5，也不知道是多是少。其实认真的说:我确实不知道我自己编码上的问题所占比例，毕竟：基本上所有问题都是纠结在一起的，并没有划分那么详细。
     面试官问了我一个很有意思的问题：你有过创业的打算吗？  我很直白的回答说：没有，因为我没有好的idea，没有资金没有经~balabala~   后来我才发觉：这样回答不太合适。因为面试官后来说：创新工厂是一个创业型公司什么的~汗一个~~
      后来看我项目经验主要集中在移动开发上边，他就问我对symbian ,maemo,android，iphone这几个主流手机操作系统的看法。 幸好以前我专门查过这方面的资料，上来直接就说：对个人而言：我不喜欢android，我觉得它是一种伪开源，然后balabala~~~呵呵~面试卷一边听一边在记着什么。   面试完出来后我才开始琢磨：这面试官不会是跟李开复老师从谷歌过来的吧？整不好以前就是做andorid的，我在他面前这么说android是不是有点不合适？呵呵~  然后他还问了很多symbain方面的东西以及让我说一下个人对这个os的看法，我就结合symbian在智能手机市场份额日益下降的现状说明了下这个操作系统的优劣势和现状，总体来说:自己对这方面还算比较了解，回答的都行。
     项目经验问完之后，工程师出了一道算法题,我大概花了5min给出了解决方法，工程师看了之后让我算了下时间复杂度。说这个太高了，让我想办法再继续优化，降低时间复杂度。我可能因为前边的方法给思维固化了，想了有5min多，在那画图，后来终于想出来解决之法，结果还没等我开始编码实现的，那工程师可能觉得时间有点长了，就打断了我，跟我一起分析。结果他要说的方法跟我最后想出来的方法是一样的。呵呵·他也看到我上边画的图了，应该知道我也想出来了吧？谁知道~
      这道题目结束后，整个面试就结束了。然后他说：我这没有问题了，你有什么问题吗？ 我壮着胆子问了下待遇问题以及传说中的加班问题。终于得到确切数字：一周至少工作70h。汗一个先~~（我不知道这个数字是针对正式员工还是也针对实习生）。他还问我：有没在网上搜过他们公司的信息，我说：搜过，但是很少，所以不是很清楚。 [...]]]></description>
			<content:encoded><![CDATA[<p>  周五接到创新工厂的面试电话，让周一过去。我原先是投的实习岗位，毕竟NOKIA离学校太远了，想找个离学校近点的地方。咨询过原本去面试过的同学，说起来题目都很简单，无非是折半查找什么的，面试个把小时就结束了。结果到我这：我12点50到那，跟一个面试我的工程师一直面对面的聊到2点半，活活面了1个半小时，悲惨~午饭都没吃。（面试完了，我才明白：那工程师以为我是来面正式员工的，所以~~）</p>
<p>      我以前也参加过几个公司的面试，但是这次面试的经历是最nice的！以前去朗讯面试，基本上过去做了张试卷然后和team中的四个工程师随便聊了20分钟就被告知：明天就可以来入职了，当时自己还一愣一愣的（后来因为种种原因没去，非常可惜）。这次在创新工厂面试和笔试不是分开的，工程师找了一张桌子，我们俩就像朋友一样一起坐那，然后开始聊天一样的面试。刚开始主要是问我一些：以前自己做过的项目的经历，从框架设计上，设计模式使用上，具体问题解决上~~基本上都要巨细无遗的询问，我觉得：除非你真的有大的工程项目经验，否则真的蒙不过去。 面试官还让我举出在项目中间我认为最难得一个问题，以及如何解决的，  我举了一个关于多线程之间冲突的解决方法：用的二维映射表来处理彼此之间的冲突。<br />
<span id="more-363"></span><br />
      我觉得让我不太好回答的问题是：你觉得所做项目的Bug-list中：你自己的问题所占比例有多少~  呵呵，这个我确实不知道该如何回答是好，最后勉勉强强说了个1/5，也不知道是多是少。其实认真的说:我确实不知道我自己编码上的问题所占比例，毕竟：基本上所有问题都是纠结在一起的，并没有划分那么详细。</p>
<p>     面试官问了我一个很有意思的问题：你有过创业的打算吗？  我很直白的回答说：没有，因为我没有好的idea，没有资金没有经~balabala~   后来我才发觉：这样回答不太合适。因为面试官后来说：创新工厂是一个创业型公司什么的~汗一个~~</p>
<p>      后来看我项目经验主要集中在移动开发上边，他就问我对symbian ,maemo,android，iphone这几个主流手机操作系统的看法。 幸好以前我专门查过这方面的资料，上来直接就说：对个人而言：我不喜欢android，我觉得它是一种伪开源，然后balabala~~~呵呵~面试卷一边听一边在记着什么。   面试完出来后我才开始琢磨：这面试官不会是跟李开复老师从谷歌过来的吧？整不好以前就是做andorid的，我在他面前这么说android是不是有点不合适？呵呵~  然后他还问了很多symbain方面的东西以及让我说一下个人对这个os的看法，我就结合symbian在智能手机市场份额日益下降的现状说明了下这个操作系统的优劣势和现状，总体来说:自己对这方面还算比较了解，回答的都行。</p>
<p>     项目经验问完之后，工程师出了一道算法题,我大概花了5min给出了解决方法，工程师看了之后让我算了下时间复杂度。说这个太高了，让我想办法再继续优化，降低时间复杂度。我可能因为前边的方法给思维固化了，想了有5min多，在那画图，后来终于想出来解决之法，结果还没等我开始编码实现的，那工程师可能觉得时间有点长了，就打断了我，跟我一起分析。结果他要说的方法跟我最后想出来的方法是一样的。呵呵·他也看到我上边画的图了，应该知道我也想出来了吧？谁知道~</p>
<p>      这道题目结束后，整个面试就结束了。然后他说：我这没有问题了，你有什么问题吗？ 我壮着胆子问了下待遇问题以及传说中的加班问题。终于得到确切数字：一周至少工作70h。汗一个先~~（我不知道这个数字是针对正式员工还是也针对实习生）。他还问我：有没在网上搜过他们公司的信息，我说：搜过，但是很少，所以不是很清楚。  最后我问了一下创新工厂的研发主要集中在那几块，得到答复是：电子商务，移动互联网还有云计算。 然后面试官问我对这几个方向都了解多少，我坦言像云计算这种概念过新，只有这么个概念，实际到底怎么回事不是很清楚。其实后边我很想斗胆问一下：创新工厂从开始到现在，什么产品都没做出来，没有什么实质性的进展，这是个什么问题？  这也是我大多数同学和朋友的疑问，但是最后我也没这个胆子问，呵呵~</p>
<p>      在面试的整个过程中：只要我回答问题，面试官就一直在记着，可能是打分或者写评语吧，及其认真！而且所问的问题确实能考察简历的真实性！而且面试官人很nice，在给我出算法题时：我笑着对他说：我可能不会。但是他也一笑，说:没关系，不行我们一起讨论。 在我做题过程中：他并没有离开，一直坐我旁边等着。而且对同一个问题，我们会想同学讨论问题那样，一起在草稿纸上写写画画在那商量着解决，我受益匪浅！  </p>
<p>      创新工厂的面试经历给我的感觉非常nice！当然：我所见到的工厂内部的气氛和公司文化也和我以前见过的公司大不相同！！如果能有更多的这种面试经历，我很愿意去感受！！</p>
<p>      外界对创新工厂现在的说法很多，但是我觉得李老师的开拓和创新精神始终是最值得肯定的！佩服之！！不管最后能不能拿到实习offer，这次面试经历始终是一次很好的经历！！</p>
]]></content:encoded>
			<wfw:commentRss>http://column.ibeifeng.com/allg0/20100614363.shtml/feed</wfw:commentRss>
		</item>
		<item>
		<title>用C语言在NDS上编写程序</title>
		<link>http://column.ibeifeng.com/allg0/20100614361.shtml</link>
		<comments>http://column.ibeifeng.com/allg0/20100614361.shtml#comments</comments>
		<pubDate>Mon, 14 Jun 2010 11:50:46 +0000</pubDate>
		<dc:creator>风风</dc:creator>
		
		<category><![CDATA[其他]]></category>

		<guid isPermaLink="false">http://column.ibeifeng.com/?p=361</guid>
		<description><![CDATA[在DS上进行开发是我一直的梦想，虽然有DSBasic, DSLua等解释器，但是总感觉很别扭，而且没有更多的语言支持。昨天偶然发现了一个DS上的x86虚拟机，我想在这上面测试一下。

我们需要以下组件：
**DSx86**
在DS上模拟x86环境的虚拟机
地址：http://dsx86.patrickaalto.com/，目前最新版本0.14Beta
需要的文件有：
DSx86.nds &#8212; 引导文件
DSx86.ini &#8212; 配置文件
DSx86Cfg &#8212; 配置设置工具
把下载的文件解压到/data/dsx86/就行了。
但是这只是x86虚拟机，我们还需要一个操作系统。（往下看）
**4DOS**
命令提示符外壳
地址：ftp://jpsoft.com/4dos/files/，目前最新版本7.2
这里需要的文件只有：
4dos.com
下载到/data/dsx86/4dos/, /data/dsx86/, /4dos/中任意一个文件夹都可以，其他的几个辅助文件也可以一并下载。
**Vim**
文本编辑工具
地址：http://www.vim.org/download.php#pc
我们需要的部分是：
vim71d16.zip &#8212; 16位dos下的可执行文件
vim72rt.zip &#8212; 所有版本vim所需要的运行时包，包括了文档，语法还有其他的配置文件
把上面的文件下载后解压到/vim/vim71/进行一些配置来时编辑器更加符合程序员的使用，在/vim/下创建_vimrc文件，内容为下面的语句
syntax enable
set smartindent
set tabstop=4
set shiftwidth=4
set nu!
这里面已经包括了设置语法高亮，自动缩进，行号等功能了。
**DJGPP**
一个GNU在DOS下的编译系统实现
地址：http://www.delorie.com/djgpp/
我们可以在他给出的ftp中找到需要的文件：
gccXXXb.zip &#8212; GNU C编译器
gppXXXb.zip &#8212; GNU C++编译器
bnuXXXb.zip &#8212; 链接库
djdevXXXb.zip &#8212; 库，头文件等
csdpmiXb.zip &#8212; DOS 保护模式方法接口
makXXXb.zip &#8212; GNU Make工具
注：以上的X替换为你能找到的最新版本。
把下载到的文件都解压到/djgpp/下
到此，我们已经完成了虚拟机，操作系统，编译环境，代码编辑工具的搭建。
现在我们来开发在DS上的第一个项目：Hello, World!
打开DS，从你烧录卡的引导器中找到/data/dsx86/DSx86.nds并启动，屏幕将会出现如下画面：
***** DSx86 v0.14 by Patrick Aalto *****
BIOS date: Jun 8 2010
Initializing llibDAT: Success!
/DATADSX86/DSX86.INI loaded!
Starting command shell:
Try C:\DATA\DSX86\4DOS\4DOS.COM &#8230;OK!
4DOS EMS swapping [...]]]></description>
			<content:encoded><![CDATA[<p>在DS上进行开发是我一直的梦想，虽然有DSBasic, DSLua等解释器，但是总感觉很别扭，而且没有更多的语言支持。昨天偶然发现了一个DS上的x86虚拟机，我想在这上面测试一下。<br />
<span id="more-361"></span><br />
我们需要以下组件：</p>
<p>**DSx86**<br />
在DS上模拟x86环境的虚拟机<br />
地址：http://dsx86.patrickaalto.com/，目前最新版本0.14Beta<br />
需要的文件有：<br />
DSx86.nds &#8212; 引导文件<br />
DSx86.ini &#8212; 配置文件<br />
DSx86Cfg &#8212; 配置设置工具<br />
把下载的文件解压到/data/dsx86/就行了。<br />
但是这只是x86虚拟机，我们还需要一个操作系统。（往下看）</p>
<p>**4DOS**<br />
命令提示符外壳<br />
地址：ftp://jpsoft.com/4dos/files/，目前最新版本7.2<br />
这里需要的文件只有：<br />
4dos.com<br />
下载到/data/dsx86/4dos/, /data/dsx86/, /4dos/中任意一个文件夹都可以，其他的几个辅助文件也可以一并下载。</p>
<p>**Vim**<br />
文本编辑工具<br />
地址：http://www.vim.org/download.php#pc<br />
我们需要的部分是：<br />
vim71d16.zip &#8212; 16位dos下的可执行文件<br />
vim72rt.zip &#8212; 所有版本vim所需要的运行时包，包括了文档，语法还有其他的配置文件<br />
把上面的文件下载后解压到/vim/vim71/进行一些配置来时编辑器更加符合程序员的使用，在/vim/下创建_vimrc文件，内容为下面的语句<br />
syntax enable<br />
set smartindent<br />
set tabstop=4<br />
set shiftwidth=4<br />
set nu!<br />
这里面已经包括了设置语法高亮，自动缩进，行号等功能了。</p>
<p>**DJGPP**<br />
一个GNU在DOS下的编译系统实现<br />
地址：http://www.delorie.com/djgpp/<br />
我们可以在他给出的ftp中找到需要的文件：<br />
gccXXXb.zip &#8212; GNU C编译器<br />
gppXXXb.zip &#8212; GNU C++编译器<br />
bnuXXXb.zip &#8212; 链接库<br />
djdevXXXb.zip &#8212; 库，头文件等<br />
csdpmiXb.zip &#8212; DOS 保护模式方法接口<br />
makXXXb.zip &#8212; GNU Make工具<br />
注：以上的X替换为你能找到的最新版本。<br />
把下载到的文件都解压到/djgpp/下</p>
<p>到此，我们已经完成了虚拟机，操作系统，编译环境，代码编辑工具的搭建。<br />
现在我们来开发在DS上的第一个项目：Hello, World!</p>
<p>打开DS，从你烧录卡的引导器中找到/data/dsx86/DSx86.nds并启动，屏幕将会出现如下画面：<br />
***** DSx86 v0.14 by Patrick Aalto *****</p>
<p>BIOS date: Jun 8 2010<br />
Initializing llibDAT: Success!</p>
<p>/DATADSX86/DSX86.INI loaded!<br />
Starting command shell:<br />
Try C:\DATA\DSX86\4DOS\4DOS.COM &#8230;OK!</p>
<p>4DOS EMS swapping initialized (240K)</p>
<p>4DOS 7.50 DOS5.00<br />
Copyright 1988-2004 Rex Conn &amp; JP Software Inc. All Rights Reserved<br />
C:\&gt;_</p>
<p>这说明4DOS已经载入成功，可以开始运行DOS程序了。<br />
进入Vim目录，并创建a.c源文件：<br />
C:\&gt;cd vim\vim71<br />
C:\vim\vim71&gt;vim a.c<br />
按I进入插入模式，输入程序：<br />
#include<br />
int main()<br />
{<br />
  printf(&#8221;Hello, world!\n&#8221;);<br />
  return 0;<br />
}<br />
按ESC返回普通模式，用ZZ命令保存并退出。</p>
<p>要得到可执行文件必须先编译，我们首先要设置编译器路径，在命令提示符下输入以下命令：<br />
set PATH=C:\DJGPP\BIN;%PATH%<br />
set DJGPP=c:/djgpp/djgpp.env<br />
现在可以开始编译了，使用命令：<br />
gcc -o a.c</p>
<p>这时屏幕提示错误并输出一堆乱码：<br />
80386 required.</p>
<p>好，我们的工作到这里暂时告一段落，首先说明一下，为什么我们没有得到可执行文件。<br />
根据DSx86主页上作者的说明，目前DSx86只能模拟到没有保护模式的80286，也就差不多等于80186。而我们的编译环境需要80386，当然就不能</p>
<p>进行编译了。<br />
所以，如果我们需要用DJGPP完成开头提出的目标，比如等待作者继续更新DSx86，使它支持80386，或者自己重新编译gcc，让它支持80186实模</p>
<p>式。</p>
<p>没有合适的自由软件或免费软件，我们只能用商业软件代替了。一款古老的编译器，Turbo C将会帮助我们完成接下来的工作。</p>
<p>**Turbo C**<br />
Borland的古老的C编译器，我们需要的是2.0版，虽然同时代同系列的最新版本是3.0，但是经测试，TC3.0需要的处理器最低为80386。<br />
安装TC2.0后在PC上运行TC.EXE，依次展开Options-Directories菜单，将里面的路径设置为正确的，如：<br />
Include directories: C:\TURBOC2\INCLUDE<br />
Library directories: C:\TURBOC2\LIB<br />
Output directories:<br />
Turbo C directories: C:\TURBOC2<br />
Pick file name:<br />
设置完毕后使用Options-Save options命令保存刚才的设置。<br />
并且在TC2目录下建立刚才的a.c文件。因为TC2年代久远，当时的C标准与现在不同，所以我们的程序需要修改一下才能运行。<br />
把第一行的：#include<br />
改为：#include &#8220;stdio.h&#8221;<br />
重新启动DS，进入C:\TURBOC目录，执行编译命令：<br />
tcc a.c<br />
程序将会自动编译并链接为一个a.exe<br />
然后输入a就可以看到效果了，屏幕打印一串字：</p>
<p>Hello, world!</p>
]]></content:encoded>
			<wfw:commentRss>http://column.ibeifeng.com/allg0/20100614361.shtml/feed</wfw:commentRss>
		</item>
		<item>
		<title>苹果为何是Linux的最大竞争对手？</title>
		<link>http://column.ibeifeng.com/allg0/20100614359.shtml</link>
		<comments>http://column.ibeifeng.com/allg0/20100614359.shtml#comments</comments>
		<pubDate>Mon, 14 Jun 2010 11:49:12 +0000</pubDate>
		<dc:creator>风风</dc:creator>
		
		<category><![CDATA[其他]]></category>

		<guid isPermaLink="false">http://column.ibeifeng.com/?p=359</guid>
		<description><![CDATA[当今，尤其是进入移动互联网时代，苹果日益成为 Linux 的竞争对手，两者的竞争日趋激烈。何故？
    回顾这十年来，我们是看着微软在走下坡路的， Vista 极大地伤害了它。人们不断地诅咒微软，它也没有脾气了。老实说，我在心里面很同情微软，微软来中国，帮了我们不少忙。但是，人们似乎没有注意到，这十年来，在老 Jobs 的带领下，苹果日渐壮大，如今变得相当牛气了。苹果借助自由软件（比如， FreeBSD ），独创一套操作系统和用户界面（ GUI ），以及自己的硬件体系（包括 CPU 处理器），自成一套，独行其是。苹果的 iPhone 盈利模式（与电信运营商 AT&#38;T 合作，搞所谓“签约价”销售），本质上就是特别适合移动互联网时代的服务盈利模式。说穿了， iPhone 里面的技术其实并不神秘、新颖， Linux 体系里面都有相应的技术（或原型）。苹果分享 Linux 自由软件成果的贪婪方式（只顾自己独吃，从来不管别人），历来遭到 Linux 业界的严厉批评，但是，苹果就是听不进去。

    坦率地说，对于 Linux 而言，苹果产品的“厉害”之处，不在于产品的技术和性能的优劣，而在于产品的“精美绝伦”。我儿媳妇用的手机就是 iPhone ，其精美程度与我的国产老手机（而且很可能是山寨机）相比，那简直不能相提并论。苹果 iPhone 4 发布之后， Linux 全球司令部（即《 Linux 基金会》）立即发出战斗号令，“ Linux needs to more effectively compete with Steve Jobs and the [...]]]></description>
			<content:encoded><![CDATA[<p>当今，尤其是进入移动互联网时代，苹果日益成为 Linux 的竞争对手，两者的竞争日趋激烈。何故？<br />
    回顾这十年来，我们是看着微软在走下坡路的， Vista 极大地伤害了它。人们不断地诅咒微软，它也没有脾气了。老实说，我在心里面很同情微软，微软来中国，帮了我们不少忙。但是，人们似乎没有注意到，这十年来，在老 Jobs 的带领下，苹果日渐壮大，如今变得相当牛气了。苹果借助自由软件（比如， FreeBSD ），独创一套操作系统和用户界面（ GUI ），以及自己的硬件体系（包括 CPU 处理器），自成一套，独行其是。苹果的 iPhone 盈利模式（与电信运营商 AT&amp;T 合作，搞所谓“签约价”销售），本质上就是特别适合移动互联网时代的服务盈利模式。说穿了， iPhone 里面的技术其实并不神秘、新颖， Linux 体系里面都有相应的技术（或原型）。苹果分享 Linux 自由软件成果的贪婪方式（只顾自己独吃，从来不管别人），历来遭到 Linux 业界的严厉批评，但是，苹果就是听不进去。<br />
<span id="more-359"></span><br />
    坦率地说，对于 Linux 而言，苹果产品的“厉害”之处，不在于产品的技术和性能的优劣，而在于产品的“精美绝伦”。我儿媳妇用的手机就是 iPhone ，其精美程度与我的国产老手机（而且很可能是山寨机）相比，那简直不能相提并论。苹果 iPhone 4 发布之后， Linux 全球司令部（即《 Linux 基金会》）立即发出战斗号令，“ Linux needs to more effectively compete with Steve Jobs and the magic of Apple” ，意思是说， Linux 业界需要更为有效地与苹果神话（ Magic ）展开竞争，同时要求，“ Linux must &#8216;out fabulous&#8217; （超精美） Apple&#8217;s iPhone” 。人们要问， Linux 能不能做到比苹果精美，甚至超精美呢？ </p>
<p>    老实说，以往 Linux 是编程高手云集的领域，他们只注意程序代码的精美与否，很少关注程序代码的“外表”（用户界面）美丽不美丽，胡子拉碴的。如今被苹果欺负了（超越了），原本对苹果就有怨气（或怒气），《 Linux 基金会》的这把火一定会烧起来的。实际上， Linux 小伙子长得并不错，以往因为没有女朋友，不注重打扮自己。如今， Linux 穿西装打领带，要与 iPhone 当面比试比试（否则，女朋友会丢掉的。注：这里女朋友指的是用户）。事实上， Ubuntu 10.04 新版本相比以往漂亮多了，将来还要更加美丽。<br />
    近来，我注意到，新近在 Linux 国际论坛里面有一种“背景音”：别再无休无止地追求新功能的实现，而是要集中力量把已有的成果搞得更加“美好”（就是上面讲的那种“精美”的意思）。我们可以看出，《 Linux 基金会》正在带领全球 Linux 大军沿着正确的方向在前进，前进，再前进， &#8230;&#8230; </p>
]]></content:encoded>
			<wfw:commentRss>http://column.ibeifeng.com/allg0/20100614359.shtml/feed</wfw:commentRss>
		</item>
		<item>
		<title>M8系统编程应用之数字时钟的实现</title>
		<link>http://column.ibeifeng.com/allg0/20100614357.shtml</link>
		<comments>http://column.ibeifeng.com/allg0/20100614357.shtml#comments</comments>
		<pubDate>Mon, 14 Jun 2010 11:48:16 +0000</pubDate>
		<dc:creator>风风</dc:creator>
		
		<category><![CDATA[其他]]></category>

		<guid isPermaLink="false">http://column.ibeifeng.com/?p=357</guid>
		<description><![CDATA[ 写在前面的话
自从上一篇文章更新之后，又过了很久。说实话，原本我准备是每周更新一次的。但是，事实却往往事与愿违。之所以隔了那么久，一来是因为工作和学习上刚进入一个新的环境，所以还没有稳定，再者我自己也需要学习一些新的东西，整理一下曾经的内容。不过，现在回想起来我更新的频率远没有原来那么高了，或许是自己老了吧。

写了那么多关于软件相关的东西，我也想试着写一些和硬件有关的文章。所以，这次我想先试验一下写一篇看看，如果觉得不好，请各位不要拍砖。如果觉得好，那还请各位多多支持了。毕竟，你们的支持是我最大的动力。 
曾经有一位朋友，看到我说M8的时候问过我，M8是不是某手机的型号。不过很可惜，我这里说的M8是一款由ATMEL生产的一款单片机。至于为什么选这款单片机而不是选择应用相当广泛的51单片机，我想主要有两个原因。第一，M8能够得到GCC的支持。第二，M8的性能和体系结构比同为ATMEL的 AT89S52要好很多。 
1   ATmega8微控制器概述
ATmega8是一款基于AVR RISC体系结构的低功耗8位微控制器。能实现每MHz百万条指令的执行效率。从体系结构上讲，其拥有130条指令，且大部分都是单时钟周期的。此外，还拥有32个8位通用寄存器。最高能在16MHz外部时钟频率下达到16MIPS的执行速度。在其内部集成了8KB的可编程Flash ROM，用于存储MCU所执行的程序。其次还拥有1K的内部SRAM。至于其片内功能则也是相当丰富，如USART 1 、计时计数器、AD转换、SPI通讯接口、I2 C通讯接口 等诸多功能。其封装形式主要有双列支插和贴片两种形式。作为一款单片机来说，还是相当不错的，至少同ATMEL的51单片机相比，其优势还是相当高的。另外，对于最小系统，由于51需要外部晶振和复位电路，因此存在最小系统的概念。而ATmega8，由于默认情况下采用的是内部上电复位以及片内时钟，所以不存在最小系统的概念，通电便可工作。 
2   I/O端口概述
对于一款MCU来说，他与外部交流的主要途径就是通过其I/O口。所以，在这篇文章中，我就先从I/O端口开始。 
2.1   I/O端口物理描述
在ATmega8系列的单片机上，所有的I/O接口都能实现读写功能，而且，引脚之间是互相独立的，因此，你可以通过 SBI或者CBI这种位操作指令改变某一个引脚的功能而不影响其他引脚。 ATmega8拥3个8位的I/O端口,他们分别被命名为B、C和D。如果你曾经有过使用51的经验。那么你或许会对51中的上拉电阻记忆犹新，但是在ATmega8中其拥有内部可选的上拉电阻。也就是说，你可以选择使用内部的上拉电阻或者采用外部上拉电阻。如果你要选择外部上拉电阻，建议使用20kΩ ∼ 50kΩ 
从电气性能上讲，ATmega8的引脚驱动力还是相当强的，而且输出和输入的驱动力是对称的，所以你不会遇到在51上遇到的输入能力大于输出能力的情况。根据手册上描述，其驱动电流为20mA。当然在具体的应用时，会存如下几点限制。 
所有引脚的电流总和不得超过300mA
C0 ∼ C5 引脚的电流总和不能超过100mA
B0 ∼ B7、C6、D0 ∼ D7和XTAL2引脚的电流总和不应超过200mA
从手册的指标上讲，一个引脚驱动一个5mA的发光二极管应该是没什么问题的。而对于7段数码管来说，也不存在51的适合采用共阴极的限制。 
2.2   I/O端口相关软件描述
从软件的层面讲，I/O 端口的功能主要通过DDxn、PORTxn这两类寄存器，以及PUD这个bit位来进行控制。其中&#8221;x&#8221;为端口名，而&#8221;n&#8221;则为寄存器位。各端口寄存器的功能描述，可以见表1 。表中&#8221;X&#8221;表示的为任意数，即0或1。 
DDxn  PORTxn  PUD  I/O  上拉电阻  说明
0  0  [...]]]></description>
			<content:encoded><![CDATA[<p> 写在前面的话<br />
自从上一篇文章更新之后，又过了很久。说实话，原本我准备是每周更新一次的。但是，事实却往往事与愿违。之所以隔了那么久，一来是因为工作和学习上刚进入一个新的环境，所以还没有稳定，再者我自己也需要学习一些新的东西，整理一下曾经的内容。不过，现在回想起来我更新的频率远没有原来那么高了，或许是自己老了吧。<br />
<span id="more-357"></span><br />
写了那么多关于软件相关的东西，我也想试着写一些和硬件有关的文章。所以，这次我想先试验一下写一篇看看，如果觉得不好，请各位不要拍砖。如果觉得好，那还请各位多多支持了。毕竟，你们的支持是我最大的动力。 </p>
<p>曾经有一位朋友，看到我说M8的时候问过我，M8是不是某手机的型号。不过很可惜，我这里说的M8是一款由ATMEL生产的一款单片机。至于为什么选这款单片机而不是选择应用相当广泛的51单片机，我想主要有两个原因。第一，M8能够得到GCC的支持。第二，M8的性能和体系结构比同为ATMEL的 AT89S52要好很多。 </p>
<p>1   ATmega8微控制器概述<br />
ATmega8是一款基于AVR RISC体系结构的低功耗8位微控制器。能实现每MHz百万条指令的执行效率。从体系结构上讲，其拥有130条指令，且大部分都是单时钟周期的。此外，还拥有32个8位通用寄存器。最高能在16MHz外部时钟频率下达到16MIPS的执行速度。在其内部集成了8KB的可编程Flash ROM，用于存储MCU所执行的程序。其次还拥有1K的内部SRAM。至于其片内功能则也是相当丰富，如USART 1 、计时计数器、AD转换、SPI通讯接口、I2 C通讯接口 等诸多功能。其封装形式主要有双列支插和贴片两种形式。作为一款单片机来说，还是相当不错的，至少同ATMEL的51单片机相比，其优势还是相当高的。另外，对于最小系统，由于51需要外部晶振和复位电路，因此存在最小系统的概念。而ATmega8，由于默认情况下采用的是内部上电复位以及片内时钟，所以不存在最小系统的概念，通电便可工作。 </p>
<p>2   I/O端口概述<br />
对于一款MCU来说，他与外部交流的主要途径就是通过其I/O口。所以，在这篇文章中，我就先从I/O端口开始。 </p>
<p>2.1   I/O端口物理描述<br />
在ATmega8系列的单片机上，所有的I/O接口都能实现读写功能，而且，引脚之间是互相独立的，因此，你可以通过 SBI或者CBI这种位操作指令改变某一个引脚的功能而不影响其他引脚。 ATmega8拥3个8位的I/O端口,他们分别被命名为B、C和D。如果你曾经有过使用51的经验。那么你或许会对51中的上拉电阻记忆犹新，但是在ATmega8中其拥有内部可选的上拉电阻。也就是说，你可以选择使用内部的上拉电阻或者采用外部上拉电阻。如果你要选择外部上拉电阻，建议使用20kΩ ∼ 50kΩ </p>
<p>从电气性能上讲，ATmega8的引脚驱动力还是相当强的，而且输出和输入的驱动力是对称的，所以你不会遇到在51上遇到的输入能力大于输出能力的情况。根据手册上描述，其驱动电流为20mA。当然在具体的应用时，会存如下几点限制。 </p>
<p>所有引脚的电流总和不得超过300mA<br />
C0 ∼ C5 引脚的电流总和不能超过100mA<br />
B0 ∼ B7、C6、D0 ∼ D7和XTAL2引脚的电流总和不应超过200mA<br />
从手册的指标上讲，一个引脚驱动一个5mA的发光二极管应该是没什么问题的。而对于7段数码管来说，也不存在51的适合采用共阴极的限制。 </p>
<p>2.2   I/O端口相关软件描述<br />
从软件的层面讲，I/O 端口的功能主要通过DDxn、PORTxn这两类寄存器，以及PUD这个bit位来进行控制。其中&#8221;x&#8221;为端口名，而&#8221;n&#8221;则为寄存器位。各端口寄存器的功能描述，可以见表1 。表中&#8221;X&#8221;表示的为任意数，即0或1。 </p>
<p>DDxn  PORTxn  PUD  I/O  上拉电阻  说明<br />
0  0  X  输入  无  高阻态<br />
0  1  0  输入  有  与外部引脚变化相当<br />
0  1  1  输入  无  高阻态<br />
1  0  X  输出  无  输出低电平<br />
1  1  X  输出  无  输出高电平  </p>
<p>Table 1: M8 I/O端口寄存器功能描述 </p>
<p>对于对硬件比较陌生的人，可能会不太理解高阻态。其实，高阻态就相当于引脚上接一个阻值很大的电阻，等同于断开。其中PUD为SFIOR 寄存器中的一位。同时，M8也能够通过可重复编程的熔丝位设置PUD，一般来说M8的上拉电阻是无效的。 </p>
<p>2.3   软件操作范例<br />
下面我们将提供一组M8端口的读写C代码2 。在这段代码中，我们将从B口读取一个8位数据，送到D口上。 </p>
<p>view plaincopy to clipboardprint?#include    #include      int main(void) {     uint8_t t;     DDRB = 0&#215;00;     PORTB = 0xff;       DDRD = 0xff;     PORTD = 0&#215;00;       do {       __asm__(&#8221;nop&#8221;);       t = PORTB;       PORTD = t;     } while (1);          return(0);   }  #include<br />
#include </p>
<p>int main(void) {<br />
  uint8_t t;<br />
  DDRB = 0&#215;00;<br />
  PORTB = 0xff;</p>
<p>  DDRD = 0xff;<br />
  PORTD = 0&#215;00;</p>
<p>  do {<br />
    __asm__(&#8221;nop&#8221;);<br />
    t = PORTB;<br />
    PORTD = t;<br />
  } while (1);</p>
<p>  return(0);<br />
}</p>
<p>3   Timer0部件概述<br />
计时/计数器是用于限定时间的主要部件。而我们这次要实现的是一个数字时钟。因此，计时/计数器是我们的核心功能器件。这次我们只涉及到两个计时器的部分功能，所以让我们继续看计时/计数器吧。 </p>
<p>3.1   Timer0物理描述<br />
M8中的Timer0部件是一个8-bit的计时/计数器。其计时/计数功能是独立于MCU的，也就是说Timer0的工作是不占用MCU的指令空间的。其计时的基准信号能通过软件内部选择。可以是ClkI/O 分频后的信号，也可以是外部T0引脚的输入信号。当采用分频时，则Timer0为计时器，当采用T0引脚的输入信号时，就可以作为计数器了。 </p>
<p>Timer0相关的计数器寄存器在每次信号到达后，将累加1。当达到最大值0xFF时， TOV0将被置位，如果中断被允许的话，将触发相关的中断程序，并且将TOV0清零。此时计数器寄存器将从0&#215;00开始重新计数。 </p>
<p>3.2   Timer0软件功能描述<br />
Timer0从软件角度看主要通过TCCR0来选择时钟信号，TIMSK中的TOIE0位控制时钟中断， TIFR中的TOV0位判断计数器是否溢出。最后，TCNT0为Timer0的计数寄存器。 </p>
<p>CS02  CS01  CS00  说明<br />
0  0  0  无时钟源，计时器停止<br />
0  0  1  采用clkI/O 作为时钟源。<br />
0  1  0  采用clkI/O /8作为时钟源。<br />
0  1  1  采用clkI/O /64作为时钟源。<br />
1  0  0  采用clkI/O /256作为时钟源。<br />
1  0  1  采用clkI/O /1024作为时钟源。<br />
1  1  0  采用T0引脚的下降沿跳变作为时钟源。<br />
1  1  1  采用T0引脚的上升沿跳变作为时钟源。 </p>
<p>Table 2: TCCR0 时钟选择寄存器说明 </p>
<p>其中TCNT0就直接保存着计数器的值，通过对其赋值便可设定相应的时间。而TCCR0的低三位为 CS02、CS01和CS00用于选择时钟源，其他位为保留位，其具体的意义可见表 2 </p>
<p>在具体的使用中，我们经过改变TCNT0的值来等待相应的时间。假设T为分频基数，其数值为 1、8、64、256或者1024中的一个。 S为等待的秒数。则我们根据原理可以得到等式(1 ) 。根据要求，将相应的数代入便得到TCNT0的值了。 </p>
<p>TCNT0 =255 −  clkI/O </p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>T<br />
 S<br />
 (1) </p>
<p>3.3   软件操作与范例<br />
在这里，我将提供一组C代码。采用中断方式响应计时计数器溢出事件。这里我们将让计时器每隔约50ms发生一次，并假设时钟频率为1MHz。</p>
<p>view plaincopy to clipboardprint?#include    #include    #include      int main(void) {     TCCR0 = 0&#215;05;     TIMSK |= _BV(TOIE0);     TCNT0 = 255 - 48;     sei();       while(1);     return(0);   }     ISR(TIMER0_OVF_vect) {     TCNT0 = 255 - 48;     //some code here   }  #include<br />
#include<br />
#include </p>
<p>int main(void) {<br />
  TCCR0 = 0&#215;05;<br />
  TIMSK |= _BV(TOIE0);<br />
  TCNT0 = 255 - 48;<br />
  sei();</p>
<p>  while(1);<br />
  return(0);<br />
}</p>
<p>ISR(TIMER0_OVF_vect) {<br />
  TCNT0 = 255 - 48;<br />
  //some code here<br />
}</p>
<p>4   Timer1部件概述<br />
Timer1相对于Timer0的功能更多，但是在这里我们只使用Timer1中的CTC模式。 </p>
<p>4.1   Timer1物理描述<br />
Timer1是一个16bit的计时/计数器。除了拥有Timer0的功能之外，还拥有PWM模式以及CTC模式等。在计数器读写方面由于M8的数据总线是8位的，所以Timer1的各个16为寄存器都采用双缓存模式。Timer1的控制主要有 TCNT1、OCR1A/B、ICR1 这些16bit寄存器和一个TCCR1A/B八位寄存器对其控制。 </p>
<p>由于我们这里只用到了CTC模式，因此其他具体的硬件描述就暂且省略了。不过，正因为Timer1是一个16bit的计时/计数器，因此其计数范围远大于Timer0。 Normal模式就和Timer0的功能是一样的，不过主要是计数范围更广。 CTC模式即Clear Timer on Compare Match。主要运用OCR1A或者 ICR1 两个寄存器。在CTC模式下，当TCNT1的值等于OCR1A或者ICR1时，TCNT1将被清零。 </p>
<p>4.2   Timer1软件功能描述<br />
Timer1的功能应该是在M8的3个计时计数器中功能最强大的一个了。但限于篇幅问题，我这里只简单阐述一下CTC的运用。 </p>
<p>根据M8的手册，我们可以看到，当Timer1工作在Mode4和Mode12时，其工作模式为CTC。其中Mode4时，采用的比较寄存器为OCR1A，而Mode12采用的是ICR1。除此之外，从软件角度考虑，这两种CTC模式没有太大的区别。 </p>
<p>在比较寄存器设置上，鉴于CTC的工作模式，我们可以得到和Timer0类似的公式。 公式 2 中，S 为等待的秒数，T为分频的基数。将相应的值代入后便可得到OCR1A的值了。 </p>
<p>同时，因为CTC模式下，比较数是存储在OCR1A寄存器中的，而在比较结果相同时， TCNT1会自动清零，因此在设置完寄存器后，不用像Timer0那样，每次都要手动重新设置TCNT中的值。 </p>
<p>OCR1A = clkI/O </p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>T<br />
 S<br />
 (2) </p>
<p>对于时钟频率的选择，Timer1的TCCR1B的第三位同Timer0的TCCR0的第三位一样，是用于选择时钟频率的。而且，数值也类似，只是在外部平率的选择上， Timer0采用的是T0引脚，而Timer1采用的是T1引脚。除此之外，都类似。 </p>
<p>4.3   软件操作与范例<br />
下面的代码也将采用中断响应模式，对计时器比较事件进行响应。这里，我们将让计时器每个1s发生一次中断事件，并假设时钟频率为1MHz。 </p>
<p>view plaincopy to clipboardprint?#include    #include    #include      int main(void) {       TCCR1A = 0&#215;00;     TCCR1B = 0&#215;0d;       OCR1A = 0&#215;03d0;     TCNT1 = 0&#215;0000;     TIMSK |= _BV(OCIE1A);       sei();       while(1);     return(0);   }     ISR(TIMER1_COMPA_vect) {     //some code here   }  #include<br />
#include<br />
#include </p>
<p>int main(void) {</p>
<p>  TCCR1A = 0&#215;00;<br />
  TCCR1B = 0&#215;0d;</p>
<p>  OCR1A = 0&#215;03d0;<br />
  TCNT1 = 0&#215;0000;<br />
  TIMSK |= _BV(OCIE1A);</p>
<p>  sei();</p>
<p>  while(1);<br />
  return(0);<br />
}</p>
<p>ISR(TIMER1_COMPA_vect) {<br />
  //some code here<br />
}</p>
<p>5   硬件环境概述<br />
对于一个单片机系统而言，光有单片机是不够的，还需要外部电路的支持。当然，这个数字时钟从理论上说，也算一个微型系统。因此，单片机外围的硬件也同样是免不了的。这里的内容主要是针对在硬件方面不太了解的人所设置的，如果您是硬件牛人，那就跳过啦。 </p>
<p>5.1   7段数码管的连接描述<br />
对于一个系统而言，我们都需要有一组交互界面。比如，输出功能能之类的。在硬件的开发中，比较简单而常见的，就是LED作为输出，即发光二极管。这个玩意儿其实就是一个具有二极管单向导通性且会发光的器件。一般来说，一个发光二极管的驱动电流在5mA以上即可。当然，高出一点也是可以的，根据一般的经验来说，发光二极管还是非常经得起&#8221;折磨&#8221;的。 </p>
<p>那7段数码管又是个啥呢？就是我们日常生活中，在电梯或者电子秤上看到的那种显示数字用的那种器件。一般来说，那7个管全部点亮时，显示的是数字8。不过这里其实有个误导，7段数码管，一般来说有8个LED，最后一个LED就是数字边上的小数点。从结构上讲，7段数码管就是7个LED拼成一个数字8的形状，再用一个LED 表示一个小数点。 </p>
<p>在实际的使用中，为了简化连线和便于使用，常把那一组LED的某个极性的引脚连在一起作为一个引脚使用。所以，7段数码管常被分为共阴和共阳两种。这两种的区别就在于，共阴极是把所有LED的阴极连在一起，而共阳极则是把所有LED的阳极连在一起。一般来说，因为M8的输出电流和输入电流的驱动力是一样的，所以我个人比较喜欢共阴极的。 </p>
<p>当然，共极连接也会带来一个问题，那就是LED控制的问题。因为是共阴，所以，当8个LED全部点亮的时候，其共阴极的电流将至少达到40mA。这对于单片机来说，如果要控制的话，是一个不小的负担。因此，在使用的时候，我们会在共阴极上用一个NPN三级管搭一个控制电路，利用小电流来控制三极管的截止和导通，起到开关的作用。一般来说这个电流不会超过1mA。 </p>
<p>5.2   LED的动态刷新法描述<br />
前面，我已经说过了，LED是硬件输出最基本的形式。但是，随之会有另一个问题产生。单片机的引脚是有限的，而一个7段数码管就要占用8个引脚。而对于一般的系统而言，一个7段数码管是不够的。就比如这次实现的数字时钟，至少要用4个7段数码管。如此一来，我们需要至少32个引脚。但是，我们使用的M8是28引脚的。怎么算也不可能用32个引脚控制啊。 </p>
<p>对于这种问题，有两种解决办法。其中比较直接的就是使用外部的寄存器，将每个脚的数值送到寄存器上锁住，然后驱动数码管。这种方式被称为&#8221;静态显示法&#8221;。这种现实方式的优点是便于控制，并且显示方面也比较稳定。缺点么自然很明朗啦，那就是成本太高了。 </p>
<p>另一种现实方式，就是我们标题所提到的，&#8221;动态刷新法&#8221;。动态刷新法的原理比较简单，就是利用人眼睛的暂留现象，快速的现实每一位的内容，就和电影的原理差不多。在器件上来说，同样是4个7段数码管，我们只要用12个引脚就够了。这种方式的优点是节约了引脚的资源，而且连线也减少了。但缺点是需要一个定时器来控制刷新。 </p>
<p>在实践中，有些人会发生利用动态刷新法时，显示的数字会闪烁，或者出现乱码的情况。其实，出现这种问题的原因，除了是程序编写方面的问题，比如刷新间隔太长，或者 7段数码显示方面的编码问题，也可能是因为刷新方式不对。在使用共阴极数码管进行动态刷新显示的时候，先要将共阴极置高位熄灭所有LED，然后将信息送到数码管的各引脚上，最后拉低共阴极的电平点亮指定的数码管。通常，采用这个刷新顺序可以保证显示的结果相对比较稳定。 </p>
<p>6   数字时钟实现概述<br />
在前面那么多篇幅的基础知识准备后，真正描写数字时钟的篇幅却是那么的少。不过，从另一方面来说，前面的内容其实都是在围绕这个数字时钟的。因此，这篇文章也不能完全的说是偏题。 </p>
<p>6.1   硬件环境的简单描述<br />
通过上面一系列的描述，硬件的链接已经不是啥秘密了。当然，唯一需要说明的是，为了保证时钟的精确性，我考虑下来准备采用外部 8MHz晶振。使用外部晶振的原因主要是因为，M8内部的振荡电路是RC振荡，因此随外界温度的变化会有所误差，当然对于这种变化幅度允许比较大的时钟来说， RC振荡也是足够了，毕竟想想我们的父辈们，利用555单稳态电路都能做时钟，那我们这个近8MHz的RC振荡电路上的一点温度系数的误差又算得了啥？但是，本着对将时钟从非洲带到北极都能让时钟比较正常工作的目标，选择一个外部晶振也是可以的。 </p>
<p>显示部分，我设计采用的是4个7段数码管进行动态刷新。而输入，则利用M8自带的两个外部中断来实现。内部的两个时钟Timer0和Timer1。因为Timer1的计数范围更广而且拥有CTC模式，因此用于秒的计数。而Timer0，则用于动态刷新的计时，因为动态刷新的定时对时间的误差要求不是很高。 </p>
<p>电路图么，其实都是一些简单的连线，也没什么特别的。如果有特别需要，或者有什么不明白的，可以留言于我。这里就不给出了。 </p>
<p>6.2   数字时钟相关的数据结构<br />
在刚开始设计这个玩意儿的时候，我想到的是记录从某一时刻开始到现在的秒数，也就是像Unix中的那个时间戳那种。但是，由于我们这里用的是单片机，虽然性能很强大，不过在频繁的高密度的16bit乘除法面前，还是会有些问题的。因此，我最后用空间换取了时间。C语言描述的数据结构如下。其中status为时钟所处的状态，即比如是显示时间还是年月等。其他的根据意义都可以理解。至于为什么year要采用16bit，是因为年的数字远大于255，现在都已经是2000年以后了。 </p>
<p>view plaincopy to clipboardprint?typedef struct {     uint8_t status;     uint8_t sec;     uint8_t min;     uint8_t hour;     uint8_t day;     uint8_t month;     uint16_t year;   } x_time_t;  typedef struct {<br />
  uint8_t status;<br />
  uint8_t sec;<br />
  uint8_t min;<br />
  uint8_t hour;<br />
  uint8_t day;<br />
  uint8_t month;<br />
  uint16_t year;<br />
} x_time_t;</p>
<p>这样，我们计时部分的代码就是简单的加法和比较跳转指令。效率远比将秒数转换成具体的时间要高，更重要的是，也方便了时钟调整功能的实现。 </p>
<p>6.3   动态刷新的代码<br />
在前面，我们已经了解了动态刷新法的刷新过程。接下来，我以动态刷新法写一段代码。其中，假设B端口连着各7段数码管的那八个引脚上。D端口的低四位接在4个数码管的共阴极控制电路上。 </p>
<p>view plaincopy to clipboardprint?#include    #include    #include      #define X_CPU_HZ 1000000   #define X_SW_FPS 36   #define X_TCNT0_SET (0xff - X_CPU_HZ / 1024 / X_SW_FPS)     #define X_LED0 0b00111111   #define X_LED1 0b00000011   #define X_LED2 0b01101101   #define X_LED3 0b01100111     uint8_t sw_list[4] __attribute__((section(&#8221;.noinit&#8221;)));     int main(void) {       TCCR0 = 0&#215;05;     TCNT0 = X_TCNT0_SET;     TIMSK |= _BV(TOIE0);       DDRB = 0xff;     PORTB = 0&#215;00;     DDRD = 0&#215;0f;     PORTD = 0&#215;00;       sw_list[0] = X_LED0;     sw_list[1] = X_LED1;     sw_list[2] = X_LED2;     sw_list[3] = X_LED3;       sei();       while(1);     return(0);     }     ISR(TIMER0_OVF_vect) {     static uint8_t c = 0;       PORTD = 0&#215;00;     PORTB = sw_list[c];     PORTD = (0&#215;01 &lt;&lt; c);     c = (c + 1) % 4;   }  #include<br />
#include<br />
#include </p>
<p>#define X_CPU_HZ 1000000<br />
#define X_SW_FPS 36<br />
#define X_TCNT0_SET (0xff - X_CPU_HZ / 1024 / X_SW_FPS)</p>
<p>#define X_LED0 0b00111111<br />
#define X_LED1 0b00000011<br />
#define X_LED2 0b01101101<br />
#define X_LED3 0b01100111</p>
<p>uint8_t sw_list[4] __attribute__((section(&#8221;.noinit&#8221;)));</p>
<p>int main(void) {</p>
<p>  TCCR0 = 0&#215;05;<br />
  TCNT0 = X_TCNT0_SET;<br />
  TIMSK |= _BV(TOIE0);</p>
<p>  DDRB = 0xff;<br />
  PORTB = 0&#215;00;<br />
  DDRD = 0&#215;0f;<br />
  PORTD = 0&#215;00;</p>
<p>  sw_list[0] = X_LED0;<br />
  sw_list[1] = X_LED1;<br />
  sw_list[2] = X_LED2;<br />
  sw_list[3] = X_LED3;</p>
<p>  sei();</p>
<p>  while(1);<br />
  return(0);</p>
<p>}</p>
<p>ISR(TIMER0_OVF_vect) {<br />
  static uint8_t c = 0;</p>
<p>  PORTD = 0&#215;00;<br />
  PORTB = sw_list[c];<br />
  PORTD = (0&#215;01 &lt;&lt; c);<br />
  c = (c + 1) % 4;<br />
}</p>
<p>6.4   计时功能的代码<br />
根据我文章开始的描述，计时功能主要依赖于那个计时模块。没秒钟执行一次计时函数，更新其中的数值。其代码如下。 </p>
<p>view plaincopy to clipboardprint?#include    #include    #include      #define X_CPU_HZ 1000000     typedef struct {     uint8_t sec;     uint8_t min;     uint8_t hour;     uint8_t day;     uint8_t month;     uint16_t year;   } x_time_t;     x_time_t g_time_s __attribute__((section(&#8221;.noinit&#8221;)));     int main(void) {          TCCR1A = 0&#215;00;     TCCR1B = 0&#215;0D;     TIMSK |= _BV(OCIE1A);     OCR1A = X_CPU_HZ / 1024;       g_time_s.sec = 0;     g_time_s.min = 0;     g_time_s.hour = 0;     g_time_s.day = 0;     g_time_s.month = 0;     g_time_s.year = 2000;       sei();       while(1);     return(0);   }     ISR(TIMER1_COMPA_vect){     uint8_t month[] = {       31,28,31,30,31,30,31,31,30,31,30,31     };     uint8_t day_fix;     day_fix = g_time_s.day == 1 &amp;&amp; g_time_s.year % 4 == 0 ? 1 : 0;       g_time_s.sec += 1;     do {       if (g_time_s.sec == 60) {         g_time_s.sec = 0;         g_time_s.min += 1;       } else break;         if (g_time_s.min == 60) {         g_time_s.min = 0;         g_time_s.hour += 1;       } else break;         if (g_time_s.hour == 24) {         g_time_s.hour = 0;         g_time_s.day += 1;       } else break;         if (g_time_s.day == (month[g_time_s.month] + day_fix)) {         g_time_s.day = 0;         g_time_s.month += 1;       } else break;         if (g_time_s.month == 12) {         g_time_s.month = 0;         g_time_s.year += 1;       }     }while(0);   }  #include<br />
#include<br />
#include </p>
<p>#define X_CPU_HZ 1000000</p>
<p>typedef struct {<br />
  uint8_t sec;<br />
  uint8_t min;<br />
  uint8_t hour;<br />
  uint8_t day;<br />
  uint8_t month;<br />
  uint16_t year;<br />
} x_time_t;</p>
<p>x_time_t g_time_s __attribute__((section(&#8221;.noinit&#8221;)));</p>
<p>int main(void) {</p>
<p>  TCCR1A = 0&#215;00;<br />
  TCCR1B = 0&#215;0D;<br />
  TIMSK |= _BV(OCIE1A);<br />
  OCR1A = X_CPU_HZ / 1024;</p>
<p>  g_time_s.sec = 0;<br />
  g_time_s.min = 0;<br />
  g_time_s.hour = 0;<br />
  g_time_s.day = 0;<br />
  g_time_s.month = 0;<br />
  g_time_s.year = 2000;</p>
<p>  sei();</p>
<p>  while(1);<br />
  return(0);<br />
}</p>
<p>ISR(TIMER1_COMPA_vect){<br />
  uint8_t month[] = {<br />
    31,28,31,30,31,30,31,31,30,31,30,31<br />
  };<br />
  uint8_t day_fix;<br />
  day_fix = g_time_s.day == 1 &amp;&amp; g_time_s.year % 4 == 0 ? 1 : 0;</p>
<p>  g_time_s.sec += 1;<br />
  do {<br />
    if (g_time_s.sec == 60) {<br />
      g_time_s.sec = 0;<br />
      g_time_s.min += 1;<br />
    } else break;</p>
<p>    if (g_time_s.min == 60) {<br />
      g_time_s.min = 0;<br />
      g_time_s.hour += 1;<br />
    } else break;</p>
<p>    if (g_time_s.hour == 24) {<br />
      g_time_s.hour = 0;<br />
      g_time_s.day += 1;<br />
    } else break;</p>
<p>    if (g_time_s.day == (month[g_time_s.month] + day_fix)) {<br />
      g_time_s.day = 0;<br />
      g_time_s.month += 1;<br />
    } else break;</p>
<p>    if (g_time_s.month == 12) {<br />
      g_time_s.month = 0;<br />
      g_time_s.year += 1;<br />
    }<br />
  }while(0);<br />
}</p>
<p>7   文外音<br />
这次的文章距上一次间隔比较长，其中有很多原因，很大原因是我个人的因素。这篇文章主要还是用于尝试写点新的内容，有不足的地方还请各位多多包涵并指出。至于为什么会开始玩玩硬件么，这个故事就说来话长了。感觉最近发生在身边的感触都能写成一本书了，我想主要是现在周遭的环境不好吧，有时候觉得，在国内，技术和人际关系，貌似人际关系会比较重要，技术则可有可无。同时我又觉得，在国内的技术现状中，真正想为社会做贡献的人才，往往会受到各种奇怪的阻挠，最后却事与愿违。感觉自己最近貌似牢骚比较多了。 </p>
<p>最后还是这句话，如果你要转载此文，请转载时注明出处，以便读者能尽快的得到回复。如果你们有任何的问题，可以到 http://blog.csdn.net/visioncat 上留下你的疑惑，我会第一时间内回答你的。如需要获取此文的PDF版，也可以留言索取。最后的最后，我要感谢各位对我一直以来的关注和支持，谢谢你们。 </p>
]]></content:encoded>
			<wfw:commentRss>http://column.ibeifeng.com/allg0/20100614357.shtml/feed</wfw:commentRss>
		</item>
		<item>
		<title>不断优化配置，逐步提高性能——我的一次性能测试经历</title>
		<link>http://column.ibeifeng.com/allg0/20100614355.shtml</link>
		<comments>http://column.ibeifeng.com/allg0/20100614355.shtml#comments</comments>
		<pubDate>Mon, 14 Jun 2010 11:46:52 +0000</pubDate>
		<dc:creator>风风</dc:creator>
		
		<category><![CDATA[其他]]></category>

		<guid isPermaLink="false">http://column.ibeifeng.com/?p=355</guid>
		<description><![CDATA[   近日，合作伙伴想要针对我们的应用服务器做一个性能测试，测试的基础是伙伴原有的一个功能庞大而结构复杂的业务系统，目的是看应用服务器是否能够满足业务系统的需要，并对应用服务器做一个总体评价。由于硬件资源有限，硬件服务器的配置为：2颗四核的志强E5520，8G内存，250G硬盘，一台普通PC Server，操作系统使用的是Windows Server 2003 SP2.

        在测试初期，客户端并发在100的时候，跑上不到1小时，服务器基本就没有反应了，此时查看应用服务器的JVM堆，都已经满满的了，而且非常平稳（几乎没有垃圾收集），貌似是客户端100并发的时候，内存都已经用尽了。但是内存一直得不到释放，想想看可能有这么几个原因：
应用系统内部存在内存泄漏，导致JVM不能及时执行垃圾回收，最终导致内存耗尽
应用系统在Session中放入太多的大对象数据，导致内存占用过高
JVM参数设置不恰当，导致JVM不能及时垃圾回收（这条是在本次测试过程中总结出来的，这也是平时最容易碰到的问题，想想之前开发时碰到的一些问题，也许跟这个关系巨大）
应用服务器存在bug
分析一下，客户描述应用是一个省级的业务系统，生产环境下最大并发数能达到1000左右，运行时也没有问题，而且业务系统已稳定运行很长时间，看样子1、2两条可能性不高。同时，查看此时的服务器资源占用情况，发现CPU（2颗4核超线程的CPU）使用率极低，一直在3%-7%之间，而其中有一个核，利用率一直在90%以上，甚至经常达到100%，而其他核心非常闲，没有任何运算在执行。此时，也没有使用过任何Java监控及管理工具，一时陷入困惑中。无意间翻看之前的一些针对应用服务器的测试报告，发现几乎所有的测试，都对Java运行的参数做了大量改动，尤其是指定了很多关于Java虚拟机的运行控制参数，在大体了解几个参数的功能以及具体的服务器情况之后，决定不妨一试。于是在Java的启动参数中加上了一些关于JVM堆栈及垃圾收集的一些参数，经过几次调整，最终使用了参数：“-XX:NewSize=500m -XX:MaxNewSize=500m -XX:NewRatio=2 -XX:SurvivorRatio=8 -XX:+UseParallelGC -XX:ParallelGCThreads=8”（关于这些参数的意义，将在以后的文章中逐渐补充，或者可以搜一下），在此次参数改动之后，系统的8个核心，在闲（没有接收大并发）的时候一直处于10%左右的使用率的情况，估计这些核心在一直不停的进行垃圾收集，而此后，再也没有出现之前发生的内存一直被占用，系统没有反应的情况。甚至并发达到300时，系统运行效率仍然很高。至此，总结出一条结论：所有的Java系统都是运行在JVM之上，JVM的性能直接影响整个系统的性能，好的JVM是好Java应用系统的基础。当你的Java应用出现性能瓶颈的时候，首先考虑优化JVM启动参数。
另外，据说为保证系统在性能测试时的效率，防止JVM进行FullGC，可以将JVM的FullGC关闭，即在启动参数中加上“-XX:+DisableExplicitGC”。
在性能测试中出现的另外一个情况是：系统反应慢，但是应用服务器所在的服务器资源占用率很低，缓慢的反应速度使测试再次陷入僵局。此时，仍然是一个意外，解开了谜题。使用应用服务器内置的数据库连接池监控工具，发现数据库连接池中存在大量等待的线程，最多时甚至到了将近200个，难道是数据库连接池不够大？于是放大连接池的容量一倍，最大连接数达到300个。在重启数据源之后，系统性能立马提升，瓶颈消失了。
由此看来，影响Java应用的性能的最常见的2个问题就是：JVM的效率以及数据库连接池。配置一个最合适的JVM就成功了一半，再加上一个合适的数据库连接池（当然也可以使用Spring等管理连接池甚至自己编写相关的数据库连接管理工具），剩下的就只有开发一个优异的应用系统了。
另外，一个好的管理监控工具也可以成为提高性能的辅助手段。JDK5.0以上的jconsole工具，已经非常直观的将JVM内存及线程信息显示出来了，基本上可以满足一般系统的需要。IBM、Oracle的Java虚拟机也提供了很多性能监控管理工具。这里再加一句，如果应用系统在运行时出现性能问题，或者出现类似内存一直占满，CPU比较闲的情况，可以使用JConsole提供的手动GC按钮，强制执行一次GC，再查看内存情况，也许这时候问题就迎刃而解了。
最后，还是要阐述一下，没有最好只有最均衡，这是原来做开发的感悟，现在看来是整个软件领域的公理。由于此次针对压力测试，会进行一些性能优先的参数配置，而实际测试过程中，由于网络或其他原因，总是导致数据库连接失效，在重新启用闲置数据库时，未进行连接有效性检查，最终导致系统全部无法获取数据库连接，并进入一个永远使用无效数据库连接的“死循环”里面。此时，综合考虑稳定性与性能，最终决定放弃一部分性能，来保证稳定性，最终，应用服务器取得了一个较好的性能与稳定性，得到客户赞同。
]]></description>
			<content:encoded><![CDATA[<p>   近日，合作伙伴想要针对我们的应用服务器做一个性能测试，测试的基础是伙伴原有的一个功能庞大而结构复杂的业务系统，目的是看应用服务器是否能够满足业务系统的需要，并对应用服务器做一个总体评价。由于硬件资源有限，硬件服务器的配置为：2颗四核的志强E5520，8G内存，250G硬盘，一台普通PC Server，操作系统使用的是Windows Server 2003 SP2.<br />
<span id="more-355"></span><br />
        在测试初期，客户端并发在100的时候，跑上不到1小时，服务器基本就没有反应了，此时查看应用服务器的JVM堆，都已经满满的了，而且非常平稳（几乎没有垃圾收集），貌似是客户端100并发的时候，内存都已经用尽了。但是内存一直得不到释放，想想看可能有这么几个原因：</p>
<p>应用系统内部存在内存泄漏，导致JVM不能及时执行垃圾回收，最终导致内存耗尽<br />
应用系统在Session中放入太多的大对象数据，导致内存占用过高<br />
JVM参数设置不恰当，导致JVM不能及时垃圾回收（这条是在本次测试过程中总结出来的，这也是平时最容易碰到的问题，想想之前开发时碰到的一些问题，也许跟这个关系巨大）<br />
应用服务器存在bug<br />
分析一下，客户描述应用是一个省级的业务系统，生产环境下最大并发数能达到1000左右，运行时也没有问题，而且业务系统已稳定运行很长时间，看样子1、2两条可能性不高。同时，查看此时的服务器资源占用情况，发现CPU（2颗4核超线程的CPU）使用率极低，一直在3%-7%之间，而其中有一个核，利用率一直在90%以上，甚至经常达到100%，而其他核心非常闲，没有任何运算在执行。此时，也没有使用过任何Java监控及管理工具，一时陷入困惑中。无意间翻看之前的一些针对应用服务器的测试报告，发现几乎所有的测试，都对Java运行的参数做了大量改动，尤其是指定了很多关于Java虚拟机的运行控制参数，在大体了解几个参数的功能以及具体的服务器情况之后，决定不妨一试。于是在Java的启动参数中加上了一些关于JVM堆栈及垃圾收集的一些参数，经过几次调整，最终使用了参数：“-XX:NewSize=500m -XX:MaxNewSize=500m -XX:NewRatio=2 -XX:SurvivorRatio=8 -XX:+UseParallelGC -XX:ParallelGCThreads=8”（关于这些参数的意义，将在以后的文章中逐渐补充，或者可以搜一下），在此次参数改动之后，系统的8个核心，在闲（没有接收大并发）的时候一直处于10%左右的使用率的情况，估计这些核心在一直不停的进行垃圾收集，而此后，再也没有出现之前发生的内存一直被占用，系统没有反应的情况。甚至并发达到300时，系统运行效率仍然很高。至此，总结出一条结论：所有的Java系统都是运行在JVM之上，JVM的性能直接影响整个系统的性能，好的JVM是好Java应用系统的基础。当你的Java应用出现性能瓶颈的时候，首先考虑优化JVM启动参数。</p>
<p>另外，据说为保证系统在性能测试时的效率，防止JVM进行FullGC，可以将JVM的FullGC关闭，即在启动参数中加上“-XX:+DisableExplicitGC”。</p>
<p>在性能测试中出现的另外一个情况是：系统反应慢，但是应用服务器所在的服务器资源占用率很低，缓慢的反应速度使测试再次陷入僵局。此时，仍然是一个意外，解开了谜题。使用应用服务器内置的数据库连接池监控工具，发现数据库连接池中存在大量等待的线程，最多时甚至到了将近200个，难道是数据库连接池不够大？于是放大连接池的容量一倍，最大连接数达到300个。在重启数据源之后，系统性能立马提升，瓶颈消失了。</p>
<p>由此看来，影响Java应用的性能的最常见的2个问题就是：JVM的效率以及数据库连接池。配置一个最合适的JVM就成功了一半，再加上一个合适的数据库连接池（当然也可以使用Spring等管理连接池甚至自己编写相关的数据库连接管理工具），剩下的就只有开发一个优异的应用系统了。</p>
<p>另外，一个好的管理监控工具也可以成为提高性能的辅助手段。JDK5.0以上的jconsole工具，已经非常直观的将JVM内存及线程信息显示出来了，基本上可以满足一般系统的需要。IBM、Oracle的Java虚拟机也提供了很多性能监控管理工具。这里再加一句，如果应用系统在运行时出现性能问题，或者出现类似内存一直占满，CPU比较闲的情况，可以使用JConsole提供的手动GC按钮，强制执行一次GC，再查看内存情况，也许这时候问题就迎刃而解了。</p>
<p>最后，还是要阐述一下，没有最好只有最均衡，这是原来做开发的感悟，现在看来是整个软件领域的公理。由于此次针对压力测试，会进行一些性能优先的参数配置，而实际测试过程中，由于网络或其他原因，总是导致数据库连接失效，在重新启用闲置数据库时，未进行连接有效性检查，最终导致系统全部无法获取数据库连接，并进入一个永远使用无效数据库连接的“死循环”里面。此时，综合考虑稳定性与性能，最终决定放弃一部分性能，来保证稳定性，最终，应用服务器取得了一个较好的性能与稳定性，得到客户赞同。</p>
]]></content:encoded>
			<wfw:commentRss>http://column.ibeifeng.com/allg0/20100614355.shtml/feed</wfw:commentRss>
		</item>
		<item>
		<title>为什么我们要从现成的游戏引擎学习开始</title>
		<link>http://column.ibeifeng.com/allg0/20100614353.shtml</link>
		<comments>http://column.ibeifeng.com/allg0/20100614353.shtml#comments</comments>
		<pubDate>Mon, 14 Jun 2010 11:46:14 +0000</pubDate>
		<dc:creator>风风</dc:creator>
		
		<category><![CDATA[其他]]></category>

		<guid isPermaLink="false">http://column.ibeifeng.com/?p=353</guid>
		<description><![CDATA[很多人问过我类似的问题，学习程序该从什么入手？怎么样开始编写一个游戏？实际上的游戏开发都是从OpenGL开始的吗？学了OpenGL后怎么开始做游戏？
    这些问题可能很难有什么标准答案，不过个人认为，在学习一门编程语言后，开始真正的做一些东西是很重要的，并且，这些东西要上一定的规模，那种玩具式的开发虽然也能学到一些东西，但是因为其过于简单，会掩盖很多随着规模变大而碰到的问题，这样也就会让你无法获得真实开发中获得的经验及教训。经验，那是作为一个程序员最为宝贵的财富。
    游戏的开发，很少有公司/个人会真的从零开始开发，得益于开源运动的努力，现在已经有很多开源的游戏引擎可以使用，从3D中最为著名的OGRE，irrlicht，2D的HGE。都是其中的佼佼者，从这些引擎的基础上开始自己的工作，会让你事半功倍，就像站在巨人的肩膀上，能看的更高，更远，更加专注于自己关心的游戏逻辑模块。诚然，假如需要真的对一款游戏引擎了解透彻，并掌握自己开发游戏引擎的技术，从零开发的经验是很重要的，但是对于大多数人来讲，即使是学习，先采取从上之下的学习方式，（即先学会使用一款引擎，然后再深入了解这个引擎的原理）也会轻松愉快很多。有了一定的对引擎的经验后，再去尝试开发自己的引擎，那会使你受益匪浅。假如一开始就做太大规模的尝试，很可能使得你有太强的挫败感，毕竟，这是游戏编写最难的部分，人都是需要先学会走路然后才学会跑的。
    另外，我选择从2D引擎Orx开始，也是出于这样的考虑，虽然事实上，也许我对Irrlicht的使用经验比对orx的使用经验还要多。

Orx介绍（http://orx-project.org/）
Orx的LOGO，有点像我们常提及的orz。。。。。
    Orx不是世界上最优秀的2D游戏引擎，也不是最流行的一个，事实上,Orx还有太多不成熟的地方，我也常常对这些地方感觉非常郁闷，由于Orx的小知名度，所以周边的模块开发，文档等也非常少，这样极大的限制了其传播，并且极大的限制了其发展。
    但是，我还是很喜欢Orx,因为它很有特点。
Orx以配置为基础
    以配置为基础，所以使得Orx非常的灵活，可以进行快速的开发，快速的实验，快速的调整，并且因为配置文件模块写的比较强大，你也很容易添加进自己的配置，这点我非常喜欢，我一直很喜欢一句话，lua之父说：只有当配置的使用足够的简单，人们才会乐于使用它。虽然此话是针对lua的，但是对于任何配置的使用都适用，Orx就有这样的特质。这也是Orx最大的特点。
    虽然在初期，对于太多配置的理解会比对于一些代码的理解更加困难，但是掌握后的好处是无穷无尽的。
Orx是跨平台的
    目前Orx直接支持的平台包含了所有流行的平台，包括了Windows,MacOS,Linux，还有IPhone,IPad。事实上，我当年就是在寻找一个合适的跨平台IPhone引擎时发现Orx的。（我前段时间的工作就是在IPhone平台上，所以比较关注）当然，即使对于IPhone平台来说，最优秀的2D引擎毋庸置疑的是Cocos2D for Iphone，Cocos2D for Iphone是我见过的支持特性最多的2D引擎，不仅仅针对IPhone平台，在所有的开源2D引擎中，它支持的特性都是堪称最多的，得益于IPhone开发的热门，其周边的工具也是非常的丰富，实际建立在Cocos2D for Iphone引擎上的游戏也是数以十计。但是，Cocos2D for IPhone是仅限Iphone平台的，并且使用的是Objective C语言开发。这是它的强项，也是其弱项。我希望有个跨平台的引擎，这样才能看到更多，并且易于协作，（在公司也是这样）在Windows下开发，然后在其他平台运行，这是很重要的，别的不说，就说Macos独霸的XCode，根本没有办法与在Windows下经历过多次残酷竞争并且胜出的Visual studio相比，再加上Visual assist和ViEmu两个插件，VS绝对是梦幻级的平台！
    并且，虽然我也可以使用Objective C来开发，但是我更加熟悉的还是C++，所以我希望使用C++来开发，这样对于我来说，效率会更加高。
    跨平台，对于很多只关注Windows平台的人来说是完全不考虑的，但是，其实，优势有太多太多。
Orx的协议非常自由
   [...]]]></description>
			<content:encoded><![CDATA[<p>很多人问过我类似的问题，学习程序该从什么入手？怎么样开始编写一个游戏？实际上的游戏开发都是从OpenGL开始的吗？学了OpenGL后怎么开始做游戏？<br />
    这些问题可能很难有什么标准答案，不过个人认为，在学习一门编程语言后，开始真正的做一些东西是很重要的，并且，这些东西要上一定的规模，那种玩具式的开发虽然也能学到一些东西，但是因为其过于简单，会掩盖很多随着规模变大而碰到的问题，这样也就会让你无法获得真实开发中获得的经验及教训。经验，那是作为一个程序员最为宝贵的财富。<br />
    游戏的开发，很少有公司/个人会真的从零开始开发，得益于开源运动的努力，现在已经有很多开源的游戏引擎可以使用，从3D中最为著名的OGRE，irrlicht，2D的HGE。都是其中的佼佼者，从这些引擎的基础上开始自己的工作，会让你事半功倍，就像站在巨人的肩膀上，能看的更高，更远，更加专注于自己关心的游戏逻辑模块。诚然，假如需要真的对一款游戏引擎了解透彻，并掌握自己开发游戏引擎的技术，从零开发的经验是很重要的，但是对于大多数人来讲，即使是学习，先采取从上之下的学习方式，（即先学会使用一款引擎，然后再深入了解这个引擎的原理）也会轻松愉快很多。有了一定的对引擎的经验后，再去尝试开发自己的引擎，那会使你受益匪浅。假如一开始就做太大规模的尝试，很可能使得你有太强的挫败感，毕竟，这是游戏编写最难的部分，人都是需要先学会走路然后才学会跑的。<br />
    另外，我选择从2D引擎Orx开始，也是出于这样的考虑，虽然事实上，也许我对Irrlicht的使用经验比对orx的使用经验还要多。<br />
<span id="more-353"></span><br />
Orx介绍（http://orx-project.org/）<br />
Orx的LOGO，有点像我们常提及的orz。。。。。</p>
<p>    Orx不是世界上最优秀的2D游戏引擎，也不是最流行的一个，事实上,Orx还有太多不成熟的地方，我也常常对这些地方感觉非常郁闷，由于Orx的小知名度，所以周边的模块开发，文档等也非常少，这样极大的限制了其传播，并且极大的限制了其发展。<br />
    但是，我还是很喜欢Orx,因为它很有特点。</p>
<p>Orx以配置为基础<br />
    以配置为基础，所以使得Orx非常的灵活，可以进行快速的开发，快速的实验，快速的调整，并且因为配置文件模块写的比较强大，你也很容易添加进自己的配置，这点我非常喜欢，我一直很喜欢一句话，lua之父说：只有当配置的使用足够的简单，人们才会乐于使用它。虽然此话是针对lua的，但是对于任何配置的使用都适用，Orx就有这样的特质。这也是Orx最大的特点。<br />
    虽然在初期，对于太多配置的理解会比对于一些代码的理解更加困难，但是掌握后的好处是无穷无尽的。</p>
<p>Orx是跨平台的<br />
    目前Orx直接支持的平台包含了所有流行的平台，包括了Windows,MacOS,Linux，还有IPhone,IPad。事实上，我当年就是在寻找一个合适的跨平台IPhone引擎时发现Orx的。（我前段时间的工作就是在IPhone平台上，所以比较关注）当然，即使对于IPhone平台来说，最优秀的2D引擎毋庸置疑的是Cocos2D for Iphone，Cocos2D for Iphone是我见过的支持特性最多的2D引擎，不仅仅针对IPhone平台，在所有的开源2D引擎中，它支持的特性都是堪称最多的，得益于IPhone开发的热门，其周边的工具也是非常的丰富，实际建立在Cocos2D for Iphone引擎上的游戏也是数以十计。但是，Cocos2D for IPhone是仅限Iphone平台的，并且使用的是Objective C语言开发。这是它的强项，也是其弱项。我希望有个跨平台的引擎，这样才能看到更多，并且易于协作，（在公司也是这样）在Windows下开发，然后在其他平台运行，这是很重要的，别的不说，就说Macos独霸的XCode，根本没有办法与在Windows下经历过多次残酷竞争并且胜出的Visual studio相比，再加上Visual assist和ViEmu两个插件，VS绝对是梦幻级的平台！<br />
    并且，虽然我也可以使用Objective C来开发，但是我更加熟悉的还是C++，所以我希望使用C++来开发，这样对于我来说，效率会更加高。<br />
    跨平台，对于很多只关注Windows平台的人来说是完全不考虑的，但是，其实，优势有太多太多。</p>
<p>Orx的协议非常自由<br />
    在外企的工作经验使我对协议非常敏感，不再像在国内企业时那样，只要是世界上最强大的，拿来就用，Orx的新版本（1.2)会使用Zlib协议，这是一个非常非常自由的协议，支持进行商业闭源的开发，并且也完全可以对Orx进行任何的闭源的修改。</p>
<p>Orx支持的特性比较多<br />
    Orx不是最强大的，但是支持的特性已经足够多了，可以很方便的做一些简单的游戏，其内嵌物理引擎Box2D，内嵌声音引擎，有很多有用的图形特效，比如缩放，翻转，移动，alpha值变化等，事实也提供了对addcolor和普通透明混合效果的支持。</p>
<p>Orx使用较为简单<br />
    Orx的使用很简单，不仅仅其以配置为基础（事实上我感觉这点在初期还比较麻烦），Orx的作者对Orx的定位是一款完整的游戏引擎，而不仅仅是一个图形引擎，在Orx中所有的东西都抽象成了Object，拥有统一的接口，并且可以方便的通过配置/代码来更改属性及效果。并且最最重要的是，Orx对于物理引擎的支持不是简单的外挂（如Cocos2D for Iphone)，而是内嵌，直接将Box2D与其Object绑定在一起，可以直接通过配置的设置，不用知道任何Box2D的东西，就能直接使用物理引擎。当然，事实上，知道其相关的物理概念还是很重要的，不然怎么知道配置什么啊？但是起码可以不使用任何Box2D的API。（目前仅提供一些基础的支持，不支持Joint这样稍微复杂一点的特性）目前个人使用感觉是，用Orx做物理相关的东西，那是非常的简单。但是，由于Orx对于图形动画的支持较弱，而且也没有一款动画编辑器支持，所以用来做复杂的动画（其实即使是简单的动画）会比较麻烦，需要非常多的手动配置。我正考虑为Orx做一款以Json为基础的动画编辑器以简化此过程。</p>
<p>Orx的开发者有丰富的经验，并且极为热心<br />
    我在Orx的论坛上，以及私下与Orx的开发者（目前Orx核心主要由iarwain开发）有很多的交流，他有着15年以上的程序编写经验，10年以上的游戏开发经验，并且一直是从事底层开发，现在任职于Ubisoft的加拿大蒙特利尔工作室，他的工作经验，使得Orx有着坚实的基础，良好的架构，特别值得一提的是其编码风格，注释详尽到几乎每行都有，我曾经询问过这个问题，因为通常来讲，推荐的注释的作用为解释代码的运行原理和作用（即Why？How？），而不是具体干了什么(what)，但是他认为，整个代码他就是分为两部分，一部分为逻辑，一部分为实现，逻辑由注释描述，实现由代码描述，方便他在不看代码的情况下就能方便的了解逻辑，进行全面的了解或者深入的调试。并且其提出，在他那里，有很多编程经验丰富的人尝试用这种风格来编码，从来没有人说这种风格不好的，最后都坚持使用了这种风格。当然，这仅是一家之言，他的个人看法，但是对比现在我工作中的几乎没有注释的代码，我还是感受良多。<br />
    他经验丰富，最难得的是他非常热心，在论坛中，他知无不答，答无不尽，纠正了很多我对游戏开发的一些不对看法，也解释了很多Orx的设计，运行原理和思想，我受益良多。在私下的用steam的交流中，他也是给了我很多提示和解答，对我的帮助非常多。</p>
<p>最后<br />
    推荐有兴趣的人都去其网站看看，并了解了解，希望你也能像我一样喜欢上Orx,网址是http://orx-project.org/，在WIKI上有两个教程 ，讲的还算比较详细，但是也有很多我认为遗漏的地方，API Doc 得益于iarwain的详尽注释风格，非常详细。事实上，我准备按照我的学习经验，自己组织一系列关于Orx的教程，并且，以开发一款完整的游戏为脉络，而不是以特性介绍为原则。会以Windows为平时的开发平台。</p>
]]></content:encoded>
			<wfw:commentRss>http://column.ibeifeng.com/allg0/20100614353.shtml/feed</wfw:commentRss>
		</item>
	</channel>
</rss>
