一、概念
可修改性理解可理解為:指系統或軟件的能夠快速地以較高的性價比對系統進行變更的能力。比如說:對於一個網站,我們要修改它某一板塊的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]; }
個人理解 軟件可修改性的核心思想是模塊化,並在此基礎上,降低模塊間的耦合性,提供模塊的復用性。模塊通過分布式部署,獨立的模塊部署在獨立的服務器上集群從物理上分離模塊之間的耦合關系。我們的系統有大量的統計數據。我們的項目隨時都有可能進行修改,比如發布新功能,這時就需要在服務器上關閉原有的應用,重新部署新的應用,整個過程要求不影響用戶的使用。
另外,一個項目的架構是隨需而變的。關於項目的擴展性架構設計,是對現有系統影響最小的情況下,系統功能可持續擴展及提升的能力。對現有系統影響最小的情況下,系統功能可持續擴展或提升的能力。它是系統架構設計層面的開閉原則,架構設計考慮未來功能擴展,當系統增加新功能時,不需要對現有系統的結構和代碼進行修改。