设为首页 加入收藏

TOP

改善代码可测性的若干技巧(三)
2018-01-11 06:06:47 】 浏览:584
Tags:改善 代码 若干 技巧
ng tableName, List<String> rowKeyList, String cfName, List<String> columns, boolean allowNull) throws Exception { HTable table = getHtable(tableName); final String cf = (cfName == null) ? "cf" : cfName; List<Get> gets = rowKeyList.stream().map( rowKey -> { String rowKeyNotEmpty = (rowKey == null ? "null" : rowKey); Get get = new Get(Bytes.toBytes(rowKeyNotEmpty)); if (columns != null && !columns.isEmpty()) { for (String col: columns) { get.addColumn(Bytes.toBytes(cf), Bytes.toBytes(col)); } } return get; } ).collect(Collectors.toList()); Result[] results = table.get(gets); logger.info("Got {} results from hbase table {}. cf: {}, columns: {}", results.length, tableName, cf, columns); List<Result> rsList = new ArrayList<>(); for (int i = 0; i < rowKeyList.size(); i++) { if (!allowNull && isResultEmpty(results[i])) { logger.warn("cant't get record for rowkey:{}", rowKeyList.get(i)); continue; } rsList.add(results[i]); } logger.info("got {} rows from table {} with {} rowkeys", rsList.size(), tableName, rowKeyList.size()); return rsList; }

这段代码有大部分代码惯有的毛病:多个逻辑混杂在一起;大量条件性的业务逻辑中间藏有一小段外部依赖的调用(HTable table = getHtable(tableName); Result[] results = table.get(gets); 访问 Hbase数据源),而这一小段外部依赖使得整个方法的单测编写变得麻烦了。 在 “使用Java函数接口及lambda表达式隔离和模拟外部依赖更容易滴单测” 一文中已经指出,只要使用一个 BiFunction 来模拟 Result[] results = table.get(gets); 这段调用,即可使得 getRows 整个方法变成纯函数。 不过,这个方法已经有好几个参数了,再增加一个参数会比较难看。可以应用参数对象模式,将多个紧密关联的原子参数聚合为一个参数对象。注意到 htableName,rowkeyList, cf, columns, allowNull 确实是从Hbase获取数据所需要的紧密关联的参数聚合,因此适合参数对象模式。重构后代码如下所示:

    public List<Result> getRows(String tableName, List<String> rowKeyList,
                                String cfName, List<String> columns,
                                boolean allowNull) throws Exception {
        return getRows(
            new HbaseFetchParamObject(tableName, rowKeyList, cfName, columns, allowNull),
            this::getFromHbase
        );
    }

    private Result[] getFromHbase(String tableName, List<Get> gets) {
        try {
            HTable table = getHtable(tableName);
            return table.get(gets);
        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
            throw new RuntimeException(ex);
        }
    }

    public List<Result> getRows(HbaseFetchParamObject hbaseFetchParamObject,
                                BiFunction<String, List<Get>, Result[]> getFromHbaseFunc) throws Exception {
        String tableName = hbaseFetchParamObject.getTableName();
        String cfName = hbaseFetchParamObject.getCfName();
        List<String> rowKeyList = hbaseFetchParamObject.getRowKeyList();
        List<String> columns = hbaseFetchParamObject.getColumns();
        boolean allowNull = hbaseFetchParamObject.isAllowNull();

        String cf = (cfName == null) ? "cf" : cfName;
        List<Get> gets = buildGets(rowKeyList, cf, columns);
        Result[] results = getFromHbaseFunc.apply(tableName, gets);
        logger.info("Got {} results from hbase table {}. cf: {}, columns: {}", results.length, tableName, cf, columns);
        List<Result> rsList = buildResult(rowKeyList, results, allowNull);
        logger.info("got {} rows from table {} with {} rowkeys", rsList.size(), tableName, rowKeyList.size());
        return rsList;
    }

    private List<Get> buildGets(List<String> rowKeyLis
首页 上一页 1 2 3 4 下一页 尾页 3/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Java Proxy 和 CGLIB 动态代理原理 下一篇200 行 Java 代码搞定计算器程序

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目