写一手容易理解的代码是否很重要?
转于 http://publish.itpub.net/a2008/1022/209/000000209000.shtml
【IT168 技术文档】
在过去的三个星期里,我拜访了几个公司,谈及了关于编写容易理解的代码的问题。令人惊奇的是,发现几位程序开发者意见很不一致!下面就是他们的几个不同的想法。
1、只要程序运行良好,其他的我不在意。
2、我没有足够的时间去写好的代码。
3、客户看的不是代码,所以只要应用效果达到要求我就满意了。
4、大部分的客户想用最少的钱换来最大的实惠,还要按时交付使用,我能确定的仅仅是程序的可靠使用。
5、我明白我们可以用分解的办法使程序更加有可读性,但是我们没有时间去做这些。
当我问到阅读别人编写的代码和维护更改这些代码的时候,大多人是这样回答的:
1、这一向不是件很容易的事情。
2、解读这些代码的含义和作用是很困难的。
这里有几个这样的结果,当一个开发者仅仅为了使之工作快速完成,或者他们自己理解,而不关心其他人怎么去理解它。
有个在我的报告里经常用的一个例子,这是一个关于计算出租一个电影所需价钱的方法的程序代码,不同种类的客户与不同种类的电影以及不同的价钱。
Code
public class MovieRenter
{
public double CalculatePrice(string customerType, string movieType)
{
if (customerType == "VIC" && movieType == "Transfer")
return 20;
else if (customerType == "Regular" && movieType == "Transfer")
return 30;
else if (customerType == "VIC" && movieType == "Normal")
return 10;
else if (customerType == "Regular" && movieType == "Normal")
return 20;
else
return 50;
}
}
MovieRenter movieRenter = new MovieRenter();
double price = movieRenter.CalculatePrice("VIC", "Transfer");
我问出席的人员这个办法怎么样,我很吃惊他们说很好。有人告诉我,应该使用枚举和switch语句而不是字符串,在出席人员的帮助下我做了些修改,使用枚举和switch语句代替。结果就是下面的代码:
Code
public class MovieRenter
{
public double CalculatePrice(CustomerType customerType, MovieType movieType)
{
switch (customerType)
{
case CustomerType.VIC:
switch (movieType)
{
case MovieType.Transfer:
return 20;
case MovieType.Normal:
return 10;
default:
return 20;
}
break;
case CustomerType.Regular:
switch (movieType)
{
case MovieType.Transfer:
return 30;
case MovieType.Normal:
return 20;
default:
return 30;
}
break;
default:
return 30;
}
}
public enum MovieType
{
Transfer,
Normal
}
public enum CustomerType
{
VIC,
Regular
}
MovieRenter movieRenter = new MovieRenter();
double price = movieRenter.CalculatePrice(CustomerType.VIC, MovieType.Transfer);
当我问我们是不是可以把它做得更好,有人想分裂switch语句内的CustomerType.VIC作为一个单独的方法, CustomerType.Regular 。我做了那些改变,每一个人都很高兴。问题是代码里的条件语言是很难理解的,就像需要新增加一类电影和客户,需要增加更多的条件在代码里面,迟早代码会变 得难于理解和维护。因此,有件事我们可以这样做,用多态语句替换条件语言。
如果我们审查这段代码,我们会发现,有一个客户和一场电影, 当一个客户要租。所以我们建立2个实体,一个客户实体,一个电影实体。我们可以增加一个价格上的折扣给我们的客户实体,一个金钱上的价格给流动的客户群。 一部电影有自己的价格,客户实体有他们的折扣。现在,当我们有一个客户和一部待租的电影,我们需要确定有不同种类的客户群和不同电影的等级描述。我们不是 想增加一个客户群或者电影适合客户或者电影的等级,如果我们这样做,将用新的条件语句结束。所以我们建立一个叫做VIC的客户群,作为继承的客户,同样, 我们也要建立一个用于继承的转移电影类别。我们让客户类别代表老客户和电影级别为正常的电影。由于VIC的客户应该有它自己的折扣和转移电影应该有它自己 的价格,我们确定这些虚拟财富的实质上是我们优先服务于我们的会员。
Code
public class Customer
{
public virtual double Rebate
{
get { return 0; }
}
}
public class CustomerVIC : Customer
{
public override double Rebate
{
get { return 10; }
}
}
public class Movie
{
public virtual double Price
{
get { return 20; }
}
}
public class MovieTransfer : Movie
{
public virtual double Price
{
get { return 30; }
}
}
如果比较一下普通客户和会员客户,我们可以看到会员会有10个折扣,所以我们确定会员电影价格的折扣在普通客户之上的会员返还折扣的级别。转移电影的价格是30,普通电影的价格是20. 现在,当我们建立我们的客户和电影,在这种情况下,应采取客户作为一个论据和电影,我们能改变电影租赁人计算价格的方法。
Code
public class MovieRenter
{
public double CalculatePrice(Customer customer, Movie movie)
{
return movie.Price - customer.Rebate;
}
}
CustomerVIC vicCustomer = new CustomerVIC();
MovieTransfer transferMovie = new MovieTransfer();
MovieRenter movieRenter = new MovieRenter();
double price = movieRenter.CalculatePrice(vicCustomer, transferMovie);
所以在采用多态性和更多标准实用的程序设计方法,我们可以移走条件语言。如果我们需要增加一种新的客户或电影,我们只需建立一个新的组别,从而继 承基本组别属性而不必理会折扣和价格。任何人都可以有其他的建议使开始那段代码变得更加好,所以,即使它原来能工作,那么把它做的更好是否更重要呢?
当你准备写代码的时候,你认为什么最重要呢?
当开发者写代码出错的时候,你认为什么是最常见的事情呢?
猛的一看,有可能不理解这其中的奥妙,但笔者所希望的也就是让这种编码风格成为你我的习惯