Java_語法基礎_邊界,邊界,還是邊界

某商家生產的電子產品非常暢銷,需要提前30天預訂才能搶到手,同時它還規定了一個會員可擁有的最多產品數量,目的是防止囤積壓貨肆意加價。會員的預定過程是這樣的:先登錄官方網站,選擇產品型號,然後設置需要預定的數量,提交,符合規則即提示下單成功,不符合規則提示下單失敗。後臺的處理邏輯模擬如下:

package deep;

import java.util.Scanner;

public class Client {
    // 一個會員擁有產品的最多數量
    public static final int LIMIT = 2000;

    public static void main(String[] args) {
        // 會員當前擁有的產品數量
        int cur = 1000;
        Scanner input = new Scanner(System.in);
        System.out.println("請輸入需要預定的數量:");
        while (input.hasNextInt()) {
            int order = input.nextInt();
            // 當前擁有的與準備訂購的產品數量之和
            if (order > 0 && order + cur <= LIMIT) {
                System.out.println("你已成功預定了" + order + "個產品!");
            } else {
                System.out.println("超過限額,預訂失敗!");
            }
        }
    }
}

這是一個簡單的訂單處理程序,其中cur代表的是會員已經擁有的產品數量,LIMIT是一個會員最多擁有的產品數量(現實中這兩個參數當然是從數據庫中獲得的,不過這裏是一個模擬程序),如果當前預訂數量與擁有數量之和超過了最大數量,則預訂失敗,否則下單成功。業務邏輯很簡單,同時在Web界面上對訂單數量做了嚴格的校驗,比如不能是負值、不能超過最大數量等,但是人算不如天算,運行不到兩小時數據庫中就出現了異常數據:某會員擁有產品的數量與預訂數量之和遠遠大於限額。怎麼會這樣?程序邏輯上不可能有問題呀,這是如何產生的呢?我們來模擬一下,第一次輸入:

請輸入需要預定的數量:
600
你已成功預定了600個產品!

這完全滿足條件,沒有任何問題,繼續輸入:

請輸入需要預定的數量:
2147483647
你已成功預定了2147483647個產品!

看到沒,這個數字遠遠超過了2000的限額,但是竟然預訂成功了,真是神奇!
看着2147483647這個數字很熟?那就對了,它是int類型的最大值(2^31-1),沒錯,有人輸入了一個最大值,使校驗條件失效了,Why?我們來看程序,order的值是2147483647,那再加上1000就超出int的範圍了,其結果是-2147482649,那當然是小於正數2000了!一句話可歸結其原因:數字越界使校驗條件失效。

所以我們可以把判斷條件修改爲(order > 0 && order <= LIMIT - cur),這樣就避免了用戶輸入的數值參與計算,而僅用來比較。

在單元測試中,有一項測試叫做邊界測試(也有叫做臨界測試),如果一個方法接收的是int類型的參數,那以下三個值是必測的:0、正最大、負最小,其中正最大和負最小是邊界值,如果這三個值都沒有問題,方法纔是比較安全可靠的。我們的例子就是因爲缺少邊界測試,致使生產系統產生了嚴重的偏差。

也許你要疑惑了,Web界面既然已經做了嚴格的校驗,爲什麼還能輸入2147483647這麼大的數字呢?是否說明Web校驗不嚴格?錯了,不是這樣的,Web校驗都是在頁面上通過JavaScript實現的,只能限制普通用戶(這裏的普通用戶是指不懂HTML、不懂HTTP、不懂Java的簡單使用者),而對於高手,這些校驗基本上就是擺設,HTTP是明文傳輸的,將其攔截幾次,分析一下數據結構,然後再寫一個模擬器,一切前端校驗都成了浮雲!想往後臺提交個什麼數據那還不是信手拈來?!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章