• 可测试性战术分析


      本篇博客参考《信息领域热词分析》,设计实现可测试性战术。

      首先我们要了解一下可测试性,软件可测试性是指通过测试(通常是基于运行的测试)揭示软件缺陷的容易程度。

      接下来就介绍在项目开发中运用的可测试性战术:

      1.面向对象编程

      作为一名软件工程的学生,我们都知道编码原则:

    • 单一责任原则
    • 开放/封闭原则
    • 里氏代换原则
    • 接口分离原则
    • 依赖反转原则

      不论是在爬虫爬取信息阶段,还是热词统计阶段,还有最后的可视化展示,都离不开这些原则。尤其是遵循了单一职责原则和接口分离原则后,面向接口编程,

      每一个函数或者对象,都只完成单一的功能,主函数只对其进行调用或传参,可测试性就会大大提高,这些原则会引导我们持续重构。

      单一职责:

    interface UserOpr2 {
        boolean updatePassword(User user, String password);
        boolean updateUserInfo(User user);
    }
    
    class UserOprImpl2 implements UserOpr2 {
    
        @Override
        public boolean updatePassword(User user, String password) {
            user.setPassword(password);
            // update password
            return true;
        }
    
        @Override
        public boolean updateUserInfo(User user) {
            // update user info
            return true;
        }
    }
    View Code

      修改密码和修改名字分离开来,也就是把修改密码和修改名字都当做独自的职责处理,这样子就很清晰明了,你调用哪个方法,就很明确的知道这个方法是实现什么逻辑。

      接口隔离(提高了系统的内聚性,减少了对外交互,降低了系统的耦合性):

     

    package org.byron4j.cookbook.designpattern.segregation;
    
    /**
     * 施乐公司系统机器接口
     */
    public interface IMachine {
        /**
         * 打印
         */
        public void print();
    
        /**
         * 装订
         */
        public void staple();
    
        /**
         * 扫描
         */
        public void scan();
    
        /**
         * 复印
         */
        public void photoCopy();
    }
    
    package org.byron4j.cookbook.designpattern.segregation;
    
    public class XeroxMachine implements  IMachine {
        @Override
        public void print() {
            System.out.println("打印任务...");
        }
    
        @Override
        public void staple() {
            System.out.println("装订任务...");
        }
    
        @Override
        public void scan() {
            System.out.println("扫描任务...");
        }
    
        @Override
        public void photoCopy() {
            System.out.println("复印任务...");
        }
    }
    View Code

      2.使用设计模式

      上学期我们学习过设计模式这门课程,设计模式其实是代码经验的总结。

      比如策略模式,策略模式定义了一组算法,将每个算法都封装起来,并使它们之间可以互换。这个模式让法算法的变化独立于客户端的调用。

      策略模式优点:1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。

      

    package com.hotwords.dao;
     
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.Statement;
    import java.util.ArrayList;
    import java.util.List;
     
    import com.hotwords.entity.entity;
     
    public class dao {
        public List<entity> list1(){
            List<entity> list =new ArrayList<entity>();
            try {
                // 加载数据库驱动,注册到驱动管理器
                Class.forName("com.mysql.jdbc.Driver");
                // 数据库连接字符串
                String url = "jdbc:mysql://localhost:3306/xinwen?useUnicode=true&characterEncoding=utf-8";
                // 数据库用户名
                String username = "root";
                // 数据库密码
                String password = "893225523";
                // 创建Connection连接
                Connection conn = DriverManager.getConnection(url, username,
                        password);
                // 添加图书信息的SQL语句
                String sql = "select * from final_hotword";
                // 获取Statement
                Statement statement = conn.createStatement();
       
                ResultSet resultSet = statement.executeQuery(sql);
       
                while (resultSet.next()) {
                    entity book = new entity();
                    book.setHotwords(resultSet.getString("热词"));
                    book.setNum(resultSet.getString("次数"));
                    list.add(book);
                }
                resultSet.close();
                statement.close();
                conn.close();
    }catch (Exception e) {
        e.printStackTrace();
    }
            return list;
        }
        //
        public List<entity> list2(){
            List<entity> list =new ArrayList<entity>();
            try {
                // 加载数据库驱动,注册到驱动管理器
                Class.forName("com.mysql.jdbc.Driver");
                // 数据库连接字符串
                String url = "jdbc:mysql://localhost:3306/xinwen?useUnicode=true&characterEncoding=utf-8";
                // 数据库用户名
                String username = "root";
                // 数据库密码
                String password = "893225523";
                // 创建Connection连接
                Connection conn = DriverManager.getConnection(url, username,
                        password);
                // 添加图书信息的SQL语句
                String sql = "select * from website";
                // 获取Statement
                Statement statement = conn.createStatement();
       
                ResultSet resultSet = statement.executeQuery(sql);
       
                while (resultSet.next()) {
                    entity book = new entity();
                    book.setHotwords(resultSet.getString("热词"));
                    book.setExplain(resultSet.getString("解释"));
                    book.setWebsite(resultSet.getString("网址"));
                    list.add(book);
                }
                resultSet.close();
                statement.close();
                conn.close();
    }catch (Exception e) {
        e.printStackTrace();
    }
            return list;
        }
    }
    View Code

      

        

       3.特定化访问接口

      面向接口编程有两层含义:类级别,面向接口编程; 方法级别,面向函数接口编程。

      既定的接口具有自我描述性,并能够促进代码的重用性,接口可以提供一种信息,告诉外部一个类需要实现哪些方法。还有助于稳定不同类之间的通信方式,减少了继承两个对象的过程中出现的问题。

      比如 A 对象依赖 B 对象里的 M 方法,而 M 方法会从数据库里读取数据。那么 A 就不要直接依赖 B 的实体类,而引用 B 的接口。 当对 A 编写单测时,只要注入 B 的 接口实现即可。 同理,方法中含有 service 调用时,不要直接依赖 service 调用,而是依赖函数接口,在函数接口中传递 service 调用,如上面的做法。

      

    @FunctionalInterface
    public interface Predicate<T>{
        boolean test(T t);
    }
    public static <T> List<T> filter(List<T> list, Predicate<T> p) {
        List<T> results = new ArrayList<>();
        for(T s: list){
            if(p.test(s)){
                results.add(s);
            }
        }
        return results;
    }
    Predicate<String> nonEmptyStringPredicate = (String s) -> !s.isEmpty();
    List<String> nonEmpty = filter(listOfStrings, nonEmptyStringPredicate);

     

  • 相关阅读:
    青蛙的约会
    欧拉函数
    Tarjan
    计算器的改良
    记忆化搜索
    火柴棒等式
    hdu6601 Keen On Everything But Triangle(主席树)
    P2774 方格取数(网络流)
    第四百二十七、八、九天 how can I 坚持
    第四百二十五、六天 how can I 坚持
  • 原文地址:https://www.cnblogs.com/Aduorisk/p/12397255.html
Copyright © 2020-2023  润新知