如何写好代码

前言

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

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

什么是好代码

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

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

好代码是什么样子的

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

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.

posted @ 2016-11-15 15:42  一杯半盏  阅读(337)  评论(0编辑  收藏  举报