Java代码重构

1、什么是重构?

在不改变代码接口的情况下,对代码作出修改,以改进程序的内部结构。本质上说,重构就是在代码写好之后改进它的设计。

2、重构的目的?

重构的目的是使软件更容易被理解和修改。代码重构是软件开发过程中提高开发效率和质量的重要手段。重构不会改变软件可观察的行为,重构之后软件功能一如既往。

  • 提高代码质量(性能、可读性、可重用性)
  • 修改Bug
  • 增加新功能

3、为什么要重构?

随着需求的不断变更,之前的结构开始慢慢变得不适应。为了快速的完成需求,开发者可能会使用一些违背当前软件架构的方式实现功能,久而久之,这种「另类」的代码越来越多,导致软件之前的结构已经淹没在了这些杂乱无章的逻辑中,使得整个软件没有一个清晰的脉络,严重降低了代码的可读性和可维护性,一点小小的修改都有会造成不可预知的BUG产生。在这种情况下再进行大规模的需求开发,后果可能是灾难性的。重构就是在保留现有功能的基础上,重新梳理软件中的代码结构,让原本杂乱无章的代码重新具有可读性、结构性和可扩展性,增加软件的开发效率,优化程序的性能。重构的范围可大可小,大到涉及整个产品的各个模块,小到一个函数。

重构代码-提取统一的数据访问和业务接口

通用结果返回
public class JsonResult<T> {

    private String code = ResponseCode.SUCCESS.getCode();
    private String message = ResponseCode.SUCCESS.getDesc();
    private T data;

全局响应代码enum

public enum  ResponseCode {

    SUCCESS("200","操作成功!"),
    FAIL("400","网络异常!")
    ;

    private String code;
    private String desc;

    private ResponseCode(String code, String desc){
        this.code = code;
        this.desc = desc;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}

通用服务层
public interface BaseService<T> {
   public List<T> list();
}

接口实现

public class BaseServiceImpl<T> implements BaseService<T> {

    @Resource
    Mapper<T> mapper;

    public List<T> list() {
        return mapper.selectAll();
    }
}
通用Controller
public class BaseController {
    public final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 获取客户端真实IP地址
     *
     */
    public String getRemoteIp(HttpServletRequest request){
        return CusAccessObjectUtil.getIpAddress(request);
    }
}

Spring中Template模式与callback的结合使用浅析

Spring不论是与ibatis,还是与Hibernate的结合中,都使用到了Template模式与callback技术,来达到简化代码实现的目的

public interface BaseTemplate {
    public int insertRecord() throws Exception;
    /**
     *   操作数据库回调接口
     */
    public interface DatebasePoolCallback<T> {
        T doInDatabase(Connection connection);
    }
}

实现

public class BaseTemplateImpl implements BaseTemplate {

    private DatabasePool pool;

    public BaseTemplateImpl(DatabasePool pool){
        this.pool = pool;
    }

    public <T> T execute(DatebasePoolCallback<T> action) throws Exception {
        T value = null;
        Connection connection = null;
        try {
            //执行数据库操作前先取出连接
            connection = pool.getConnection();
            return action.doInDatabase(connection);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            //TODO 返还到连接池
            System.out.println("返还到连接池");
            //returnResource(pool, connection);
        }
    }
    public int insertRecord() throws Exception {
        return execute(new DatebasePoolCallback<Integer>() {
            public Integer doInDatabase(Connection connection) {
                //TODO 数据库操作
                System.out.println("数据库操作");
                return 0;
            }
        }).intValue();
    }
}

利用Java回调机制实现短信自动重发

/**
 * 异常重试工具类
 * @author Suoron
 */
public class RetryUtils {

    private static Logger logger = LogManager.getLogger(RetryUtils.class);

    /**
     * 回调结果检查
     */
    public interface ResultCheck {
        boolean matching();
        
        String getJson();

        HashMap<String, Object> getHashMap();
    }
    
    /**
     * 在遇到异常时尝试重试
     * @param retryLimit 重试次数
     * @param retryCallable 重试回调
     * @return V
     */
    public static <V extends ResultCheck> V retryOnException(int retryLimit,
            java.util.concurrent.Callable<V> retryCallable) {

        V v = null;
        for (int i = 0; i < retryLimit; i++) {
            logger.info("请求第" + (i+1) + "次");
            try {
                v = retryCallable.call();
            } catch (Exception e) {
                e.printStackTrace();                
            }
            logger.info("结果:" + v.getJson());
            if (v.matching()) break;
            logger.info("重试第" + (i+1) + "次");
        }
        return v;
    }
    
    /**
     * 在遇到异常时尝试重试
     * @param retryLimit 重试次数
     * @param sleepMillis 每次重试之后休眠的时间
     * @param retryCallable 重试回调
     * @return V
     * @throws InterruptedException
     */
    public static <V extends ResultCheck> V retryOnException(int retryLimit, long sleepMillis,
            java.util.concurrent.Callable<V> retryCallable) throws InterruptedException {

        V v = null;
        for (int i = 0; i < retryLimit; i++) {
            logger.info("请求第" + (i+1) + "次");
            try {
                v = retryCallable.call();
            } catch (Exception e) {
                e.printStackTrace();                
            }
            logger.info("结果:" + v.getJson());
            if (v.matching()) break;
            logger.info(sleepMillis/1000 + "秒后重试第" + (i+1) + "次");
            Thread.sleep(sleepMillis);
        }
        return v;
    }
    
}

使用

   /**
     * 用于发送短信验证码
     * @param phone     需要接受验证码的手机号码
     * @param template  短信模板ID
     * @return 发送成功或失败  statusCode:错误码, statusMsg:错误信息
     * 000000   成功
     * 160042   号码格式有误
     * 160038   短信验证码发送过频繁
     * 160040   验证码超出同模板同号码天发送上限
     */
    public static HashMap<String, Object> sendSMS (final String phone, final String template, final String...params) {

        final CCPRestSDK restAPI = new CCPRestSDK();

        // 初始化服务器地址和端口,格式如下,服务器地址不需要写https://
        restAPI.init(serverAddress, serverPort);

        // 初始化主帐号和主帐号TOKEN
        restAPI.setAccount(acount, acountToken);

        // 初始化应用ID
        restAPI.setAppId(appId);

        long second = 3 * 1000;

        HashMap<String, Object> result;

        if ("64754".equals(template) || "64757".equals(template)) {
            // 发送(+重试)
            SmsRetry smsRetry = new SmsRetry();
            try {
                smsRetry = RetryUtils.retryOnException(3, second, new Callable<SmsRetry>() {

                    @Override
                    public SmsRetry call() throws Exception {
                        // 发送
                        HashMap<String, Object> result = restAPI.sendTemplateSMS(phone,template ,params);
                        return new SmsRetry().setResult(result);
                    }
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            result = smsRetry.getHashMap();
        } else {
            // 发送
            result = restAPI.sendTemplateSMS(phone,template ,params);
        }

        return result;

/*
        //成功代码:"000000"
        //异常返回输出错误码和错误信息
        "错误码=" + result.get("statusCode") +" 错误信息= "+result.get("statusMsg");
*/
    }

    // 重试
    private static class SmsRetry implements RetryUtils.ResultCheck {

        private HashMap<String, Object> result = null;

        public SmsRetry setResult(HashMap<String, Object> result) {
            this.result = result;
            return this;
        }

        @Override
        public boolean matching() {
            return result != null && "000000".equals(result.get("statusCode").toString());
        }

        @Override
        public String getJson() {
            return JsonUtil.toJson(result);
        }

        @Override
        public HashMap<String, Object> getHashMap() {
            return result;
        }
    }

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,128评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,316评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,737评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,283评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,384评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,458评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,467评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,251评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,688评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,980评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,155评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,818评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,492评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,142评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,382评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,020评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,044评论 2 352