现在的位置: 首页 > 综合 > 正文

从当前的项目说起-杂说编码

2019年11月20日 ⁄ 综合 ⁄ 共 3358字 ⁄ 字号 评论关闭

    公司的项目已经到了收口阶段,虽然那些业务人员还在没完没了的提需求,但实质性的变更已经不多了。由于这次项目使用了全新的框架,当时看起来工期又紧,而我进入项目的时间又恰巧是编码开始前的一周,因此在开发中几乎是套用人家之前开发好的示例,然后对出现错误的地方进行微调。这样做的结果可想而知,那些本身就是拼凑出来的东西,照着写下去,程序又能好到哪里?虽然代码出自本人之手,说出这话很是痛心疾首,但确实够烂。
    前两天在看月影写的《JavaScript王者归来》,其中一段,大意是说,作为有经验的程序员,在开发时首先要做的不是立即开始编码,而是先要思考,思考该如何写自己的程序。我想我在写程序之前就没思考过,或者虽然思考过,但也没有认真思考,这似乎已经成了我一贯的风格了。像我现在这样的能力,大约在刚工作的时候还是很得公司喜欢的,毕竟能干活呀,但如果想有更深层次的发展,只写出像现在这种代码,肯定是不行的。

    大约是对迭代有误解,又或者是《重构》这本书只学会了一半,我总以为代码写得烂,大不了到后期去调整、去重构,但现实是,当我打开编辑器的时候,一百多个文件,一眼望不到头,虽然其中有大量的重复代码,但就是这些东西,已足以令我胆战心惊了。
    虽然看到程序之后就不再有修改代码的动力了,但在一番心理斗争之后,终于还是下了决心,从今天开始,利用空档修改代码。今天修改量比较少,主要有两处,第一处是OP程序,大约相当于Struts的Action,我们公司叫OP,Operation,交易的意思。我的程序在初始化的时候每次都会生成一个HashMap的字典项,然后设置给有关对象,代码大约如下:
    public class XxxOp {
        ……
        public void doInit() {
            ……
            HashMap hm = new HashMap();
            hm.put(“”, “全部”);
            hm.pub(“01”, “待提交”); 
            hm.pub(“02”, “被退回”);
            selControl.setMap(hm);
            ……
        }
        ……
    }
虽然这个HashMap只是一个局部对象,在调用之后就会因作用域的原因而失效,但这里我想应该注意几个问题:第一,这里所谓的失效,仅仅指作用域结束,并不意味着内存真的被收回了;第二,系统每次调用OP都会生成该对象,虽然该对象看起来不会占用我们对少内存,而且公司提供的服务器性能也绝对一流,但毕竟我们的系统是全国性的,累加起来嘛,呵呵,那可就不一定是小问题了;第三,拥有这样代码的OP还不只一个,有N个OP都会做类似操作。基于以上问题,我开始考虑将字典项抽取出来,放到另一个类中,并且考虑做成单例模式,修改后的程序大体如下:
    public class XxxService {
        private static class MyMap {
            static HashMap hm = new HashMap();
   
            static {
                hm.put(“”, “全部”);
                hm.pub(“01”, “待提交”); 
                hm.pub(“02”, “被退回”);
            }
        }
  
        public static HashMap getMap() {
            return MyMap.hm;
        }
    }

    pulbic class XxxOp {
        ……
        public void doInit() {
            ……
            selControl.setMap(XxxService.getMap());
            ……
        }
        ……
    }
这段代码套用了Bob Lee提供的单例模式,据说可以有效避免多线程的问题,虽然看起来应用的还很生涩,不过这里集中我两个第一次呢。例如static块,以前只是在书本上看到过,从未在实际开发中应用过,而且说出来不怕大家笑话,工作5年了,今天是第一次套用设计模式。虽然这话说出来有点惭愧,但心里还是有种莫名的兴奋。
    另一处改动原代码如下:
    public void doDetail() {
        ……
        String path = null;
        String subtype = getSubtype();
        if (“01”.equals(subtype))
            path = “path1”;
        else if (“02”.equals(subtype))
            path = “path2”;
        else if (“03”.equals(subtype))
            path = “path3”;
        else
            path = “default”;
        this.forward(path);
    }
修改之后如下:
    public void doDetail() {
        ……
        this.forward(getPath(getSubtype()));
    }

    public String getPath(String subtype) {
        String path = null;
        if (“01”.equals(subtype))
            path = “path1”;
        else if (“02”.equals(subtype))
            path = “path2”;
        else if (“03”.equals(subtype))
            path = “path3”;
        else
            path = “default”;
        return path;
}
这里主要考虑的是doDetail方法里集中了太多代码,代码已然难于维护,所以把这段抽取出来,虽然逻辑上没有改变,而性能上可能会较原来有那么一点损失,但出于更长远考虑,我想这样还是值得的。
    其实我之前就一直因为这类问题而遭人诟病,而面向对象程序设计、设计模式、重构这些也确实没有关注过,以前不大懂,总觉得能解决问题、写出代码就行,但经历过几次面试之后,我发现远不是那么回事,还是多了解一些更有益处,而且在今天的代码修改过程中,这些知识的优势也能够看出来了。

 

事后思考
    由于之前没用过static块,不了解执行效果,顺口便问了句技术经理,他推荐我使用Spring,这个东西在我们的项目有所使用。虽然技术经理的法子可以解决我的问题,但我也有所考虑:
    第一,这部分代码一直就没做Spring配置,一旦配置进去,还是有很多东西要改的;
    第二,按照我们系统的配置,Spring会在程序启动的时候把所有字典项加载到内存中,这个是否有必要?
然后我便对static块进行了测试,发现执行效果跟static字段一样,也没啥好担心的,便采用了自己的想法。

 

几句闲话
    虽然今天有点兴奋,但更多的恐怕还是惭愧吧,作为一个有5年工作经验的人,到今天才开始领悟这些东西,不能不总结一下了。
    我想也该给自己充充电了,以前总觉得js、Java、Oracle这些自己都会了,至少干活是没问题的,但自打看了《JavaScript王者归来》之后,终于发现自己不过是只井底之蛙,其实世界上需要学的东西还有太多太多。我想我会先从这本《JavaScript王者归来》开始,然后Java、JSP/Servlet、Oracle、Hibernate、Spring、SOA、设计模式、重构的一本一本读下去。

抱歉!评论已关闭.