2010年12月2日

明星软件工程师的十种特质

如今,每家公司都似乎成了科技公司。从软件创业公司到投机性投资公司、制药巨头和媒体巨头,它们都越来越多地加入到软件业务行列。

  代码质量不仅成为了一个必需品,更成为了一个竞争优势。因为众多公司围绕软件而竞争,开发软件的人——软件工程师正显得越发重要。但是,你该如何发现那种百里挑一的程序员呢?在本文中,我们简明扼要地列出了明星开发人员的10种特质。

明星软件工程师的10种特质

  1. 热爱编程

  编程是一种为了满足兴趣而心甘情愿去做的劳动(Programming is a labor of love)。和其他任何职业一样,唯有真正的热情,才能完成真正的伟大事情。这里有个误解,认为编写代码是机械化并纯科学性的。事实上,最优秀的软件工程师是工匠,他们能把能量、独创性和创造力融入到每一行代码中。伟大的工程师知道何时该把代码雕琢至完美,知道何时把大型系统像拼图一样组装到一块。热爱编程的工程师从构建软件中获得满足,就好比一位作曲家在完成一部交响乐后而欣喜若狂。正是兴奋感和成就感,才造就了喜爱编程的明星工程师。

  2. 完成事情

  有很多技术人员只谈论软件而不编写代码(只说不做型)。而伟大软件工程师会真正去编码,这也是他们最为重要的品质之一。他们是实际做事的人。聪明人都知道,解决问题的最佳途径是直面问题,而不是花上数周来设计复杂又不必要的架构和函数库。优秀工程师应当会问:解决手头问题的最简单方法是什么?最近的软件开发方法——敏捷实践,正是专注那个。它的思想是,把复杂的项目拆分为短小的迭代,每个迭代只关注一小部分的增量功能。因为每个迭代对应的编码只需要数周,所以功能易于管理并简单。

  3. 持续重构代码

  编码很像雕刻。要像艺术家一样不断完善自己的作品,软件工程师也要通过可能的最佳方式来持续完善自己的代码,以达到目标。重新塑造代码的原则称为“重构”,Martin Fowler在他的创意书中有相应描述。重构背后的原始思想是:改善代码而不改变其功能,移动调整部分代码以确保系统不腐,还有确保系统完成基于当前需求该完成的事。持续重构可以让开发人员解决另一个著名的问题——“黑盒遗留代码”(这个问题基本无人想触及)。

  几十年的软件开发文化要求我们,不应该去改变正常工作的东西。然而,随着时间推移,问题是我们成为了老旧代码的奴隶,老旧代码变得不稳定和不兼容。而重构正好可以改变这一状况,因为我们是代码的主人,不是它的奴隶。重构在工程师和代码之间建立起持续的“对话”,并带来所有权、确定性、自信心和系统的稳定性。

  千万不要成为老旧代码的奴隶。如果代码是他人所写,或许你可以轻易推脱责任。但大多数时候,那些代码是自己所写,要拿得起放得下,旧代码该埋时,就把它埋了!

  4. 使用设计模式

  自从所谓的“四人帮”(Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides)发表他们的著作——《设计模式》后,全世界的软件工程师一直都在讨论模式。在我们所处世界,不管是自然界还是人类行为,模式无处不在。软件工程自然也不例外。模式就是不断重现的跨语言跨系统的场景和机制。一位优秀的工程师通常能识别并利用模式,而不是受制于模式。工程师不应(强制)让系统去适应某种模式,而需发现在系统中使用模式的时机(恰当使用模式)。在使用模式来确保正确性时,应借鉴利用前人的智慧结晶,使用以前能正当解决特定工程问题的方法。但请切记:模式不是万灵药;不要为了使用设计模式而使用设计模式。

  5. 编写测试

  曾有段时间,软件工程师们认为测试不值得他们去做。然而,如果你不做测试,你怎么能确保代码就能正常工作呢?敏捷实践中的“单元测试”已获得普遍认可,因为它注重编写测试来反映代码是否有效。随着系统增大,测试也随之增大。有经验的工程师知道并了解测试的价值所在,因为测试的目的就是创建一个能正常运作的系统。优秀的工程师通常会确保出现过一次的Bug不会再出现第二次。但优秀的工程师也知道,不应该浪费时间写那些琐碎或多余的测试,而需要专注测试各个组件中的核心部分。

  6. 善用现有代码

  “重新发明轮子”一直是软件行业中的巨大问题之一。从发明新语言到从写函数库,忽视并重写那些已经存在并已能工作的奇怪驱动力,已经造成大量软件开发的失败案例。一位明星工程师会专注三种基本类型的重用:第一,内部基础架构的重用,相应代码是他自己或同事编写的;第二,使用第三方的函数库,比如JDK.最后,研究使用某些大型网络服务商提供的相应服务,比如Amazon.总之,正确善用现有的代码,使得软件工程师能真正专注于最为重要的事情上——应用程序本身。

  7. 专注可用性

  优秀的工程师通常都专注于用户。无论用户是企业还是个人,无论是为消费型的软件公司还是投资银行,需要关注的都是可用性。用户如何和系统交互?系统是否提供一种简单、直接和平稳的操作体验?有种说法,因为软件工程师是技术人员,他/她和“用户如何与系统交互”没有关联,这种说法严重错误。优秀工程师努力工作是为了什么?不正是让系统简单并易于使用。他们无时无刻都会想到用户,不会尝试去发明那些令人费解,只有极客才能理解并欣赏的东西。

  有些时候,一些软件工程师过于投入,反而忘记所编写的程序/软件,是供他人使用,不是做给自己看的“艺术品”。所以,在软件开发过程中,一直要把“用户”放在心中。

  8. 编写可维护的代码

  软件开发界的另外一个小秘密是:编写优秀代码和糟糕代码所花费的时间是一样多。一位训练有素的工程师,他/她会从第一行代码开始就考虑可维护性和代码的演化。没有任何理由编写“丑陋”的代码、长达数页的函数,或是稀奇古怪的变量名。优秀的工程师编写代码会遵循命名惯例,代码编写紧凑、简单和不过度炫耀聪明。代码的每一行,都应恰如其分地展现出其原有目的。在给不便理解的代码(块)合理注释时,别忘了命名规则。清晰明了的函数名和变量名可以让代码不言而明。

  在编码时,有些程序员会有这种心态:过一会儿再来修改或完善某部分代码或某条语句。但谁知这一“过一会”竟然是“一天”、“一周”、“一个月”或“一年”,甚至以后根本就没机会再回头修改。所以,尽量别妥协写出暂时堪用的代码。否则,不仅不会节省开发时间,也可以阻碍整个进程。当然也不利于后续维护人员的工作。

  9. 能用任何语言编程

  优秀的软件工程师活血有自己一门特别钟爱的编程语言,但从不会执迷于当中。如今已有很多优秀的编程语言,也就是说,如果你只会使用其中一门语言,说明你缺乏多样性。你可以用Java、C#或C++编写任何现代软件,可以用PHP、Perl或Ruby编写任何网站的后台。简而言之,编程所用语言,远远没有语言相应的函数库重要。优秀的工程师能够认知到这一点,并愿意去学习新语言、新函数库和构建系统的新方法。

  10. 知晓基本的计算机科学知识

  最后,但肯定不是优秀工程师最不重要的特质就是:扎实的基础。优秀的工程师或许并没有计算机科学的学位,但他/她必须知道基础——数据结构和算法。如果不知道哈希表,或者不知道链表和数组之间的差别,你如何构建一款大型的软件?。这些都是每位从事软件开发的开发人员应当知道的。算法也同样重要,从二分查找到各种排序,到图形遍历,一位明星工程师必须知道并内在消化这些基础东西。因为这些基础就是你在构建任何现代软件中做抉择时的必备品。

  结束语

  以上就是区分伟大软件工程师的诸多特质。其中讨论的“热情”,是非常重要的。代码重用、设计模式、基础数据结构和算法都是必须知道的,而敏捷实践中的重构和单元测试则有助于工程师应对复杂的软件。尤为重要的是,明星工程师相信简洁和常识。也正是这些信念,帮助他们成功构建当今世界所需的看似不可能又错综复杂的系统。

  来源:伯乐在线投稿,原文链接。

2010年11月29日

管理业务往来的最佳在线工具

不管你是从事营销、广告还是新闻业,你的工作总是需要管理项目、任务、专业人士联系方式、日程安排。大多数人都用Outlook, Google Apps或地址簿来管理,但是客户关系管理(CRM)工具可以是你将所有信息保存在一个地方,并可与同事共享。
1、ZOHO——不贵的客户关系管理选择
Zoho成立于1996年,致力于在线办公的研究,是全球第一大在线软件提供商,由印度人Sridhar Vembu创立。Zoho提供全方位的在线商务办公解决方案,并且完全同现在主流程序兼容,可以直接导入现在主流办公系统的各种文件,同时还可以管理计划、客户,甚至你无需懂编程也可以创建网站应用程序。
优点:与Google Apps整合。
缺点:无法关联像LinkedIn或Twitter这样的社交网站。
价格:免费增值模式(freemium)。

2、Free CRM——不完美,但够用
Free CRM为你免费提供诸如日程安排、联系、任务管理等基本功能。PC World将其评为最佳免费在线商务工具之一
优点:价格合理。
缺点:仪表板较为碍眼。
价格:五人以下免费。

3、Salesforce(销售队伍)——最受欢迎的客户关系管理程序之一
Salesforce(销售队伍)是全球按需 CRM 解决方案的领导者。灵活的定制:这是业界灵活度最高的 CRM 解决方案,独有的自定义选项卡和全新设计的 Customforce 令自定义灵活度显著提高,用户可深度扩展,因此能满足各种规模的企业的需求。最佳的用户体验:方便易用,简洁的界面一目了然。多语言支持:支持 14 种语言。
优点:卓越的界面、iPhone app和百万仪表板工具。
缺点:价格不便宜,但是最好的之一。
价格:按需应用、按需付费。Salesforce CRM 价格分别有5美元、17美元、65美元、125美元和250美元的不同版本,当然功能也不相同。

4、SugarCRM——开源、不贵
SugarCRM开源版是一款完全开放源代码的免费软件,具有界面活泼、简单易学的特点。美国SugarCRM公司是一间创立时间不到三年、但迅速在全球范围取得一定影响的客户关系管理软件厂商。其基本的商业策略是一边销售收费低廉的企业版/专业版软件,获得收益;一边推出免费的、功能较少的开源版软件,培养未来的付费客户、吸引志愿者参加研发。
优点:整合了Twitter。
缺点:免费版无法移动访问。
价格:提供基本功能的免费版当然是免费的。多功能版每人每年360美元。

5、vTiger——另一个开源选择
vTiger 是根据 SugarCRM 的程序,移除原本的商标,新加上了一些模块,并且加上一个安装程序,以重新命名为vTigerCRM。虽然感觉上觉得不是很对,但是根据SugarCRM 公众授权 (SPL)条款,这个举动是合法的;SPL是根据Mozilla Public Licence 改编而来
优点:免费!
缺点:只适用于Windows和Linux平台。
价格:全功能版每人每月12美元。

6、Highrise——我们都爱Highrise的设计
Highrise客户关系管理系统非常简单,没有提供许多额外的功能。Highrise仪表板看起来有点像Facebook的新闻回馈。但它是使你随时掌握客户需求的一个非常方便的工具。
优点:卓越的设计,整合了iPhone app等。
缺点:最多只能允许40个用户。所以大型公司会选用Salesforce(销售队伍)。
价格:支持6个用户的基本版每月24元。

7、BatchBook——一款“社交客户关系管理软件”
BatchBook聚焦于社交网络整合。你可以从BatchBook的仪表板上看到联系人的Twitter, Flickr, blog, and LinkedIn更新。而且你还以使用其标签功能将联系人按主题进行分类。
优点:整合了社交网络和MailChimp、Google等第三方服务。
缺点:社交媒体更新很酷,但可能不适用于所有业务。
价格:有五个套餐,最低的是每月9.95美元。

8、Daylite——只适用于苹果机的客户关系管理软件
Daylite是一款只适用于Mac OS X和iPhone的平台应用。其服务适合于电影、摄影和设计行业,因为这些领域大多数单位都是使用苹果机。
优点:整合了Mac OS X和iPhone。
缺点:不适用于Linux或Windows。
价格:五个用户的起步价是1499.95美元。

DataGridView的几个技巧

 DataGridView的几个技巧
DataGridView是一个强大而灵活的数据显示编辑控件.网上流传着大量简单而且实用的于DataGridView有关的开发技巧.不过,要从纷繁杂乱的网络资源中筛选出自己真正需要的也并不是一件省心省力的事.因此,这里将平时常用的几个DataGridView技巧整理出来,供有需要的朋友参考.
先用图片来说明本文将要涉及到的相关技巧吧:






一,数据列计数与汇总的计算
还是先看一段代码再来说事吧:
///
/// 计算各种状态的数量及总金额
///
///
private void SetItemCount()
{
    int refilling = 0, success = 0, failed = 0, totalcount = 0;
    decimal TotalRefillMoney = 0, TotalCharge = 0;
    for (int i = 0; i < dataGridView1.Rows.Count; i++)
    {
        int state = Convert.ToInt16(dataGridView1["stateCodeDataGridViewTextBoxColumn", i].Value);
        decimal RefillMoney = Convert.ToDecimal(dataGridView1["refillMoneyDataGridViewTextBoxColumn", i].Value);
        decimal Charge = Convert.ToDecimal(dataGridView1["chargeDataGridViewTextBoxColumn", i].Value);
        switch (state)
        {
            case 3:
                failed++;
                break;
            case 2:
                success++;
                break;
            case 0:
            case 1:                       
            default:
                refilling++;
                break;
        }
        totalcount++;               
        TotalRefillMoney += RefillMoney;
        TotalCharge += Charge;
    }
    if (totalcount == dataGridView1.Rows.Count)
    {
        lbRefilling.Text = string.Format("    {0}", refilling);
        lbSuccess.Text = string.Format("    {0}", success);
        lbFailed.Text = string.Format("    {0}", failed);
        lbTotal.Text = string.Format("Total: Charge/RefillMoney = {1}/{0}", TotalRefillMoney, TotalCharge);
    }
}
这段代码是一个私有的方法,它根据StateCode列的值,分别计算种状态(成功,失败和正在执行)的数量,同时计算金额列的总和.然后在标签控件中显示出来.我们只需要在刷新或检索数据的之后,调用该方法就可以了.当然,有朋友可能会觉得在DataGridView本身的事件RowPrePaint或CellPrePaint中进行计算会更好一些.这当然也是一种不错的选择,但是,这些事件在第次重绘的时候都会执行.而事实上大多数时候的重绘并不是因为数据发生了改变,这时原本是不需要重新计算数量和汇总的,因此大增加了系统的运算量,在数据量大的时候它的弊端就更加明显了.把计算放在方法中,可以在需要的时候才调用,比如重新检索了数据,修改了数据或增加删除了行.
二,添加图片列和替换单元格内容
图片的使用会使原本显得有些枯燥无味的纯数据罗列变得生动形象了不少.因此,很多人都想在自己的DataGridView中添加上适当的图片,以达到更好的显示效果.
我们可以在"编辑列"中添加一个图片列,命名为"Image",然后在CellFormatting事件中根据不同的单元格数据显示不同的图片.代码示例如下:
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    if(dataGridView1.Columns[e.ColumnIndex].Name)=="Image")
    {
            switch (Convert.ToInt16((dataGridView1["stateCodeDataGridViewTextBoxColumn", e.RowIndex].Value)))
            {
                case 2:
                    e.Value = imageList1.Images["TrayXP_green.ico"];
                    break;
                case 3:
                    e.Value = imageList1.Images["TrayXP_red.ico"];
                    break;
                case 0:
                case 1:
                default:
                    e.Value = imageList1.Images["TrayXP_purple.ico"];
                    break;
            }
    }
}
细心的朋友可能会发现,在这个代码段中,我们用到了一个名为imageList1的ImageList控件,事先给它添加好了几个ICO图片.值得一提是这里用到的CellFormatting事件,这是一个非常重要的DataGridView事件,很多预显示的内容都可以在这里完成,比如单元格内容的替换,背景色的更改等.将上面的文字稍微改一下就可以了:
if(dataGridView1.Columns[e.ColumnIndex].Name)=="stateCodeDataGridViewTextBoxColumn")
{                
    switch(Convert.ToInt16(e.Value))
    {
        case 2:
            e.CellStyle.BackColor = Color.LightGreen;
            e.Value = "Success";
            break;
        case 3:
            e.CellStyle.BackColor = Color.LightPink;
            e.Value = "Failed";
            break;
        case 0:
        case 1:
        default:
            e.Value = "Refilling";
            break;
    }
}
三,灵活查询DataGridView数据
当DataGridView控件的数据源绑定到DataAdapter时,我们通常使用DataAdapter的SelectCommand对象中的CommandText字符串语句来做为从数据库读取数据的Select语句.当我们在设计器界面通过DataGridView控件的"添加查询"功能来增加一种新的查询方式的时候,其实就是为与它绑定DataAdapter添加一个SelectCommand对象,通过设定新对象的CommandText语句,来使用新参数完成新的查询功能.这种方式简单易用,但却不够灵活,也不够强大.最灵活强大的方式莫过于是自己生成Select语句的Where条件部分,然后用新SQL语句替换现有的SelectCommand对象中的CommandText部分.示例如下:
private void ToolBarQuery_Click(object sender, EventArgs e)
{
    string QueryString = tx_QueryString.Text.Trim();//这就是自定义的Where部分.
    if (QueryString.Length > 0)
    {
        string oldsql = string.Empty;
        string newsql = string.Empty;
        try
        {
            oldsql = this.accountTableAdapter.Adapter.SelectCommand.CommandText;
            string ClearSql = oldsql.Replace(" TOP 100 ", " ").Replace("ORDER BY ID DESC", "");
            newsql = ClearSql + " " + QueryString + " ORDER BY ID DESC";
            this.accountTableAdapter.Adapter.SelectCommand.CommandText = newsql;
            this.accountTableAdapter.Fill(this.refillingDataSet.Account);
        }
        catch (Exception)
        {
            MessageBox.Show("Select Command Error:\r\n" + newsql, Text);
        }
        finally
        {
            this.accountTableAdapter.Adapter.SelectCommand.CommandText = oldsql;
        }               
    }
    else
    {
        this.accountTableAdapter.Fill(this.refillingDataSet.Account);
    }
}
需要提醒的是:一定要先保存原SQL语句,使用完新的Select语句后,再替换回去.要不然替换几次下来就不知道会变得什么样子啦.而且,当新的SQL语句有错的时候,应该及时提醒用户,并替换回原语句.
四,DataGridView中显示下拉列表框
这里将介绍两种情况下的下拉列表框,一种是下拉列表框关联DataSet中的一个表,即下拉列表框数据来自与表.另一种是下拉列表框数据预定义好的几个值.
前一种比较简单,只需要点几下鼠标就可以完成了:编辑列时,将要显示成下拉列表框的列的ColumnType设置为DataGridViewComboBoxColumn,然后在该列的DataSource属性中为它指定或新建一个BindingSource,最后再为它指定要显示的字段和数据字段就可以了.解释一下:显示字段(DisplayMember)就是界面上我们看到的文字对应的列,而数据字段(ValueMember)就是该列真正的值,这个值和数据库中的值是一致的.
后一种方法在设置列为DataGridViewComboBoxColumn后,还需要自己写代码来声明一个DataTable.然后定义它的列,再加DataTable中添加数据,最后将它绑定到需要显示成下拉框的列中,并指定其DisplayMember和ValueMember所对应的DataTable列.如:
private System.Data.DataTable dt = new System.Data.DataTable();
dt.Columns.Add("Level", System.Type.GetType("System.String"));
dt.Rows.Add("1");
dt.Rows.Add("2");
dt.Rows.Add("3");
this.PowerLevel.DataSource = this.dt;//其中的PowerLevel是DataGridView中的列名
this.PowerLevel.DisplayMember = "Level";
this.PowerLevel.ValueMember = "Level";
这里dt只添加了一列,并将显示字段和数据字段都设成了这一列.
五,DataGridView中显示密码字符
关于在DataGridView中显示密码字符,网上有多种方法,如将真正的密码列隐藏,添加一个"影子"列来显示几个星号等等.这些都不是真正的我们想要的样子(我们希望能像文本框中的密码编辑那样可以方便的输入,修改密码,只是不显示文字内容).今天这里介绍一种真正的密码框的设计方法,请看代码:
private void TheDataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    if (TheTableName == "User")
    {
        //密码显示:
        if (TheDataGridView.Columns[e.ColumnIndex].Name == "Password" && e.Value != null && e.Value.ToString().Length > 0)
        {
            e.Value = new string('*', e.Value.ToString().Length);
        }
    }
}
private void TheDataGridView_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    if (TheTableName == "User")
    {
        //密码编辑:
        TextBox t = e.Control as TextBox;
        if (t != null)
        {
            for (int i = 0; i < TheDataGridView.Columns.Count; i++)
            {
                if (this.TheDataGridView.Columns[i].Name == "Password")
                    t.PasswordChar = '*';
                else
                    t.PasswordChar = new char();
            }
        }
    }
}
其实很简单,就是在CellFormatting事件中将原密码内容替换成星号(呵呵,上面讲过的技巧这里又用到了),在EditingControlShowing事件中编辑密码.这里的一个关键是"TextBox t = e.Control as TextBox;",这使得当前单元格有了文本框的特性.这样我们编辑起来就和在文本框中编辑密码一样简单方面了.而且这样做的一个非常直观的好处就是:可以直接更新单元格中的数据,而不需要做任何额外的处理.
六,给新增列指定默认值
一个用户友好的程序,往往会为用户操作指定合适的默认值,这样可以在一定程序上减少用户的操作,提高操作效率.在DataGridView的操作中,这一点显示尤其重要.因为一些列是不能为空的.如果用户忘记输入数据,就会弹出错误提示.因此,为新增行的各列指定合适的默认值是很有必要的.那么我们需要用到DefaultValuesNeeded事件.
private void TheDataGridView_DefaultValuesNeeded(object sender, DataGridViewRowEventArgs e)
{
    e.Row.Cells["UserName"].Value = "User";
    e.Row.Cells["Password"].Value = "8888";
    e.Row.Cells["PowerLevel"].Value = "2";
    e.Row.Cells["Remark"].Value = "Default Password is '8888'.The user can change it by himself.";
}
以上小技巧并不高深,而且很常用,相信对于初学者来说,还是有一定价值的.如有不妥,欢迎大虾们给我修正.

2010年10月29日

Flash获取当前文件名、路径名

Flash获取当前文件名、路径名

其实这个功能没有什么大用,很简单;只是最近在做一些课件时,并不知道这节课将来属于某个年级,即便知道,现在的教材这么混杂,也有可能更换。

为了方便课件使用,我决定,用目录与文件名来设定是哪节课,如课件放在“\小学\语文\3年级\上册”目录下时,打开课件,会自动显示“小学语文三年级上册”;课件的文件名称写为“12.春.swf”,则打开课件时,课堂标题会显示为“第十二课 《春》”。

实现如上效果,无法是判断课件所处的路径与文件名,并将数字转到汉字就行了。

如下是一个完整的类。

class FileName extends MovieClip {
//构造方法
function FileName() {
}
//获取文件路径
function getPath():String {
   var filePath:String = _root._url;  
   return filePath.substring(0, filePath.lastIndexOf("/"));
}
//获取当前文件名
function getFileName():String {
   var filePath:String = _root._url;
   return filePath.substring(filePath.lastIndexOf("/")+1, filePath.length);
}
//获取课程名称
function getCaseName():String {
   //取出文件名
   var fileName:String = this.getFileName();
   //取出课程名称                           
   if (fileName.indexOf(".")>-1) {
    var tName = fileName.substring(fileName.indexOf(".")+1, fileName.lastIndexOf("."));
    return unescape(tName);
   }
   return "";
}
//获取课程编号,即第几节课
function getCaseNumber():Number {
   //取出文件名
   var fileName:String = this.getFileName();
   //取出课程编号
   if (fileName.indexOf(".")>-1) {
    var tNum = fileName.substring(0, fileName.indexOf("."));
    var caseNum = Number(tNum);
    if (isNaN(caseNum)) {
     caseNum = 100;
    }
    return caseNum;
   }
   return 0;
}
//获取课程中文编号,即第几节课,如第十节,第二十一节;
function getCaseChineseNumber(num):String {
   var caseNum = num;
   //中文课程编号
   var chinaNum:String;
   var arrNum:Array = new Array("零", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "百");
   if (caseNum<=10) {
    //个位数
    chinaNum = arrNum[caseNum];
   } else {
    //取十位
    var tNum = Math.floor(caseNum/10);
    if (caseNum%10 == 0) {
     //十位整数,如20,30,50
     chinaNum = arrNum[tNum]+"十";
    } else {
     if (caseNum>10 && caseNum<20) {
      //十至20
      tNum = caseNum-tNum*10;
      chinaNum = "十"+arrNum[tNum];
     } else {
      chinaNum = arrNum[tNum];
      chinaNum += arrNum[10];
      //取个位
      tNum = caseNum-tNum*10;
      chinaNum += arrNum[tNum];
     }
    }
   }
   return chinaNum;
}
//获取科目
function getSubject() {
   var filePath:String = this.getPath();
   //去除上下册
   filePath = filePath.substring(0, filePath.lastIndexOf("/"));
   //去除年级
   filePath = filePath.substring(0, filePath.lastIndexOf("/"));
   return filePath.substring(filePath.lastIndexOf("/")+1, filePath.length);
}
//获取年级
function getLevel() {
   var filePath:String = this.getPath();
   //去除上下册
   filePath = filePath.substring(0, filePath.lastIndexOf("/"));
   return filePath.substring(filePath.lastIndexOf("/")+1, filePath.length);
}
//获取上下册
function getBook() {
   var filePath:String = this.getPath();
   return filePath.substring(filePath.lastIndexOf("/")+1, filePath.length);
}
//获取当前课件的名称,并返回“第N课 (课程名)”
public function getCaseTitle() {
   //中文课程编号
   var chinaNum:String = this.getCaseChineseNumber(this.getCaseNumber());
   //课程名称
   var caseName:String = this.getCaseName();
   caseName = "第"+chinaNum+"课 \n《"+caseName+"》";
   caseName = unescape(caseName);
   return caseName;
}
//获取当前课件的主标题,如“小学语文一年级上册”
public function getTitle():String {
   var title = this.getSubject();
   var level = this.getLevel();
   var book = this.getBook();
   //
   if (level.length>0) {
    var t = level.substring(0, 1);
    level = this.getCaseChineseNumber(Number(t))+level.substring(1);
   }
   var reTitle = title+level+book;
   if (reTitle == "" || reTitle.length<1||reTitle.indexOf("%")>-1) {
    return "该课件存放位置错误!";
   }
   return reTitle;
}
}


2010年10月24日

IIS 6 的 PHP 最佳配置方法

 IIS 6 的 PHP 最佳配置方法

作者:andot 时间: 2005-12-27 文档类型:原创 来自:CoolCode.CN

虽然 LAMP 组合很不错,但是如果想要架设一台同时支持 PHP、ASP、ASP.NET、JSP、Perl 的 Web 虚拟主机服务器,还是用 Windows 2003 的 IIS 6 最好。网上有很多介绍在 IIS 6 上配置 PHP 的文章,但是那些方法不是性能不好,就是升级麻烦。下面的方法可以让你在第一次配置好后,能够非常方便的进行升级。

这里所说的升级,是指从某个 php4 版本升级到另一个 php4 版本,或者从某个 php5 版本升级到另一个 php5 版本,而不是指从 php4 升级到 php5。

准备:

1、一台安装好的 Windows 2003 服务器,并且已经安装了 IIS 6。

2、下载 windows 版的 PHP 二进制压缩包

安装:

解压缩 PHP 二进制压缩包到 C:\php 目录下(这里假设 C: 盘是系统盘,即安装了Windows 系统的盘,如果系统盘是 D: 盘,则解压缩到 D:\php 目录下,以此类推,下同)。

然后打开“我的电脑”->“属性”->“高级”->“环境变量”->“系统变量”->“path”,编辑其值,在前面增加下面的路径地址:

C:\php;C:\php\dlls;C:\php\extensions;C:\php\sapi;

将 php.ini-dist 或 php.ini-recommended 复制到 C:\Windows 目录下,并改名为 php.ini,一般正式发布网站的服务器用 php.ini-dist,而作为调试用的服务器用 php.ini-recommended 更好。当然一般情况下,这个 php.ini 还是需要根据实际情况来修改的。

下面来介绍一下几个必要的修改选项:

extension_dir = "C:\php\extensions"

这个是 PHP 扩展所放置的目录,请确保跟你实际安装的目录相同。 

extension=php_mbstring.dll
;extension=php_big_int.dll
extension=php_bz2.dll
extension=php_cpdf.dll
extension=php_crack.dll
extension=php_curl.dll
extension=php_db.dll
extension=php_dba.dll
extension=php_dbase.dll
extension=php_dbx.dll
extension=php_domxml.dll
;extension=php_exif.dll
;extension=php_fdf.dll
;extension=php_filepro.dll
extension=php_gd2.dll
extension=php_gettext.dll
extension=php_hyperwave.dll
extension=php_iconv.dll
;extension=php_ifx.dll
;extension=php_iisfunc.dll
extension=php_imap.dll
;extension=php_interbase.dll
extension=php_java.dll
extension=php_ldap.dll
;extension=php_mcrypt.dll
extension=php_mhash.dll
extension=php_mime_magic.dll
extension=php_ming.dll
extension=php_mssql.dll
extension=php_msql.dll
;extension=php_oci8.dll
extension=php_openssl.dll
;extension=php_oracle.dll
extension=php_pdf.dll
extension=php_pgsql.dll
;extension=php_printer.dll
extension=php_shmop.dll
;extension=php_snmp.dll
extension=php_sockets.dll
;extension=php_sybase_ct.dll
extension=php_w32api.dll
extension=php_xmlrpc.dll
extension=php_xslt.dll
extension=php_yaz.dll
extension=php_zip.dll

上面这些,开头没有加分号的是打开的扩展,加了分号的是没有打开的扩展。上面的设置包含了在 Windows 2003 上默认安装情况下可以打开所有扩展(这里列出的是 php 4 的)。

session.save_path = b:\sessions

这个是 session 文件默认保存的目录,这个目录必须是一个存在的目录,不然默认的 session 功能会无效。我这里设置的是一个 ramdisk 上的一个目录。将 session.save_path 设置在 ramdisk 上可以加快 session 处理的速度。如果你没有安装 ramdisk,你可以把它指定到其他盘的任何一个目录下,如 C:\sessions 目录、C:\Windows\Temp 目录等。

OK,基本工作作完了,现在该配置 IIS 了。

打开“ Internet 信息服务(IIS)管理器”,在“ Web 服务扩展”里,选择“添加一个新的 Web 服务扩展”,扩展名可填写“PHP ISAPI 扩展”,要求的文件选择:C:\php\sapi\php4isapi.dll(如果安装的是 PHP5,则此处是 C:\php\sapi\php5isapi.dll,下同),并设置扩展状态为允许。

打开“网站”->“属性”->“ISAPI 筛选器”->“添加”,筛选器名称可填写“PHP”,可执行文件仍然选择 C:\php\sapi\php4isapi.dll。

打开“网站”->“属性”->“主目录”->“应用程序设置”->“配置”->“应用程序扩展”->“添加”,可执行文件还是选择 C:\php\sapi\php4isapi.dll。扩展名填写“.php”,动作限制为“HEAD,GET,POST”。

打开“网站”->“属性”->“文档”->“启用默认内容文档”->“添加”,可以将 index.php 添加为默认内容文档。

然后选择“服务器机器名”->“所有任务”->“重新启动 IIS”来重启 IIS。

测试

在默认网站发布目录下,建立一个测试页面:

下载:phptest.php

<?php
    phpinfo();
?>

如果打开这个页面能够看到 php 安装配置信息,就算是安装成功了。

如果想要更优化的执行 php 程序,可以安装 ZendOptimizer-2.6.0-Windows-i386.exe ,这个东西安装非常简单,这里就不介绍了。

升级

现在升级就非常简单了。只需要将新版本的 PHP 二进制压缩包下载下来,将原来的 C:\php 目录删除,将新版本解压缩到 C:\php 目录中,然后重新启动一下 IIS 就可以了。不需要修改任何配置,也不需要往 System32 目录中复制任何文件。是不是很方便啊?



2010年10月20日

Subversion和TortoiseSVN如何在Windows下进行构建SVN版本控制



    本文介绍一下如何在Windows下进行Subversion和TortoiseSVN构建SVN版本控制,希望对你能有所启示 。


    Subversion已经是一个热门话题,下面介绍一下Windows下Subversion和TortoiseSVN构建SVN版本控制 问题。

    首先看一些基础知识: Subversion是架设一个SVN server 必要的工具,自己必须手动配置Subversion 脚本或者执行命令行命令.最后通过命令行输入访问 svn server. 当然这是没有TortoiseSVN前的时代.TortoiseSVN是Subversion一个客户端访问工具,灵活的运用TortoiseSVN 可以最大化的减少配置Subversion   烦琐的命令行 参数输入.

    下面看一下Windows下Subversion和TortoiseSVN构建SVN版本控制 的具体步骤:

    1.下载Subversion的window安装版本svn-1.4.6-setup.exe

    http://subversion.tigris.org/

    http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=8100

    2.下载TortoiseSVN的TortoiseSVN-1.5.2.13595-win32-svn-1.5.1.msi版本

    http://tortoisesvn.net/

    http://tortoisesvn.net/downloads

    3.安装Subversion

    双击svn-1.4.6-setup.exe,一路next完成安装。设置环境变量,将subversion对bin设置到path中。如:D:ProgramFilesSubversionbin

    4.安装TortoiseSVN

    双击TortoiseSVN-1.5.2.13595-win32-svn-1.5.1.msi,一路next完成安装。

    5.创建svn容器Repository

    在硬盘上任意位置创建一文件夹,如D:svnRepository,在文件夹上右键TortoiseSVN->Createrepositoryhere创建成功后将在D:svnRepository下生成一系列文件。

    6.配置容器的访问权限

    在容器的目录下D:svnRepository的conf中,用记事本打开svnserve.conf文件,找到

    #anon-access=read

    #auth-access=write

    #password-db=passwd

    并去掉注释#,注意,去掉注释后,不要留下空格,保持每行顶格,切记!!!

    配置访问用户列表,用户名加密码

    记事本打开该目录下的文件passwd,去掉#harry=harryssecret,#sally=sallyssecret的注释#,同意注意每行要顶格,开头也不能有空格。

    说明harry=harryssecret表示:用户名=密码,当然也可以自己增加,如gary=gary。

    最好效果如下:

    ###Thisfileisanexamplepasswordfileforsvnserve.

    ###Itsformatissimilartothatofsvnserve.conf.Asshowninthe

    ###examplebelowitcontainsonesectionlabelled[users].

    ###Thenameandpasswordforeachuserfollow,oneaccountperline.

    [users]

    harry=harryssecret

    sally=sallyssecret

    gary=gary

    7.启动Subversion

    因为之前设置了环境变量path=D:ProgramFilesSubversionbin;因此打开cmd,直接运行命令:svnserve-d-rD:svnRepository这样Subversion服务器就假设好了。

    8.向容器添加需版本控制的文件(也可以远程,只需url为ip就行)

    在硬盘上任意位置,右键需要上传的文件的上级文件夹,TortoiseSVN->Import…此处为了测试,创建文件夹D:importFiles,里面放一doc文件test.doc,即要将test.doc上传到svn中去。右键importFiles,TortoiseSVN->Import…,输入容器的url:svn://localhost/svnRepository输入用户名和密码:就将test.doc文件上传到svn容器了。

    9.从容器获得test.doc文件(也可以远程,只需url为ip就行)

    在任意位置,某文件上右键D:checkOutFiles,点击SVNCheckout…输入url即可。

    10.完成

    这样就完成Windows下进行Subversion和TortoiseSVN构建SVN版本控制的部署和存取,修改相应的文件,提交即可,注意始终保持Subversion的运行。注意,在第8步中会报错“期望文件系统格式“2”;发现格式“3””原因是TortoisSVN的版本过高,或与Subversion不匹配。应该换成低版本的TortoisSVN用TortoiseSVN-1.4.8.12137-win32-svn-1.4.6.msi,即应该为svn-1.4.6-setup.exe和TortoiseSVN-1.4.8.12137-win32-svn-1.4.6.msi的组合才行,步骤和之前的一样,只是在第6步中的svnserve.conf文件中没有后面的内容:

    [sasl]

    ###ThisoptionspecifieswhetheryouwanttousetheCyrusSASL

    ###libraryforauthentication.Defaultisfalse.

    ###ThissectionwillbeignoredifsvnserveisnotbuiltwithCyrus

    ###SASLsupport;tocheck,run'svnserve--version'andlookforaline

    ###reading'CyrusSASLauthenticationisavailable.'

    #use-sasl=true

    ###Theseoptionsspecifythedesiredstrengthofthesecuritylayer

    ###thatyouwantSASLtoprovide.0meansnoencryption,1means

    ###integrity-checkingonly,valueslargerthan1arecorrelated

    ###totheeffectivekeylengthforencryption(e.g.128means128-bit

    ###encryption).Thevaluesbelowarethedefaults.

    #min-encryption=0

    #max-encryption=256

    ====================================================================================================================

    以上SVN服务器版本和TortoiseSVN客户端版本应匹配,最新版本1.6.1。TortoiseSVN是windows下的external版本控制工具,VS非expressediton可以用开源插件Ankhsvn(http://ankhsvn.tigris.org/)或收费的VisualSVN来集成。Windows下Subversion和TortoiseSVN构建SVN版本控制 问题介绍完毕。


subversion、TortoiseSVN版本控制

因为公司代理问题,还有团队开发人员不在一起的原因,手头上的这个项目就放弃了vss,改用svn做版本控制。研究了几天,算是基本了解点。subversion支持http和svn两种方式的版本控制,因为是用的iis,http方式貌似需要apache,就算了,这里说下svn方式,希望对大家有帮助。

首先要下载subversion、TortoiseSVN、TortoiseSVN中文语言包。其中中文语言包看个人爱好了。推荐的是服务器上安装subversion、TortoiseSVN,而客户端只需要安装TortoiseSVN就好。

安装过程就是一路的下一步,就不多说了。

先说服务器端安装:

建立一个文件夹code放所有的版本库,类似于我们用的“游戏”文件夹。然后在code下面再建立具体的项目文件夹,例如baiduhi,类似于游戏文件夹下的“魔兽世界”。在baiduhi文件夹上点右键,选择“TortoiseSVN”----“在此创建版本库”,然后版本库就弄好了。进入baiduhai里的conf文件夹,修改svnserve.conf里的内容,也就是取消注释

anon-access = none
auth-access = write
password-db = passwd

变成这样的,再修改passwd文件,添加用户就好了,=的前面是用户名,后面是密码。

如果服务器上不安装TortoiseSVN,就得在命令行里用svnadmin create了,那个看着晕晕的,就不管了,这也是我为什么推荐在服务器上也安装TortoiseSVN的原因了。

到这里,服务器上的版本库创建好了,但是别人要怎么访问呢,总得有个地址吧。

开始菜单--运行--输入cmd,在命令行里输入svnserve -d -r f:/code就好了。来解释下,svnserve就是subversion自带的一个服务器,可以实现svn://这样的地址。-d 表示后台运行 -r表示设置版本库的路径。还有好多其它的参数,可以输入svnserve -help获得,自己看。

需要提醒的是,这个命令窗口不能关闭,关闭了就没有用了。不过可以通过把这个服务变成系统服务的方式来解决,这个放后面说。

到这里服务器端,就全部设置好了。

客户端的配置:

在客户端安装TortoiseSVN,然后新建立一个文件夹,点右键,选择“SVN检出”,输入地址、用户名、密码什么的就好了。svn地址就类似这样的svn://localhost/baiduhi,localhost对应于服务器上面的code文件夹,实际使用时换成ip地址或者域名。

上面说到服务器的那个命令行窗口要关闭的话换成系统服务,可以用下面的方法:

sc create subversion binpath= "D:\Program Files\Subversion\bin\svnserve.exe --service -r f:/code" displayname= "Subversion Repository" depend= Tcpip

sc是系统自带的一个创建服务的工具。

嗯,基本上就是这样了。