王廷瑋|數位醫療|智慧醫療: 2024 WFU

2024年8月27日 星期二

227. Basic Calculator II

227. Basic Calculator II


給定一個表示算式的字串 s,計算該算式的結果並返回其值。

整數除法應該向零截斷。

你可以假設給定的算式總是有效的。所有中間結果都會在 [-2³¹, 2³¹ - 1] 的範圍內。

注意:你不允許使用任何內建函數來直接計算字符串中的數學表達式,例如 eval()

範例:

輸入: s = "3+2*2"
輸出: 7


Python


class Solution:
def calculate(self, s: str) -> int:
def update(op, v):
if op == "+": stack.append(v)
if op == "-": stack.append(-v)
if op == "*": stack.append(stack.pop() * v)
if op == "/": stack.append(int(stack.pop() / v))
it, num, stack, sign = 0, 0, [], "+"
while it < len(s):
if s[it].isdigit():
num = num * 10 + int(s[it])
elif s[it] in "+-*/":
update(sign, num)
num, sign = 0, s[it]
elif s[it] == "(":
num, j = self.calculate(s[it + 1:])
it = it + j
elif s[it] == ")":
update(sign, num)
return sum(stack), it + 1
it += 1
update(sign, num)
return sum(stack)

19.89MB, 125ms


C++


class Solution {
public:
int calculate(string s) {
int length = s.length();
if (length == 0) return 0;
int currentNumber = 0, lastNumber = 0, result = 0;
char sign = '+';
for (int i = 0; i < length; i++) {
char currentChar = s[i];
if (isdigit(currentChar)) {
currentNumber = (currentNumber * 10) + (currentChar - '0');
}
if (!isdigit(currentChar) && !iswspace(currentChar) || i == length - 1) {
if (sign == '+' || sign == '-') {
result += lastNumber;
lastNumber = (sign == '+') ? currentNumber : -currentNumber;
} else if (sign == '*') {
lastNumber = lastNumber * currentNumber;
} else if (sign == '/') {
lastNumber = lastNumber / currentNumber;
}
sign = currentChar;
currentNumber = 0;
}
}
result += lastNumber;
return result;
}
};

11.04MB, 18ms


Javascript


/**
* @param {string} s
* @return {number}
*/
var calculate = function(s) {
// Remove all white spaces from the string
s = s.replace(/\s+/g, '');

// Initialize a stack to keep track of numbers and operations
let stack = [];
let currentNumber = 0;
let operation = '+'; // Start with an addition operation by default

for (let i = 0; i < s.length; i++) {
let currentChar = s[i];

if (!isNaN(currentChar)) {
// Build the current number
currentNumber = currentNumber * 10 + parseInt(currentChar);
}

// If the current character is an operator or we're at the end of the string
if (isNaN(currentChar) || i === s.length - 1) {
if (operation === '+') {
stack.push(currentNumber);
} else if (operation === '-') {
stack.push(-currentNumber);
} else if (operation === '*') {
stack.push(stack.pop() * currentNumber);
} else if (operation === '/') {
stack.push(Math.trunc(stack.pop() / currentNumber));
}
// Update the operation and reset currentNumber
operation = currentChar;
currentNumber = 0;
}
}

// Sum up all the numbers in the stack to get the final result
return stack.reduce((a, b) => a + b, 0);
};

58.36MB, 92ms


226. Invert Binary Tree

226. Invert Binary Tree


給定一個二叉樹的根節點,反轉這棵樹,並返回其根節點。

範例 1:

輸入: root = [4,2,7,1,3,6,9]
輸出: [4,7,2,9,6,3,1]



Python


# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if not root:
return None
# Swap the left and right children
root.left, root.right = root.right, root.left
# Recursively invert the left and right subtrees
self.invertTree(root.left)
self.invertTree(root.right)
return root

16.52MB, 34ms


C++


/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if (root == nullptr) {
return nullptr;
}
// Swap the left and right children
TreeNode* temp = root->left;
root->left = root->right;
root->right = temp;
// Recursively invert the left and right subtrees
invertTree(root->left);
invertTree(root->right);
return root;
}
};

11.88MB, 5ms


Javascript


/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {TreeNode}
*/
var invertTree = function(root) {
if (root === null) {
return null;
}
// Swap the left and right children
const temp = root.left;
root.left = root.right;
root.right = temp;
// Recursively invert the left and right subtrees
invertTree(root.left);
invertTree(root.right);
return root;
};

49.44MB, 54ms


225. Implement Stack using Queues

225. Implement Stack using Queues

使用兩個隊列實現一個後進先出(LIFO)的堆疊。實現的堆疊應該支持所有正常堆疊的功能(推入、取頂、彈出和判空)。

實現 MyStack 類:

  • void push(int x):將元素 x 推入堆疊的頂部。
  • int pop():移除堆疊頂部的元素並返回該元素。
  • int top():返回堆疊頂部的元素。
  • boolean empty():如果堆疊為空,返回 true;否則返回 false。

注意:

  • 你只能使用隊列的標準操作,這意味著只能使用「後端推入」、「前端查看/彈出」、「查詢大小」和「判空」操作。

  • 根據你使用的語言,隊列可能不原生支持。你可以使用列表或雙端隊列(deque)來模擬隊列,只要你只使用隊列的標準操作即可。

範例:

輸入
["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]

輸出
[null, null, null, 2, 2, false]



Python


from collections import deque

class MyStack:
def __init__(self):
self.q1 = deque()
self.q2 = deque()

def push(self, x: int) -> None:
self.q2.append(x)
while self.q1:
self.q2.append(self.q1.popleft())
self.q1, self.q2 = self.q2, self.q1

def pop(self) -> int:
return self.q1.popleft()

def top(self) -> int:
return self.q1[0]

def empty(self) -> bool:
return len(self.q1) == 0

16.49MB, 36ms


C++


#include <queue>

class MyStack {
private:
std::queue<int> q1, q2;

public:
MyStack() {}
void push(int x) {
q2.push(x);
while (!q1.empty()) {
q2.push(q1.front());
q1.pop();
}
std::swap(q1, q2);
}
int pop() {
int top = q1.front();
q1.pop();
return top;
}
int top() {
return q1.front();
}
bool empty() {
return q1.empty();
}
};

8.52MB, 0ms


Javascript


class MyStack {
constructor() {
this.q1 = [];
this.q2 = [];
}

push(x) {
this.q2.push(x);
while (this.q1.length > 0) {
this.q2.push(this.q1.shift());
}
[this.q1, this.q2] = [this.q2, this.q1];
}

pop() {
return this.q1.shift();
}

top() {
return this.q1[0];
}

empty() {
return this.q1.length === 0;
}
}

49.05MB, 49ms


224. Basic Calculator

224. Basic Calculator


給定一個表示有效表達式的字串 s,實現一個基本的計算器來計算並返回該表達式的結果。

注意:你不允許使用任何內建函數來將字串作為數學表達式進行計算,例如 eval()。

範例 1:

輸入: s = "1 + 1" 輸出: 2


Python


class Solution:
    def calculate(self, s: str) -> int:
        def calc(it):
            stack = []
            num = 0
            op = '+'
           
            while it < len(s):
                if s[it].isdigit():
                    num = num * 10 + int(s[it])
                elif s[it] in '+-*/':
                    if op == '+':
                        stack.append(num)
                    elif op == '-':
                        stack.append(-num)
                    elif op == '*':
                        stack.append(stack.pop() * num)
                    elif op == '/':
                        stack.append(int(stack.pop() / num))
                    num = 0
                    op = s[it]
                elif s[it] == '(':
                    num, it = calc(it + 1)
                elif s[it] == ')':
                    break
                it += 1
           
            if op == '+':
                stack.append(num)
            elif op == '-':
                stack.append(-num)
            elif op == '*':
                stack.append(stack.pop() * num)
            elif op == '/':
                stack.append(int(stack.pop() / num))
           
            return sum(stack), it
       
        return calc(0)[0]

18.26MB, 18ms


C++


#include <string>
#include <stack>
#include <cctype>

class Solution {
public:
    int calculate(string s) {
        return calc(s, 0).first;
    }

private:
    std::pair<int, int> calc(const string& s, int i) {
        std::stack<int> stack;
        int num = 0;
        char op = '+';

        while (i < s.length()) {
            if (std::isdigit(s[i])) {
                num = num * 10 + (s[i] - '0');
            } else if (s[i] == '(') {
                auto [res, next_i] = calc(s, i + 1);
                num = res;
                i = next_i;
            } else if (s[i] == ')') {
                updateStack(stack, op, num);
                return {getResult(stack), i};
            } else if (s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/') {
                updateStack(stack, op, num);
                op = s[i];
                num = 0;
            }
            i++;
        }

        updateStack(stack, op, num);
        return {getResult(stack), i};
    }

    void updateStack(std::stack<int>& stack, char op, int num) {
        if (op == '+') stack.push(num);
        else if (op == '-') stack.push(-num);
        else if (op == '*') {
            int top = stack.top();
            stack.pop();
            stack.push(top * num);
        } else if (op == '/') {
            int top = stack.top();
            stack.pop();
            stack.push(top / num);
        }
    }

    int getResult(std::stack<int>& stack) {
        int result = 0;
        while (!stack.empty()) {
            result += stack.top();
            stack.pop();
        }
        return result;
    }
};

15.19MB, 16ms


Javascript


/**
 * @param {string} s
 * @return {number}
 */
var calculate = function(s) {
    const stack = [];
    let num = 0;
    let sign = 1;
    let result = 0;
   
    for (let i = 0; i < s.length; i++) {
        const char = s[i];
       
        if (char >= '0' && char <= '9') {
            num = num * 10 + (char - '0');
        } else if (char === '+' || char === '-') {
            result += sign * num;
            num = 0;
            sign = char === '+' ? 1 : -1;
        } else if (char === '(') {
            stack.push(result);
            stack.push(sign);
            result = 0;
            sign = 1;
        } else if (char === ')') {
            result += sign * num;
            result *= stack.pop(); // Get the sign before the parenthesis
            result += stack.pop(); // Add the result before the parenthesis
            num = 0;
        }
    }
   
    if (num !== 0) result += sign * num;
    return result;
};

54.34MB, 56ms


223. Rectangle Area

223. Rectangle Area



給定在二維平面上兩個直角矩形的座標,返回這兩個矩形覆蓋的總面積。

第一個矩形由其左下角 (ax1, ay1) 和右上角 (ax2, ay2) 定義。

第二個矩形由其左下角 (bx1, by1) 和右上角 (bx2, by2) 定義。


範例


Python


class Solution:
    def computeArea(self, ax1: int, ay1: int, ax2: int, ay2: int, bx1: int, by1: int, bx2: int, by2: int) -> int:
        # Calculate areas of both rectangles
        area1 = (ax2 - ax1) * (ay2 - ay1)
        area2 = (bx2 - bx1) * (by2 - by1)
       
        # Find the overlapping region
        left = max(ax1, bx1)
        right = min(ax2, bx2)
        top = min(ay2, by2)
        bottom = max(ay1, by1)
       
        # Calculate overlapping area
        overlap_area = 0
        if left < right and bottom < top:
            overlap_area = (right - left) * (top - bottom)
       
        # Total area is sum of both areas minus the overlap
        total_area = area1 + area2 - overlap_area
       
        return total_area

16.62MB, 12ms


C++


class Solution {
public:
    int computeArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2) {
        // Calculate areas of both rectangles
        long long area1 = static_cast<long long>(ax2 - ax1) * (ay2 - ay1);
        long long area2 = static_cast<long long>(bx2 - bx1) * (by2 - by1);
       
        // Find the overlapping region
        int left = max(ax1, bx1);
        int right = min(ax2, bx2);
        int top = min(ay2, by2);
        int bottom = max(ay1, by1);
       
        // Calculate overlapping area
        long long overlap_area = 0;
        if (left < right && bottom < top) {
            overlap_area = static_cast<long long>(right - left) * (top - bottom);
        }
       
        // Total area is sum of both areas minus the overlap
        long long total_area = area1 + area2 - overlap_area;
       
        return static_cast<int>(total_area);
    }
};

9.92MB, 0ms


Javascript


/**
 * @param {number} ax1
 * @param {number} ay1
 * @param {number} ax2
 * @param {number} ay2
 * @param {number} bx1
 * @param {number} by1
 * @param {number} bx2
 * @param {number} by2
 * @return {number}
 */
var computeArea = function(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2) {
    // Calculate areas of both rectangles
    const area1 = (ax2 - ax1) * (ay2 - ay1);
    const area2 = (bx2 - bx1) * (by2 - by1);
   
    // Find the overlapping region
    const left = Math.max(ax1, bx1);
    const right = Math.min(ax2, bx2);
    const top = Math.min(ay2, by2);
    const bottom = Math.max(ay1, by1);
   
    // Calculate overlapping area
    let overlapArea = 0;
    if (left < right && bottom < top) {
        overlapArea = (right - left) * (top - bottom);
    }
   
    // Total area is sum of both areas minus the overlap
    const totalArea = area1 + area2 - overlapArea;
   
    return totalArea;
};

55.62MB, 119ms


2024年8月26日 星期一

碼農新生:Johns Hopkins電腦科學碩士的第一堂課

作者:王廷瑋


第一幕:起跑線上的領跑者


剛踏入Johns Hopkins電腦科學碩士課程的第一天,我就如同參加百米賽跑般,在起跑線上就已經領先一步。憑藉著與舊識快速組隊的優勢,我們團隊宛如一支訓練有素的接力隊,每次作業和專題都以迅雷不及掩耳之勢完成。這種領先優勢就像是滾雪球效應,越滾越大,推動著我們持續保持高水準的輸出。

誰說第一印象不重要?在這裡,它可是決定了至少一半的成敗!


第二幕:在團隊與個人之間尋找平衡


在這場學術馬拉松中,我們就像是在走鋼絲的特技演員,必須在兩個看似矛盾的目標之間保持完美的平衡:

一邊是「群雁齊飛」—— 與同儕協作,互相砥礪,形成一個強大的團隊。我們像是一群遷徙的候鳥,彼此呼應,共同前進。

另一邊則是「獨木成林」—— 培養獨立解決問題的能力,鍛煉自己成為一棵參天大樹。在這個過程中,我們像是孤獨的探險家,在未知的知識叢林中開闢自己的道路。

雖然我們也像考古學家一樣,不斷地在網絡的汪洋大海中尋寶,但面對的卻是全新的未知領域。這種體驗,讓我們如同踏上月球的太空人,為未來探索未知做好了充分準備。

Johns Hopkins的EP課程就像是一間精品店,堅持小班教學,保證每位「顧客」都能得到VIP待遇。我們這些「顧客」被分成幾個小組,既能互相參考,又能在追求卓越的路上齊頭並進。畢竟,長期來看,大家的表現總會回歸平均。所以,一開始就需要像設計師般精心規劃,為自己的作品注入獨特的靈魂。

在這個過程中,我們既要學會在團隊中協作,又要培養獨立思考的能力。這種平衡,就像是在煮一鍋完美的湯 —— 每種ingredientient都要恰到好處,才能激發出最佳的風味。


第三幕:多元共生的團隊生態系


我們的團隊簡直就是一個微型聯合國!兩個白人、兩個華人;兩個電腦科學本科生、兩個生物醫學背景的「異類」。這種多元組合不僅能互補,更能激發出意想不到的火花。電腦科學本科生就像是專業的建築師,精通程式架構與項目管理;而我則是一名出色的室內設計師,擅長報告呈現、抽象思考與文件整理。

白人隊友彷彿天生的社交達人,表達能力一流;華人則是細節控,計劃執行起來一絲不苟。在這個團隊裡,我們就像在參加一場跨文化交流會,每天都在互相學習,共同成長。


第四幕:軟件工程的真相大白


誰說軟件工程就是整天對著電腦敲代碼?那只是冰山一角!在AI大神的加持下,老師甚至豪言:「任何項目的代碼部分,2-3天就能搞定!」

軟件工程的精髓,其實是一場精心策劃的舞台劇。從編劇(項目策劃)、選角(團隊組建)、劇本(需求分析)到舞台設計(系統架構),每一個環節都不容忽視。而寫代碼,不過是演員上台表演的一小部分罷了。最後,還有品質把關、彩排(測試)和長期演出(維護)等諸多工作。

這台大戲中的每一個細節都環環相扣,一旦早期出現任何紕漏,後期都可能釀成無法挽回的災難。所以,軟件工程師其實是集編劇、導演、演員於一身的全能藝術家!


尾聲:AI,我的得力助手


每次完成作業,我們都要寫下學習心得和AI應用體驗。目前看來,AI就像是一個永不疲倦的超級助理,能夠迅速完成各種任務。但它並非萬能,有時輸出的結果並不盡如人意,需要我們不斷溝通和校正。面對複雜問題時,人類的智慧仍然是不可或缺的。





電腦瑣談(Trivial Compute)

作者:王廷瑋




軟體工程


電腦瑣談(Trivial Compute)是一個創新的教育遊戲專案,旨在通過互動式問答遊戲來增進學生對計算機科學概念的理解。這個專案不僅展示了遊戲化學習的潛力,還體現了軟體工程(Software Engineering)的核心原則和最佳實踐。

在開發過程中,團隊製作了多份重要文件,每份文件都在軟體工程中扮演關鍵角色:
 
  • 團隊章程(Team Charter):定義了團隊成員的角色、責任和溝通流程,為專案奠定了堅實的基礎。
  • 專案計畫(Project Plan):概述了專案的生命週期(Life Cycle)、風險評估(Risk Assessment)和資源分配(Resource Allocation),指導整個開發過程。
  • 願景文件(Vision Document):闡明了專案的目標、範圍和價值主張,確保所有相關者(Stakeholders)對產品有共同的理解。
  • 軟體需求規格說明書(Software Requirements Specification, SRS):詳細描述了系統的功能需求(Functional Requirements)和非功能需求(Non-Functional Requirements),為後續設計和開發提供了明確的指導。
  • 設計文件(Design Document):包含了系統的靜態設計(Static Design)和動態設計(Dynamic Design),為開發人員提供了清晰的藍圖。

里程碑


專案採用了分階段交付模型(Staged Delivery Model),包括三個關鍵里程碑(Milestones):
 
Skeletal(骨架)里程碑:
 
  • 建立了基本的系統架構(System Architecture),包括Express伺服器、Firebase數據庫和身份驗證。
  • 實現了REST API端點和客戶端介面(Client Interface)的基本框架。
  • 使用Docker進行容器化(Containerization),確保了跨環境的一致性。

Minimal(最小)里程碑:
 
  • 開發了核心遊戲功能,如遊戲板GUI(Graphical User Interface)、玩家移動邏輯和計分系統。
  • 實現了基本的用戶介面,使遊戲可以進行基本操作。
  • 建立了後端(Backend)、前端(Frontend)和數據庫(Database)之間的基本通信。

Target(目標)里程碑:
 
  • 實現了完整的用戶認證(User Authentication)系統。
  • 添加了動態內容管理(Dynamic Content Management)功能,允許創建和刪除問答卡。
  • 優化了用戶介面和遊戲邏輯(Game Logic)。
  • 實現了安全部署(Secure Deployment)和性能優化(Performance Optimization)。

通過這個專案,團隊不僅創造了一個有趣且有教育價值的遊戲,還實踐了軟體工程的關鍵概念,如需求分析(Requirements Analysis)、系統設計(System Design)、風險管理(Risk Management)和迭代開發(Iterative Development)。"


生成式AI應用


在開發過程中,團隊巧妙地運用了生成式AI技術來輔助各個階段的工作。ChatGPT等大型語言模型(LLMs)被用於協助文件撰寫和優化,特別是在產生初步的需求描述和設計說明時。這些AI工具幫助團隊快速生成初稿,提高了文檔製作的效率。Cursor等AI增強的開發環境提高了編碼效率和代碼質量,為開發人員提供了智能代碼補全和錯誤檢測等功能。

特別值得一提的是Claude,這個AI助手在整個專案中發揮了重要作用。團隊利用Claude來生成創意想法、提供解決方案建議,並協助整理和綜合專案想法。在面對設計挑戰或功能規劃時,Claude的輸出常常為團隊提供了新的思路和靈感。

然而,團隊始終保持警惕,認識到AI只是輔助工具,無法獨自解決複雜的問題。所有AI生成的內容和建議,無論是來自ChatGPT、Cursor還是Claude,都經過了團隊成員的仔細審查和批判性思考。團隊成員運用他們的專業知識和經驗,對AI的輸出進行評估、修改和完善,確保最終的決策和成果符合專案的高標準和具體需求。

這種人機協作的方式不僅提高了開發效率,還為團隊提供了新的視角和創意靈感。同時,這個過程也凸顯了人類專業知識、經驗和判斷力在軟體開發中的不可替代性。"電腦瑣談"專案成功地展示了如何在軟體工程實踐中有效地整合AI工具,同時保持人類專業知識的核心地位,為未來的教育科技開發樹立了新的標準。


Work: 
Email LinkedIn / Github
Research: OCRID / Google Scholar / RearchGate
 

2024年7月25日 星期四

Software Testing

Testing Terminology


  • software testing is the activity of evaluating a software item to detect the differences between the item‘s required response and its actual response for a given set of input conditions
  • input, software item, response
  • scope of a test is the collection of underlying software components that will be tested
  • object-oriented software is tested, the scope could be a class, one or more methods in a class, a group of classes, or the entire system
  • dynamic testing: executing the software
  • static testing: often performed both on software components and certain work products
  • Fault-directed tests are designed to try and expose faults in the item under test.
  • Conformance-directed tests are designed to demonstrate that the item under test satisfies its requirements.
  • A test-case is a specific set of input data, events and interactions, and associated expected results, that is applied to the item under test.
  • test set is a collection of one or more test cases applied to the item under test
  • Regression testing involves repeating a subset, and sometimes a complete set, of previously-executed tests after a change has been made to the item under test.


Testing Perspectives


  • Black box testing is an approach or strategy that focuses on designing test cases based on the requirements for a product.
  • There are three key drivers to how effective a black box testing effort will be:
    • the test design techniques used
    • the quality of the requirements
    • the level of subject matter expertise there is on the test design team
  • lack of a systematic testing process
  • testing too late in life cycle
  • poor requirements
  • unclear responsibilities
  • data first test cases


Testing Principles



  • One major misconception is that software testing can prove that a software product is free from defects.
  • In order for dynamic testing to prove the correctness of a software product we would have to do exhaustive testing.
  • Testing activities should begin as early as the requirements phase
  • Test plans should be driven by, and linked to, the product requirements
  • States the components of a test case
  • Test case should be as repeatable as possible.
  • Keep a test repository
  • Regression testing
  • In practice, more defects are generally found during testing in projects where an independent test team participates.
  • Testing effectiveness can be improved by including people with business expertise on the test team.
  • Tester should never assume that software is correct.


Testing Activities and Work Products


  • In most software project life cycles, there is a phase devoted to testing
  • If a waterfall life cycle model is used, defect detection and repair costs can be significant. If an incremental life cycle model is used, defect detection and repair costs are not as extensive provided that the timeline for delivering increments is short.
  • incremental delivery is one way to help mitigate these costs.
  • life cycle approach to testing
  • Some type of testing is performed at each major phase of the software life cycle
  • testing activities are performed essentially in parallel to development activities
  • There is more frequent error detection and repair activity and some error detection and correction feedback at every major life cycle phase.
  • Major testing issues that can be addressed at the requirements phase include requirements completeness, requirements testability, and requirements ambiguity.
  • The type of testing that would be used at this point in a project would be static testing...namely conducting requirements walkthroughs or inspections.
  • A tester‘s interest in those reviews would be to assure that the three issues are addressed
  • During the design phase, the main design issues are typically correctness and completeness.
  • Two deliverables that would be produced under the life cycle approach are a test plan and a test description document.
  • In terms of timing, a test plan would be scheduled for delivery about half way through the design phase, or at the end of preliminary design if a preliminary design phase is used.
  • The test descriptions would be scheduled for delivery ideally by the end of the design phase.
  • A similar set of correctness and completeness issues applies during the coding through testing phases.
  • Of course, we would be performing dynamic testing during this period, but static testing could also be performed on additional test deliverables, and developers could also perform static testing on the code.
  • Traceability might also be applied to trace test cases back to requirements
  • Testing tools might also be used during this period to help generate the actual test case data and to verify the extent to which tests actually cover code components.
  • Additional testing work products might be test procedures, possibly test reports, and what are typically called problem reports.


Testing Levels and Responsibilities


  • Black Box Testing focuses on designing tests based upon the requirements for the item under test.
  • The code for the item under test is not needed or used in the design of tests.
  • White Box Testing focuses on designing tests based upon examination of the structural logic for the item under test.
  • It is also called structural testing, logic-based testing, clear box testing and glass box testing
  • Object-oriented designs tend to be driven by class responsibilities and collaborations rather than by functional decomposition.
  • Unit testing in object-oriented development projects works a little differently.
  • Since the individual methods belong to a class, some or all of the methods are developed and then individual methods of the class are tested one at a time.
  • A test driver simply creates a class instance and invokes one or more of its methods.
  • If a method calls another method in the same class, either a stub is used or the actual method is used. If a method calls a method in another class, a stub may be used if the other class is not yet developed.
  • In object-oriented integration testing, there really isn’t a functional-decomposition hierarchy, so we typically look at class collaborations, dependencies, and architectural layers.
  • Object-oriented design architecture is layered, so maybe these four classes constitute the application layer of the architecture.
  • We may then use a test driver to simulate the user-interface layer during the integration increments and while the actual GUI components are still under development.
  • Depending on the level of test that is being done, the testing strategies will be different.
    • At the unit level, both black box and white box tests are used.
    • As we go into integration testing, tests generally become mostly black box in nature, and at the system and acceptance levels where the software product is tested in its entirety...the tests should be all black box.
  • When it comes to object-oriented testing, the responsibilities are the same, and the objectives at the system and acceptance levels are the same...but there are additional types of testing that need to be done at the lowest levels.
  • There are different types of relationships that exist between classes in object-oriented software development, and those relationships require that more types of testing be done.
  • Also, object-oriented projects tend to be use case driven, so it is common for the use cases to serve as the basis for system and acceptance testing...at least for a product‘s functional requirements.


Requirements Based Test Design


  • The first technique that will help us to design tests is called input space partitioning.
    • Input space partitioning is used to partition the input side of a function into a set of equivalence classes that can help us identify test conditions.
    • An equivalence class is a subset of the input domain such that any values in that class will result in an equivalent system response.
  • Boundary testing focuses on identifying test conditions at the extreme points of the equivalence classes.
  • model-driven test design: started with a requirement, modeled its business rules, and then used the model to help generate test cases


Code Based Test Design


  • WHITE BOX TESTING focuses on designing tests based upon examination of the structural logic for the item under test.
  • It is also called structural testing, logic-based testing, clear box testing and glass box testing.
  • When we deal with code-based testing, one of the things we want to include as part of our testing goals is something called a coverage criteria.
  • Including a coverage criteria ensures that the code under test is adequately exercised.
  • three different levels of coverage criteria: statement coverage, branch coverage, and decision/condition coverage.
  • Statement coverage involves writing enough tests so that each programming statement in the component under test is exercised at least once.
  • For branch coverage we need to write enough tests so that each true/false branch is exercised at least once.
  • The next type of coverage criteria is decision/condition coverage. This requires that we write enough tests so that each true/false decision branch is executed at least once and all combinations that can cause a decision to be true and false be tested.
  • Basis Path Testing: Utilizes the flowgraph for a method in conjunction with the cyclomatic complexity metric to generate a set of test paths that yield a very high degree of code coverage.


2024年7月24日 星期三

Assuring Software Quality

Objectives of Software Quality Reviews



  • A review is basically some type of meeting.
  • Software quality review is a type of review in which we examine a work product that is produced during the course of a project
    • work product could be a project plan, a requirements document, a design document, code, a test plan
    • The work product is a key component of a software quality review
    • only be a few objectives for a software quality review
    • identify any defects that exist in the work product, to remove the defect
    • shouldn’t be used to share information, to inform stakeholders about what our strategy and direction are, to challenge project scope, to talk about project schedules or project, or anything else
  • round-robin review
    • work product is circulated around to a team of reviewers
    • Each reviewer reviews the work product in isolation and makes comments
    • Eventually, the document gets circulated back to the author.
    • potential advantages of this review model are that reviewers can fit the review into their own schedule for the most part
    • disadvantages of this review model are several: there is often a lack of consistency and rigor
    • another potential disadvantage is that if the review team doesn’t provide timely feedback, the project schedule can be delayed
    • And finally, in many reviews of this type the work product author is under no obligation to implement the reviewer comments
  • informal walkthrough model
    • walkthrough model is appropriate for all major project work products
    • This review model is synchronous. The review team will meet in-person or virtually over the Internet
  • formal inspection model
    • more structured, rigorous, and formal than the walkthrough model
    • industry best practice


Software Quality Reviews


  • Effective use of quality reviews has shortened project schedules by 10 to 30 percent.
  • Rework consists of unplanned repeating of tasks that were already performed
  • All of those studies have found that the cost of finding and fixing defects increases over time in an exponential-like way.
  • Performing software quality reviews can range from 5 percent to 15 percent of total project effort, depending upon the type of review process used and how many reviews need to be performed.
  • In fact, unless reviews are effective they will add to the project cost and they will cause schedule increases.


Defect Detection & Repair Costs


  • Error amplification is a phenomenon that exists on every single software project.
  • Additional drivers are size and complexity.

Informal Walkthrough


  • Used as a software quality review, the objectives of a walkthrough are to detect and remove defects in a work product, and to ensure that the work product meets its requirements.
  • The review is implemented as a meeting, either in- person or virtual
  • The work product author leads the review team through the work product, usually summarizing and paraphrasing chunks of material.
  • Reviewers, who ideally have looked through the work product as part of their pre-review meeting preparation, can ask questions, make comments, and raise defect issues.
  • The issues should be logged and resolved after the walkthrough meeting.
  • In this model, the work product author acts as both a presenter, literally walking the review team through the work product, and also typically serves as the meeting facilitator.
  • important guideline
    • minimize the objectives to include only those mentioned earlier
    • invite only those who can directly contribute to the review’s objectives
    • communicate objectives and expectations in advance
    • use a checklist to help reviewer focus attention
    • limit review meeting time
    • produce an issue list
    • include a follow-up step
    • log issues but limit discussion of solutions


Formal Inspection


  • considered to be an industry best practice for finding defects in software work products
  • Inspections have the highest defect detection rate of any defect identification technique
  • average defect detection rates of 60-90 percent, whereas the more informal walkthrough model averages 30-60 percent
  • There are specialized roles that some of the reviewers play
  • there are more steps than just the inspection meeting
  • there are rules for conducting
  • the inspection meeting
  • there is mandatory preparation and follow-up.
  • Inspections require that some participants play specialized roles
  • The moderator is responsible for ensuring that all the steps in the inspection process are followed and that all the inspection process rules are complied with
  • The moderator is also responsible for facilitating the inspection meeting
  • The author is responsible for answering questions posed by the inspection team, for providing clarifying information, and for resolving any issues for which he or she is the designated owner
  • An issues list is a mandatory inspection work product, and the person assigned to play the role of recorder is responsible for logging the issues
  • someone other than the author is selected to do walks the review team through the work product, presenter
  • Anyone else on the inspection team falls into the category of general inspector.
  • inspectors are relevant stakeholders and perhaps subject matter experts who evaluate the work product for defects and ensure the work product meets its requirement
  • The steps help to give the inspection process structure and repeatability
  • The kick-off step starts the inspection process for a given work product.
  • The author and moderator meet to verify that the work product is ready for inspection, the inspection team is selected, and the inspection meeting is scheduled
  • The moderator decides whether the overview step is necessary.
  • The preparation step is a mandatory step in the inspection process, because advance preparation is essential if the inspection meeting is to be effective.
  • Participants are also typically asked to record and report their preparation times.
  • During the inspection meeting, the work product is presented, issues are logged, and the inspection outcome is determined.
  • outcomes of an inspection meeting are defined in advance
  • conditional acceptance, re-inspect, or the inspection is not yet finished and requires another meeting


Software Metrics


  • A metric is a measurement of something.
  • metrics can provide useful visibility into project status
  • provide feedback to management, staff, and stakeholders
  • Feedback may also be in the form of quality indicators
  • Process metrics measure something associated with a process
    • total effort spent on each phase in a project life cycle
    • estimate of time remaining for project completion
  • Product metrics measure something associated with a product
  • Quality metrics measure something that is associated with the quality characteristics of a process or product
  • Quality requirement’s visibility


Specifying & Measuring Software Quality


  • At the top is the quality requirement that needs to be satisfied, such as testability
  • The next level defines product or process attributes that lead to a product having that quality characteristic.
  • Then, for each of the defined product and process attributes, one or more metrics is defined.
  • Simplicity is a characteristic of a products design and code. Are they implemented in a straightforward manner.
  • Self-descriptiveness also applies to the design and code. Are they easy to understand by visual inspection.
  • Modular applies to the design and code as well. Is it easy to see which components of the product perform certain functions.
  • Traceability has to do with the ease of relating test cases to the requirements that are being tested and to the specific product components that implement those requirements.
  • Support has to do with the infrastructure that is in place to support the testing effort.


Sample Software Quality Metrics


  • Coupling is a measure of inter-dependence between software components.
  • Loose coupling is good. Tight coupling is not good.
  • Cohesion is a measure of how single-purposed or well-defined a software component is.
  • High cohesion is good. Low cohesion is not good.
  • Cyclomatic complexity is a metric that measures how complicated the control flow logic for a software component is.
  • Halstead’s Information Volume metric. how much information is contained in a software component based on a count of operators and operands.


Software Quality

Software Quality


  • meets requirements
  • useful for situations in which the requirements were stated in terms of things that could be measured
  • typically be quality inspectors at various points in the assembly line
  • requirements are usually written in the form of stories or use cases
  • should be traceability between the requirements and the goals of the stakeholder: Vision documents
  • Achieving quality: doing things that build a quality product
  • Assuring quality: convincing ourselves and others that we are building, or have built a quality product
  • Return On Investment


Defects


  • Error: A conceptual, syntactic or clerical discrepancy which results in one or more faults in the software
  • Fault: A specific manifestation of an error. A discrepancy in the software which can impair its ability to function as intended. An error may be the cause for several faults
  • Failure: A software failure occurs when a fault in the computer program is evoked by some input data, resulting in the computer program not correctly computing the required function in an exact manner.
  • Defect: Either a fault or discrepancy between code and documentation that results in mischief in the testing, installation, maintenance, or use of software
  • errors cause defects, which, in turn, can result in failures
  • multiple ways to detect defects
    • Reviews are performed by a group of people, including the developer of the code
      • An informal review is called a walkthrough.
      • A more formal type of review is a formal inspection
  • root cause analysis
    • Starting with a failure, we ask why did it happen? What was the defect that led to the failure?
    • why did the defect occur? What error led to the defect?
  • Handling Defects
    • Record and categorize the defect
    • Identify and record the error
    • Look for similar defects and errors
  • Categories of Defects
    • by nature
    • severity
    • priority
  • Removing Defects
    • Change control: When we fix a defect, we are changing the software
    • Regression testing: If you make a change to the software, you need to re-run some of the test cases to make sure you haven’t accidentally broken something else.
    • Ripple effect: We need to do a careful job of analyzing the changes we make to the software to avoid ripple effects.
  • Preventing Defects
    • Defect tracking and cataloging
    • Continuous Process Improvement


The Quality Triangle


  • People, Processes, and Tools
  • People
    • Software is a labor-intensive operation
    • Hire good people.
    • Retain good people.
    • Train your staff to keep their skills up to date.
    • Management:
      • Project managers.
      • People managers.
    • Technical staff:
      • Analysts.
      • Designers.
      • Programmers.
    • Quality Assurance Function.
      • Testers.
      • Configuration Management.
      • Software Quality Assurance.
  • Processes
    • document our processes and standards.
      • Based on our own experience
      • Based on industry standards
    • Maintain
    • Train
    • Ensure we are following the standards
      • This is the role of Software Quality Assurance.
    • Tools
      • Reduces errors
      • Increases productivity and efficiency
      • Makes job easier
      • Saves money in the long run


Quality Assurance


  • People: Quality Organization
    • Configuration Management:
      • responsible for version control of the artifacts being produced by the developers
      • code, of course, but also requirements and design documentation
    • Testing
      • developers themselves are responsible for unit testing of their own pieces of work
      • separate group of people responsible for larger scale testing
    • Software Quality Assurance.
      • managerially Independent from the developers, as well as configuration management and testing
      • ensures that standards are in place and are approved
      • ensure that the standards are placed under configuration control
      • runs periodic reviews to ensure that the standards are being followed
      • assures all stakeholders of the quality of the workmanship of the rest of the team
  • Process: Standards
    • Standards are embodiments of best practices
    • Government standards
    • IEEE standards
    • ISO standards
  • Tools
    • Computer-Aided Software Engineering
    • Upper CASE tools
      • Planning and estimating.
      • Project management.
      • Requirements analysis.
      • Analysis and design.
    • Lower CASE tools
      • Coding and reuse.
      • Analyzing code.
      • Testing.
      • Configuration management.
      • Metrics.
      • Documentation.
      • Maintenance.


2024年7月23日 星期二

Patterns, Implementation, Maintenance & Reuse

Design Patterns


  • Solution to a commonly occurring design problem that can be applied over and over again in many different project context.
  • A formal design pattern has a name, a description of the problem it solves, and a solution strategy
  • Design patterns also incorporate best practices in their solutions, and result in very flexible, and reusable designs.
  • Creational patterns
    • address design issues that focus on how to make a system independent of how its objects are created which results in designs very robust in response to changes.
  • Structural patterns
    • describe ways to design objects that work with each other in very robust ways to realize new functionality
  • Behavioral patterns
    • deal with how to assign responsibilities to objects and how objects communicate with one another


Sample Design Patterns


  • Singleton pattern
    • used when we want to ensure that only a single instance from a class is instantiated
    • class constructor is not made public.
    • static variable “instance”, which in this case is a pointer to a Singleton object
    • static method named Instance, that returns a pointer to the unique Singleton object
  • Façade pattern
    • can be used to provide a unified, more simplified interface that hides any complex relationships that might exist
  • Observer pattern
    • publish-subscribe pattern
    • very useful pattern in situations where an object needs to notify other objects whenever its state changes


Implementation


  • component reuse
  • framework reuse
  • level of reuse
    • clear box: we can’t see the code
    • translucent box: Not only can we see
    • the code, but we can make changes to it
    • black box: can see can’t change


Benefit of reuse


  • Software reliability, as well as hardware reliability, is measured as “mean time to failure,” or MTTF.
  • There are two main reasons why reused software has higher reliability than hand-crafted software.
    • if I am building some software that I know will be reused by other people; I will take more care to do a good job.
    • software has higher reliability is because of something we will cover in our module on assuring software quality
  • less expensive
  • capture expert knowledge
  • standardization
  • less develop time


Impediments to Reuse


  • creating components
  • paying
  • not exact fit
  • legal
  • trust


Software maintenance


  • why we need to do maintenance
    • The better products actually received bigger maintenance budgets than the poorer ones
    • Corrective maintenance is fixing bugs
    • Adaptive maintenance is when we make changes to keep up with new technology such as new hardware or operating systems.
    • perfective maintenance
  • cost maintenance
    • 60% to 80% of the total life cycle cost of software is in maintenance
    • Another thing to keep in mind is that we are continually building more software that will need to be maintained.
    • The only thing we can do is to reduce the unit cost of maintenance.