2015年5月25日

調節定向理論 Regulatory focus theory

我們應該如何構建複雜系統文末提到調節性匹配理論。一個團隊同時需要這兩類人維持彼此間的平衡,一類以危險為關注焦點,他們會提前預防失敗,判斷是不是安全的;另一類是以成功為關注焦點的,他們會創造財富,說幹就幹!

Higgins(1997)提出人類個體為達到特定目標,會努力改變或控制自己的思想、反應,這一過程被稱為自我調節。個體在實現目標的自我調節過程中會表現出特定的方式或傾向,這就是調節定向,調節定向理論(regulatory focus theory),說明了人們如何趨近積極目標狀態和迴避消極目標狀態。

該理論區分了兩種不同的調節定向:促進定向和預防定向,兩者在服務的需要類型、對目標的表徵、對結果的關注點、情緒體驗等方面存在區別,並會產生獨立的動機結果。

促進定向(promotion focus)與提高需要(advancement,即,成長、發展和培養等)相關。預防定向(prevention focus)則是與安全需要(security,即,保護、免受傷害等)相關。

促進定向更關注有無好結果,而預防定向更關注有沒有壞結果。

預防定向的個體關注如何採取所有必要措施來避免損失,能更準確地理解連續事件的內涵,進而更準確地估計連續事件的發生;而促進定向的個體關注如何採取各種可能的方式以獲得收益,能更好地理解獨立事件的內涵,進而更準確地估計獨立事件的發生,因此,促進定向的個體可能高估連續事件的概率,預防定向的個體可能低估獨立事件的概率。

預防定向的人做事的態度是比較保守,盡可能守住擁有的,而不去追逐新鮮事物;促進定向的人,是傾向去冒險、嚐鮮。根據這樣的特質,可以預期到預防定向的人,會傾向停留在原本的狀態。

整理以上的說明,促進定向 promotion focus 的人有下列的特徵:

  1. 與提高需要(advancement,即,成長、發展和培養等)相關
  2. 關注有無好結果
  3. 關注如何採取各種可能的方式以獲得收益
  4. 可能高估連續事件的概率
  5. 傾向去冒險、嚐鮮

而預防定向 prevention focus 的人,有下列的特徵:

  1. 與安全需要(security,即,保護、免受傷害等)相關
  2. 關注有沒有壞結果
  3. 關注如何採取所有必要措施來避免損失
  4. 可能低估獨立事件的概率
  5. 做事的態度是比較保守,盡可能守住擁有的,而不去追逐新鮮事物

以我個人的理解,公司裡面的業務行為接近於促進定向的方式與策略,而開發單位是屬於預防定向這種特性的個體。

軟體開發最重要的就是要 debug,任何一個功能在撰寫了第一個版本的程式之後,緊接著就是開發者的自行測試,然後接著會跟其他開發者寫的程式整合,進行第二階段的整合測試,接下來到了測試單位,進行初步的系統測試,然後有前期使用者的實際測試,上線後就是使用者的測試。

一連串不斷的測試的過程,都需要回饋給開發者進行 debug 的工作。而一般認為,一個最好的系統開發人員,除了能把程式寫好,寫的速度快之外,還需要有最少錯誤的極高品質,一個系統的設計人員,在決定開發的方法時,已經事先考慮過最壞的狀況,系統能在最糟糕的狀況下存活是基本的要求。

軟體系統開發,其實就是在一連串的趨吉避凶的過程,正好跟預防定向的個體的特徵有相同的狀況,寫程式要事先考慮到可能會出錯的狀況,然後避免程式進入錯誤的邏輯條件。

更簡單的來說,我們這種死工程師,每天都是在寫這樣的程式,在變數可能會出錯的先決條件下,每個使用到這個資料的程式,都必須要增加很多對應的迴避錯誤的方案。

if(A!=null) { } else { }

而業務行為,正好相反,在跟客戶協商的過程中,軟體系統不需要達到 100分,而只要有 60~80 分的程度就可以了,最重要的是業務人員需要一個實際可用的系統,對客戶進行前期銷售,剩下來的部份,就是如何說服客戶系統會越來越好,一切都是要以拿到案子為基準,沒有案子就沒有收入,就算有 100分的系統,也是枉然。

業務跟開發總是在天平的兩端拉鋸,業務會希望「盡快」得到可以展示的系統,而開發人員會希望得到「不會出錯」的系統。我覺得重點在於,不管如何,當系統展示出錯時,我們是用接受的態度面對開發人員,還是用「責難」的方式,調侃開發者。

要知道沒有一個系統是不會出錯的,問題在於出錯的頻率與狀況的程度有多少,如果使用者每走一兩步,系統就當機,那麼誰敢使用這樣的系統。而開發人員要如何確定,系統到底有多穩定?除了一直不斷地測試,似乎也沒別的辦法了。

回到一開始的文章,提到建設成功的團隊必須同時容納兩種不同類型的人類個體。究竟這樣兩種不同的方式,要如何「平衡」在公司日常的運作當中,可能需要更有智慧的方式,進行雙邊的協商。

2015年5月18日

測試員需不需要知道系統是怎麼做的?

測試員通常會需要知道系統規格,要知道功能項目,然後才能知道要怎麼撰寫測試計畫。好一點的測試者,能夠從使用者的角度,設計測試情境。換句話說,越懂得如何去「使用」軟體的測試員,就越能勝任測試的工作。但是測試員需不需要知道更多事情,需不需要知道系統是怎麼設計出來的呢?知道更多,能不能幫助自己找出系統更多的問題呢?

  • 如果你是專案管理者
  1. 空降的測試員
    在一個大型專案中,比較會有可能配置專門的測試員,大部分的時候,或許是由專案管理者自己兼任測試工作,這時候,沒辦法對測試員期待太多,能按照測試計畫做完就算是很好的狀況了。

  2. 產品測試在那個階段?
    產品的生命週期,會經過系統開發,beta release 測試,系統驗收,終端客戶使用這些階段,不同的階段,會有不同的測試焦點,例如開發時期,通常由開發者自行測試,beta release 可能會有專門的測試者進行測試,驗收後,開始會有更多前期使用者進行使用,系統上線後,終端客戶,也就是實際的使用者,在使用時,也是在測試及驗證系統的強度。

    不同的角色,伴隨著不同的能力,對產品的認識程度也不同,最重要的是終端客戶的使用順不順利,但這些人,就不大可能會去了解系統是怎麼做。

  3. 測試員是消耗品,專職的測試員不適合測試同一個產品太久
    要說專職的測試員是消耗品,並不是刻意貶抑或是看輕測試員的意思,而是認為測試員在反覆進行產品測試的過程中,慢慢地會因為不斷地重複,而麻痺了自己測試時的感覺。

    越接近產品 release 的階段,測試的感覺就會慢慢地麻痺後,接下來就會慢慢地忽略最基本最常做的測試項目,認為這些項目都是最基本的,不會有問題,不需要注意測試。

    這些問題並不是一味地強迫測試員一直努力測試就可以避免的,因為重複的動作,人性就會自然而然地慢慢地麻痺了,如果可以的話,當然可以自動化,而避免這個問題,所以,如果成本夠,人員夠,就及早把能夠自動化測試的部份補起來吧!

    換句話說,有個能寫程式,將能夠自動化測試的自動測試機制做起來的人,有個長期的專案要做的話,就趕快做吧,要做這樣的測試工作的人,必須要懂得並知道系統是怎麼設計的。

  4. 產品推出後,人人都是測試員
    愛你的產品的人,會常常使用你的產品,甚至會一直主動地回報系統的問題,或是希望你調整或增加某些功能,有著這樣的使用者是很幸福的事。回報問題時,就要小心地應對。

  • 如果你是測試員
  1. 要知道自己在公司的地位
    在每個組織內,都有先來後到,每個人在工作上也有能力的高低,職務上被分配承擔的責任多少不同,自然而然就會形成某個程度的地位分別,這是多人組織自然就會產生的人際關係,不管再怎麼想消弭都是會存在的。

    所謂的地位,意思就是要知道自己能做什麼,能講什麼,能處理什麼事情,在能處理的範圍盡量做吧!

  2. 到底熟不熟悉這個產品
    測試員首先一定要知道的是一個產品或系統的功能規格,選單上每一個功能會對其他功能產生什麼附帶的影響,輸入什麼資料後得到什麼資料,要知道這些基本的功能,基本上才能正確地測試這個產品。

    對產品的熟悉程度,最終就是要知道程式是怎麼寫的,模組跟模組之間的關係是重點,系統整合就可能會產生一些問題,必須設計出對應的測試項目。

  3. 有沒有開發過其他系統
    有時候因為不是實際的開發人員,勢必是無法掌握開發的細節的,就算是這樣,有開發經驗的測試人員,可以用自己的經驗去猜測實際上會是怎麼寫的,有沒有闕漏的地方,進而找出測試項目,然後發現 bug。

    講起來測試員就很像是個 hacker,hacker 是個高明的測試人員,他們能夠利用各種方式,取得可能的突破口,找出並利用 bug,破解進入系統。

  4. 跟開發者的合作關係如何?
    如果一個開發單位,測試員跟開發人員之間的交流是順暢的,這也是一個取得系統內部資訊的方法,拿到資訊就更能掌握系統的變化。

  • 如果你是開發者
  1. 一邊開發就要一邊測試了
    系統開發人員是系統最初的測試者,系統是程式設計師堆積程式取得的結果,當然在設計完成後,就要進行基本的測試。能把握最初的關卡,程式設計時就能減少產生 bug 的機會。

  2. 對功能越熟悉,反而會產生測試的盲點
    某個功能如果在撰寫時,一直產生 bug,而且是不知道原因的 bug,為了解決問題,程式設計師難免得一直面對 bug 持續奮戰,當視野從整個系統面,為了 bug 逐漸縮小自己的焦點後,coding -> debug -> testing 的過程,會讓自己陷入在某個測試的盲點中。

    這是人之常情,產生失誤並不是故意的,只能夠靠自己在每一天開始的時候,試著規劃並整理自己該做什麼事情,減少失誤發生的機會。

  3. 花一點時間跟同事 code review,會事半功倍
    程式碼是很笨拙的,必須一行一行地靠程式設計師輸入程式碼,而程式的邏輯,通常是線性的,必須靠每一行程式完成線性的邏輯,寫程式的時候,會因為這樣的邏輯循環,陷入可能的失誤。

    把自己的程式講給別人聽,是一種檢視自己程式的邏輯最直接的方法,一邊講就等於一邊 review,沒有考慮到的邏輯錯誤也會因為這個過程,自己就浮現出來。

  • 到底要不要知道系統是怎麼做的?
  1. 有經驗的開發者,可以找到更多問題,但也不是全部
    有經驗的開發者,即使不是系統的開發者,可以透過自己的經驗,找到可能發生的問題點,雖說並不一定會有幫助,但總是一種發現與解決問題的方法。

    透過開發者的說明,也是一種 review,也可以幫助整個系統,朝更穩定的方向前進。

  2. 想像自己是開發者
    如果你的工作是程式設計師,想像自己是開發者,會怎麼去實作這個功能,就會有另一種視野來看這個資訊系統。揣摩實作的過程,在查看系統時,測試時,會有不同的想法。

  3. 想像自己是使用者
    使用者通常是沒有耐心的,系統開發時,內部測試時,會因為了解系統的一些問題與限制,而不會用使用者使用系統的方法去使用系統。

    最常見的狀況是,當自己是使用者時,點了一個按鈕,是不會知道要等待的,點了一個按鈕,如果可以點其他地方,就有可能會產生問題,除非系統本來就是設計可以多工執行的。

  • 結論

總結一句話,能力越強,責任越大,知道越多,就越能找到更多的 bug。不管如何,如果系統出了問題,只要抱持著正面的看法,堅持下去做就對了,會逐漸變好的。

2015年5月11日

snmp4j table view

在 SNMP 中,如果要查詢多個 oid 的資料,就只能一個一個查詢,不然就是用 walk 的方式,將所有 oid 的節點都走過一次。但是在 oid 的定義 tree 中,有時後會遇到某個節點,下面有數十個都一樣類型的資料,例如 traffic 流量,可能一次就有十幾個連續的 oid,必須要一次將這些 oid 的結果都查出來,我們可以使用 table view 的方式,來進行這類型的資料查詢。

延續先前的 SNMPClient class,我們可以增加一個 getTable 的 method,SNMP4j 提供了 TableUtils 這個 class,當我們進行一連串的 oid 查詢後,結果會存在 List snmpList 回傳回來。

    public List<TableEvent> snmpGetTable(String oid, String lowerBound,
            String upperBound) throws Exception {
        try {
            int maxRepetitions = 100;

            PDUFactory pF = new DefaultPDUFactory(PDU.GETNEXT);

            TableUtils tableUtils = new TableUtils(snmp, pF);
            tableUtils.setMaxNumRowsPerPDU(maxRepetitions);

            OID[] columns = new OID[1];
            columns[0] = new VariableBinding(new OID(oid)).getOid();
            OID lowerBoundIndex = new OID(lowerBound);
            OID upperBoundIndex = new OID(upperBound);

            logger.debug("Vector Bulk SNMP oid= " + columns[0]);
            logger.debug("Vector Bulk SNMP lower= " + lowerBoundIndex);
            logger.debug("Vector Bulk SNMP upper= " + upperBoundIndex);

            List<TableEvent> snmpList = tableUtils.getTable(target, columns,
                    lowerBoundIndex, upperBoundIndex);

            logger.debug("snmpList size : " + snmpList.size());

            for (int j = 0; j < snmpList.size(); j++) {
                logger.debug("snmpList : " + snmpList.get(j));
            }

        } catch (Exception e) {
            logger.error("Error", e);
            throw e;
        }
        return null;
    }

至於要如何使用這個 method,以下這個呼叫,會得到 .1.3.6.1.4.1.119.2.3.76.2.4.6.1 .2.1 ~ .1.3.6.1.4.1.119.2.3.76.2.4.6.1 .2.21 的所有資料。

tester.snmpGetTable(".1.3.6.1.4.1.119.2.3.76.2.4.6.1", "2.0",
                    "2.21");

在做 SNMP Client 的程式時,如果是在做一般類似 mib browser 功能的 stand alone client,SNMP get/set 程式當然就得放在 client 裡面。但如果是在做 web browser 為使用者界面的 SNMP client 網頁應用程式時,我們就得要注意,每一個頁面會產生多少 SNMP Query,網頁前端點擊一個動作後,要等待多久,網頁的回應要等待多久這些問題。

當我們考慮到網頁的快速回應時,就不能以同步的方式,等待 server 將所有 query 都查完,再把結果回傳給前端的網頁,當 agent 存在,且能快速回應時,系統不會有什麼問題,但這種方式的缺點是,如果 query 時,SNMP Agent 剛好不存在時,網頁就必須等待所有 snmp request timeout 之後,才會回應給前端,使用者就會覺得網頁怎麼用起來卡卡的。

尤其如果在同樣的頁面,而且是多人同時查詢時,這種情況會更糟糕,而且相同的資料,會因為多人同時查詢而需要查詢好幾次。以這種狀況為前提來考量,我們必須要考慮使用 server cache 來暫存查詢的結果,而且在網頁進行查詢時,實際上是去查詢這個 cache。

然而這種設計雖然保障了使用者前端的高可用性,但卻讓資料的正確性降低了,因為系統並不是一直取得最新的資料,傳送給前端使用。因此這樣的設計方式必須要用在使用者頁面的高可用性為前提的頁面上,而且使用者不需要隨時都看到最新的資料,只需要資料可以一直更新就好了,幾分鐘的誤差不造成特別的影響。

系統設計時,除了要注意使用者的使用感受,還要注意 server 端要如何儲存資料,如果用到 cache 的機制,就要注意多執行緒修改資料的問題,還要知道多久要更新一次資料。綜合許多的考量,才能得到一個最佳調適沒有偏頗的資訊系統。

2015年5月4日

AJAX Testing Tool: Postman

在專案上常會使用到 AJAX,這些 request 通常是 server 提供的操作 API,回傳的資料通常是 JSON 格式。在工作分配上如果是前端與後端分開實作的,後端的開發人員常會在還沒有實作前端畫面的時候,就已經把後端的 AJAX API 都寫好了,這時候,我們就能使用 Postman - REST Client 這個 Chrome plugin,來進行 API 的測試與驗證。

完整的 Postman 工具,除了安裝 Postman 之外,還需要再安裝 Postman Interceptor ,根據頁面上的說明,安裝了 Interceptor 才能使用 browser cookie,也能傳送一些受 chrome 限制不能使用的 http headers。

AJAX 測試

如同畫面,我們可為一個 AJAX 測試命名,並填寫網址以及選擇http method(通常為 POST),接下來在 x-www-form-urlencoded 裡面填寫參數。點擊 Save 儲存此 request 之後,點 Send 就是發送 request。要記得在發送 request 之前,先把右上角 Toggle Interceptor 的功能打開,才能正常地使用 cookie。

我們可以看到結果是登入成功的 JSON 字串,並取得了三個 cookie value,同時也能查閱 response headers。

Environments 環境變數

當我們想要調整測試的 collection,換到另一個 server 進行測試的時候,我們可以使用 Postman 的 enviroments 功能。畫面上的功能很簡單,就是填寫環境變數的名稱以及數值,並為這一組環境變數命名。

如同畫面上的網址的部份,使用環境變數就是直接把 server ip 的地方改為 {{SERVERIP}} 就可以了,未來想要更換到另一台測試 server,定義一組新的 environments 就可以了。

Collections

我們可將專案相關的 requests 收集到一個 Collection 裡面,也可以將 collections 匯出或匯入。

Collection Runner

當然我們也很自然地想到,可以定時讓 collecitons 自動執行進行批次的測試,不過設定測試結果的條件,以及批次執行 collection 的功能,都必須在付費版中才有。

目前以免費版來進行基本開發的功能測試與驗證就很有用了。