• 为什么一个项目有那么多BUG


    经常与代码打交道,或多或少总会出些问题。一方面是自己相当然,过去是这样写的,没有问题,通常认为不太可能会出错,另一方面,项目时间紧迫,没有那么多时间去仔细考虑,每天有十几个功能等着你去实现,大多数的programmer会等程序忙完了,测试的时候再发现问题。

    下面我列举一下,在项目开发中,我曾经犯过的错误,有的是我看到过的,我认为有不合理的地方。

    1 时间的处理
    举例:取当前时间是DateTime.Now属性,那么取当前时间的下个月的今天,你是否会用下面的代码
    DateTime  current=DateTime.Now;
    DateTime nextMonth=new DateTime(current.Year, current.Month + 1, current.Day);
    还有,取到昨天和明天的日期,是否是直接调用current.Day+1和current.Day-1。

    2  数据库字段的返回值
    如果要返回的数据库字段值为空,比如
    SELECT  LastName FROM  Northwind.dbo.Employees WHERE  EmployeeID=999
    在程序中,下面的方法合理吗
    DataSet ds = SqlHelper.ExecuteDataSet(sql);
    if (ds.Tables[0].Rows.Count > 0){
       if (ds.Tables[0].Rows[0]["LastName "].ToString() != "")
          { string  name=ds.Tables[0].Rows[0]["LastName ”].Trim(); }  }
    有时候,为了方便,直接拿来就用
    int  age=Int32.Parse(ds.Tables[0].Rows[0]["Age”]);

    3 SQL语句的写法
    经常看到的以下的SQL语句的写法,有什么问题
    1) “SELECT  LastName FROM  Northwind.dbo.Employees
    WHERE  EmployeeID=”+txtEmployeeID.Text ;
    2 )  int EmplyeeID=Convert.ToInt32(txtEmployeeID.Text);
    string sql=”SELECT  LastName FROM  Northwind.dbo.Employees  WHERE  EmployeeID={0} “;
    sql=string.Format(sql,EmplyeeID);

    4  SQL的WHERE参数的位置
    有两种情况,一种是直接在界面的代码中拼接SQL WHERE参数,一种情况是在DAL方法中拼接SQL 参数
    1) DateTime dtFrom = Convert.ToDateTime(txtDateFrom.Text);
          DateTime dtTo = Convert.ToDateTime(txtDateTo.Text);
          string where=” WHERE OTTime BETWEEN “+dtFrom + “ AND "+dtTo ;
    2 )  DataTable tbl=OTReport.GetMonthReport(dtFrom ,dtTo );
    然后在GetMonthReport同上面的代码一样,拼接SQL WHRER参数
    这两种方法,各有什么问题?

    5  比较字符串,你选用下面的哪一种方法
    string obj=txtEmployeeName.Text;
    1) int ret=String.Compare(obj,"CN\\SHLI",true);
    2) “CN\\SHLI”==obj
    3) obj.Trim().Equals(“CN\\SHHLI”, StringComparison.InvariantCultureIgnoreCase)


    6 在需要表示业务处理状态的地方,还在用数字。
    例如:表示申请,审批,拒绝,批准的状态,程序中还在用1,2,3作为标识。
    1表示正在申请中,2 表是审批中,3表示拒绝

    7  在需要用数值类型的地方,仍然还用string
    例如,在SQL语句中无法直接得出一列值,需要在程序中判断后得出,于是多加一列,类型是string
    DataColumn OTSummary = new DataColumn("OTSummary", typeof(string));
    tbl.Columns.Add(OTSummary);

    8  在一个ASP.NET 页面中,还在用静态变量保存临时的变量值。比如,一个页面中同时可以进行新增用户或修改用户两种业务,于是你需要一个静态变量,保存当前的动作状态是Insert还是Update。
    public partial class OTDefault : System.Web.UI.Page  {
    static string Action= "Insert";
    }

    9  在界面层,还在用如下的方法转换用户输入的数据
    比如,你需要用户输入员工编号,刚好你设计的员工表,员工编号的字段类型是int,而且是自增长
    int EmployeeID=Convert.ToInt32(txtEmployeeName.Text);
    或者更喜欢用 int EmployeeID=Int32.Parse(txtEmployeeName.Text);

    10 在设定DropDownList当前选择值时,还是喜欢用SelectedValue
    比如,你有一个DropDownList控件,绑定公司的所有部门的名称.这时,有一个用户A登陆到系统,你需要把DropDownList中的当前选择项目,设为他所在的部门,代码大概是这样写的ddlDepartment.SelectedValue=UserDAL.GetDepartmentName(CurrentUser)

    11  因为需要对数值结果进行四舍五入,在精度要求保留小数点后面一位小数时,你使用方法
    Math.Round,不错,方法选的很对。 可是你对下面的结果始终表示怀疑
    Math.Round(3.44,1)=Math.Round(3.45,1)=3.4

    12  喜欢用查询字符串,通常的情况是拿来即用,简单方便
    string id= Request.QueryString["GUID"];
    Guid key=new Guid(id);

    13 在一个报表呈现界面中,你用AJAX控件,让用户选择日期区间,然后根据用户选择的时间区域,得到报表数据。有两个控件txtDateFrom, txtDateTo
    <asp:TextBox ID="txtDateFrom" runat="server" Width="160"></asp:TextBox><asp:ImageButton ID="btnDateFrom" runat="server" Width="16" ImageUrl="Image/Calendar.png"                                                Height="16"></asp:ImageButton>
    <ajax:CalendarExtender ID="CalendarExtender1" runat="server" PopupButtonID="btnDateFrom"                                                 TargetControlID="txtDateFrom" Format="yyyy-MM-dd"> </ajax:CalendarExtender>

    <asp:TextBox ID="txtDateTo" runat="server" Width="160"></asp:TextBox><asp:ImageButton ID="btnDateTo" runat="server" Width="16" ImageUrl="Image/Calendar.png"                                                Height="16"></asp:ImageButton>
    <ajax:CalendarExtender ID="CalendarExtender1" runat="server" PopupButtonID="btnDateTo"                                                 TargetControlID="txtDateTo" Format="yyyy-MM-dd"> </ajax:CalendarExtender>
    编译,运行一点问题也没有。有一天,用户想查看过去某一天,该天发生的所有业务,于是用下面的代码来获取用户选择的那一天的时间
    DateTime dtFrom = Convert.ToDateTime(txtDateFrom.Text);
    DateTime dtTo = Convert.ToDateTime(txtDateTo.Text);

    程序运行正常,可是什么数据也没有呈现出来。奇怪,明明当天发生过100多笔业务,怎么一笔数据也看不到。

    14  为了返回一个字段的集合,还是习惯ArrayList.
    比如,为了读取数据库中部门表中的所有部门的名称,如下代码
    ArrayList list;
    while(dataRead.Read())
    {    list.Add(dataRead[“DepartmentName”].ToString());    }
    有时候为了省事,也会这样做,直接返回一个数组
    public static string [] GetDepartmentList(string DeparmentID)


    15  不习惯于处理异常,只在开发阶段处理异常。
    在界面层,对于可能会发生的异常,用cath把它截获,导致界面层里一堆一堆的try { } catch{ }
    在业务层,不知道怎样的行为会导致异常,而又不愿意对方法的参数进行效验。
    在数据访问层,发生数据库异常后,没有向上抛出,导致一个问题找了很久也没有找到答案。

    16  同一个项目,因为不同的客户,对于同样的功能,有不同的需求。
    于是直接把代码拷贝两份,分别维护。
    比如,一个IPR项目,有两个客户需要使用,一个是客户A,一个是客户B。当IPR项目开发完后,负责维护客户A的IPR项目的开发员,就只负责维护他的那份拷贝,负责维护B客户的IPR项目的开发员,就只维护他的那份拷贝。
    同样的功能有不同的需求。比如报表,同一个WIP报表,A客户要求的报表格式和B客户要求的格式不一样,而且报表中还要打上他们自己公司的Logo, A客户是要按生产组别呈现数据,B客户要求按照项目名呈现数据,也许还有一个潜在的C客户,他可能会要求报表按照工序来呈现WIP数据。

    17 在数据库字段中很喜欢用自增的ID做主键,而且正在做一个存储配置信息的表,叫IPRParam.
    ID是主键,当ID为1时 表示,当前正在使用的业务的最大的流水号,ID为2表示,当前的报表呈现方式,是按照生产组别,还是按照员工工号,于是,这样的自增ID不停的增长,在你的开发阶段,也从来没有发生过问题。上面两行数据的看起来想这样,
    image
    配置表终于做好了,程序也做好了,于是把这个配置数据表用SQL导入导出功能,导入到服务器中;出错,提示无法导入,一身冷汗。
    于是,还想到可以用一个工具,把SQL表的数据转换为INSERT语句,于是拿来用一下,
    image
    很快就生成了对应的SQL语句,打开查询分析器,执行上面生成的SQL语句,还是报错。
    难道一定要用SQL企业管理器,直接在服务器的数据库表中手工输入这些数据?

    以上所列出的种种问题,不一定是bug,在有些情况下也不会有任何问题。
    当这些问题隐藏在各种业务代码中的时候,你还能都注意到,并且避免吗?

    欢迎大家补充开发中经常出现的错误,让我们做的项目少一些bug,稳定一些,再稳定一些。

  • 相关阅读:
    死锁
    线程池
    jQuery param()作用与使用方法
    jQuery remove()与jQuery empty()的区别
    jQuery局部动态刷新
    jQuery事件函数位置放置的两种方法
    跨语言通信方案的比较—Thrift、Protobuf和Avro
    Nodejs下如何判断文件夹的存在以及删除文件夹下所有的文件
    如何缓存hbase数据以减少下次取数据的时间
    javascript Date对象的介绍及linux时间戳如何在javascript中转化成标准时间格式
  • 原文地址:https://www.cnblogs.com/JamesLi2015/p/1665056.html
Copyright © 2020-2023  润新知