Structural QA: Difference between revisions
Added category Quality Assurance definitions |
No edit summary |
||
| Line 16: | Line 16: | ||
A common structural problem in PHP is deeply nested code, which makes it difficult to read and maintain. | A common structural problem in PHP is deeply nested code, which makes it difficult to read and maintain. | ||
<syntaxhighlight>// Bad practice: | <syntaxhighlight lang="php">// Bad practice: | ||
if (condition1) { | if (condition1) { | ||
if (condition2) { | if (condition2) { | ||
| Line 36: | Line 36: | ||
Rather than including or requiring files manually, use autoloaders to load classes automatically. This is a structural improvement that makes code more maintainable. | Rather than including or requiring files manually, use autoloaders to load classes automatically. This is a structural improvement that makes code more maintainable. | ||
<syntaxhighlight>// Instead of this: | <syntaxhighlight lang="php">// Instead of this: | ||
require 'User.php'; | require 'User.php'; | ||
require 'Order.php'; | require 'Order.php'; | ||
| Line 49: | Line 49: | ||
Global variables can make code unpredictable and harder to maintain. Encapsulate your data and use dependency injection or pass them as arguments. | Global variables can make code unpredictable and harder to maintain. Encapsulate your data and use dependency injection or pass them as arguments. | ||
<syntaxhighlight>// Avoid this: | <syntaxhighlight lang="php">// Avoid this: | ||
global $database; | global $database; | ||
| Line 61: | Line 61: | ||
Coupling refers to the degree to which one class knows about another class. If classes are too dependent on each other, it results in tight coupling, making the system harder to modify. | Coupling refers to the degree to which one class knows about another class. If classes are too dependent on each other, it results in tight coupling, making the system harder to modify. | ||
<syntaxhighlight>// bad | <syntaxhighlight lang="php">// bad | ||
class Order { | class Order { | ||
public function calculateTotal() { | public function calculateTotal() { | ||
$shipping = new Shipping(); | $shipping = new Shipping(); | ||
return $this- | return $this->subtotal + $shipping->calculate(); | ||
} | } | ||
} | } | ||
| Line 74: | Line 74: | ||
public function __construct(Shipping $shipping) { | public function __construct(Shipping $shipping) { | ||
$this- | $this->shipping = $shipping; | ||
} | } | ||
public function calculateTotal() { | public function calculateTotal() { | ||
return $this- | return $this->subtotal + $this->shipping->calculate(); | ||
} | } | ||
}</syntaxhighlight> | }</syntaxhighlight> | ||
| Line 86: | Line 86: | ||
These are objects that know too much or do too much, essentially violating the Single Responsibility Principle (SRP). Breaking them down helps in making the system modular and maintainable. | These are objects that know too much or do too much, essentially violating the Single Responsibility Principle (SRP). Breaking them down helps in making the system modular and maintainable. | ||
<syntaxhighlight>// Bad | <syntaxhighlight lang="php">// Bad | ||
class System { | class System { | ||
public function authenticateUser() { /*...*/ } | public function authenticateUser() { /*...*/ } | ||
| Line 114: | Line 114: | ||
Rather than hardcoding values, it's better to use configuration files or constants. | Rather than hardcoding values, it's better to use configuration files or constants. | ||
<syntaxhighlight>// Bad | <syntaxhighlight lang="php">// Bad | ||
function getConnection() { | function getConnection() { | ||
return new DatabaseConnection( | return new DatabaseConnection("localhost", "root", "password123"); | ||
} | } | ||
// Better | // Better | ||
| Line 125: | Line 125: | ||
Not handling potential errors can lead to unexpected system crashes or bugs. | Not handling potential errors can lead to unexpected system crashes or bugs. | ||
<syntaxhighlight>// Bad | <syntaxhighlight lang="php">// Bad | ||
function divide($a, $b) { | function divide($a, $b) { | ||
return $a / $b; | return $a / $b; | ||
| Line 132: | Line 132: | ||
function divide($a, $b) { | function divide($a, $b) { | ||
if ($b == 0) { | if ($b == 0) { | ||
throw new DivisionByZeroException( | throw new DivisionByZeroException("Cannot divide by zero"); | ||
} | } | ||
return $a / $b; | return $a / $b; | ||
| Line 155: | Line 155: | ||
By focusing on structural quality assurance developers can ensure that their codebase remains maintainable, scalable, and less prone to bugs. | By focusing on structural quality assurance developers can ensure that their codebase remains maintainable, scalable, and less prone to bugs. | ||
[[Category:Quality Assurance definitions]] | [[Category:Quality Assurance definitions]] | ||
Latest revision as of 17:25, 22 October 2025
Structural Quality Assurance is the process of evaluating the non-functional attributes of a software system, particularly focusing on how well it is structured internally. Unlike external quality (which deals with factors like usability, functionality, and reliability perceived by users), structural quality looks into the architecture, code, and components of the software.
Structural quality assurance aims to ensure that the software:
- Is maintainable.
- Can be efficiently scaled.
- Is robust and does not have vulnerabilities.
- Has an architecture that is both coherent and cohesive. To understand it better, think of a building: if the foundation, materials, and architectural design are sound, the building will be more durable and safe.
Examples of structural QA
Avoiding Deep Nesting
A common structural problem in PHP is deeply nested code, which makes it difficult to read and maintain.
// Bad practice:
if (condition1) {
if (condition2) {
if (condition3) {
// Do something
}
}
}
// Improved practice:
if (!condition1) return;
if (!condition2) return;
if (condition3) {
// Do something
}
Using Autoloaders
Rather than including or requiring files manually, use autoloaders to load classes automatically. This is a structural improvement that makes code more maintainable.
// Instead of this:
require 'User.php';
require 'Order.php';
// Use autoloading:
spl_autoload_register(function ($class_name) {
include $class_name . '.php';
});
Avoiding Global Variables
Global variables can make code unpredictable and harder to maintain. Encapsulate your data and use dependency injection or pass them as arguments.
// Avoid this:
global $database;
// Instead, inject it:
function doSomething($database) {
// ...
}
Tight Coupling
Coupling refers to the degree to which one class knows about another class. If classes are too dependent on each other, it results in tight coupling, making the system harder to modify.
// bad
class Order {
public function calculateTotal() {
$shipping = new Shipping();
return $this->subtotal + $shipping->calculate();
}
}
// Better
class Order {
private $shipping;
public function __construct(Shipping $shipping) {
$this->shipping = $shipping;
}
public function calculateTotal() {
return $this->subtotal + $this->shipping->calculate();
}
}
God Objects
These are objects that know too much or do too much, essentially violating the Single Responsibility Principle (SRP). Breaking them down helps in making the system modular and maintainable.
// Bad
class System {
public function authenticateUser() { /*...*/ }
public function logError() { /*...*/ }
public function sendEmail() { /*...*/ }
// ... and many more unrelated methods.
}Better: Split into distinct classes: UserAuthentication, ErrorLogger, EmailService, etc.
Cyclic Dependencies
Cyclic dependencies occur when two or more modules depend on each other, which makes the system hard to maintain and understand. Module A depends on Module B, and Module B depends on Module A.
Refactoring and re-architecting the system can help eliminate such cycles.
Lack of Modularization
Not breaking down the system into modular parts makes it hard to manage and extend.
For a web application, rather than having a single massive script handling everything, it's better to break down functionality into controllers, services, repositories, etc.
Hardcoding Values
Rather than hardcoding values, it's better to use configuration files or constants.
// Bad
function getConnection() {
return new DatabaseConnection("localhost", "root", "password123");
}
// Better
Use configuration files or environment variables to store such values.
Lack of Error Handling
Not handling potential errors can lead to unexpected system crashes or bugs.
// Bad
function divide($a, $b) {
return $a / $b;
}
// Better
function divide($a, $b) {
if ($b == 0) {
throw new DivisionByZeroException("Cannot divide by zero");
}
return $a / $b;
}
Tools for Structural Quality Assurance in PHP
PHP_CodeSniffer (PHPCS)
This tool checks your PHP code against certain coding standards. It can be used to ensure that your code adheres to popular coding standards such as PSR-12 or custom ones.
PHPStan
A static analysis tool for PHP that focuses on discovering bugs in your code. It can help identify type errors, unused variables, and much more.
PHPUnit
While primarily a testing framework, good test coverage with PHPUnit can be seen as a structural quality metric, ensuring that your code behaves as expected.
By focusing on structural quality assurance developers can ensure that their codebase remains maintainable, scalable, and less prone to bugs.