zoukankan      html  css  js  c++  java
  • 如何写好代码

    前言

    最近在接手别人的项目,看人家的代码是痛苦的,尤其是写的不怎么样的代码。想到之前看了一本《代码整洁之道》,对我影响深远,便想作此文舒缓一下心情。

    如果你是大牛请忽略本文。

    什么是好代码

    书中说:好的代码就是它恰好为解决某一问题而存在。
    听人说:好的代码就是给一个应届毕业生也可以看懂。

    我现在深深的秉承 单一职责原则,就这一条足以写出我认为漂亮的代码。
    作为一个无名小卒,为了梦想,就算为了后人能看懂,必须好好写代码。

    好代码是什么样子的

    举个抽象的例子,如果代码写成这样,把所有的逻辑按照顺序都堆砌在这个方法中,那么这段代码或许思路清晰,路径考虑周全,效率非常高,但是这并不算好的代码。

    public class MechandiseManager{
        private static final Integer TYPE_ONE = 1;
        private static final String CODE_EXAMPLE_DELICIOUS = "delicious";
        private static final String MAP_KEY_EXAMPLE = "key";
        private static volatile boolean running = false;
        @Autowired
        private static SomeService someService;
    
    public static GoodsParam setGoodParam(String code,Integer id, Float price, Integer type) throws Exception{
            GoodsParam goodParam = new FoodParam();
            goodParam.setCode(code);
            goodParam.setXXId(id);  
            if(type.equals("1")){
                if(){
                //shit mass
                }else{
                //shit mass
                }
                for(int i=0;i<SOME;i++){
                    map.get("field1");
                }
            }else{
                String val = someDataMap.get(obj.getSomeField());
                if(val==SOME || ((CONDITION2)&&(CONDITION3))){
                    //shit mass
                    Data data = someService.selectSomeData();
                    for(){
                    }
                }else{
                //shit mass
                    if(){
                    }
                }
            }
            if(){
            //businsess
            }
            return goodParam ;
        }
    }

    分析代码

    代码中if条件语义不是非常人性化,分支混乱,本来是处理Goods的参数的,混杂太多条件,写的人或许过一段时间再来,就看的云里雾里,更别指望别人来给他改BUG。不过,该代码值得参考的地方在于设置了一些可读性强的常量。

    改进代码

    public static GoodsParam setGoodParam(String code,Integer id, Float price, Integer type) throws Exception{
            GoodsParam goodParam = new FoodParam();
            goodParam.setCode(code);
            goodParam.setXXId(id);  
            if(type.equals(TYPE_ONE)){
                processSomething(goodParam);
            }else{
                String val = someDataMap.get(MAP_KEY_EXAMPLE);
                processAnotherThing(goodsParam,val);
            }
            if(){
            //businsess
            }
            return goodParam ;
    }

    再次改进

    public static GoodsParam setGoodParam(String code,Integer id, Float price, Integer type) throws Exception{
            GoodsParam goodParam = new FoodParam();
            goodParam.setCode(code);
            goodParam.setXXId(id);  
            if(isTypeONE(type)){
                processSomething(goodParam);
            }else{
                processAnotherThing(goodsParam,val);
            }
            thenProcessSomeThing();
            return goodParam ;
    }
    
    public static boolean isTypeONE(Integer type){
        return type.equals(TYPE_ONE);
    }

    终极改进

    public static GoodsParam setGoodParam(String code,Integer id, Float price, Integer type) throws Exception{
            GoodsParam goodParam = new FoodParam();
            goodParam.setCode(code);
            goodParam.setXXId(id);  
            processType(goodParam );
            thenProcessSomeThing();
            return goodParam ;
    }

    多学习开源项目

    以下节选自Spring框架的内部源码:

    public void refresh() throws BeansException, IllegalStateException {  
            synchronized (this.startupShutdownMonitor) {  
                // Prepare this context for refreshing.  
                prepareRefresh();  
    
                // Tell the subclass to refresh the internal bean factory.  
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();  
    
                // Prepare the bean factory for use in this context.  
                prepareBeanFactory(beanFactory);  
    
                try {  
                    // Allows post-processing of the bean factory in context subclasses.  
                    postProcessBeanFactory(beanFactory);  
    
                    // Invoke factory processors registered as beans in the context.  
                    invokeBeanFactoryPostProcessors(beanFactory);  
    
                    // Register bean processors that intercept bean creation.  
                    registerBeanPostProcessors(beanFactory);  
    
                    // Initialize message source for this context.  
                    initMessageSource();  
    
                    // Initialize event multicaster for this context.  
                    initApplicationEventMulticaster();  
    
                    // Initialize other special beans in specific context subclasses.  
                    onRefresh();  
    
                    // Check for listener beans and register them.  
                    registerListeners();  
    
                    // Instantiate all remaining (non-lazy-init) singletons.  
                    finishBeanFactoryInitialization(beanFactory);  
    
                    // Last step: publish corresponding event.  
                    finishRefresh();  
                }  
    
                catch (BeansException ex) {  
                    // Destroy already created singletons to avoid dangling resources.  
                    destroyBeans();  
    
                    // Reset 'active' flag.  
                    cancelRefresh(ex);  
    
                    // Propagate exception to caller.  
                    throw ex;  
                }  
            }  

    再看一个DispatcherServlet的源码:

        protected void onRefresh(ApplicationContext context) throws BeansException {  
            initStrategies(context);  
        }  
    
        /** 
         * Initialize the strategy objects that this servlet uses. 
        * <p>May be overridden in subclasses in order to initialize 
        * further strategy objects. 
        */  
        protected void initStrategies(ApplicationContext context) {  
            initMultipartResolver(context);  
            initLocaleResolver(context);  
            initThemeResolver(context);  
            initHandlerMappings(context);  
            initHandlerAdapters(context);  
            initHandlerExceptionResolvers(context);  
            initRequestToViewNameTranslator(context);  
            initViewResolvers(context);  
        }  

    有没有觉得非常清晰,一步一步,非常震撼,当时见到的时候真的觉得自己写的代码写的就是Shit…

    总结

    个人总结:写代码并不是一下子就能写出那么漂亮而简洁的代码,在写的过程中,要像写文章一样思考,而不是记流水账一样,想到哪里就写到哪里,先把逻辑写完,然后回顾代码,看看能不能把那些分支,循环尽可能简化,例如把每一个判断都尽可能让人看懂,用一个函数表达他的含义,这样函数调用函数,层次分明,看着就知道哪一步是做什么,哪一步又需要处理什么,一目了然。以后再查看自己的代码或者别人维护你的代码时,自顶向下,由主干要枝叶,条理清晰,神清气爽。

    在下无名小卒,但愿能 make you impressive.

  • 相关阅读:
    HeidiSQL 导入Excel数据
    两片74门实现的双边沿D触发器
    java多线程
    java集合框架
    java异常处理
    java基础学习5
    java基础学习4
    Java基础学习3
    Java基础学习2
    LeetCode 184场周赛
  • 原文地址:https://www.cnblogs.com/slankka/p/9158507.html
Copyright © 2011-2022 走看看