• 代码重构——程序员应有的基因


    去年帮另一个项目组赶项目时,总是有很多地方令我不舒服。本人编码有点小小的“洁癖”——即不喜欢见到冗余代码。即时现在忙,没时间整理,但是一有时间,我都尽可能的去重构。也许本人是个完美主义者吧。

    个人认为重构有以下好处:

    • 改善软件的性能、质量。
    • 使架构更加合理。
    • 使代码更容易被理解。
    • 提高软件的扩展性和可维护性。
    • 提高代码的重用率,通用性。
    • 提高软件的开发速度。
    • 更容易发现BUG。
    • 可以提高开发人员的开发水平。

    在我见过的很多代码中,很多程序员宁愿无限复制粘贴代码,也不愿意重构代码。比如经常可以看到这样一个Switch结构中,每个Case块除了某个参数不同,里面的代码几乎一模一样。看到这种代码,不知道是我的悲哀,还是他的悲哀。

    这里就展开说说:

    一、控件绑定

    在开发表单的时候,我们经常会用到下拉列表。如果是服务器控件,我们通常会在后台绑定,但如果是html控件,我们通常需要写JavaScript来绑定,比如下面这个例子:

    $.post(siteBase + "MktUser/Op.aspx?op=items", {}, function(res) {
        if (res != null) {
            // 事业别
            var html = "<option value=''></option>";
            $(res.Data.items).each(function(i, item) {
                html += "<option value='" + item.Id + "'>" + item.Name + "</option>";
            });
            $("#item_id").html(html);
        }
    }, 'json');
    
    这是一个绑定下拉列表(select)的例子,如果每次都写这么多,一个不太复杂的页面也会让这些代码占满,那么我们可以重构下,如下面的代码:
    function setSelect(se, key, data, val, txt, seval, setf) {
        $.post("Op.aspx?op=" + key, data, function (res) {
            if (res != null) {
                var html = "<option value=''></option>";
                var jsonData = (res.Data.items !== undefined ? res.Data.items : res.Data);
                $(jsonData).each(function (i, item) {
                    var jTxt = '';
                    var jVal = '';
                    $.each(item, function (j) {
                        if (j == val)
                            jVal = item[j];
                        else if (j == txt)
                            jTxt = item[j];
                    });
                    html += "<option value='" + jVal + "' " + ((seval !== undefined && seval == jVal) ? "selected='selected'" : "") + ">" + jTxt + "</option>";
                });
                $(se).html(html);
                if (setf !== undefined)
                    setTimeout(setf, 100);
            }
        }, 'json');
    }
    

    二、代码简化、灵活运用

    很多代码我们可以简化或者灵活运用。关于简化,比如使用三元运算符。关于灵活运用,比如很多朋友喜欢将不为空的判断写死在JS里,那么我们也可以换一种方式,比如使用html元素的自定义属性或者文本来判断,比如:

    function valText() {
        var isFlag = true;
        $("td:contains('*')").each(function () {
            var lbl = $(this).text();
            $(this).next().find("input,select").each(function () {
                if ($(this).val() == '') {
                    alert("请填写:o" + lbl);
                    isFlag = false;
                    return isFlag;
                }
            });
            if (!isFlag)
                return isFlag;
        });
        return isFlag;
    }
    

    三、代码归类

    很多人经常羡慕别人有代码库,自己总是没有呢?其实在平常编码中,只要用心重构就会有了。

    在你重构代码的时候,一般你就会思考,如何重构才能够更优,如何重构这段代码就能尽可能多的重复利用(以后也能用),于是乎,有时你会去找找相关的代码,有时你会把类似的处理逻辑的代码统一放在一起,比如邮件处理的代码、文件操作的代码等等。如果是C#,你可以归类,如果是JS,你可以考虑放到一个JS文件里。

    关于这些,大家可以从这里《也把咱的小类库拿出来晒晒》打劫。

    四、提取函数

    提取函数很实用,在VS中使用快捷键——Ctrl+R+M就能实现提取方法了。提取方法一方面方便代码重用,另一方面也增加了发现问题的几率。比如看下面的异常:

    _shutDownMessage=关键目录的更改通知。
    bin dir change or directory rename
    HostingEnvironment initiated shutdown
    关键目录的更改通知。
    bin dir change or directory rename
    HostingEnvironment 导致关闭
    
    _shutDownStack=   在 System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
       在 System.Environment.get_StackTrace()
       在 System.Web.Hosting.HostingEnvironment.InitiateShutdownInternal()
       在 System.Web.Hosting.HostingEnvironment.InitiateShutdown()
       在 System.Web.HttpRuntime.ShutdownAppDomain(String stackTrace)
       在 System.Web.HttpRuntime.OnCriticalDirectoryChange(Object sender, FileChangeEvent e)
       在 System.Web.FileChangesMonitor.OnCriticaldirChange(Object sender, FileChangeEvent e)
       在 System.Web.DirectoryMonitor.FireNotifications()
       在 System.Web.Util.WorkItem.CallCallbackWithAssert(WorkItemCallback callback)
       在 System.Web.Util.WorkItem.OnQueueUserWorkItemCompletion(Object state)
       在 System.Threading._ThreadPoolWaitCallback.WaitCallback_Context(Object state)
       在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       在 System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal(_ThreadPoolWaitCallback tpWaitCallBack)
       在 System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state)
    从上面文字中,我们可以看到异常捕获是到方法为止的,比如类似于“未将对象引用到对象的实例”异常,如果没有报出具体对象的话,茫茫代码中是很难查找的(在很多情况下无法调试或者无法模拟当时环境时),但是我们可以从最后提示的执行的方法名来限定问题代码范围,然后仔细检查推敲。
     
     

    五、方法重载

    有时候,可能要满足多种需求,但是又不想更改代码,那么方法重载就能派上用场了。比如下面两个方法:

       1:      /// <summary>
       2:      /// 将string类型的fDateTime转换为formatStr格式的日期类型
       3:      /// </summary>      
       4:      public static string GetStandardDateTime(string fDateTime, string formatStr)
       5:      {
       6:          DateTime s = Convert.ToDateTime(fDateTime);
       7:          return s.ToString(formatStr);
       8:      }
       9:   
      10:      /// <summary>
      11:      ///将string类型的fDateTime转换为日期类型 yyyy-MM-dd HH:mm:ss
      12:      /// </sumary>
      13:      public static string GetStandardDateTime(string fDateTime)
      14:      {
      15:          return GetStandardDateTime(fDateTime, "yyyy-MM-dd HH:mm:ss");
      16:      }

    最后

    写了这么多,就此结束吧。

    如果你还沉浸在日复一日的重复编码中,那么就想想重构吧。重构也是个费力活,但是却可以让你更上一层楼。

    作者:雪雁
    出处:http://www.cnblogs.com/codelove/
    沟通渠道:编程交流群<85318032> 产品交流群<897857351>
    如果喜欢作者的文章,请关注【麦扣聊技术】订阅号以便第一时间获得最新内容。本文版权归作者和湖南心莱信息科技有限公司共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    静听鸟语花香,漫赏云卷云舒。
  • 相关阅读:
    Java
    Linux
    Linux
    Linux
    Java
    Ansible
    Ansible
    Java
    ACM&OI 基础数论算法专题
    题解 P4781 【【模板】拉格朗日插值】
  • 原文地址:https://www.cnblogs.com/codelove/p/2331479.html
Copyright © 2020-2023  润新知