大家不要以为面向对象是从石头里蹦出来的。它只是提供了新的思维模式和代码组织结构,其他都是我们常常用到的东西。大家可能觉得歌手很风光,随便上台唱首 歌就可以拿到比较好的报酬。但你知道吗?他们每天都得练基本功,声带、气息、咬字、共鸣等等,你觉得这些很简单吧~但恰恰是这些基本功,才让他们唱出最美 丽的声音。 先把自己的卫生做好 大家在舒适、整洁的环境里工作时,会感到心情舒畅,。我们写的代码也是,杂乱无章的代码,会让我们感到摸不着头绪,工工整整的代码,会让我们感到精神振奋。大部分公司都有自己的编码规则,大家一定要遵守。下面呢,我举几个最基本但非常重要的规则。 命名规则 ,可能是大家觉得命名不重要,所以在实际的工作当中常常被忽视。我们写的程 序像文章一样,不光是要让自己读懂,还要让别人读懂,所以规范命名是非常重要的。那怎么能够让人容易读懂呢?那就是用我们生活当中的日常用语,因为日常用 语是被大家所接受的,所以大家容易达成共识。比如说顾客可以命名为Customer、工资可以命名为Salary,一目了然。 还有在命名时尽量使用英语不要使用汉语拼音,因为程序语言是英语,英语和汉语拼音混杂在一起,不容易达成统一。另外一个原因,我们的开发环境正走向国际化,你把命名写成汉语拼音,老外肯定不知道你写的是什么,你总不能让老外去学习汉语拼音再来编程吧? 控件的命名也很重要,比如说在.NET里创建了一个WINFORM,它的默认命名是From1,还有一些程序员使用这样的默认命名,因为他们觉得反正程序 只有一个WINFORM,所以费劲脑汁去想名字,没那个必要。但你有没有想到过,假如你的程序有几十个WINFORM的时候,假如你是跟别人合作开发的时 候,你怎么管理这些WINFORM?,你怎么跟别的同事沟通?。更要注意的是要做好WINFROM里的常规控件的命名,因为这些控件在一个WINFORM 里重复率高,所以如果没有做好命名,你只有反复切换代码窗和属性窗,才可以知道这个控件是做什么的。看下面的例子,大家肯定不知道他是在做什么。
private
void
button1_Click(
object
sender,EventArgse)
{ textBox1.Text="Name"; textBox2.Text="Sex"; textBox3.Text="Age"; }
再看下面的例子,大家是不是觉得很好理解?
private
void
btnSave_Click(
object
sender,EventArgse)
{ txtName.Text="Name"; txtAge.Text="Sex"; txtSex.Text="Age"; }
代码注释 ,上面提到了命名规则会让代码容易读懂,如果加上注释的话就会锦上添花。最关 键的问题,人的记忆力不太好。你写程序,开发过程中呢,可能感到轻车熟路,但时间久了,你再看代码时,我确信80%的逻辑你都忘记了。还有如果你写底层的 类库,那你更应该要写好注释,因为你要保证代码准确性的同时,也要保证别人容易读懂。 注释根据开发语言的规范来写,开发完成后可以直接生成代码文档。大家都知道JAVA、.NET、PHP都有自己的注释规范。 注释根据开发语言的规范来写,开发完成后可以直接生成代码文档。大家都知道JAVA、.NET、PHP都有自己的注释规范。 每个类和函数都要有注释,哪怕是简短的一句。这个是起代码的概括说明作用,可以让我们不读代码也可以知道大概的功能。 公用变量和重要的变量要有注释,因为这些变量在程序中起重要的作用,所以一定要有注释,必要时要详细注释。 复杂的逻辑要有详细的注释,这里说的详细注释是指,实现功能时你的思路。 函数的变量和返回值要有注释,这个也不必多说了吧。 函数代码比较长时,在一个逻辑分段上注释,可以增加代码的易读性。下面是例子,大家可以参考一下,
/**/
/// <summary> /// 用户登录系统 /// </summary> /// <paramname="Id"> 用户ID </param> /// <paramname="Password"> 用户密码 </param> /// <returnsname="LOGIN_STATUS"value="LOGIN_OK"> /// 登录成功 /// </returns> /// <returnsname="LOGIN_STATUS"value="LOGIN_FALSE"> /// 登录失败,ID或密码不正确 /// </returns> /// <returnsname="LOGIN_STATUS"value="LOGIN_LOGINED"> /// 已登录 /// </returns>
private
LOGIN_STATUSLogin(
string
Id,
string
Password)
{ //判断用户有没有登录 if ( this .IsLogin(Id,Password) {
return LOGIN_LOGINED; }
//判断用户ID和密码是否正确 if (! this .IsValidUser(Id,Password)) { . return LOGIN_FALSE; }
//处理登录 .. .. return LOGIN_OK; }
代代码格式 ,这个也是增加代码易读性的一个方法,初级程序员,容易忽视这些问题,但只要你稍微注点意,就可以做好。 统一的缩进可以让代码看起来整洁规范,现在流行的IDE环境这方面做的很好,它会给你自动缩进,但手写代码时大家一定要注意缩进的问题。 不要使用过多的if嵌套来实现逻辑。这个问题呢,可能出现在没有写过C语言的程序员身上(其他语言对return的例子不是很多)。比如我们举上面的例子,用户登录。用户在没有登录并且ID和密码正确时才可以登录系统,有的程序员会写出一下代码,
/**/
/// <summary> /// 用户登录系统 /// </summary> /// <paramname="Id"> 用户ID </param> /// <paramname="Password"> 用户密码 </param> /// <returnsname="LOGIN_STATUS"value="LOGIN_OK"> /// 登录成功 /// </returns> /// <returnsname="LOGIN_STATUS"value="LOGIN_FALSE"> /// 登录失败,ID或密码不正确 /// </returns> /// <returnsname="LOGIN_STATUS"value="LOGIN_LOGINED"> /// 已登录 /// </returns>
private
LOGIN_STATUSLogin(
string
Id,
string
Password)
{ //判断用户有没有登录 if ( this .IsLogin(Id,Password)) { //判断用户ID和密码是否正确 if ( this .IsValidUser(Id,Password)) { //处理登录 return LOGIN_OK; } else return LOGIN_FALSE; } else return LOGIN_LOGINED;
}
大家可以比较一下,哪段代码更容易读?这个还算是比较好的,如果if里的代码超过一个屏幕的长度时,那才叫超级郁闷! 一个函数的代码过长时要把它分解成几个函数,可以增加易读性和复用性。 养成懒的习惯 这里指懒,不是让你去偷懒,而是让你培养复用意识,如果软件开发的世界里没有复用,那是一个多么黑暗的世界啊!复用包括很多方面,比如说变量、算法、业务逻辑、框架、系统等等,按开发的角度来说从前到后开发的难度是越来越大的。 系统当中一个功能只能有一个接口 ,这样可以避免重复代码,增加复用性。比如说有一个订 单管理项目,项目经理让A程序员写订单管理模块,让B程序员写用户管理模块。两个模块都有查询客户的功能,A程序员写了SearchCustomer函 数,B程序员写了FindCustomer函数,大家想一想,这里有什么错误?首先有重复的代码,浪费了资源。第二,代码不容易维护和扩展,如果客户的表 结构发生变化或有新的逻辑增加,那必须要修改两个函数。 功能必须要写成函数 ,这是复用的基础。如果你还没有这样做,那你现在开始做吧。还是要用上面的例子来说明问题,查询客户并显示的代码如下,
//查询客户信息
StringSqlStr="SELECT*FROMcustomerWHEREid="+CustomerId; DataSetdsCustomer=
this
.query(SqlStr);
//把客户信息显示在页面
. .
这段代码把查询客户逻辑直接写到了显示页面的代码里,这样写,会比上面的例子,有更大的隐患,起码上面的例子,从程序员个人的角度来说做到了复用, 并且如果业务发生变化,只需要改两个函数。但在这个例子里,如果业务发生变化,你需要修改所有包含查询客户逻辑的代码,你会不会觉得头大呢?我们不能确定 一个功能会在项目里得到复用,但不怕一万就怕万一。再说写函数也不是一件非常困难的事情。 必须要使用MVC模式,这里是指逻辑上的MVC。MVC是一个很好的设计模式,即使你还不了解,你也要用MVC。MVC让你的业务逻辑、显示逻辑、界面逻辑分开,使得各个层都可以复用。现在我们用MVC的结构写一下,上面的例子,
//客户信息管理模块CustomerInfo.cs里处理客户查询的逻辑
//查询客户
public
DataSetFindCustomer(StringCustomerId)
{
StringSqlStr="SELECT*FROMcustomerWHEREid="+CustomerId; DataSetdsCustomer= this .query(SqlStr); return dsCustomer; }
//A程序员的订单管理代码
//客户信息
DataSetdsCustomer=CustomerInfo.FindCustomer(CustomerId);
//查询订单的剩余操作
.. ..
//B程序员的查询客户代码
//客户信息
DataSetdsCustomer=CustomerInfo.FindCustomer(CustomerId);
//查询客户的剩余操作
.. ..
大家可以看到,因为我们把业务逻辑分离出来了,所以A程序员和B程序员都使用了同一个函数FindCustomer(代码得到了复用)。 而且如果业务逻辑发生变化,我们只需要修改一个函数就可以了。 不要把逻辑写到控件里 ,因为这样做逻辑不清晰,而且逻辑不能得到复用。现在的开发工具 为了提高开发效率,提供了很多方便的控件,但是我们要记住,不要把逻辑写到控件里。其实这个呢,跟上面说的一定要使用MVC是一样的道理。在这里呢,举数 据库控件的例子,如果你直接用数据库控件(把SQL语句写到控件里),来写代码,第一,代码的逻辑不清晰,因为逻辑是隐藏在控件里的,而且数据库控件多时 很难管理(DELPHI,DataModule里放了几十个TQuery控件,你不烦吗?)第二,很难复用逻辑,比如两个程序员要用同样的逻辑,那数据库 控件里的逻辑应该怎么共享呢?你说,可以使用引用,对,是可以用,但需要用控件的名称来做接口, 控件的名称远不如函数名称来得清晰吧。 要把可变值放到变量里 ,不要写死在程序里,那样你会非常累。这好像是最基本的常识,我 们在学校里学习C语言的时候都学过。比如圆周率是3.14,就不要把它写死在代码里,要写成常量。我们在实际的工作当中使用圆周率的机会不太多,但还是有 很多相似的情况,大家一定要注意。还有能写后台管理程序的,就写成管理程序,不要每当需要修改或添加需求时直接修改代码,这样你会累,更危险的是当你离开 公司之后会出现维护问题。这个要在代码设计时就要规划。举个实际的例子吧,A是一个游戏公司的程序员,公司让他写了一个双倍经验活动的代码。比如在 6.1~6.2日,打怪会得到双倍经验。A写的代码逻辑如下, 如果今天是6.1或6.2日,经验*2 代码写的没错,活动圆满结束了。10.1又要举办双倍经验活动,A修改原代码里的日期完成了任务,而且每当有活动时A就修 改代码,不久A觉得不耐烦了,因为每当活动时,他都需要修改代码。后来A离开了公司,公司要举办双倍活动,但现在公司里没有懂游戏编程的程序员,公司只好 取消了活动计划。 要有开放的心态、谦虚的态度 ,对项目组、对公司尤其重要。 那为什么要有开放的心态呢?只有拥有开放的心态,才可以跟身边的同事很好地沟通,才可以听取别人的意见,才可以提高团队的工作效率。如果有同事向你求教 时,把你所知道的全都告诉他吧!如果你有问题,就问身边的同事吧,即使你的职位比他高!如果你写的代码,不是绝密的,就跟其他同事共享吧。 那为什么要有谦虚的心态呢?只有拥有谦虚的态度,才可以得到别人的尊重,才可以互相学习共同进步。曾经在网上看到,有一个 人炫耀地说自己用一个高深的问题难倒了公司的技术总监,使他离开了公司(很难理解)。软件技术有很多领域,有人喜欢研究算法,有人喜欢研究系统底层,有人 喜欢研究框架,有人喜欢数据库编程,在各个领域里要想做到专家级别都很难,所以不要给这些领域划分等级,如果你做了3年的SI业务(成为了专家),现在让 你去做游戏开发,你需要多长时间才可以成为专家?返过来也是一样的。 不断地总结,才可以进步 。每件事都不可能做到完美,编程也是一样的。大名鼎鼎的 WINDOWS不也有很多BUG吗?但人家会总结经验,下一个版本里不会出现同样的BUG。不要因为你写的代码不够完美而气馁,只要你在下一个项目中修正 了一个错误也是进步。学习面向对象也是,不要想一下子把面向对象所提到的所有概念都应用到实际的项目当中,比如,继承、多态、接口、设计模式,不久你会失 去信心。我们可以一步一步来,比如先把代码封装到类里,等项目完成之后,你会发现,项目当中的一些地方可以使用多态,如果下一个项目有类似情况时,你就可 以使用多态来实现代码,这样循序渐进。你会发现,你在慢慢进步。你的信心也增加了。 上面讲了学习面向对象之前要做的基础训练,可能还有别的,但这不重要,提这些的原因是让你明确基本功的重要性。这些都是一个程序员应该所具备的基本素质。 只要你在日常编码中,多练、多总结,就可以做到。如果你掌握了这些基础,并且理解其背后的思想的话,我相信你,运用这些知识也可以写出很好的程序(从代码 组织上来说这些是足够了,但要做好的产品,还要加上算法、对技术领域的了解、对业务领域的了解)。 |