在效率和可靠性之间挣扎

 
写程序,完成功能是最基本的要求,但要应对真实世界的各种情况,则会追求多种目标,如性能、稳定性、可扩展性、可维护性等。然而,在某一个历史阶段,有些目标之间是相互冲突的,需要程序设计人员选择合适的策略,在冲突与矛盾中寻求平衡,以达到最佳的综合效果。其中,效率和可靠性是一对矛盾,需要小心面对。
举个例来说,使用asp.net从SQL Server数据库中读取数据时,我们一般会使用SqlDataReader。.如: SqlDataReader reader = cmd.ExecuteReader();
获得reader对象之后,一般采用循环语句逐条读出记录,如
while(reader.Read())
{
       reader[“UserName”].value.ToString();
       reader.GetString(1);
}
在上面的循环语句中,我采用了两种方法来读取数据。第一个语句读取记录的第1个字段:UserName,并将其转换成字符串,第二条语句直接根据索引号,返回字符串。已经有很多文章说明,用第2条语句的方法比用第1条语句的方法,效率更高(可以去理解和测试一下)。
毫无疑问,我在程序中会追捧第2第语句的方法,即便只会带来少许的性能提高,在成千上万次数据读取中,差别就明显了。
根据效率优先原则,我选择了第2条语句所采用的方法来读取数据。但问题犹如幽灵,总会在你得意时对你当头一棒!假设字段的内容为空(在这数据库表中大量存在)时,你将会遭遇一个错误:“数据为空。不能对空值调用此方法或属性。”这个错误会让你手足无措。
但是,你采用第1条语句的方法,在字段值为空时,却不会有前面的错误。由此可推断,微软在实现GetString()时,并没有打算处理数据为空的情况。效率优先原则在这里遭遇了挫折。系统漏洞百出,再高的效率也没有多大意义,尤其对于面向公众的信息网站来讲,更是这样。
是不是就放弃第2条语句的方法,全部采用第1条语句的方法呢?如果能够尽可能利用两种方法的优点就更好了。
解决这个问题就要摒弃一刀切,根据具体情况具体分析。如果字段在定义时就不能为空的,就可以不用考虑空值的情况,采用第2条语句的方法,以提高效率。如果字段定义可以为空时,则采用第1条语句的方法,以提高可靠性。
当然,也可以先进行空值判断,再采用第2条语句的方法,如:
string userName = reader.IsDBNull(1)?null:reader.Getstring(1);
这样,就可以在保证可靠性和提高效率之间都有所照顾。
类似这样的效率与可靠性之间的矛盾,在程序中大量存在。有时可能为了应付发生概率很小的意外,却要写上大段大段的代码来进行检测、分析和处理。
从某处看了一段使用FileUpload控件来上传图象的代码。点击浏览按钮,可以选择相应图片文件,并使文件全路径显示在控件的文本框中。然后再通过一段代码来实现上传:
            imagePath = upImage.PostedFile.FileName;
            // 取得图片类型
            imageType = imagePath.Substring(imagePath.LastIndexOf(".") + 1);
            // 取得图片名称
            imageName = imagePath.Substring(imagePath.LastIndexOf("//") + 1);
            string tmp = imageName.Split('.')[0];
            string hashImageName =tmp.GetHashCode().ToString() + "." + imageType;
 
            // 判断是否指定图片格式
            if ("jpg" == imageType || "JPG" == imageType || "gif" == imageType || "GIF" == imageType || "bmp" == imageType || "BMP" == imageType || "Bmp" == imageType)
            {
                imageUrl = "~/Images/" + hashImageName;
                try
                {
                    // 建立虚拟路径
                    mPath = Server.MapPath("~/Images");
                    // 保存到虚拟路径
                    upImage.PostedFile.SaveAs(mPath + "//" + hashImageName);
                    Response.Write(" 图片上传成功!" );
                }
                catch(Exception err)
                {
                    Response.Write(err.Message + ", 图片上传失败!" );
                }
            }
            else
            {
                Response.Write("<script language='javascript'> alert(' 对不起!请您选择jpg/bmp/gif格式的图片!');</script>" );
                return;
            }      
        }
 
这一段代码,对文件格式进行了判断,如果格式是指定的图片格式之一,则执行上传。一般情况下,这段程序没有问题。但是,当我选择了图片之后,却人为修改了控件文本框中的路径和文件信息,修改后的文件可能并不存在,此时会发生什么呢?
我曾以为程序不会正常运行,上传图片会失败。然后实验的结果却是显示了“图片上传成功!”。查看服务器上图片文件夹,发现确实有了指定的文件名,但图像大小为0字节。这说明这个成功的信息是个假象!(看来有必要去理解SaveAs()的真实原理)。
为了防止原文件不存在,却能上传成功的假象出现,在进行上传之前,有必要对原文件是否存在进行验证。于是我前面的代码前加了一个判断语句:
if (File.Exists(upImage.PostedFile.FileName))
{
}
这样,就可以得到这样一个逻辑:
  逻辑图
 这一个流程图,两次判断对于大多数操作来讲,没有任何意义,如果不要这两个判断,效率会更高。但对于少数不按“规矩”办事的操作来讲,这两次判断必不可少,没有就会出现问题。
总而言之,要做优雅的程序,需要缜密的思考,仔细应对意外情况,同时尽可能保证效率,才能使程序的最大限度地接近期望的目标。
 
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值