美文网首页
自下而上的开发实践

自下而上的开发实践

作者: zhanghTK | 来源:发表于2018-07-01 17:29 被阅读0次

    title: 自下而上的开发实践
    date: 2016-10-22 19:23:25
    tags:

    • 设计模式
    • Java
      categories: 设计模式

    两种开发思路

    自上而下:设计先行,根据设计开发

    自下而上:开发先行,给予开发重构

    关注点分离

    类似于文章段落的划分,代码拆分的简单过程可以概括为:

    • 分行
      • 方法真实逻辑与业务支撑逻辑的划分
      • 基于模块层次的划分,而不是语句行数的划分
    • 注释
      • 良好命名要胜过写大量的注释
    • 抽象提取方法
      • 合理封装
      • 参数内联
      • 方法名、可访问性
    • 删除不必要的分行与注释

    共性与可变性分析

    软件工程的两个敌人:

    • 共性:开发成本、维护成本
    • 可变性:维护成本

    共性的复用两种模式:

    • 继承
      • 强耦合关系,父类的修改影响所有子类
      • 单继承限制
      • 多态
      • 差异式编程
      • 钩子方法
    • 组合
      • 优先使用
      • 依赖注入
      • 优先组合接口而非实现
        • 控制翻转

    接口

    context+role+collaborator

    好处:类型确定,但实现可变、不确定

    类与接口的关系类似于人与角色的关系:

    • 人可以有多个角色,类可以有多个接口
    • 人的某一个角色的确定是由环境决定的,类某一接口的确定是由上下文环境决定的

    接口设计应当遵循的原则:接口隔离原则(SIP)

    接口应该是干净的,单一的,细粒度的,而不是混合过多的方法,职责单一

    扩展式设计的一般过程:

    1. 分离职责各司其职:关注点分离
      • 向上分离:继承
      • 向外分离:组合
    2. 统一接口:
      • 提炼接口,提供多态
      • 面向接口编程
    3. 引用接口预留空白
      • 依赖注入

    以一个事务为例子展示扩展式设计的一般过程:

    首先,有一个Service,在方法中业务逻辑与JDBC事务粘合在一起:

    public class OrderService {
        private DatabasePool dbPool;
    
        public void subscribTrainings(List<Training> trainings, 
                                      Customer customer) throws SQLException {
            // 初始化方法
            Connection c = null;
            PreparedStatement ps = null;
            Statement s = null;
            ResultSet rs = null;
            boolean transactionState = false;
          
            try {
                // 开启事务 
                s = c.createStatement();
                transactionState = c.getAutoCommit();
                c.setAutoCommit(false);
              
                // 业务操作
                for (Training training : trainings) {
                    addTrainingItem(customer, training);
                }
                addOrder(customer, trainings);
                
                // 提交事务
                c.commit();
            } catch (SQLException sqlx) {
                // 回滚
                c.rollback();
              
                throw sqlx;
            } finally {
                // 关闭操作
                try {
                    c.setAutoCommit(transactionState);
                    dbPool.release(c);
                    if (s != null) s.close();
                    if (ps != null) ps.close();
                    if (rs != null) rs.close();
                } catch (SQLException ignored) {
                }
            }
        }
    
        private void addOrder(Customer customer, List<Training> trainings) {
        
        }
    
        private void addTrainingItem(Customer customer, Training training) {
    
        }
    }
    

    第一步在原始代码上分段并添加注释后代码如上所示。对每段代码提取方法,向上抽象:

    public class TransactionScope {
        private DatabasePool dbPool;
        private Connection connection;
        private PreparedStatement preparedStatement;
        private Statement statement;
        private ResultSet resultSet;
        private boolean transactionState;
    
        public void using() throws SQLException {
            setup();
            try {
                beginTransaction();
                // 留白一个具体的业务的实现:
                //      1. (模板方法)继承->钩子方法
                //      2. (委派)传递一个方法(方法接口)
                commitTransaction();
            } catch (SQLException sqlx) {
                rollbackTransaction();
                throw sqlx;
            } finally {
                teardown();
            }
        }
    
        private void rollbackTransaction() throws SQLException {
            connection.rollback();
        }
    
        private void setup() {
            connection = null;
            preparedStatement = null;
            statement = null;
            resultSet = null;
            transactionState = false;
        }
    
        private void teardown() {
            try {
                connection.setAutoCommit(transactionState);
                dbPool.release(connection);
                if (statement != null) statement.close();
                if (preparedStatement != null) preparedStatement.close();
                if (resultSet != null) resultSet.close();
            } catch (SQLException ignored) {
            }
        }
    
        private void commitTransaction() throws SQLException {
            connection.commit();
        }
    
        private void beginTransaction() throws SQLException {
            statement = connection.createStatement();
            transactionState = connection.getAutoCommit();
            connection.setAutoCommit(false);
        }
    }
    
    public interface Command {
        void execute();
    }
    
    

    现在提炼出了一个本地事务的基本控制模板,实现了事务控制与业务逻辑控制基本分离。

    继续提炼事务控制类的接口,用于横向扩展继承使用:

    public interface TransactionScope {
        void using(Command command) throws SQLException;
    }
    
    public class LocalTransactionScope implements TransactionScope {
        @Override
        public void using(Command action) throws SQLException {
            setup();
            try {
                beginTransaction();
                action.execute();  // 具体的业务逻辑
                commitTransaction();
            } catch (SQLException sqlx) {
                rollbackTransaction();
                throw sqlx;
            } finally {
                teardown();
            }
        }
    }
    
    public class DistructedTransactionScope implements TransactionScope {
        @Override
        public void using(Command command) throws SQLException {
          
        }
    }
    

    调用方通过接口留白,实现依赖注入:

    public class OrderService {
        private TransactionScope transactionScope;
    
        public void setTransactionScope(TransactionScope transactionScope) {
            this.transactionScope = transactionScope;
        }
    
        public void subscribTrainings(List<Training> trainings, 
                                      Customer customer) throws SQLException {
            transactionScope.using(() -> {
                    for (Training training : trainings) {
                        addTrainingItem(customer, training);
                    }
                    addOrder(customer, trainings);
            });
        }
    }
    

    相关文章

      网友评论

          本文标题:自下而上的开发实践

          本文链接:https://www.haomeiwen.com/subject/vjjseftx.html