软件质量属性——可修改性

一、概念

  可修改性理解可理解为:指系统或软件的能够快速地以较高的性价比对系统进行变更的能力。比如说:对于一个网站,我们要修改它某一板块的UI界面,当我们对界面进行修改时是否会引起对另一个UI模块的影响,是否会引起后台控制,业务逻辑代码的变更,是否会引起整个网站的崩溃,这体现了一个网站的整个架构的是否具备可修改性。

二、引起软件可修改性的因素

  1.用户需求

  这里就要看“需求、成本、修改”三者之间的关系了;需求无处不在,时时刻刻产生。判别一个需求的重要性来自于它对系统的成本产生的影响,如果严重影响了系统带来的的收益,那必须对系统进行修改,如果一部分相对于系统来说微不足道,则可以选择性不改。

  举例:一些网站的图标有人觉得不好,有人觉得不错

  场景:使用该系统的人对此系统已经有了明确的认知,或者是已经习惯了这个图标代表的意义,如果修改了,然而对原有的使用者(老顾客)有了错误的判断——此系统停止运维了?则这些客户就会选择其他新的系统。

  结果:系统的可修改性是必备的,但是最终修不修改是靠利益和人为因素决定的。

  2.系统内在需求

  以淘宝为说明对象,相关资料显示,初期的淘宝数据库是MySQL,众所周知MySQL是一个适用于小型企业的数据库,对于起初的淘宝也是适用的,因为没有产生MySQL无法处理的大量数据及相应的实时处理业务。但是近几年来淘宝的数据爆炸产生,在2012年11月30号到达全天访问用户总人数:2亿1千3百万,占中国网民40%;高峰期:每分钟成交订单89678笔。这就要求淘宝网对自身的数据库体系架构进行不断地更新和修改。

三、可修改性战术分类

  可修改性战术目标:控制实现、测试、和部署变更的时间和成本。可修改性可以理解为系统或软件的能够快速地以较高的性价比对系统举行调换的能力。

好比说:对于一个网站,我们要修改它某一板块的UI界面,当我们对界面举行修改时是否会引起对另一个UI模块的影响,是否会引起后台控制,营业逻辑代码的调换,是否会引起整个网站的溃逃,这体现了一个网站的整个架构的是否具备可修改性。

  根据目标划分,为减少由某个变更直接影响的模块的数量的可修改性战术称为“局部化修改“

  1、维持语义的一致性

  语义的一致性是指模块中责任之间的关系,目标是确保所有这些责任都能协同工作,不需要过多得依赖别的模块。

热词分析中亦或者任意项目中比较典型能体现这一战术的便是数据库的相关操作。

  ①数据库连接类DBUtil.java

package reci;

import java.sql.*;

public class Main {
 public static void main(String [] args)
 {
  String driverName="com.microsoft.sqlserver.jdbc.SQLServerDriver";
  String dbURL="jdbc:sqlserver://127.0.0.1:1433;DatabaseName=jsp";
  String userName="sa";
  String userPwd="123";
 try
{
    Class.forName(driverName);
    System.out.println("加载驱动成功!");
}catch(Exception e){
    e.printStackTrace();
    System.out.println("加载驱动失败!");
}
try{
    Connection dbConn=DriverManager.getConnection(dbURL,userName,userPwd);
        System.out.println("连接数据库成功!");
}catch(Exception e)
{
    e.printStackTrace();
    System.out.print("SQL Server连接失败!");
}        
}

}

  ②Service层Service.java

public class TopSearchService{
     private Connection connection = null;    
     private Statement statement = null;    
     private ResultSet resultSet = null;     
    
     @Override    
     public List<String> list() {        
         String sql = "select title from info order by clickCount desc";        
         List<String> list = new ArrayList<>(10);        
         try {            
             connection = DBUtil.getConn();           
             statement = connection.createStatement();           
             resultSet = statement.executeQuery(sql);          
             while (resultSet.next()) {       
                 list.add(resultSet.getString("title"));     
                 }      
             } catch (SQLException e) {       
                 e.printStackTrace();      
             } finally {       
                 DBUtil.close(connection, statement, resultSet);     
             }       
         return list;  
     }

  ③Servlet层Servlet.java

public class TopSearchServlet extends HttpServlet {
     private static final long serialVersionUID = 1L;
     TopSearchService topSearchService=new TopSearchService();   
     /**
      * @see HttpServlet#HttpServlet()
      */
     public TopSearchServlet() {
         super();
         // TODO Auto-generated constructor stub
   }
 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         //设置跨域请求        
         response.setHeader("Access-Control-Allow-Origin","*");        
         //处理中文乱码       
         response.setContentType("text/html;charset=utf-8");        
         //获取热搜列表       
         List<String> lists=topSearchService.list();        
         PrintWriter out=response.getWriter();        
         if (lists.size() > 0) {            
             out.println(toJson(lists));        
         }    
     }
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         // TODO Auto-generated method stub
         doGet(request, response);
     }
}

通过这样一层一层,实现了数据库的访问操作。可修改的体现:

  1.数据库更换,修改DBUtill.java文件即可。

  2.数据表更换,修改持久层中表名即可。

  3.添加功能,在service中定义新的函数。  

数据库操作独立存在,修改不会影响到其他模块。

   2、防止连锁反应

  我们平时编程无论是写函数照样写类,都会被其它的类或方法挪用,若何实现对被挪用部门的修改不会引起对挪用它的部门的影响,这就是连锁反映。

信息隐藏:最大化实现模块分解,最大化的隐藏私有信息,限制通信路径,减少共享数据数量。

对于immutable string 来说,能够从accessor 方法中安全返回。

@interface MYSimpleClass 
{ 
  NSString        *_myStringValue; 
} 
- (NSString *)safeStringValue; 
@end

@implementation MYSimpleClass 
- (NSString *)safeStringValue 
{ 
  // 安全返回
 return    _myStringValue; 
} 
@end

但是,如果是mutable string,下面的accessor 方法将破坏类的封装:

@interface MYSimpleClass 
{ 
  NSMutableString        *_myStringValue; 
} 
- (NSMutableString *)unsafeStringValue; 
@end

@implementation MYSimpleClass 
- (NSMutableString *)unsafeStringValue 
{ 
  / / myStringValue may be changed externally

  return myStringValue; 
}

  安全返回mutabel 变量的解决办法:
  1. 方法要强行 type casting返回变量. mutable -> immutable
  2. 返回变量的一个 mutable copy.

@interface MYSimpleClass 
{ 
  NSMutableString        *_myStringValue; 
} 
- (NSString *)safeStringValue1; 
- (NSMutableString *)safeStringValue2; 
} 
@implementation MYSimpleClass 
- (NSString *)safeStringValue1 
{ 
  // 安全返回方案1 - type casting
  // 
  return myStringValue; 
} 
- (NSMutableString *)safeStringValue2 
{ 
  // 安全返回方案 2 - mutable copy 
  return [[myStringValue mutableCopy] autorelease]; 
}

  个人理解 软件可修改性的核心思想是模块化,并在此基础上,降低模块间的耦合性,提供模块的复用性。模块通过分布式部署,独立的模块部署在独立的服务器上集群从物理上分离模块之间的耦合关系。我们的系统有大量的统计数据。我们的项目随时都有可能进行修改,比如发布新功能,这时就需要在服务器上关闭原有的应用,重新部署新的应用,整个过程要求不影响用户的使用。

   另外,一个项目的架构是随需而变的。关于项目的扩展性架构设计,是对现有系统影响最小的情况下,系统功能可持续扩展及提升的能力。对现有系统影响最小的情况下,系统功能可持续扩展或提升的能力。它是系统架构设计层面的开闭原则,架构设计考虑未来功能扩展,当系统增加新功能时,不需要对现有系统的结构和代码进行修改。

posted @ 2022-03-07 17:32  马梦佳  阅读(1323)  评论(0编辑  收藏  举报