2021/05/06
2021/05/07 (補充)
2022/05/15 (新增連結)
2022/05/16 (新增連結)
2022/06/06 (新增投影片)
2024/05/20 (補充投影片內容)
軟體品質是個多面向的概念 (詳參: Software quality),包括需求面、穩定性(reliability)、安全性 (security)、效率 (efficiency)、可維護性 (maintainability)。
2022/06/06 (新增投影片)
2024/05/20 (補充內容)
軟體品質
需求面
穩定性
安全性
效率
可維護性
滿足使用者的需求是最重要的品質,一般而言,管理的方式包含過程的管理及結果的管理。
過程的管理,就是必須有嚴謹的需求開發與管理的流程,確保正確的取得使用者的需求,並且當需求更動時,正確的更動相關的文件,需求更動也正確的落實。
結果的管理通常是透過測試來達成,不過,測試有很多種類,與需求相關的測試通常稱為功能性測試。就CMMI的建議就是Validation。
軟體的穩定性也是可以透過過程的管理及結果的管理來達成。
過程的管理通常是透過制定程式碼的規範並進行人工的code review或自動化的code analysis工具。
結果的管理則是透過測試工具進行負載測試,了解在特定負載下系統是否能穩定操作,也可以進行壓力測試,壓力測試的目的在於了解系統的最高可承載的壓力。
9 Best Website Monitoring Solutions for Small to Enterprise Business
JMeter
測好測滿(一) : 壓力測試Jmeter (2021)
Day 20 Jmeter 壓力測試工具 (2018)
JMeterTutorial (5個影片) (2013)
JMeter - 壓力測試 - 簡單版 (2008)
JMeter - 壓力測試 - 進階版 (2009)
軟體的安全性也是可以透過過程的管理及結果的管理來達成。
過程的管理可以透過制定程式碼的安全規範並進行人工的code review或利用自動化的code analysis工具找出安全漏洞。
結果的管理利通常透過安全性檢測,安全性檢測可分為白箱檢測與黑箱檢測,白箱檢測通常是針對程式碼進行檢測,可以透過制定程式碼的安全規範並進行人工的code review或利用自動化的code analysis工具找出安全漏洞。黑箱檢測則是透過測試工具進行測試,了解在各種可能的攻擊下系統是否有效防禦。
Top 10 Web Application Security Risks (by OWASP)
13 Online Free Tools to Scan Website Security Vulnerabilities & Malware
軟體的效率也是可以透過過程的管理及結果的管理來達成。
過程的管理通常是透過制定程式碼的規範並進行人工的code review或自動化的code analysis工具找出效率瓶頸。
結果的管理則是透過測試工具進行負載測試,了解在特定負載下系統的效率是否達到目標的回應速度。
工具
Lighthouse in Chrome DevTools **
也可使用 PageSpeed Insights
軟體的可維護性通常是過程的管理來達成,利用透過制定程式碼的規範(如: Clean Code原則)並進行人工的code review或自動化的code analysis工具。
有些寫程式的原則,可以提昇軟體品質,尤其是可維護性,以PHP為例,可參考:
有些規則可以使用工具來幫忙檢查
變數命名、函數命名要容易理解,例如,陣列就使用複數(如:customers)、個別資料就使用單數(如:customer)。
//php
$customers = ["Ben", "Mary", "Tom", "Nancy", "Peter"];
foreach( $customers as $customer ) {
echo "Value is $customer <br />";
}
function的名稱應該與行為一致,例如,設定變數內容就在function名稱前加set,取得資料就在function名稱前加get,後面就加上要處理的變數名稱,不同的字,就用大寫區分。
// php
function setName($name){
$this->name = $name;
}
function getName(){
return $this->name;
}
遵守命名規則會讓自己容易閱讀自己寫過的程式,也可以讓同組同學容易閱讀彼此的程式碼
盡量利用命名讓程式碼容易閱讀,就可以減少註解的使用,然而,真的需要說明的部分(如:複雜的公式)可利用註解說明
程式碼的變動盡量利用git的commit註解,在程式碼中利用註解說明更動的內容,可能讓程式碼不容易閱讀
盡量利用「===」或「!==」,PHP跟Javascript的「==」與「!=」可以將字串與數字進行比較,並且會自動轉換資料型態,但是,這樣也會有一些負作用,所以,盡量使用「===」或「!==」
利用「??」檢查空值,取代isset(),讓語法精簡
$name = $_GET['name'] ?? $_POST['name'] ?? 'nobody';
每個函數只做一件事,如果函數處理了兩件事,盡量就切割為兩個函數
避免使用太多參數,可利用物件減少參數的數量
利用例外處理代替回傳錯誤碼
避免完全不處理錯誤
避免利用PHP mysqli error() Function 處理錯誤
函數或迴圈應該利用縮排來讓程式碼容易閱讀
可以利用Linter來協助
目的
模組化讓程式碼容易閱讀
模組化讓程式碼容易除錯
模組化讓程式碼容易共用,共用的好處是,修改時,改一個地方,不用到處改
** 以下內容還沒改為mysqli的語法 **
<?php
$servername = "localhost";
$dbname = "practice";
$username = "root";
$password = "12345678";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected successfully";
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
$sql="select * from job";
$stmt = $conn->prepare($sql);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<table width='85%' style='float:center'>
<tr style='text-align:center'>
<td>求才廠商</td>
<td>求才內容</td>
<td>日期</td>
</tr>
<?php
foreach($rows as $job){ ?>
<tr style='text-align:center'>
<td><?=$job["company"]?></td>
<td><?=$job["content"]?></td>
<td><?=$job["pdate"]?></td>
</tr>
<?php
}
$conn = null;
?>
</table>
?>
我們可以把共用的邏輯獨立成一個檔案,讓不同程式可以共用,未來需要改變的時候,只要改一個地方就好了,例如,將資料庫的參數獨立。
db.php
$servername = "localhost";
$dbname = "practice";
$username = "root";
$password = "12345678";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected successfully";
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
get_jobs.php
<?php
require 'db.php';
$sql="select * from job";
$stmt = $conn->prepare($sql);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<table width='85%' style='float:center'>
<tr style='text-align:center'>
<td>求才廠商</td>
<td>求才內容</td>
<td>日期</td>
</tr>
<?php
foreach($rows as $job){ ?>
<tr style='text-align:center'>
<td><?=$job["company"]?></td>
<td><?=$job["content"]?></td>
<td><?=$job["pdate"]?></td>
</tr>
<?php
}
$conn = null;
?>
</table>
變數的範圍越小越好,全域變數很容易產生意外的讓程式碼錯誤,在PHP裡是不能取得函數外的變數,雖然,PHP裡可以使用global變數,但盡量避免。
<?php
$x = 5; // global scope
function myTest() {
// using x inside this function will generate an error
echo "<p>Variable x inside function is: $x</p>";
}
myTest();
echo "<p>Variable x outside function is: $x</p>";
?>
如果需要,就要把變數利用參數傳入函數
<?php
$x = 5; // global scope
function myTest($x) {
echo "<p>Variable x inside function is: $x</p>";
}
myTest($x);
echo "<p>Variable x outside function is: $x</p>";
?>
盡可能是用常數,否則,當常數要修改時,很容易就會遺漏
前端、後端分離,以PHP開發而言,HTML的內容與PHP的程式碼盡可能分離。盡量不要把資料存取的邏輯和呈現的邏輯放在一起,請參考上面的get_jobs.php。
可套用以MVC架構為基礎的框架,如: Laravel。
該加密的資料庫欄位應該加密
[PHP] 使用 password_hash 與 password_verify 來做密碼的加密與檢查 (PHP 5.5以後)
PHP之密碼加密的幾種方式 (更深入的說明)
更動資料表盡量使用Prepared Statement,避免SQL Injection。以PHP為例:
軟體品質 (吳濟聰老師專案管理課程網站)
The Software Engineer’s Complete Guide to Code Quality **很不錯的簡介文章
What Is Code Quality?
Documentation, Code Standards, and Style Guides
The Importance of Code Reviews
Tools To Review Code Quality
Code Refactoring
Decreasing Technical Debt
逐步提昇PHP技術能力 - 逐步改善軟體架構