<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_玄歌</title><subtitle type="text">唯快不破!</subtitle><id>http://feed.cnblogs.com/blog/u/67833/rss</id><updated>2012-05-18T02:48:57Z</updated><author><name>玄歌</name><uri>http://www.cnblogs.com/by1990/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/by1990/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/67833/rss"/><entry><id>http://www.cnblogs.com/by1990/archive/2011/12/12/2284653.html</id><title type="text">一个月学会VC++2010 5.对话框的数据交换</title><summary type="text">对于正常的应用项目开发来说，入门显然有两块比较重要的：如何方便的设计界面，业务对象如果与界面交互数据。只有解决这两个问题，你才能真正开始动手。很显然，完全动态的用代码来一个个的在View中写控件这种方式，明显的属于高手范畴，很多人号称完全用记事本就能写程序。不过，从工业角度来说，这种炫耀的方式，显然是很奇怪的，为什么不能用最简单的办法？ VC里我们唯一能够看到的可视化设计器，是对话框设计器。老...</summary><published>2011-12-12T04:11:00Z</published><updated>2011-12-12T04:11:00Z</updated><author><name>玄歌</name><uri>http://www.cnblogs.com/by1990/</uri></author><link rel="alternate" href="http://www.cnblogs.com/by1990/archive/2011/12/12/2284653.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/by1990/archive/2011/12/12/2284653.html"/><content type="html">&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 对于正常的应用项目开发来说，入门显然有两块比较重要的：如何方便的设计界面，业务对象如果与界面交互数据。只有解决这两个问题，你才能真正开始动手。很显然，完全动态的用代码来一个个的在View中写控件这种方式，明显的属于高手范畴，很多人号称完全用记事本就能写程序。不过，从工业角度来说，这种炫耀的方式，显然是很奇怪的，为什么不能用最简单的办法？&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp; VC里我们唯一能够看到的可视化设计器，是对话框设计器。老实说，Ribbon设计器仿佛也不错，但你总不可能将所有界面都放到Ribbon工具栏里吧？虽然这并不是不可行的，你可以想象一下，整个应用就由Ribbon工具栏组成----微软曾经有例子在Ribbon工具栏实现一个计算器，作为一个反面的例子，来说明“不能这样使用Ribbon”，因为整体看起来确实会显得太奇怪。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp; 所以对每一项主要的功能，对话框还是无法绕过的，我目前所知，用于操纵对话框的类，包括：CDialogEx，CFormView，CMFCPropertyPage几种，最直观的当然是对话框类。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp; 所以这一节我们讲解对话框的数据交换:我们怎样在对话框类中创建我们的对象与实际的对话框控件联系起来，从而获取对话框控件的值或者为对话框控件设置相应的值。只有两种方法，一种是DDX数据交换机制，一种是GetDlgItem方式。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 前者实际上是建立一个数据交换机制，当你执行UpDateDate()的时候，所有控件都使用当前用户的输入，更新你绑定的变量。而执行UpdateData(false)的时候，则反过来，你所有绑定的变量值都将传递给控件。这里“正反”记忆的方式：updateData的意思是控件更新你的数据，这是其基本功能，带false参数自然是反向操作。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 后者，则是直接获取或者设置某个对话框控件的值，这个需要带控件的ID参数。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 如何选择呢？实际上，DDX机制我们多可以通过类向导简便的完成，不需要考虑太多，只要记得及时或者需要的时候UpdateData就行了，我们当然选择这种方式，另一种方式我们就无需理会了，节约脑力。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 那么我们考虑先看看导入日线对话框的外观：&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/by1990/201112/201112121210367237.jpg"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="更新日线对话框" border="0" alt="更新日线对话框" src="http://images.cnblogs.com/cnblogs_com/by1990/201112/201112121210375732.jpg" width="587" height="475"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;用户在编辑浏览控件中，选中文件，那么我们需要一个变量绑定这个控件的值。选中这个控件，右键，添加变量，会出现下面的选项窗体：&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/by1990/201112/201112121210396454.jpg"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="添加变量" border="0" alt="添加变量" src="http://images.cnblogs.com/cnblogs_com/by1990/201112/20111212121041763.jpg" width="619" height="521"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;请注意“类别”有“Value”和”Control”两种选择，前者表示我们只关心这个控件的值，无论是字符串或其他类型，此刻是一个CString对象；后者则是要求替我们创建一个完整的对象，对应这个控件，将是一个CMfcEditBrow的实例。同时也注意生成的变量名称命名风格，成员以m_开始。&lt;/p&gt; &lt;p&gt;完成之后，看看代码有什么变化：&lt;/p&gt; &lt;p&gt;1、首先，头文件中对话框类增加了一个成员：&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp; CString m_FilePath;&lt;/p&gt; &lt;p&gt;2、其次，源文件中，构造方法对这个成员初始化&lt;/p&gt; &lt;p&gt;&lt;br&gt;CQuoteDialog::CQuoteDialog(CWnd* pParent /*=NULL*/)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; : CDialogEx(CQuoteDialog::IDD, pParent)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , m_FilePath(_T(""))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , m_Info(_T(""))&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , m_lastday(_T(""))&lt;br&gt;{&lt;/p&gt; &lt;p&gt;}&lt;/p&gt; &lt;p&gt;3、源文件中，在DoDataExchange里面自动添加了相应的映射，这个方法显然是在UpdateDate时会运行的。&lt;/p&gt; &lt;p&gt;void CQuoteDialog::DoDataExchange(CDataExchange* pDX)&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CDialogEx::DoDataExchange(pDX);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DDX_Text(pDX, IDC_MFCEDITBROWSE_QUOTE, m_FilePath);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DDX_Text(pDX, IDC_STATIC_INFO, m_Info);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DDX_Control(pDX, IDC_PROGRESS_QUOTE, ProgressBar);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DDX_Text(pDX, IDC_STATIC_LASTDAY, m_lastday);&lt;br&gt;}&lt;/p&gt; &lt;p&gt;当然，不需要我们做其他的事情，我们仅仅需要理解这些简单的操作，一个变量的值和我们对话框类的一个成员就绑定起来，不过需要你手工使用UpdateData来双向的交换。对于这些代码的阅读，我们仍然和针对消息映射的处理一样，仅从字面上理解：&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DDX_Text：在控件和这个成员变量，交换值。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DDX_Control：完整的复制控件内容和到相应的控件对象。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 很明显，这样的方法都包括控件ID和类成员两个参数，事实上是建立双方的映射关系。不要继续探究，那样很费脑力且对你的工作、思考、理解帮助不大。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;那么我们看看怎样使用这个变量&lt;/p&gt; &lt;p&gt;1、获取：任何时候，我们只要下面两行语句就可以获取最新的值：&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; UpdateDate()&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 然后使用m_FilePath&lt;/p&gt; &lt;p&gt;2、设置：&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_FilePath=“C:\sample.dad”;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; UpdateData(false);&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;这样，我们在使用对话框编程的时候，最基本的问题就解决了：这是一种老式的、手工的、简单的数据绑定方式，但它能够正常工作。&lt;/p&gt; &lt;p&gt;我们小结一下，在界面开发模式方面，最终的选择：&lt;/p&gt; &lt;p&gt;1、我们使用单文档结构创建项目。&lt;/p&gt; &lt;p&gt;2、我们使用Ribbon在各项功能间导航&lt;/p&gt; &lt;p&gt;3、我们让视图类、文档类无事可做，通过在视图中切换显示子对话框，来实现不同功能的界面切换，所有界面开发基于对话框。&lt;/p&gt; &lt;p&gt;4、在资源视图中设计对话框，实际上是保留了对话框的位置、大小、颜色等信息，其中包括的各个控件，以及这些控件的属性，和代码无关，是纯粹的数据文件。&lt;/p&gt; &lt;p&gt;5、由于对话框的布局方式比较原始，因此我们默认让多数对话框居中显示，少数需要适应主窗口大小的对话框，使用EasySize解决。&lt;/p&gt; &lt;p&gt;6、我们使用DDX数据交换机制，绑定类成员和实际的控件。&lt;/p&gt; &lt;p&gt;这种模式，已经能做出比较专业的界面，同时也最充分的利用了VS提供的各类工具，比如Ribbon设计器、对话框设计器、类向导。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;另外，遇到一些简单的问题，没有必要“冰天雪地裸体旋转三百六十度跪求各位大大”，或者扮作娘们“小女子有个弱弱的问题有请各位大哥……”，稍稍动点脑筋，在MSDN里基本上都能解决：&lt;/p&gt; &lt;p&gt;1、VC的示例：&lt;/p&gt; &lt;p&gt;&lt;a title="http://archive.msdn.microsoft.com/vcsamplesmfc" href="http://archive.msdn.microsoft.com/vcsamplesmfc"&gt;http://archive.msdn.microsoft.com/vcsamplesmfc&lt;/a&gt;&lt;/p&gt; &lt;p&gt;2、VC帮助：&lt;/p&gt; &lt;p&gt;&lt;a title="http://msdn.microsoft.com/library/60k1461a(VS.100).aspx" href="http://msdn.microsoft.com/library/60k1461a(VS.100).aspx"&gt;http://msdn.microsoft.com/library/60k1461a(VS.100).aspx&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/by1990/aggbug/2284653.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/by1990/archive/2011/12/12/2284653.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/by1990/archive/2011/12/08/2280611.html</id><title type="text">一个月学会VC++2010 4.细说对象之香艳旖旎</title><summary type="text">作为程序员，我们其实生活在一个荒诞的空间。每次看到白发苍苍的教授，很认真很庄重的说：“面向对象灰常灰常重要”的时候，我都完全忍不住要笑出来。我们用所有的词，第一个反映怕是从字面上来理解。对象，准备结婚的异性，面，你的脸，向，朝着她。你的脸朝着异性，接下来会发生什么，外交部曰：“那是他们的内政，各国无权干涉”。教授究竟在教我们什么？ 所以在这个众牛奔腾的圈子里，好象每个人都生活在这样香艳的语境中。随随便便拉头牛过来，他估计能够告诉你面向对象是多么的重要、多么的牛，你不会面向对象你都不好意思摸着键盘。你要问他什么是面向对象，他会告诉你：“嗯，不是写个类就完了，这是一种思想，一种……”，然后还是归.</summary><published>2011-12-08T05:23:00Z</published><updated>2011-12-08T05:23:00Z</updated><author><name>玄歌</name><uri>http://www.cnblogs.com/by1990/</uri></author><link rel="alternate" href="http://www.cnblogs.com/by1990/archive/2011/12/08/2280611.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/by1990/archive/2011/12/08/2280611.html"/><content type="html">&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 作为程序员，我们其实生活在一个荒诞的空间。每次看到白发苍苍的教授，很认真很庄重的说：&amp;ldquo;面向对象灰常灰常重要&amp;rdquo;的时候，我都完全忍不住要笑出来。我们用所有的词，第一个反映怕是从字面上来理解。对象，准备结婚的异性，面，你的脸，向，朝着她。你的脸朝着异性，接下来会发生什么，外交部曰：&amp;ldquo;那是他们的内政，各国无权干涉&amp;rdquo;。教授究竟在教我们什么？&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 所以在这个众牛奔腾的圈子里，好象每个人都生活在这样香艳的语境中。随随便便拉头牛过来，他估计能够告诉你面向对象是多么的重要、多么的牛，你不会面向对象你都不好意思摸着键盘。你要问他什么是面向对象，他会告诉你：&amp;ldquo;嗯，不是写个类就完了，这是一种思想，一种&amp;hellip;&amp;hellip;&amp;rdquo;，然后还是归于那三个指头、五个字，&amp;ldquo;博大精深&amp;rdquo;。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 台湾对object的翻译有些不同，相对来说更合理一些：&amp;ldquo;物件&amp;rdquo;，面向对象被翻译成&amp;ldquo;物件导向&amp;rdquo;。世易时移，这两片土地的语言都在渐渐分化，作为反面角色的我们，早已经成为文化的沙漠和马某人的余孽。那是题外话，说正题。如果用今天的汉语，准确的翻译，我猜测只有一个词：&amp;ldquo;东西&amp;rdquo;，&amp;ldquo;面向对象&amp;rdquo;不妨翻译成&amp;ldquo;站在东西的角度&amp;rdquo;。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 汉语原本是比较模糊的语言，生造一些词汇，或者给一些词汇赋予完全不一样的含义，这是最糟糕的情形。之所以最糟糕，因为我一向所强调的&amp;ldquo;简单&amp;rdquo;，首当其冲的就是&amp;ldquo;理解的简单&amp;rdquo;。站在东西的角度，这个小学生都能够理解，而面向对象，其他专业的博士生都无法理解。之所以会出现这类翻译，是因为语言和技术都精通，而且具备专业翻译技巧的人，几乎没有。最明显的例子，大家可以看看微软的Team Fundation Server，里面的ms agile模版，其中优先级，翻译成&amp;ldquo;堆栈级别&amp;rdquo;；然后&amp;ldquo;产品积压工作&amp;rdquo;、&amp;ldquo;用户情景&amp;rdquo;、&amp;ldquo;迭代&amp;rdquo;、&amp;ldquo;情景点&amp;rdquo;，看看，哪里象是正常人说的话？&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 面向对象，也令我想起一句广为流传的小资名言：&amp;ldquo;面朝大海，春暖花开&amp;rdquo;。当然你略微动动脑子，这实际是个病句。面朝大海的时候，你看到的往往是一片蓝色，如果你的身体这时候感觉到温暖，倒也正常，同一瞬间你的思维居然意识到是在春天，这就是不专心了----比较恐怖的是，你的眼睛居然在海面上发现了鲜花正在开放，唉，一段时间好象不说这句话都算是没素质，所以断章取义是不行的，这是海子的一首很平常的诗，这句话前面还有一句是&amp;ldquo;我有一所房子&amp;rdquo;，当然，是这房子面朝大海，是这房子春暖花开。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 然后第一句是：&amp;ldquo;从明天起，做一个幸福的人&amp;rdquo;，两个月之后，诗人卧轨自杀，成就了杯具般的凄美。我一直不太敢说：&amp;ldquo;从明天起&amp;rdquo;如何如何，也知道幸福的人不是你想做就能做的。必须给自己保证，做一个活人，哪怕是垃圾般生存，这个比幸福重要。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 我们可以回忆一下，所有教科书，都将&amp;ldquo;面向对象&amp;rdquo;概念和如何用面向对象的方式设计割裂开来，讲概念通常是一章的内容，特别精细的还分成多章，将封装、继承、多态拿出来逐一讲解。通过漫长的岁月之后，恐怕很多人还是不理解，为什么？黑板、讲解、瞌睡的三部曲而已讲解面向对象的概念，仿佛是入门的东西，讲解面向对象的思考方法，则是需求分析、设计模式等等看起来高端的范畴。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 其实，还是那句话，哪里有那么复杂？我国专业人士，基本上个个都是老中医，仿佛不磨你几十年你就能够做好事情，那就谈不上博大精深。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 我们就拿他们常见的场景，用我们的语言来剖析一下。假设我们要做一个模拟的生物世界游戏，有树、草、花、苹果树，有鸟、有鱼、也有狗狗和牛牛。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 那么我们看到了什么？就是这些&amp;ldquo;东西&amp;rdquo;，嗯，他们说的对象：树、草、鸟、鱼等等。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 他们说的继承是什么？这些东西是有分类的，分类是通过相同的特性、相同的行为来划定的。分类的原因是什么？不要重复。这里首先是生物类，哪些特性？生或者死、寿命。哪些行为，比如&amp;ldquo;生长&amp;rdquo;。然后动物和植物类，可以继承自生物类，而树可以继承自植物类，鱼可以继承自动物类。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这样，共同的特性和行为，往往不需要每个类都要重复编写。看清了吗？实际上来源于一种树形分类的方式，目的是令相同的代码不要重复编写，是一种提高效率的手段。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 类对对象的区别：我们用一类东西和一群东西来表达，比如一种叫做鱼的动物，我们用class 鱼{}来定义，实际上是抽象所有鱼的特性和行为。游戏中要呈现三头鱼，两条鱼合作生下了很多鱼籽，然后又产生很多小鱼，那就是一群鱼，什么意思的：&amp;ldquo;创建了具体的鱼&amp;rdquo;，这就是所谓的实例化，常常有人鼻孔朝天的说：&amp;ldquo;你知道对象和类的区别吗？&amp;rdquo;，就象说：&amp;ldquo;你知道VC和C++的区别吗？&amp;rdquo;一样，其实是普通初中生都能够轻易理解的东西。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 再说说封装：如果我们着手写这个游戏，早期的方法，显然是写一大堆的函数，会有&amp;ldquo;鱼游动&amp;rdquo;、&amp;ldquo;狗跑动&amp;rdquo;，然后一大堆数组，描述存在多个各种类型的动物、植物。这时候程序员象上帝一样，每一个细节都由他的代码所控制----这意味着他独自面对复杂的世界，编程是不是很麻烦？现在，我们将这些东西找出来，对于鱼、狗狗，他们的特性和行为都看成是一类东西，也就是类。一个名字：狗狗；一堆特性、一堆行为，这样我们的代码，就将和狗狗相关的一切包裹在一起。程序员就能站在更高层面思考问题：比如他可以先不实现这些类，这个场景需要N只狗狗、两头牛牛，创建相应数量的实例就行了，他们的移动、生长、繁殖不需要在这个层面考虑。&lt;/p&gt;&lt;p&gt;所以封装首先是一种良好的代码组织方式，能够简化复杂性、有利于团队合作：比如游戏中鱼居然飞起来了，去找写鱼这个东西的程序员；狗狗竟然不会动了，去找写狗狗的程序员；牛居然只有3厘米高，嗯，去找博客园的牛牛们。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 至于多态，则是一种弥补方式，树形分类的思维，也就是划分层次的思维，虽然效能要高过线性思维，但也存在问题：比如动物有&amp;ldquo;移动&amp;rdquo;的行为，但鸟在飞、牛在爬、狗在跳，行为的方式不同。那么，我们只约定动物这&amp;ldquo;类&amp;rdquo;东西有个虚方法&amp;ldquo;移动&amp;rdquo;，让它从一个点到另一个点，而鸟可以重写这个需方法，可以既保持动物类在不同点之间的移动过程，又增加自己移动的姿态，方便界面上呈现出来。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 大体上就这么些内容，面对任何问题，找出里面所有的东西，归纳这些东西具备的共同特征和行为，在抽象的层面寻求继承、多态从而从整体上减少代码量的可能。这就是面向对象的思考方法和实际的编程方法。东西不一定是业务上的，比如&amp;ldquo;线程&amp;rdquo;也是一种东西，操作系统范畴的。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 那么针对导入日线文件这项功能，我们站在东西的角度，怎样做？&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 首先，我们知道要做什么：用户从其它行情软件下载日线数据；用户选择这些日线数据；系统识别这些日线数据；系统将这些日线数据保存在自己的数据库中。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这是主要的流程。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 另外：因为存在对这些日线数据进行预处理的工作，用户要求只能增加系统中最新交易日之后的数据，这就存在着当某日没有；因为数据量大，导入过程等待的时间比较长，而且界面僵死不能做其他事情，因此需要随时告知导入进度，同时使用后台线程导入。因为用户选择文件很可能有误操作选中了不是我们采纳格式的文件，因此需要有文件格式的合法性检查。因为用户对行情数据的利用有大量查询要求，因此要建立相应的索引以突出查询性能，但这与导入性能冲突，因此要做好权衡，并比较禁止索引--导入--重建索引和直接导入之间的性能差异。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 那么上面就是这项功能的主要描述，请注意我称它为&amp;ldquo;功能&amp;rdquo;，这是人话，不是&amp;ldquo;用例&amp;rdquo;、&amp;ldquo;用户场景&amp;rdquo;、&amp;ldquo;故事&amp;rdquo;。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 我们首先看看，这里面有哪些类型的东西？&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 纯业务角度：用户、其他行情软件、行情文件、日线、数据库。其中没有对用户和其他行情软件的要求。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 非业务角度：线程。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 因此我们将用三个类来体现业务因素：日线类Quote，表达一只股票一天的日线，行情文件类QuoteFile，识别行情文件格式、转换成日线的集合，数据库类QuoteDB，对应数据库的日线表格。至于非业务对象，线程，则编程语言已经提供了足够的支持。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 其他如对话框、界面设计是另一个范畴的东西，当然，你看到的仍然是一系列非业务类型的类和对象。有时候我觉得又好气又好笑，不知怎么，那么多人觉得MFC是怎样的复杂、不花费几十年读它的源代码则不足以平民愤，那就是菜鸟、那就不能做500万行代码的程序。我真无法想象500万行的VC程序是干什么的，但是，站在所谓面向对象的立场，微软这个MFC不就是已经设计好的一串类吗，它们组合起来帮助你完成日常的界面呈现、互动工作。你一定要阅读其源代码，那就是不尊重微软封装的能力、质疑微软做的产品的可用性和简单性了。相对来说：你简直是在说MFC是一群菜鸟玩出来的，连最起码的封装都显得滥竽充数。在团队中，你会仔细阅读其他同事写好的类吗？对MFC，你也可以理解成其他同事写好的类，而且是文档非常丰富的、远超出我们那种应付方式的类库，还是克制一下探究细节的冲动吧。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 在你开始编程之前，这些东西大约需要一个小时甚至更短的时间就能弄清楚，忽略这个步骤往往会造成整编程过程的杂乱无章，站在东西的角度，也就是面向对象的思维方式之所以重要的原因。 这一节的主题是&amp;ldquo;谁说对象不是东西？&amp;rdquo;，起因是有牛认为多数程序员缺乏面向对象思维、算法和数据结构的知识，我不太认同。事实上，实际的编程过程中，抽象类甚至接口、继承这些出现的机率是非常小的，多数的时候大家接触最多的不过是封装特性。而算法和数据结构固然重要，但也仅仅是理解的问题，只有极少数的场景需要相应的基础---而这些东西，学院里的却未必够用，多数情形下我们的程序员接触的还是应用开发。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 所以我明确的反对将这三样东西提到过分的高度，生存逼迫你编程，兴趣才能让你成长。我们还在求生的过程中......&lt;/p&gt;&lt;img src="http://www.cnblogs.com/by1990/aggbug/2280611.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/by1990/archive/2011/12/08/2280611.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/by1990/archive/2011/12/06/2277463.html</id><title type="text">一个月学会VC++2010 3.我们动手吧!</title><summary type="text">中国的文人，有个根深蒂固的传统：皓首穷经。 从三百千千，到四书五经，到诸子百家，诗词歌赋，琴棋书画，每个学子往往要经历漫长的十几年甚至三十年。所谓十年寒窗无人问，一朝成名天下知，是所有文人的潜藏情节。所以，有老实人说出了老实话：百无一用是书生。我一直觉得他们仿佛在学东方不败大侠，先对自己狠心点，然后闭门苦练，最后终于明白了万物滋生的大道，乃至所向无敌。 作为普通人，我们还是尽早动手为好。 第一项任务很简单，精确点描述是这样的：创建一个应用程序，使用两个Ribbon按钮，在两个窗体中切换。 是啊，用户做的第一件事情，就是找到功能，然后进入相应的界面，菜单、工具栏还有Vc++2010提供的Rib.</summary><published>2011-12-06T00:42:00Z</published><updated>2011-12-06T00:42:00Z</updated><author><name>玄歌</name><uri>http://www.cnblogs.com/by1990/</uri></author><link rel="alternate" href="http://www.cnblogs.com/by1990/archive/2011/12/06/2277463.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/by1990/archive/2011/12/06/2277463.html"/><content type="html">&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 中国的文人，有个根深蒂固的传统：皓首穷经。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 从三百千千，到四书五经，到诸子百家，诗词歌赋，琴棋书画，每个学子往往要经历漫长的十几年甚至三十年。所谓十年寒窗无人问，一朝成名天下知，是所有文人的潜藏情节。所以，有老实人说出了老实话：百无一用是书生。我一直觉得他们仿佛在学东方不败大侠，先对自己狠心点，然后闭门苦练，最后终于明白了万物滋生的大道，乃至所向无敌。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 作为普通人，我们还是尽早动手为好。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 第一项任务很简单，精确点描述是这样的：创建一个应用程序，使用两个Ribbon按钮，在两个窗体中切换。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 是啊，用户做的第一件事情，就是找到功能，然后进入相应的界面，菜单、工具栏还有Vc++2010提供的Ribbon功能区方式，无论怎样，这都是首先要掌握的内容。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 站在程序员的角度，你最经常遇见的可能是哪些场景呢？界面、读写文件、读写数据库、设计业务类，就这些，做得专业点，号称程序员就顺理成章了。我觉得各种知识的讲解很多，但如何在实际工作中，做到像模象样，好象没有多少这样的资料。因此，这个系列讲解的虽然只是一项不太复杂的功能，但会尽量的讲透，涉及到界面、性能、异常、用户体验诸方面。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 因为是首次接触VC，那么我给自己定下的规矩很明确：学习阶段，绝不考虑重用性问题、绝不考虑扩展性问题、绝不考虑代码风格问题，尽量在第一时间将功能稳定的实现。在不熟悉语言的时候，你七七八八太多，那简直是在虐待自己的大脑。语言熟悉后这些东西你有精力再去玩，现在，还是老实点好。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 那么，我们首先面临的问题是使用传统的菜单、工具栏形式，还是使用Ribbon界面。这种选择对于我来说，不是什么问题，喜新厌旧据说是男人的本能，嗯，照照镜子，我发现里面是一张男人胡子拉碴的脸。然后呢？我遇到的第一个问题，是文档视图结构。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这是一种延续了几十年的模式，换句话说，是一种古老的模式。大家看看记事本就知道了，处理一种后缀名为TXT的文件，打开、关闭、保存文件，将文件后缀在操作系统注册到记事本，简单的说，就是你创建的这种应用，将针对某种专用的格式，相关的一些处理工作，由文档视图结构预先的帮你做好，很贴心，是不是？&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 所谓文档视图结构，马上动手，用项目向导创建一个简单的单文档、单视图结构的应用，可以看到VS帮我们创建的一些代码，嗯，四个类：一个应用程序类，是整个系统的入口，然后创建MainFrame实例、后者将管理文档类和视图类。文档类负责处理对这种格式的文档的各类操作，视图类负责呈现、编辑这种格式的文档。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 但是，两个问题：首先，我们现在已经很少敢于制定自己专有的文件格式，比如各类视频格式，都是几家恐怖的巨头在发布标准然后互相撕咬。一个可怜的程序员竟然做这种不合身份的事情，实在令人齿冷。其次，相对于专有格式而言，我们做桌面应用普遍还是以数据库应用居多。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 所以我的想法很简单，文档类基本不用，放个空壳在哪里。视图类呢？首先我想找寻类似Wpf的窗体设计器，视图能不能直接的&amp;ldquo;画界面&amp;rdquo;？很沮丧，不能，我只找到了对话框设计器。接下来，我们知道，若视图继承于CFormView，则可以使用对话框设计器来设计界面。 但这样我们需要做多视图项目，&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 为了利用对话框的界面设计能力、同时保持整个程序的简单，浮现在我脑子里的，是一种古怪的想法：对话框有一种&amp;ldquo;子对话框&amp;rdquo;风格，我们在视图中直接打开这个对话框，则看起来是无缝集成的，我们就能自如的在两个对话框之间切换了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 嗯，有熟悉的程序员马上要问了：不是有基于对话框的应用程序向导吗？两个问题：首先我们希望的是处理多个窗体，但不要弹出，这个是木有办法的；其次，更重要的是，这时候你不能在应用程序向导中选择Ribbon方式，也许有&amp;ldquo;在对话框应用中使用Ribbon&amp;ldquo;之类的深入研究，但我确实很懒惰，不太愿意在这类事情上消耗时间。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 接下来，我按照工作的步骤，简单的描述完成这项任务的过程。需要说明的是，这个系列的帖子是休闲贴，我不会一边做一边截图一边写，时间和精力不允许，所以很难做到step by step的方式，仅仅是列出步骤和基本的知识点，当然也包括初学者肯定会闹出的笑话。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;1、创建项目：创建一个MFC应用，在配置向导中，注意勾上&amp;ldquo;功能区方式&amp;rdquo;，提供文档视图支持，单文档模式，其他无所谓。项目创建完毕后，运行一下。&lt;/p&gt;&lt;p&gt;2、简单的阅读一下生成的代码，次序是App类-&amp;gt;MainFrame类-&amp;gt;Document类-&amp;gt;View类。不要深究，比如View中那堆很混乱的宏，只要从字面理解就行了：定义消息循环，不需要学究到一定要弄懂这堆宏究竟会转换成怎样的代码。读代码的方法，嘿嘿，这是秘籍：看看类结构，揣摩一下方法的名字，然后不要太关注每个函数内部的代码，会很快的。需要注意的问题，是我们经常见到的项目按文件夹组织的方式，这里没有，VC项目中叫做筛选器，仅仅将同一个目录下的文件分类，并不改变文件的物理位置。&lt;/p&gt;&lt;p&gt;3、我们将创建两个对话框，注意：style设为child，去掉确定和取消按钮，不要边框。仅仅放上一个静态文本字段，分别是&amp;ldquo;第一个&amp;rdquo;和&amp;ldquo;第二个&amp;rdquo;。&lt;/p&gt;&lt;p&gt;4、我们要为两个对话框创建类，这个不要傻乎乎的自己写代码：右键，为对话框生成类，就行了。为什么要有这个步骤？对话框以&amp;ldquo;资源&amp;rdquo;形式保存，仅仅保留了一个唯一的ID和控件类型、位置、大小等信息，我们毕竟要通过代码控制其工作，那么创建类绑定这个对话框就是必须要做的事情。&lt;/p&gt;&lt;p&gt;我不太喜欢用记事本写程序那一套，今后自然会理解：类向导自动的帮我们创建对应的对话框类，一般是继承自一个公用的基类，添加消息循环等代码片段，重写一些虚方法。&lt;/p&gt;&lt;p&gt;5、那么，我们在Ribbon设计器中，创建一个&amp;ldquo;面板&amp;rdquo;，然后放上两个按钮。&lt;/p&gt;&lt;p&gt;6、当然，需要为两个按钮创建&amp;ldquo;添加消息处理程序&amp;rdquo;，也是在Ribbon设计器中，右键，就能看到了。针对消息类型&amp;ldquo;Command"&amp;rdquo;和&amp;ldquo;Update_Command_UI&amp;rdquo;都要创建，前者是用户点击按钮后要做的事情，后者我们用来处理按钮是否可用的问题，当然，这两个方法添加到View类中。&lt;/p&gt;&lt;p&gt;7、我们现在有了四个消息处理函数，以Command为例，怎样在视图中显示一个对话框？&lt;/p&gt;&lt;p&gt;8、看看下面的代码：&lt;/p&gt;&lt;p&gt;void CSouGuView::OnButtonHome()&lt;br /&gt;{&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (CurrentDialog) //如果已经有对话框打开了，干掉它。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CurrentDialog-&amp;gt;DestroyWindow();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; delete CurrentDialog;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CHomeDialog* dlg = new CHomeDialog(this);&amp;nbsp; //创建对话框类的实例&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CurrentDialog =dlg; //我们在View中定义的CDialogEx* CurrentDialog; 我们创建的对话框类都是从CDialogEx继承的，因此，这个指针用来表示当前显示的窗体。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CurrentDialog-&amp;gt;Create(dlg-&amp;gt;IDD,this); //这里创建窗体&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CurrentDialog-&amp;gt;ShowWindow(SW_SHOW);&amp;nbsp; //显示窗体&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CurrentDialog-&amp;gt;CenterWindow(this);//将对话框在视图中居中，注意屏幕大小改变后，就不再居中，需要在OnSize事件中处理&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CurrentDialog-&amp;gt;SetBackgroundColor(RGB(255,255,255));//将背景色改为白色，马虎应付一下&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;9、然后看看消息循环中的代码：&lt;/p&gt;&lt;p&gt;BEGIN_MESSAGE_MAP(CSouGuView, CView)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ON_WM_CONTEXTMENU()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ON_WM_RBUTTONUP()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ON_COMMAND(ID_BUTTON_HOME, &amp;amp;CSouGuView::OnButtonHome)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ON_WM_SIZE()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ON_UPDATE_COMMAND_UI(ID_BUTTON_HOME, &amp;amp;CSouGuView::OnUpdateButtonHome) //注意这句，如果对应的对话框已经打开，则按钮不可用&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ON_COMMAND(ID_BUTTON_QUOTE, &amp;amp;CSouGuView::OnButtonQuote) //注意这一句：如果用户点击这个按钮，执行OnButtonQuote方法。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ON_UPDATE_COMMAND_UI(ID_BUTTON_QUOTE, &amp;amp;CSouGuView::OnUpdateButtonQuote)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ON_COMMAND(ID_BUTTON_CHART, &amp;amp;CSouGuView::OnButtonChart)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ON_UPDATE_COMMAND_UI(ID_BUTTON_CHART, &amp;amp;CSouGuView::OnUpdateButtonChart)&lt;br /&gt;END_MESSAGE_MAP()&lt;/p&gt;&lt;p&gt;10、当然，如果你打开了这个对话框，可以让这个按钮失效：&lt;/p&gt;&lt;p&gt;void CSouGuView::OnUpdateButtonHome(CCmdUI *pCmdUI)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (CurrentDialog)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pCmdUI-&amp;gt;Enable(CurrentDialog-&amp;gt;GetRuntimeClass()!=RUNTIME_CLASS(CHomeDialog));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt;&lt;p&gt;很显然，消息映射中ON_UPDATE_COMMAND_UI(ID_BUTTON_HOME, &amp;amp;CSouGuView::OnUpdateButtonHome)，是对应这个的。&lt;/p&gt;&lt;p&gt;大致的意思：如果当前有对话框打开，那么：如果是CHomeDialog类的实例，这个按钮就不可用。已经打开了这个对话框，你还打开它干嘛？&lt;/p&gt;&lt;p&gt;11、另一个对话框也是一样，算起来我们创建了四个消息处理函数。代码就复制一下，运行，能够看到来回切换的效果就行。&lt;/p&gt;&lt;p&gt;12、存在的问题：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 首先，VC的对话框的布局问题，很原始。原始的意思，就是你需要自己处理。当你改变主窗体大小、或者在不同分辨率的机器上，对话框的所有控件总显示在视图的左上角，界面是很丑陋的。这是以后的问题，我最后的解决方案是：多数情况下窗体比较小，保持居中显示就行了；少数情况下，比如显示K线图的时候，需要自动适应主窗体的大小，使用一套叫做EasySize的宏解决问题。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 其次，这里虽然实现了对话框居中显示，但由于OnSize事件中没有处理，窗体大小改变的时候，对话框的位置将不再居中，这个此后再处理。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;总结一下遇到的问题：&lt;/p&gt;&lt;p&gt;1、首先是所谓指针的概念：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 其实这真是幼儿园级别的问题，往下看，五分钟差不多能够弄清了：我们假设内存有1000个字节(不用说2G了，只说1k吧，好描述)，从0开始给每个字节编号，最后一个是999。这个编号就是指针，很显然，指针实际上是整数，表示内存的编号，也就是内存地址。我们常见的，32位操作系统的电脑，不能利用4G内存的事情，大家可以算算，32位也就是4个字节的整数，最大值是什么。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 比如我们定义一个int 指针，怎么做？&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int *p；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 意思是我们现在有了一个int指针变量p&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 然后p=0，什么意思？指向内存0的位置。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 你如果没有为指针分配空间，那么对指针的操作就是一种令人崩溃的游戏。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 虽然指到了那个地方，但那里并没有你分配的一个整型的4个字节的空间，而很可能是另一个变量的位置。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 所以第二步我们可以为其分配空间：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; p=new int;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 或者p=new int();&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这个时候，你设置断点看看，p的值已经变化了。怎么回事呢？系统将从空闲的内存中画出四个字节给你，并将这小片内存的地址：也就是第一个字节的编号传给p。系统同时会给这部分内存做上标记，继续分配空间的时候，不要再拿出来献宝，&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 好吧，第三步：这片内存里的值是不可知的，为其赋值。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *p=10；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 嗯，第四步，我想将p的值传给一个局部变量 int x;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 容易：x=*p；看看，x现在也是10了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 注意x是局部变量，不是指针，那么背后发生了什么事情呢？p所指向的四个字节的内容，拷贝到x所占用的四个自己的内容，如此而已。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 那么第五步，我们反过来，令x=100，想让p接管x所占用的四个字节，怎么办？&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; p=&amp;amp;x；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这就行了，&amp;amp;表示x的地址，再看看p，他的值显然发生变化了，指向另一片位置了么。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 不过马上你面临第6步：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 原来p的那四个字节呢？没主了，谁都遗忘了，它还在那里，不再能够使用。内存泄漏？一个函数可能短暂时间执行几千次，这样不断失去控制、不断丢失的内存就可能膨胀起来，最终的结果大家很容易想象。内存泄漏是很多大侠不断用来表达自己功力深厚的东西，其实不复杂是不是？&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 第7步，怎么避免呢？&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 容易，请在改变p之前，先delete p;先不说执行析构方法之类，我们简单的理解：将p指向的内存空间还给系统，那么，虽然p指向其他地方的话，这块地方也能继续分配给其他变量。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 第8步，那么int类型的局部变量，是不是也要delete呢？不需要，堆的概念、栈的概念也不用多讲，一个函数结束的时候，所有局部变量都会自动的析构，不用我们操心。只有用手工方式分配内存的，比如new出来的，需要我们处理。我最初闹过这个笑话，自己在函数里创建一个对象，退出前自作聪明的运行其析构函数，程序运行时崩溃，因为析构方法执行了两次，第二次执行的时候那个对象已经不存在了。嗯，这种错误犯过两次，弄半天才找到原因，相当于在同一条沟沟里跌倒两次，所以我对自己的智商也委实不太自信。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 第九步：int毕竟是简单的，你创建一个类的实例，用指针指向它，一切行为没什么不同，两个区别：1、你创建的对象可能需要更多的空间；2、p-&amp;gt;访问对象的成员，对象x则用&amp;ldquo;.&amp;rdquo;这种符号。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 需要一个月才弄清指针的概念吗？不需要，没有更多的知识了，指针的指针是什么？嗯，指向指针变量本身的指针而已；Void *是什么：指向一块不知类型的内存空间罢了。p++什么意思？指针越过其类型所占的字节，这里是加4。如果你刻意将这种概念弄得太精巧和复杂，要整出很多变态的用法，我要问问你为什么？你其实只需要这些知识就能轻松的做事，何必折磨自己的大脑。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 第十步，我是怎样弄清这些的？知道内存，知道内存地址，知道指针是存放内存地址的变量，这么三句话之后，上面的这些不是很自然的理解了吗？&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 第十一步，有大牛说过，不解决内存泄漏的问题，C++无法做超大型的项目，怎么办？嗯，搜索一下&amp;ldquo;智能指针&amp;rdquo;，不过好象我们很少做超大型的项目吧？虽然这里有高手说起500万行以上代码的项目，但做那个的，我觉得和我们几乎是两个世界的人物，或者就是一帮精神病院的家伙。暂时就不要杞人忧天了，发现问题解决问题就是，仿佛一句流行的官话：&amp;ldquo;发现一起，查处一起&amp;rdquo;，当然，聪明人马上会想到：怎样才能发现？谁来监督你是否去想办法发现了？怎样查处？谁能知道是否真被查处了？查处了以后会不会马上就复出？中国语言的模糊性，注定了中国程序员的质地。&lt;/p&gt;&lt;p&gt;2、然后是头文件的问题：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 对于习惯C#命名空间的人来说，头文件真是很无聊的东西，太古老、太原始，Too simple,some times naive。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我很快弄清了原因，为什么这个是需要的？.net 最终编译之后，保存了元数据，所以你使用一个dll，有反射机制可用。C++没这种东西。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在头文件中声明，在源文件中实现。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 声明的意思是告诉编译器，我这里定义了一个类，编译器只需要知道，却不会将这些东西编译到obj或者dll中去。事实上，主要的作用，是编译器知道某个对象分配多少空间，相当于编译器使用的参数。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 源文件中include &amp;ldquo;xx.h&amp;rdquo;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 意思是将头文件全文复制到这里，然后一起交给编译器。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在这里我闹的笑话很简单，就是void CSouGuView::OnButtonHome()&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 看看这个符号&amp;ldquo;::&amp;rdquo;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 表示这个类的方法，头文件里要声明，源文件里要实现。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 如果没有这个呢？&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 最初我本能的在源文件中写int xxxx；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 当然，不在任何函数内，用起来似乎也比较正常，但总是很奇怪，为什么这里改变了，在那里它也同样改变了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 直到后来出现问题。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 甚至你这样自由的在源文件中定义不带&amp;ldquo;：：&amp;rdquo;符号的函数&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 似乎也可以用，但却很奇怪为什么里面的智能感知失效了，用类的成员会出现编译错误。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 噢，这种简单的问题是一周后才弄清楚的，不要笑话我，所有人都会碰到的，高手们不会讲解这种问题。&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;3、代码的坏味道：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 极限编程、Scrum这类敏捷流派，耳熟能详的一句话是：&amp;ldquo;当你复制剪切的时候，就要嗅到代码的坏味道，啊，重构的时机来了。&amp;rdquo;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 看看，两个Command消息函数、两个update的消息函数，是不是都是复制的？为了重用，这里显然要重构一番是吧？对不起，我现在没工夫，就这么对付了。要知道自己的目的，时间花在主要目的上，对于重构也好、对于怎样将代码设计的更柔韧也好，我相信自己比多数人都会强一些----可是我现在在干什么？尽快实现功能，熟练掌握Vc++。重构不需要时间吗？需要的，但这个阶段不能花这种时间。这个小的应用程序，总数不超过15个窗体，几秒钟就能复制粘贴一番，估计到项目结束之后才有空去考虑这个问题。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 第二个坏味道，是View类必须知道每个对话框类的名字，当然，这也意味着有多少对话框就要include多少头文件。哇，设计模式发挥作用的地方到了，为每个类提供一个创建实例的方法，然后整个接口？创建一个对话框的基类？我说是吃饱了撑的，有闲的时候再做好不好？每个小时都很重要，你追求的是可扩展性，可是至少要等到你的产品做出来再说吧？或者今后就完全没有扩展的需要呢？或者今后接手的是个菜鸟呢？最优先考虑的肯定是如期完成项目，可扩展性服务的是程序员而不是用户，而大量使用各类设计模式，因为更抽象，所消耗的时间往往是简单实现的数倍以上，是一个工时和5个工时的区别。是否能够分清重点，是智商是否达到及格线的问题，不是技术能力问题。并不是某位高手说&amp;ldquo;我主要找写库之类的岗位&amp;rdquo;，那就更高人一等，虽然写库这种词听起来就有些别扭的味道。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 做类设计的时候，多一个类可能意味着10%以上的理解难度、开发成本的增长，所以我的目标往往首先是用最少的类实现，只在会影响到实现、或者通用性考虑不足会加大开发成本的情形下，才考虑那些稍稍抽象的东西。我当然也经历过设计模式狂热的短暂阶段，以这种实用主义、直触本质的学习方法，武器显然是不缺乏的。最明显的例子，大家可以看看通达信的股票行情软件，这样以产品吃饭的公司来说，居然存在针对不同证券公司的多种版本，对于开发团队的维护、升级来说，这绝对是一个灾难：不同的公司显然会提出一些各自特色的要求，有些可以拒绝，不能拒绝的往往是公司很关注的部分，这要做好业务分析、精心抽象，并通过通用化的设计，进行单一版本的升级来向所有客户提供同样的功能，是否使用由客户自己决定。这种多样版本并存的情形，源代码管理、开发人员是否永远在公司、自动升级服务器的部署，复杂度和工作量完全是几何级数的增长。至于应用项目，短周期的情形下，则要尽可能回避复杂化的苗头。软件开发首先是生意中的一个环节，在保证交付、稳定运行的前提下，开发和维护成本该怎样控制、如何保证如期交付、如何保证符合合同规定的质量要求，其实是团队要重点平衡拿捏的，这种观念必须贯穿于软件过程的始终。简单的说：你是在工作，不是在研究。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 所以按照前面说的，我理直气壮的忽略这些&amp;ldquo;代码的坏味道&amp;rdquo;，留待项目结束之后。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 再总结一下这短短几行代码，我们逐渐嗅到了些什么东西，当然，谈不上熟悉：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1、消息循环：宏语句，不要探究细节，从字面上理解足够了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2、类向导：能够用工具就不要手工写了，相当于代码生成器，多用。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3、头文件的问题：理解多数情况下，头文件仅仅是嵌入源代码的&amp;ldquo;声明部分&amp;rdquo;。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4、调试、断点设置之类，这个没什么变化。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 5、指针：整数，记录某块内存的开始地址。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6、文档视图机制：当作阑尾吧，留着。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7、Ribbon界面的设计：操作问题罢了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 8、对话框的设计、创建类、在视图中显示子对话框。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 9、this指针：和C#中一样，this指向是指向类的当前实例的指针，访问类的成员，不是我们习惯的&amp;ldquo;this.xxx&amp;rdquo;而是this-&amp;gt;xxx，因为是指针么。创建对话框的方法中，this作为参数，意思是将目前的这个view对象的指针，作为参数传递进去。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 可能都不是特别的清晰，但不停编码的过程中，不知不觉的你的理解会一步步增强。慢慢来，最终也不会超过一个月的，我们今后会遇到std、stl、各类字符串、unicode问题、多线程问题、Directx Api，发现一起查处一起，这项功能做完，由任务的驱动会逼着我们逐一弄清所有这些语法细节，这样比你主动的去看书强吧？到时候象我这样写几篇博客总结一下，思路能够整理得更为清晰、众多有如牛毛或者过江之鲫的高手们如果肯指出理解上的问题的话，又能够更上层楼，何乐而不为？&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;略微解释几句：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这个系列，由于是面向初学者的东西，主要是希望提供一个学习的路径图，因此内容相当的初级，也不会太过详细。这里还是希望高手们要么当作游戏之作，要么带点容忍异己的心态。当然，我说起高手，一般是当贬义词用的，这是习惯，很难改变。同时因为时间的关系，一篇帖子往往用不了半个小时，两分钟写个提纲，然后顺着往下胡侃，因此错漏之处必定也有很多，就内容挑毛病我是很欢迎的，也会尽量修改。至于对我的人品挑毛病的话，就看兴趣了：兴致高的时候我会争锋相对，练练嘴皮子，体验斗嘴的乐趣，对心态保持年青、养颜防老还是很有好处的。兴致不高的时候直接忽略，所以还请各位骂手体谅，不予还击并不是不尊重你的劳动，当然也不是看不到您鼻孔朝天一脸不屑的模样，而是此人正在沮丧中&amp;hellip;&amp;hellip;非洲还有许多孩子没有校车呢。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 关于侯捷，嗯，我还是强调一下：这个人真的很无聊。他的粉丝众多，也掩盖不了这种无聊。你可以喜欢他&amp;ldquo;滴人&amp;rdquo;，我也可以不喜欢他的方法，我不能勉强你，也希望你不要逼着我和你一起做粉丝，既然都那么博大精深，我也期待你们成为星星本身，呃，通过追星这种方式？偷偷说一句：我唯一喜欢的是他的表达方式，这是个人好恶的问题，无关其他。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 继续预告：下一篇将将讲述怎样设计&amp;ldquo;导入日线对话框&amp;rdquo;的界面，如何获取对话框控件的值、处理相应的消息。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/by1990/aggbug/2277463.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/by1990/archive/2011/12/06/2277463.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/by1990/archive/2011/12/05/2276865.html</id><title type="text">一个月学会VC++2010  2.看起来风险不大</title><summary type="text">任何时候，我都希望做绝对有把握能够完成的事情。换句话说，是缺乏冒险精神。因此，对杨先生叫苦，很大程度上是一种讨价还价的手段。在同意做这个项目的前一天，我就做了完整的评估。风险主要体现在两个方面：1、语言不熟悉；2、算法具有一定复杂性；3、因为是海量的计算，而客户要求每位分析师都能在笔记本上使用，性能方面的问题会大幅增加工作量，甚至存在可行性问题。 编程语言是初哥们很重视的问题，不过从内心来说，我从来没有将这个当作问题。很多事情，都有一些人类考虑不到的死角，熟视无睹，则眼光永远无法漂移到那边。 就比如编程语言，你该怎么理解？ 简单的说，编程语言是我们命令计算机完成一系列工作的工具。假设你面对的.</summary><published>2011-12-05T07:16:00Z</published><updated>2011-12-05T07:16:00Z</updated><author><name>玄歌</name><uri>http://www.cnblogs.com/by1990/</uri></author><link rel="alternate" href="http://www.cnblogs.com/by1990/archive/2011/12/05/2276865.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/by1990/archive/2011/12/05/2276865.html"/><content type="html">&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 任何时候，我都希望做绝对有把握能够完成的事情。换句话说，是缺乏冒险精神。因此，对杨先生叫苦，很大程度上是一种讨价还价的手段。在同意做这个项目的前一天，我就做了完整的评估。风险主要体现在两个方面：1、语言不熟悉；2、算法具有一定复杂性；3、因为是海量的计算，而客户要求每位分析师都能在笔记本上使用，性能方面的问题会大幅增加工作量，甚至存在可行性问题。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 编程语言是初哥们很重视的问题，不过从内心来说，我从来没有将这个当作问题。很多事情，都有一些人类考虑不到的死角，熟视无睹，则眼光永远无法漂移到那边。 就比如编程语言，你该怎么理解？ 简单的说，编程语言是我们命令计算机完成一系列工作的工具。假设你面对的计算机是一台高度智能的机器，具备听觉和视觉，你告诉他----卧倒，主机箱便在桌面上打个滚，然后那个显示器就会可怜巴巴的望着你，等待你的下一条命令。&lt;br /&gt; 直接用机器指令给电脑下令，是最为简单的----一串零和一的组合之后，电脑能够为你做一次计算工作。但这种工作枯燥无比、容易出错、而且工作量大得惊人。所以人类在不停的想办法，让事情轻松一点。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 最初，是汇编语言。我听到许多高人谈论&amp;ldquo;你要懂得一定的底层知识&amp;rdquo;，嗯，在他们脑子里，汇编几乎是最底层的东西了----其实不是的，最底层的是机器码。最早期的程序员，是真的使用机器码编写程序的，汇编语言已经是一个很大的进步了。此时，你面对的不再是一串串指令，而是寄存器、内存、变量等等。你通过类似Mov之类的命令，要求计算机完成某个步骤。 那么，怎么办呢？必定有一个翻译机制，将我们的汇编语言转换成机器码，这就是编程语言的由来。这个翻译机制，实际上也是一套软件，它负责将你用汇编编写的程序，然后变成机器码。 所谓编译型语言和解释型语言的差别，很大程度上，是指：将你写的程序，一次性转换成机器码，还是运行这个程序的时候，动态的转换成机器码。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 而C语言，则是汇编进一步的简化。是啊，我们下命令的过程，其实仅仅是表达我们的诉求，没必要要求你控制每一个设备啊----你让计算机做一些组合工作就行了，所谓高级语言由此而来，主要的原因是：希望我们下命令的过程，变成面向问题的，而不是面向电脑内部的各种元器件、面向动作的。就象你对一个孩子说：抬手、解下腰带、蹲下，嗯，很麻烦。C语言则变成了一句话：&amp;ldquo;上厕所&amp;rdquo;。换一个角度来说：此时C语言已经包装了很多东西，你面对机器变成了面对C语言提供的功能。于是定义变量、表达式、计算、编译、分支、循环等等语言概念，逐渐稳定下来。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; C++之类，是面向对象编程语言，这实际上是简化思考的努力。而java、C#等，主要的差异是屏蔽平台差异、实现垃圾回收机制，进一步为程序员减负。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 计算机要完成一个复杂的业务过程，显然不可能要求程序员时时刻刻下命令，而是普通人使用你的程序----这个比较重要，意味着某种通用性。那么你的程序对一些重要的流程，仍然会安排一些操作方式，&amp;ldquo;最终用户&amp;rdquo;由此产生：他们运行你的程序，按照你约定的操作方式，命令计算机完成他要求的工作。所以到高级语言层面，我并不太在意语言的差异。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 至于其他两个问题，多少也有腹案。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 然后，接下来，开始简单的规划过程，列出所有的功能清单、确定要做的第一项 功能并细分任务。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我的第一个迭代，只包括一项功能，就是&amp;ldquo;导入日线行情&amp;rdquo;。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 那么这个系列一直到最后，我也只描述这项功能实现的过程，基于一项项任务，逐步描述我要做什么、怎样着手去做、怎么思考、遇到问题怎么解决。大体上，由于源码服务器完整的保留了每一次代码的变更，这个过程也很容易复述。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 仅仅希望这一个月的学习过程，对初学者有帮助。这里的方法，事实上是学习编程语言比较通用的方法：若去学习java或者object c的开发，办法其实也差不多。甚至我觉得仅仅使用这种导入日线的例子来做，就能够覆盖常见的编程任务了。至于高手们，大可以一笑而过-----我一向非常鄙视中国的编程高手，因为这些家伙虽然牛哄哄的，但作为一个整体，他们倒真的没有做成什么象样的事情，感觉和中国足球队大有一拼，整个一群浪费粮食的群体。相对来说，我比较喜欢象我一样分布广泛的低手，虽然很差，但绝对不会乱现眼，能做什么就做什么绝不挑挑拣拣，从来不敢告诉外人自己是是踢足球，噢，是写程序的。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 下一篇的题目大体是&amp;ldquo;确定界面开发模式&amp;rdquo;，特此预告。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/by1990/aggbug/2276865.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/by1990/archive/2011/12/05/2276865.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/by1990/archive/2011/12/01/2270945.html</id><title type="text">一个月学会VC++2010 1.送上门的银子</title><summary type="text">一个月学会VC++2010 1.送上门的银子 那时，我开了一间小型软件公司，包括我在内，技术人员只有5个人。全部的开发力量，也就是这五个人，在为一家企业做项目，工期还剩下2个月。整个小团队都觉得时间很紧张，但还没有到无法履行合同的程度。 然后，一个阳光不太明媚的日子，有客人过来拜访。 嗯，我的经理办公室装修的不错，老板桌、客人用的沙发、书柜、茶几看起来很有档次的样子。这当然不是我的功劳，是一位很富有的朋友，在公司成立的时候亲自挑选的。公司成立的时候找这家伙借了不少钱，于是理所当然的，他就拥有了决策能力。这种风格我觉得很暴发户的样子，不过坐在里面慢慢也习惯了，甚至偷偷的有些喜欢。事实上，这种..</summary><published>2011-12-01T09:23:00Z</published><updated>2011-12-01T09:23:00Z</updated><author><name>玄歌</name><uri>http://www.cnblogs.com/by1990/</uri></author><link rel="alternate" href="http://www.cnblogs.com/by1990/archive/2011/12/01/2270945.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/by1990/archive/2011/12/01/2270945.html"/><content type="html">&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 一个月学会VC++2010&amp;nbsp; 1.送上门的银子&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 那时，我开了一间小型软件公司，包括我在内，技术人员只有5个人。全部的开发力量，也就是这五个人，在为一家企业做项目，工期还剩下2个月。整个小团队都觉得时间很紧张，但还没有到无法履行合同的程度。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 然后，一个阳光不太明媚的日子，有客人过来拜访。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 嗯，我的经理办公室装修的不错，老板桌、客人用的沙发、书柜、茶几看起来很有档次的样子。这当然不是我的功劳，是一位很富有的朋友，在公司成立的时候亲自挑选的。公司成立的时候找这家伙借了不少钱，于是理所当然的，他就拥有了决策能力。这种风格我觉得很暴发户的样子，不过坐在里面慢慢也习惯了，甚至偷偷的有些喜欢。事实上，这种为脸面和客户准备的暴发户环境，每个月用不到两次。我知道客户现在很少会到公司来，餐厅酒店、洗浴中心、夜总会或者咖啡厅是他们经常出没的地方。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 所以真是有点浪费了，我想。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这位客人穿着风衣，四十岁样子， 瘦削、带着眼镜，面白而无须。不过眼神很锐利的样子，看起来象头很瘦但是力量和速度都不错的狼。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 标准的文人模样，如果是商人，会称作儒商。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 他介绍自己，是一间私募基金的主持人，姓杨。当然，是我的某某朋友的另一位某某朋友介绍过来的。原因：因为我是一位软件工程师，更重要的，大学的时候，我在数学方面折腾的东西往往是计算机系的同学们都没听说过的，比如神经网络、聚类、时间序列等等。简单的说，是因为我的朋友认为：如果涉及到数据挖掘方面的事情，找我比较合适。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这间私募公司有多少钱？那是个我不敢去想象的数字，相对我来说实在太恐怖了。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 但他非常的不以为然：&amp;rdquo;我们只是一间非常小的基金，是一些朋友合办的。&amp;ldquo;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 于是我暗暗的咽了口口水，努力装出副见怪不怪的样子来。 看来，穷人之所以是穷人，与他看到钱的数量太少不无关系。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 是啊，他们有两位很厉害的股票分析师，或者说操盘手。其中一位先生制定的选股、风险、仓位控制策略，据说为整个基金带来不错的收益。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 他们希望将这套方法，用软件实现。他们甚至提出要求，说要用C++来做，原因是这位先生的儿子，好象就是学金融计算的，他推荐用C++。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;rdquo;一个月时间，只要你们能做到，需要多少钱好说&amp;ldquo;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 最后，杨先生如此总结，于是我又偷偷的流了口水。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我呢，是个非常诚实而且很质朴的人，或者说，我总希望别人将我看成这种人。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 于是有些沮丧的告诉他：&amp;rdquo;不巧的很，现在，你看，大家正在赶一个项目。而且老实说，我对C++不太熟悉，最开始用过turbo Pacal、delphi、foxpro，这些年一直用Asp.net，当然这些你听着很混乱，事实上，我连C++的语法都不太熟悉。&amp;rdquo;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 杨先生很奇怪的看着我：&amp;ldquo;我看你还有时间和我聊天啊？&amp;rdquo;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;ldquo;当然，这些天我大概每天用4个小时左右，做技术方面的工作。总有些别的事吧....比如陪人喝酒，找客户。&amp;ldquo;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;rdquo;客户自己找上门了啊？&amp;ldquo;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;rdquo;呃&amp;ldquo;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我有些无奈：&amp;rdquo;可是C++很复杂啊，能不能换换？&amp;ldquo;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 杨先生说：&amp;rdquo;我儿子都会啊，他在加拿大，要不你请教他......&amp;ldquo;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我安静下来，将涌到口边的一句话吞了回去。&amp;rdquo;何不让你的儿子去做呢？&amp;ldquo;我这么恨恨的想，但终于突然聪明起来，没有说出口。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 价格对我是很有诱惑力的，能维持公司运转一年啊----只要我昧着良心答应下来。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 于是第三天晚上，在一家洗浴中心，我，杨先生和那位很厉害的大佬分析师，坐在一起。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 是一间足疗房，三位长相平常的女技师,我觉得她们的眼神似乎常常集中在杨先生身上，看来金钱的力量远远超出外貌的力量，女人们天生就能够嗅到？ 这种萎靡不振的氛围中，我大体听明白了那位大佬的想法。时间方面也达成了一致，三个月，比最初杨先生认为的一个月多了三倍。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我昨晚的辗转反侧，看起来还是有了效果。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 为什么呢？实际上C#和C++的比较，是C#有四个加号，多两个呢。即使javascript，语法也仿佛来自C或者C++，语言方面，我想问题不大。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 至于需要的算法，至少对这个领域，我的熟悉程度连自己都很吃惊。看来小时候为了写围棋程序做的那些研究和尝试，还是有一定的好处的，至少蒙住了我那时的同学，看看，这不是送上门的金钱吗？&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 三个月，我一个人，用业余的时间，赚到这些银子。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 嗯，这是最终的决定。如果下半年再接到新的项目，嘿嘿，我推开窗子，看着模模糊糊的夜空，无限憧憬。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/by1990/aggbug/2270945.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/by1990/archive/2011/12/01/2270945.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/by1990/archive/2011/11/29/2267301.html</id><title type="text">一个月掌握VC++2010?</title><summary type="text">我个人对C++毫无概念，但在实际做项目的时候，仅仅用了一个月的时间，在完成当月工作的同时，就能够没有障碍进行相当复杂的应用开发。这个过程耗时之短或许不可思议，但采纳同样的方法，相信所有程序员都能够做到。这种方法说白了，就是边学边干。对，就是很多培训机构强调的，在实际项目中学习。不过，略有不同的，是我更加强调以下几点： 1、绝不做成学习项目：即使是最简单的功能，要做成实际产品级别，这意味着几乎成倍...</summary><published>2011-11-29T02:56:00Z</published><updated>2011-11-29T02:56:00Z</updated><author><name>玄歌</name><uri>http://www.cnblogs.com/by1990/</uri></author><link rel="alternate" href="http://www.cnblogs.com/by1990/archive/2011/11/29/2267301.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/by1990/archive/2011/11/29/2267301.html"/><content type="html">&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我个人对C++毫无概念，但在实际做项目的时候，仅仅用了一个月的时间，在完成当月工作的同时，就能够没有障碍进行相当复杂的应用开发。这个过程耗时之短或许不可思议，但采纳同样的方法，相信所有程序员都能够做到。这种方法说白了，就是边学边干。对，就是很多培训机构强调的，在实际项目中学习。不过，略有不同的，是我更加强调以下几点：&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1、绝不做成学习项目：即使是最简单的功能，要做成实际产品级别，这意味着几乎成倍的时间投入。&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2、每个阶段只面对最少的知识点：只学习需要的东西。&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3、项目不断延伸的时候，掌握知识的范围开始扩大，但此时已经具备一定的基础，学习难度已经降低。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我用来学习的功能是：导入股票日线数据。 这涉及到界面开发、文件操作、本地数据库操作、进度显示、多线程等专题知识。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 学生项目，通常是这样的：&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1、用户选择一个文件&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2、系统将文件里的日线识别出来&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3、系统将这些日线写入到数据库&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 界面是这样的：一个选择文件按钮，一个导入按钮，一个显示文件名称的文本框。&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 而作为实际产品级的开发，你显然需要考虑更多，包括：&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1、应用程序的窗体大小变化的时候，你的界面是不是会显得很奇怪？&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2、用户选择的文件，不是日线文件的时候，系统该怎样反应？&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3、导入的速度较慢，是不是应该用进度条？&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4、使用进度条的时候界面往往冻结，需要开新的线程进度条才会流畅显示，这涉及到多线程编程&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 5、如何提高导入的速度？&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6、导入日线的过程是一个每天都要做的事情，如果用户的数学紊乱了怎么办？这需要删除全部日线的功能&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7、用户仅仅记不清最近两三天是否每天都导入了数据，怎么办？&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 8、用户需要进去后就看到目前系统中的最新日线是那一天的&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 9、用户希望知道导入过程真正耗时多少。&lt;br&gt;&amp;nbsp;&lt;br&gt; 考虑到这些更多的因素，界面设计显然有较大的不同。同时，因为这样产品级的开发要求，在学习的过程中会覆盖更多的知识范围，与此同时，经过仅仅一个项目的淬炼，今后任何项目，程序员都会知道该怎样思考、该考虑哪些问题、遇到没有接触过的知识该怎样学习。换句话说，一个月的时间完成这项功能的同时，这位程序员就不再需要老师，并且能够胜任所有的VC项目开发。&lt;/p&gt; &lt;p&gt; 关注点切换的过程是这样的：&lt;br&gt; 1、最初，我考虑界面的菜单结构：显然，VS2010带来了最新的Ribbon风格，我需要知道怎样创建项目支持相应功能&lt;br&gt; 2、怎样响应Ribbon按钮的命令？理解消息机制&lt;br&gt; 3、怎样创建自己的窗口：对话框设计器、为对话框创建类、对话框类的实例化、在事件代码中打开这个对话框&lt;br&gt; 4、怎样在视图区域打开对话框，以造成一个整体的印象？简单理解文档视图结构，获取视图的大小、使用子对话框&lt;br&gt; 5、怎样为对话框加入控件？对话框数据交换机制、添加控件变量&lt;br&gt; 6、应用程序窗口变化的时候，如何保持对话框布局？多数对话框保持大小，居中显示，少数使用EasySize处理布局。&lt;br&gt; 7、识别日线文件：C++类的创建、相应语法知识，比如代码页、多语言、几种字符串、完全的unicode应用等。&lt;br&gt; 8、写入Sqlite数据库：如何使用第三方Dll&lt;br&gt; 9、如何显示进度：开启新的线程、中止线程、线程安全性问题。&lt;br&gt; 10、提高导入的性能：数据库事务问题、内存使用问题、索引问题。&lt;br&gt; 11、显示导入所消耗的时间&lt;br&gt; 12、删除全部日线：使用第三方的Sqlite组件&lt;br&gt; 13、删除最近5天的数据：Sql命令的技巧，界面如何响应？&lt;br&gt; 14、删除全部日线&lt;br&gt; 15、检查日线文件格式是否合法&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 看，前后经历这么十五个步骤，很明显，过程中任何一个时刻，我只关注解决当前面临的问题。&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 以前台湾的侯捷，写过一本MFC机制解析的书，厚厚的一本。这本书很多人评价不错，但我没想过看这样的书。为什么？工作过程中，我不需要知道原理，这并不代表知其然不知其所以然。我们学会使用，与完全弄清其工作机制，所需要的时间差距至少在二十倍以上。简单的说：你买来电视是为了看的，不是为了拆的，学会看电视大约只需要几分钟，学会组装电视甚至维修电路板，这需要的时间不会少于一年。MFC是微软的产品，作为程序员我们是用户，我们将其看成一个黑箱，知道怎么用、知道使用方面的原理就行了。&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 因此在我看来，类似侯捷这种公认的高手，其实要么是真正的笨蛋，要么就是吃饱了撑的，无论怎样他都不是一个合格的程序员。为什么？任何一种职业，追求的都是效率，即用最短的时间做能力范围内最多的事情。你甚至分不清所需要的知识的逻辑层次，又怎能奢谈高手？一个人有限的生命，应该用在真正有意义的事情上。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这项功能用了一个月的时间完成。我记得后来，开始做第二项功能，也就是显示一只股票的K线图，这就涉及到了C++模版、Gdi+和DirectX的选择、双缓冲问题、热键问题等，但在具备了上个月的基础之后，这些委实都算不上多大的难题，一一很轻松的解决。第二项功能，事实上也是在你开发延伸的过程中，知识延伸的过程。掌握最少的基础知识加上最快的学习能力，这应该是每一个程序员追求的。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp; 当然，这种学习方法，并不是只能用在VC上面，比如公司开始使用Asp.net Mvc 3进行开发的时候，我用Asp.net Mvc 3，用不到两周的时间重写了上面提到的日线导入功能，当然，这也意味着后面项目中，完全能够做到无障碍开发了。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/by1990/aggbug/2267301.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/by1990/archive/2011/11/29/2267301.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/by1990/archive/2011/10/28/2227404.html</id><title type="text">个人软件过程4 功能说明和用户体验设计</title><summary type="text">更新日线，是一项我们经常遇到的数据导入功能。 这项功能的说明文字，我是这么写的： 用户在初次使用本系统的时候，需要安装沪深两市从开市到本年度的所有历史数据，这些数据可以从某证券行情软件获得，是遵循一定格式的二进制文件。此后，每天两市交易结束之后，用户必须更新当天的日线行情，当然，用户也可能在几天后一次性更新最近几天的日线行情。用户更新日线，才能建立完整准确的数据基础，我们所有的分析工作都基于...</summary><published>2011-10-28T02:52:00Z</published><updated>2011-10-28T02:52:00Z</updated><author><name>玄歌</name><uri>http://www.cnblogs.com/by1990/</uri></author><link rel="alternate" href="http://www.cnblogs.com/by1990/archive/2011/10/28/2227404.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/by1990/archive/2011/10/28/2227404.html"/><content type="html">&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 更新日线，是一项我们经常遇到的数据导入功能。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这项功能的说明文字，我是这么写的：&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 用户在初次使用本系统的时候，需要安装沪深两市从开市到本年度的所有历史数据，这些数据可以从某证券行情软件获得，是遵循一定格式的二进制文件。此后，每天两市交易结束之后，用户必须更新当天的日线行情，当然，用户也可能在几天后一次性更新最近几天的日线行情。用户更新日线，才能建立完整准确的数据基础，我们所有的分析工作都基于这些日线数据。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 事实上只需要这么简单的描述，就能够弄清楚这项功能的目标和具体的应用场景。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 不可避免的，我们需要做用户体验设计，这是将功能转换为一系列开发任务的前提。所谓用户体验设计，我们可以简单的理解为界面设计的一部分。界面设计包括两个方面：1、如何更美观；2、设置哪些最少的功能从而满足用户的全部要求。后者可以简单的理解为“用户体验设计”。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我们可以根据功能的描述按部就班的演绎，接下来就是整个思考过程。首先，我们需要列出用户可能需要的操作、可能遇到的问题：&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1、 用户每次更新日线都需要选择一个行情文件，然后开始更新。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2、用户可能误操作，导致选择的文件不是一个真正的行情文件。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3、用户从分析软件中生成行情文件的时候，可能仅包括一个市场的数据、或者包含了期货、港股等其他市场的数据。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4、用户可能记不清最近10天是否每天的日线行情都已经更新了。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 5、在更新日线的时候，用户需要看到更新的进度&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6、用户可能对系统中保存的数据完全没有信心，准备重新从两市开市的第一天开始安装历史数据。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7、用户可能将一个文件更新两次，或者一些数据已经安装了但用户选择的另一个行情文件中包含了这部分数据。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 针对上述情形，我们可以简单的对界面元素进行设计，当然这里无需考虑美观问题，仅仅关注：1、用户遇到的问题，是否都能够处理；2、在能够处理所有问题的时候，界面是否最简单且最容易理解。经过简单的思考，我们可以得到界面的原型，这里用Vc 2010的对话框设计器可以简单的绘制草图如下：&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/by1990/201110/201110281051585596.jpg"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="更新日线窗体" border="0" alt="更新日线窗体" src="http://images.cnblogs.com/cnblogs_com/by1990/201110/201110281051595761.jpg" width="686" height="551"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 第一行，“日期”那部分，用户将能够看到目前已经安装的行情数据的起止日期，每次安装数据后这里要实时刷新，这样用户就能够始终做到心中有数。下面一行很容易理解，左边是选择文件的控件，右边是启动更新的按钮。第三行是进度的文本信息报告区，刚进入界面的时候显然要提醒用户选择一个文件。第四行是进度条，开始更新之后进度条将报告更新的进度。接下来的两个按钮，第一个是删除最新的五天日线，第二个是删除全部的日线。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这里不需要过多的分析，我们知道这种界面的形式，是能够应付上面用户可能遇到的所有情形的。菜鸟程序员很容易忽略的，是报告系统中行情的起止日期和进度文本区两个部分。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这样的东西，一些资深的项目经理可能会不屑，因为什么呢？“你好象过早的进入界面设计了”，是的，确实如此。但老实说，如果项目经理的脑子里，不能在最快时间出现上面的窗体图形的话，他会怎样为团队的程序员分配开发任务？所以，书生们常常说项目管理大师，未必需要懂得编程，在软件领域甚至在其他任何领域，这简直是十足的扯淡。做事的团队，其实并不需要一个指手画脚的人，每个人需要很清晰、很简单的知道自己今天做什么、明天做什么、怎样做是对的也就是标准是什么，外行如何用他的想象力来实现？一个蹩脚的程序员永远不可能成为能干的项目经理，就如同一个从来没有碰过枪的人，怎么可能指挥千军万马作战？当然，公司经理完全可以不懂技术，为什么，因为他可以将这一块封装起来，技术总监会对他负责，公司经理也不会对技术团队指手画脚的具体到每一项工作。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 那么，完成用户体验设计之后，我们确定开发任务其实就非常简单了：&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/by1990/201110/201110281052045700.jpg"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="任务清单" border="0" alt="任务清单" src="http://images.cnblogs.com/cnblogs_com/by1990/201110/201110281052092673.jpg" width="1041" height="547"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 上面的截图是第一项功能的任务清单，当然Tfs的一些术语翻译的很生硬，比如堆栈级别，其实是开发的顺序，用户情景，就是功能；不用太理会，我们简单的将这些任务指派给团队不同的成员，项目经理大体上就能开始轻松的当监工了。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 针对这项功能，我比较看重的是一个简单的重复测试，也就是循环执行安装一个文件、删除全部日线、安装同一个文件，这样循环多次，从而确定这两项功能的稳固性。因为显示进度的需要，更新日线的操作最好在后台运行，这样界面才不会僵死，那么这种乱序测试是对这部分后台操作的一个考验。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 到现在，我们已经完整的讲述了从启动项目开始，到程序员开始写代码之间的全过程。事实上没有多少多余的工作量，但整个开发过程将在这种简单的模式下，更趋规范。后面如果仍然有时间和兴趣，可能会对开发过程完整描述，记录学习VC++2010的过程。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/by1990/aggbug/2227404.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/by1990/archive/2011/10/28/2227404.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/by1990/archive/2011/10/27/2226096.html</id><title type="text">个人软件过程3 需求分析</title><summary type="text">一间私募基金，希望开发软件实现他们自己的一种分析思路，这是一个小项目，我们隐去他们的分析思路，仅就行情更新和显示K线图这部分内容作为具体的例子，演示需求分析、阶段划分、任务划分、问题和Bug处理、源代码版本管理的全过程。这个项目由我个人承担全部工作，三个月的业余时间完成，本系列描述的是前两个月的工作内容。 我们首先需要确定项目的目标。简单的表述为：查看股票的K线图。这意味着我们需要每天更新当天的股市行情、除权除息资料，同时能够按照他们习惯的方式绘制K线图。 第二步则是列出功能清单： 所谓需求，是围绕着项目目标来定的。 既然要分析股票的走势，那么股票每天交易的行情数据，显然要保存，所以有“更新.</summary><published>2011-10-27T02:17:00Z</published><updated>2011-10-27T02:17:00Z</updated><author><name>玄歌</name><uri>http://www.cnblogs.com/by1990/</uri></author><link rel="alternate" href="http://www.cnblogs.com/by1990/archive/2011/10/27/2226096.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/by1990/archive/2011/10/27/2226096.html"/><content type="html">&lt;p&gt;&amp;nbsp;&amp;nbsp; 一间私募基金，希望开发软件实现他们自己的一种分析思路，这是一个小项目，我们隐去他们的分析思路，仅就行情更新和显示K线图这部分内容作为具体的例子，演示需求分析、阶段划分、任务划分、问题和Bug处理、源代码版本管理的全过程。这个项目由我个人承担全部工作，三个月的业余时间完成，本系列描述的是前两个月的工作内容。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我们首先需要确定项目的目标。简单的表述为：查看股票的K线图。这意味着我们需要每天更新当天的股市行情、除权除息资料，同时能够按照他们习惯的方式绘制K线图。&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 第二步则是列出功能清单： 所谓需求，是围绕着项目目标来定的。 既然要分析股票的走势，那么股票每天交易的行情数据，显然要保存，所以有&amp;ldquo;更新日线&amp;rdquo;，而除权除息，会影响到收盘价和成交量，为了让行情变化更精确，需要导入两个市场的权息资料。这些东西未必是用户能单方面写好交给你的。用户能够解释清楚他做这个项目的意图，你能够理解，最终用上面简单的文字表达，用户能够认可，这就是需求分析的过程。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我们也要注意一点，项目目标和功能清单是用户要看的，必须使用用户的语言，不要有任何计算机专业的术语。我们的思考是在"要做什么&amp;ldquo;的层次，而不是&amp;rdquo;怎么去做"的层次，所以这个过程中完全不需要做技术细节方面的考量。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 同时，功能这个词，有许多别名：用例、用户故事、情景、用户场景等等，各自都号称自己有所不同。但我的看法是，你能够轻松的告诉用户，&amp;ldquo;我们已经完成了三项功能&amp;rdquo;，但你不能对用户这么说&amp;ldquo;我们完成了三项用户场景&amp;rdquo;，听起来真的挺二的。作为项目经理很多年，我在团队中强调最多的，不是那些不靠谱的勤奋、专心之类的东西，而是&amp;ldquo;要说人话，不要说鬼话&amp;rdquo;。再复杂的东西，有办法用大白话给多数人讲清楚，这就说明你自己是真明白了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 每项功能，请大家注意语法：动宾结构，大致是&amp;ldquo;做&amp;rdquo;&amp;ldquo;什么&amp;rdquo;。比如&amp;ldquo;更新&amp;rdquo;是动词，更新什么，更新日线。主谓宾大家是知道的，这里忽略了&amp;ldquo;谁&amp;rdquo;来做什么，这个主语。比如查看K线图，一些程序员很容易写成&amp;ldquo;生成K线图&amp;rdquo;，这里的区别是立场问题，查看是用户在查看，生成是机器在生成。功能的名称应该体现用户要做的事情，站在用户的角度思考，而不是机器或者程序员要做什么。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 不要试图在需求中列出所有的业务细节，我的理解，需求更侧重于阐述用户目标，&amp;ldquo;他们希望干什么&amp;rdquo;，而不是&amp;ldquo;怎么干&amp;rdquo;，文字工作才不会太多。许多大公司动不动几百页的文字，我很怀疑用户和程序员是否有精力去看，那只是招投标的形式主义罢了。至于&amp;ldquo;怎么干&amp;rdquo;，在下一节我用&amp;ldquo;更新日线&amp;rdquo;这项功能具体来说明，如何用较少的文字清晰的说清楚&amp;ldquo;怎么干&amp;rdquo;。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; 功能清单的顺序和大小比较重要，我们按照先做什么后做什么这样的方式列出功能清单。那么顺序如何确定?一般的原则是"用户能尽快看到结果"，其次的原则是"高风险优先"。比如正常的排列，我们应该先用模拟数据实现"显示K线图"功能，然后更新日线，然后处理复权。不过虑到对VC完全没有接触过，更新日线这项功能涉及到界面处理体系、文件操作、数据库操作、多线程编程等多个方面的内容，覆盖的知识范围更广，从学习VC编程的角度来说，更为合适。所以我按照更新日线、查看K线图、复权这样的顺序来排列。对于功能相对大小的评估，我们可以看到，复权应该是最简单的，定为2，更新日线大约需要2倍的时间，定为4。查看K线图也定为4，至于单位，有的体系叫做故事点、情景点或者理想工作时，无所谓，我们只需要一个大概的工作量评估。功能清单简单的罗列如下：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1、更新日线 4&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2、查看K线图 4&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3、复权 2&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 第三步，评估风险因素：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1、因为要做成桌面系统，基金成员各自的电脑操作系统不一，同时这个项目是海量计算的项目，所以最好的选择是使用VC开发。这个我从来没用过，需要在项目过程中边学边做。这也是很有意思的事情，多年前我的母校，武汉大学，计算机编程入门的课程是Pascal，老师当时还给大家解释Basic是如何不肖、用C语言入门如何不好，然后李卫华教授因为自己以人工智能为主要的研究领域，给我们开了Lisp和Prolog两门课程，出来工作后，主要用foxpro做过应用、然后是turbo Pascal，即使是汇编语言也玩弄得精熟(因为当时无聊的去分析汉化Dos的源代码)，然后从.net平台推出开始，就一直停留下Asp.net和Wpf，整个职业经历居然与编程语言排行榜中的头两位无缘:java和C++。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2、时间和人员方面：因为公司技术人员忙于另外一个企业项目，出于对证券行业的兴趣，接下这个项目。我本人大约每天能够有3到5个小时的时间、周六周日的部分时间。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 简单的说：用从来没有用过的语言，在从未接触过的领域，花费三个月的业余时间，完成具有相当算法复杂性的项目。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 当然最后的结果肯定是皆大欢喜的，否则我不会拿出来显摆。这也说明兴趣和自信对工作效率的影响，你喜欢做的事情，必然会全力投入。至于VC，传说中复杂的C++语法、需要多少年才能精通的MFC，在我看来也就是窗户纸罢了-----对于类似MFC这类东西，我一向的原则是，你完全没必要学会制造电视、制造里面的每一块电路板，你只要会使用电视就行了，能有多复杂？至于语法，有C#的底子，反过来C++估计也不会困难。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 风险因素是列给开发团队看的，对项目的时间安排是有意义的。当然，也是和用户在价格、时间方面讨价还价的依据。比如上述风险因素中，你没有用过VC是不能说的，否则用户很可能怀疑你能否胜任。自动划分趋势的复杂性可以强调，这样有助于在不能如期完成时，预先找到拖延的借口。所以风险因素罗列如下：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1、VC完全没有接触过&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2、人员和时间不足。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 第四步，划分阶段&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我们按照功能清单的顺序、每项功能的相对大小、风险这三个方面的考虑，来划分阶段，每个阶段为四周的时间，要"彻底实现"罗列的功能，这也是Scrum、Rup之类过程同样注重的迭代开发、小版本发布的观念。简单的说：这个阶段完成的功能，通常就是用户最后见到的样子，伤其十指不如断其一指。之所以称作"阶段"而不是"迭代"，这也是考虑到和用户交流方面的问题，仍然是那个原则：说人话。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 那么第一个阶段，我们实现第一项功能；第二个阶段，我们实现第2、3两项功能。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 对于工期紧张的项目，我一般以两周为一个阶段来安排时间。这个项目因为是业余时间工作，同时VC的学习有着不可预测的因素，因此按照每个阶段四周时间安排。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 最后略微总结一下：通过和用户约两个小时的交流，我们知道了用户启动这个项目的目标，列出了功能清单，并用简单的文字描述，取得用户的认可。然后工作两个小时，列出风险因素、划分阶段。接下来我们将为第一个阶段第一项功能，划分开发任务、提出问题，这个过程大约也需要2小时左右。也就是说，对于这类小型项目，项目经理大约在一个工作日之内，就能够做好前期准备工作，第二天每个开发人员都能够在Team Fundation Server中看到自己的工作任务。即使是比较复杂的项目，这个过程也不用太长时间，我的极限是一周，任何情况下，从用户决定启动项目开始，最多一周之内开发团队的程序员就应该能够开始工作。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 接下来的一节，我们将介绍第一项功能的概要说明、用户体验设计和任务划分。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/by1990/aggbug/2226096.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/by1990/archive/2011/10/27/2226096.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/by1990/archive/2011/10/19/2217830.html</id><title type="text">个人软件过程2  项目开发的基本流程</title><summary type="text">第一步当然是需求的采集，怎么做？ 先和用户交流，弄清楚项目的目标，这个通常是几句话，用户的语言，但你必须理解，并且文字记录下来。然后我们需要做第二件事情，即软件需要提供哪些功能，来实现项目目标。当然，这和用户的作业流程、业务规则、具体岗位是有关系的，这里的产品是一份功能清单。第三个则是功能清单的说明，通常也就是一段话，使用用户的语言。 一般没有必要记录非常详细的业务规则，在交流过程中这些通常会...</summary><published>2011-10-19T08:48:00Z</published><updated>2011-10-19T08:48:00Z</updated><author><name>玄歌</name><uri>http://www.cnblogs.com/by1990/</uri></author><link rel="alternate" href="http://www.cnblogs.com/by1990/archive/2011/10/19/2217830.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/by1990/archive/2011/10/19/2217830.html"/><content type="html">&lt;p&gt;&lt;font size="3" face="宋体"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 第一步当然是需求的采集，怎么做？&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 先和用户交流，弄清楚项目的目标，这个通常是几句话，用户的语言，但你必须理解，并且文字记录下来。然后我们需要做第二件事情，即软件需要提供哪些功能，来实现项目目标。当然，这和用户的作业流程、业务规则、具体岗位是有关系的，这里的产品是一份功能清单。第三个则是功能清单的说明，通常也就是一段话，使用用户的语言。&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 一般没有必要记录非常详细的业务规则，在交流过程中这些通常会变得清晰。我们的问题是：做什么？而不要涉及太多的细节。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这三项工作完成之后，需求也就告一段落。我们的团队，将至少有一个人，完全明了这个项目的目标、我们需要实现哪些功能、这些功能主要是做什么的。关于业务细节，可以通过交流然后形成文字、简单的也可以忽略。但这个过程中，负责需求分析的先生，必须完全能够说服自己。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&lt;/font&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 此后，划分阶段，这需要一定的经验。功能清单，对应的工作时间。嗯，是有理想工作日的概念----我个人觉得不用管它，将自己初步测算的时间乘以2就是不错的选择。也有人认为此时是比大小的阶段，即找出最简单的功能，将其大小看着1，其他每项功能按比例赋值---嗯，那其实也是很麻烦。虽然那些书生给我们讲课的时候，比较鄙视估算时间这一说，但时间毕竟是最直接的的概念。&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 估算时间的作用，是考虑分阶段完成。&lt;br&gt;&amp;nbsp;&amp;nbsp; 时间紧张的项目，尽量2周一个阶段，略长的则可考虑四周一个阶段。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 划分阶段的依据是什么？4个原则：1、最快的投入使用；2、均匀分布到每个阶段；3、考虑各种风险因素；4、每项功能在每个阶段都必须是彻底完成，不要做成半成品&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我们需要在将每个阶段的目标用一到三句话记录下来。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&lt;/font&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 此后我们开始第一个阶段，这通常是和用户交流一个工作日之后1到2天的事情，不要拿起架子做多少多少准备工作。这里，我不推荐所谓的小组评估功能大小、用户决定哪些先做哪些后做，这类花头第一是浪费时间、第二是缺乏可行性。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&lt;/font&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 然后项目负责人，可以考虑为第一阶段的各项功能，做用户体验设计，并划分开发任务，这里也需要一定的经验：1、一项功能，需要考虑哪些事情？菜鸟和老手是有非常大的差异的。2、这些任务的开发顺序，尽量要自然一些。3、在这些任务中可能碰到哪些问题，也要列出来。这些问题可能是业务方面的，需要布置文档任务；可能是技术方面的，需要解决并写成文档形式，以免团队其他人同样花费时间解决这些问题。4、有哪些地方是需要测试的----不要追求覆盖全部。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;br&gt;&lt;font size="3" face="宋体"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 之后，程序员将开始第一阶段的开发工作。&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这里，对每个程序员来说，首先遇到的或者是数据库设计、类设计、界面设计这类问题。我们每项功能涉及到哪些表格，这个阶段就创建数据库、设计好这些。类设计原则上是每个程序员针对自己的任务要做的事情，但如果涉及到多个程序员都会遇到的，项目经理必须预先在任务中说明，并且最好先建立空白的类。关于常见的ORM的问题，没有必要使用某个ORM框架，从我个人的经历来看，将数据库当作一个仓库，放进去、拿出来就行了。出于性能考虑、开发耗时的考虑，依赖某个Orm框架未必是好主意。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;br&gt;&lt;font size="3" face="宋体"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 每天项目经理自己判断，是否有必要询问哪位：进度慢了？遇到问题了？做的是否有错？不需要所谓每天的站立会议之类。这个过程中鼓励程序员多看看项目中其他程序员的代码，新手初哥，实际上是在模仿的过程中形成团队接近统一 的风格的。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 至于代码规范，未必要太讲究，只要不是那种惨不忍睹的形式就可以，笼统要求一下，尽量模仿开发环境生成的代码的风格就行。项目经理若有时间，或者有耐心，不妨偶尔修改一下程序员的代码。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&lt;/font&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 程序员完成某项任务，告知项目经理，然后会接到下一项任务。项目经理在合适的时机，执行重要功能测试，并将相应的问题作为bug记录，并指定人员修复。一项功能的所有任务完成，测试没有发现问题，开始做下一项，直到这个阶段的所有功能开发完毕。此时可以邀请客户看看效果，一般是由他们自己来操作，记录下他们的想法和意愿，下一阶段考虑。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 如此循环，直到项目结束。&lt;br&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 小结一下，流程是这样的：项目目标(几句话的文档)-&amp;gt;功能清单-&amp;gt;划分阶段(包括各阶段功能和阶段目标说明这样的文档)-&amp;gt;第一项功能的用户体验设计-&amp;gt;第一项功能的开发任务、问题分配到人--&amp;gt;项目中公用的任务(数据库、界面体系、公用类设计、说明、安排人员)-&amp;gt;程序员逐项完成任务-&amp;gt;第一项功能完成-&amp;gt;重点功能测试--&amp;gt;开始下一项功能...&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&amp;nbsp;&amp;nbsp; 业务细节的文档，需要写的时候才写，作为项目任务安排进去。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 作为项目经理，可以反思一下，自己在编程的时候是什么状态：心情不好的时候，是不是会整天没办法做事？集中精力做了2个小时，会不会感到头昏眼花，需要休息3个小时？碰到问题解决不了的时候，连续被挂上好几天，是不是厌烦到极点，能不能暂时搁置一下？&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 其实每个程序员都是这样的。&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 早上可以 出去跑跑步，10分钟，有氧运动会令大家的心情奇怪的变好一些。程序员进度明显停滞的时候，要有耐心等待，不要催。可以问问他遇到什么问题了，可以考虑是否能提出合适的建议。这是很正常的现象。&lt;br&gt;工作一到两小时，完全可以集体休息一会，聊聊天。在进度没有很明显问题的情况下，不要绷得太紧张。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 进度出现问题的情形下怎么办？&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 嗯，按照这种过程，一般不会崩溃，因为用户最需要的功能在前面已经完成了，但你若遇到过于认真的客户，基本上没有多少办法：将不急的功能放在最后，某些功能想办法说服用户不做，一些功能用更简单的办法实现，要求强手担负更多的工作，或者项目经理赤膊上阵？我想，这些大家基本上都经历过。我的意见仍然是：基本上没有多少办法-----时间的减少，导致程序品质的下降，是有临界点的。公司如果在承诺的时间做的是超出能力的工作，软件过程是不能真正解决这个问题的。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 最后的结果仍然是：加班，前提是项目经理承担更多。加班的现实作用是增加紧迫感，这可以从外部倒逼程序员有略多的专注工作时间。所谓加班不能解决问题，加班本身就意味着项目失败这种说法，不适合中国人。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&lt;/font&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 当然，我们需要一套比较简易的项目管理工具，我使用的是team fundation server，上面提到的阶段、功能、任务、问题、bug、测试和源代码管理，基本上都能够简单的解决。即使是个人项目，我也使用Tfs。我推荐以基本模式安装，也就是不用管报表之类的东西，这样的话备份简单，备份一个数据库就行了------复杂的备份过程是很浪费人力、并且抑制备份欲望的，这不安全。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="3" face="宋体"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 接下来，我将以私募基金股票分析项目的例子，将上面的过程重现一遍。&lt;/font&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/by1990/aggbug/2217830.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/by1990/archive/2011/10/19/2217830.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/by1990/archive/2011/10/18/2216778.html</id><title type="text">个人软件过程 1</title><summary type="text">提到软件过程,大家首先会想到"传统的瀑布模型",当然,这个通常作为反面例子,来衬托各家的过程如何实用、先进。然后是CMMI、Rup这些重量级的软件过程，然后是Xp、Scrum这类敏捷过程。嗯，无论是哪一种软件过程，一般公司有实施过的，程序员常常会联想到两个字：痛苦。 是的，痛苦。漫长的培训、没有必要最后也没人看的文档，当然即使是XP的捉对编程也会令一些人感到私人空间收到侵犯，而单元测试这种一部分人寻找快乐的方法，也往往会让另一部分人感到繁琐。 通常叫嚣要建立良好的软件过程的人，是公司里的技术权威，或者准权威。通常这种叫嚣的结果，是所有人的无奈，和叫嚣者最后的颓败。 所以姑且</summary><published>2011-10-18T10:13:00Z</published><updated>2011-10-18T10:13:00Z</updated><author><name>玄歌</name><uri>http://www.cnblogs.com/by1990/</uri></author><link rel="alternate" href="http://www.cnblogs.com/by1990/archive/2011/10/18/2216778.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/by1990/archive/2011/10/18/2216778.html"/><content type="html">&lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 提到软件过程,大家首先会想到"传统的瀑布模型",当然,这个通常作为反面例子,来衬托各家的过程如何实用、先进。然后是CMMI、Rup这些重量级的软件过程，然后是Xp、Scrum这类敏捷过程。嗯，无论是哪一种软件过程，一般公司有实施过的，程序员常常会联想到两个字：痛苦。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 是的，痛苦。漫长的培训、没有必要最后也没人看的文档，当然即使是XP的捉对编程也会令一些人感到私人空间收到侵犯，而单元测试这种一部分人寻找快乐的方法，也往往会让另一部分人感到繁琐。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 通常叫嚣要建立良好的软件过程的人，是公司里的技术权威，或者准权威。通常这种叫嚣的结果，是所有人的无奈，和叫嚣者最后的颓败。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 所以姑且不论大公司，我所见过的中小企业，即使通过CMM几级认证之类的，往往也是挂羊头卖狗肉。为认证而认证，真正的软件过程仍然是稀烂到不能再稀烂的程度。今天想起来应该这样，强调一阵子，明天想起来应该那样，再强调一阵子。强调来强调去，随着人员频繁的进出，最后往往是我们每天在努力，然后我们每天都很稀烂。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这也许和中国人的特质有关，工作如何令人快乐？良好的过程如何长期保持？&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 西方人的经验未必有多少借鉴意义。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 很简单，在西方，程序员是高薪行业，也是能工作到退休的行业。而在中国，程序员多数是以民工状态生存的，同时是一碗青春饭。西方尚学尚能，中国唯尚官，在南为橘，在北为枳，大体就是这个道理。哦，那些每月拿到数万元高薪的家伙，没有说你，一边去吧，这里讲的东西不适合你。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我长期挣扎在一群程序员中间，维持一间十来人的小型公司多年，慢慢实践的结果，觉得对中国人，必须有针对中国人的软件过程。这不是民族主义，我也不愤青；这也不是独树一帜，我采纳的也都是各类软件过程中一般的实践。针对和地球主流不同的人群，中国程序员，当然要有和主流不一样的方法。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 首要的原则，是简单，次要的原则，是坚持。当然，不简单的东西若要坚持，往往也是天方夜谭。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我想，多数有一定年头的程序员面临的问题，往往是需求怎么采集、怎样将需求划分为开发任务、如何设计数据库、如何做类设计、怎样保证质量、怎样管理源代码和项目资料、怎样监控进度、怎样权衡进度和工作量的关系、如何判断哪些程序员贡献度最大、怎样积累开发知识、团队整体水平很差的时候怎么办？&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我最后形成的方法，或者是开发习惯，基本上一一对应的解决这些问题。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 从方法论来说，我们必须先知道为什么这样做，才会这么做。因此，有几项基本的立论：&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1、每个人都是懒惰的，勤快是因为有所图：比如需要赚钱养活自己、担心丢失工作、在团队中担心没有面子、希望将来能够赚更多钱，这些都是能够勤快点常见理由。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2、中国是没有高手的：嗯，看看操作系统、数据库、开发环境、主要的优秀产品、最强的公司，这些是不是在中国，看结果就知道。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3、人的能力是有差异的：虽然整体是中国软件处于地球上的食物链低端，但具体的个体之间还是有强有弱的。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4、每个人都喜欢听到夸奖的话，不喜欢被批评。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 5、模仿是最好的学习方法：这个，我们知道英语折磨了很多大学生，学习十年后不会说话的比比皆是，却很少听说哪个小孩因为智商问题学不会说汉语，虽然汉语看起来似乎更难一些。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6、最重要的：如果人的劳动不能带来有尊严的生活，不要指望任何方法可以让这个人为你拼命工作。这一点是所谓软件过程能够实施的前提，假设你准备开一间黑心工厂，或者你准备利用廉价到甚至难以应付生存的劳动力赚钱，任何所谓的管理、架构之类的药物都不用吃，注定没有效果的。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 所谓最简化的软件过程，大体上从这么六点出发。在公司层面来说，公司的技术负责人、项目经理可能需要真正实用、可操作性强、可持续的团队项目管理方法；在程序员个人层面来说，形成良好的工作习惯，让自己更有效率乃至今后逐步胜任团队的管理，这些知识也是必须掌握的。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 所以，这里会是一本薄薄的书，从现在开始我会结合一个实际项目，&amp;ldquo;彻底完成&amp;rdquo;其中的数据导入功能，逐步的讲解，自己个人的编程习惯、团队协作最简易的方式，包括采集和记录需求、规划用户体验、列出开发任务、估算所需时间、类设计、数据库设计、管理bug、版本控制、知识库等各方面。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 也希望牢记一个原则，你做的软件产品，只要多按一个键，意味着客户永远不会用，这种简单性，既对软件产品的用户来说是必需的，对程序员而言也是这样：多一分复杂，就不要指望每个人都守规矩。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/by1990/aggbug/2216778.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/by1990/archive/2011/10/18/2216778.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
