• “设计”你的代码(转)


    今天一个曾经共事的同行问我:“要从编码转为设计,大概需要多长时间?”
    我的回答是:“编码本身就是一种设计,你可以设计你的代码。”

     

    其实正如概要设计与详细设计,系统设计与架构设计一样,编码与设计也是没有明显的边界,每个正确成长的程序员,都必须从编码开始,慢慢锻炼抽象思维、逻辑思维、面向对象思维,然后慢慢的过渡到系统设计,再随着经验和知识的积累,慢慢过渡到架构设计。下面我将会以最近的一个手头的编码任务,简单介绍一下如何“设计”你的代码。

    任务是这样的,某银行支付系统的客户端接收银行用户录入的转账数据,当转账数据被审批通过后,状态转变为“transfer”,同时,该客户端需要通过JMS以异步的方式向支付系统后台发送一条带有转账记录(Instruction)的消息,后端在接收到信息之后,需要根据Instruction的一些相关信息,首先确定这笔转账数据是直接发送给真正进行转账的清算(Clearing)银行系统,还是停留在后端系统,等待后端系统中需要执行的工作流程(work flow)。而后端系统需要对Instruction执行的工作流程有两个,同时需要根据Instruction的一些相关信息进行选择。
    为了简化复杂度,我这里假设系统有一个InstructionHandleMsgDrivenBean,该bean有一个onMessage()方法,所有业务逻辑需要在该方法中实现。

    同时解释一下详细的业务细节:

    • 判断Instruction是否需要停留在后端等待执行指定的工作流程有三个条件:xx、yy、zz,当三个条件都为true时,停留。
    • 判断Instruction需要走A流程还是B流程,由4个因素的组合确定,如果用“Y”代表true,“N”代表false,那么由这个四个因素组成的“XXXX”一共有16种组合,不同的组合分别走A和B流程,如:YYNN、YYNY to A,NNYY、NNNY to B,……不累赘。
    好了,对于一个纯编程人员来说,拿到这样的需求,感觉逻辑很简单,可以直接编码了,于是,他开始一行一行的编写代码(伪代码):

     

    public void onMessage(InstructionInfo instructionInfo) {
        if(xx && yy && zz) { // 停留在后端等待执行指定的工作流程
            // 根据每种组合进行条件判断,走哪个流程
            if(a==true && b==true && c==true && d==true {
                ...
            }
            else if(...) {...}
            else if(...) {...}
            ...
            else(...) {...}     
        }
    }

    这种做法是最为开发人员欢迎的,因为它简单、直接,但这种做法也恰恰反映了开发人员的通病——使用Java编写纯面向过程的代码。

    好了,说了一大堆,如何“设计”你的代码呢?答案是:使用面向对象思维:

    我们拿到需求之后,可以分析,这个需求大体上分为两部分:

    • 判断是否需要停留在后端等待执行指定的工作流程的部分
    • 选择走哪个工作流程的部分

    有了这个前提,我可以设计出两个职责单一的对象了:

     

    public class InstructionHandleDecisionMaker {
        public static boolean isHandledByBackEnd(InstructionInfo info) {
            return (isXX(...) && isYY(...) && isZZ(...));
        }

        private booolean isXX(...) {
            //TODO Implement the logic
            return false;
        }
        private booolean isYY(...) {
            //TODO Implement the logic
            return false;
        }
        private booolean isZZ(...) {
            //TODO Implement the logic
            return false;
        }
    }

    public class InstructionWorkFlowSelector {
        private static Map mapping = new HashMap();
        static {
            mapping.input("YYNN",WorkFlow.A);
            mapping.input("NNYY",WorkFlow.B);
            ...
        }

        public static WorkFlow getWorkFlow(Instruction info) {
            StringBuilder result = new StringBuilder();
            result.append(isA(...)).append(isB(...));
            result.append(isC(...)).append(isD(...));
            return mapping.get(result.toString());
        }
        private static String isA(...) {
            //TODO Implment the logic
            return "N";
        }
        private static String isB(...) {
            //TODO Implment the logic
            return "N";
        }
        private static String isC(...) {
            //TODO Implment the logic
            return "N";
        }
        private static String isD(...) {
            //TODO Implment the logic
            return "N";
        }
    }

    可以看到,我先按职责划分了类,再按职责抽取了私有方法,“框架”设计好 ,为了让编译通过,我上面完整的填写了代码的,然后加上TODO标识,然后,我可以编写我的onMessage方法了:

    public void onMessage(InstructionInfo instructionInfo) {
        if( InstructionHandleDecisionMaker.isHandledByBackEnd(...) ) {
            WorkFlow wf =InstructionWorkFlowSelector.getWorkFlow(...);
            //TODO Implment the logic
        }
    }

    到目前为止,我已经用纯面向对象的思维方式“设计”好我的代码了,这时,我思维非常清晰,因而代码结构也非常清晰,职责单一,内聚高,耦合低,最后,我可以根据需求文档的细节(没有描述)慢慢的编写我的实现了。

    复杂的事物总是由一些较简单的事物组成,而这些较简单的事物也是由更简单的事物组成,如此类推。因此,在编写代码的时候,先用面向对象的思维把复杂的问题分解,再进一步分解,最后把简单的问题各个击破,这就是一种设计。开发人员只要养成这种习惯,即使你每天都只是做最底层的编码工作,其实你已经在参与设计工作了,随着知识和经验的累积,慢慢的,你从设计代码开始,上升为设计类、方法,进而是设计模块,进而设计子系统,进而设计系统……,最终,一步一步成为一个优秀的架构师。

    最后,有一个真理奉献给浮躁的程序员:

    优秀的架构师、设计师,必定是优秀的程序员,不要因为你的职位上升了,就放弃编码。

    补充说明:本博文纯粹是讨论一种思维习惯,不要把其做法生搬硬套,不管实际情况,直接在编码的时候这样做,不见得是最好的选择。在实际编码中,有如下问题你必须考虑:

    • 你需要考虑业务逻辑的可重用性和复杂程度,是否有必要设计出新的类或抽取新的私有方法来封装逻辑,或者直接在原方法上编码(如果足够简单)。
    • 新的业务逻辑,是否在某些地方已经存在,可以复用,即使不存在,这些逻辑是应该封装到新的类中,还是应该放置到现有的类中,这需要进行清晰的职责划分。
    • 需要在设计和性能上作出权衡。
    • 如果在现成的系统中增加新的功能,而现成系统的编码风格与你想要的相差很远,但你又没有足够的时间成本来进行重构,那么还是应该让你的代码与现成系统保持一致的风格。
    posted on 2010-04-28 00:51 Johnny.Liang 阅读(2018) 评论(8)  编辑  收藏 所属分类: 编程技巧 系统设计


  • 相关阅读:
    Vimium -为键盘而生
    Sublime Text 3 修改配色主题【侧边框之...】
    MyBatis-Plus文档地址
    解决:电脑新建文件后需要刷新才显示
    技术书籍博客
    js获取浏览器当前窗口的高度长度
    DataGridView隐藏列用CSS实现
    判断windows操作系统平台
    iis7.5错误 配置错误
    vmware安装mac
  • 原文地址:https://www.cnblogs.com/softwareking/p/1999258.html
Copyright © 2020-2023  润新知