Skip to content

Latest commit

 

History

History
1091 lines (820 loc) · 20.3 KB

File metadata and controls

1091 lines (820 loc) · 20.3 KB
Duplication Type Short Description
Data Duplication Repeated constants, literals, configuration values, or raw data across the codebase.
Type Duplication Similar logic implemented separately for different data types/classes.
Algorithm Duplication Repeated computational logic or processing algorithms with minor variations.
Structural Duplication Repeated control-flow or architectural structure even when logic differs slightly.
Semantic Duplication Different code expressing the same business meaning or rule.
Temporal Duplication Operations that must always occur together or in a fixed sequence.
Knowledge Duplication The same business fact or rule represented in multiple places/systems.
Representation Duplication Multiple nearly-identical models, DTOs, schemas, or data representations.
Behavioral Duplication Different implementations producing the same observable behavior.
UI Duplication Repeated interface layouts, components, interaction logic, or styling patterns.
Configuration Duplication Repeated infrastructure, deployment, runtime, or application configuration.
Test Duplication Repeated test setup, fixtures, assertions, or validation logic.
Query Duplication Repeated SQL, ORM queries, filters, or data-access patterns.
Protocol Duplication Repeated handling logic for APIs, transports, retries, auth, or serialization.
Copy-Paste Duplication Directly copied source code with little or no modification.
Textual Duplication Similar or identical raw source text regardless of meaning.
Lexical Duplication Similar token sequences after parsing source code.
Syntactic Duplication Similar AST/code structure despite formatting or naming differences.
Functional Duplication Different implementations achieving the same functional/business outcome.
Architectural Duplication Repeated subsystem, service, module, or application architecture patterns.
Process Duplication Repeated manual operational or development workflows/processes.
Cross-Service Duplication Duplicate business logic or validation spread across microservices/systems.
Clone Type-1 Duplication Exact copied code differing only in whitespace/comments.
Clone Type-2 Duplication Copied code with renamed variables, methods, or types.
Clone Type-3 Duplication Copied code with partial modifications, insertions, or deletions.
Clone Type-4 Duplication Different implementations that perform the same behavior semantically.
Logic Duplication Repeated conditional or decision-making logic throughout the system.
Validation Duplication Repeated input validation or business validation rules.
Error-Handling Duplication Repeated exception handling, retry, fallback, or logging patterns.
State Duplication Multiple independent representations of the same mutable state.
Documentation Duplication Repeated or mirrored documentation that can drift out of sync.
Dependency Duplication Multiple versions or repeated inclusion of similar libraries/packages.
Schema Duplication Repeated database, API, event, or serialization schema definitions.
Mapping Duplication Repeated object conversion or transformation code between layers/models.
Permission Duplication Repeated authorization or access-control rules across components.
Workflow Duplication Repeated orchestration or business-process flow logic.
Event Duplication Multiple systems independently reacting to or recreating the same event semantics.
Caching Duplication Duplicate caching logic, invalidation rules, or cache representations.
Localization Duplication Repeated translation strings or locale-specific formatting rules.
Build Duplication Repeated CI/CD, build scripts, packaging, or compilation logic.
Monitoring Duplication Repeated metrics, logging, tracing, or observability instrumentation.
Serialization Duplication Repeated encoding/decoding logic for JSON, XML, protobuf, etc.
Integration Duplication Repeated glue code integrating with third-party systems/services.
Policy Duplication Repeated business policy or governance rules in multiple locations.
Domain Rule Duplication Core domain/business invariants implemented independently in multiple places.
Security Duplication Repeated authentication, encryption, sanitization, or security checks.
Concurrency Duplication Repeated synchronization, locking, threading, or async coordination patterns.
Resource Lifecycle Duplication Repeated acquire/use/release patterns for files, sockets, DB connections, etc.
Boilerplate Duplication Repeated scaffolding or framework-required code with minimal variation.
Template Duplication Repeated code/templates differing only by injected values or parameters.
Generated-Code Duplication Duplicate generated artifacts caused by code generators or schema compilers.
Intentional Duplication Deliberate duplication to preserve isolation, simplicity, or deployability.
Accidental Duplication Unplanned duplication caused by copy-paste, poor abstraction, or drift.

PHP Duplication Types — Examples and Refactors

This document shows common duplication patterns in PHP codebases. Each section includes:

  1. Duplicate implementations
  2. Why the duplication is problematic
  3. A refactored/deduplicated approach

1. Data Duplication

Duplicate Code

function calculateSalesTax(float $amount): float {
    return $amount * 0.07;
}
function calculateInvoiceTax(float $amount): float {
    return $amount * 0.07;
}
function calculateRefundTax(float $amount): float {
    return $amount * 0.07;
}

Refactored

const TAX_RATE = 0.07;

function calculateTax(float $amount): float {
    return $amount * TAX_RATE;
}

2. Type Duplication

Duplicate Code

function processUser(User $user): void {
    echo $user->getName();
}
function processAdmin(Admin $admin): void {
    echo $admin->getName();
}
function processCustomer(Customer $customer): void {
    echo $customer->getName();
}

Refactored

interface NamedEntity {
    public function getName(): string;
}

function processNamedEntity(NamedEntity $entity): void {
    echo $entity->getName();
}

3. Algorithm Duplication

Duplicate Code

function calculateRegularDiscount(float $price): float {
    return $price * 0.90;
}
function calculateHolidayDiscount(float $price): float {
    return $price * 0.85;
}
function calculateVipDiscount(float $price): float {
    return $price * 0.80;
}

Refactored

function applyDiscount(float $price, float $discountRate): float {
    return $price * (1 - $discountRate);
}

4. Structural Duplication

Duplicate Code

function loadUsers(PDO $db): array {
    $stmt = $db->query('SELECT * FROM users');
    return $stmt->fetchAll();
}
function loadOrders(PDO $db): array {
    $stmt = $db->query('SELECT * FROM orders');
    return $stmt->fetchAll();
}
function loadInvoices(PDO $db): array {
    $stmt = $db->query('SELECT * FROM invoices');
    return $stmt->fetchAll();
}

Refactored

function loadTable(PDO $db, string $table): array {
    $stmt = $db->query("SELECT * FROM {$table}");
    return $stmt->fetchAll();
}

5. Semantic Duplication

Duplicate Code

function isAdult(User $user): bool {
    return $user->age >= 18;
}
function canRegister(User $user): bool {
    return $user->birthDate <= new DateTime('-18 years');
}
function allowPurchase(User $user): bool {
    return !$user->isMinor();
}

Refactored

class AgePolicy {
    public static function isAdult(User $user): bool {
        return $user->birthDate <= new DateTime('-18 years');
    }
}

6. Temporal Duplication

Duplicate Code

$lock->acquire();
updateInventory();
$lock->release();
$lock->acquire();
updateOrders();
$lock->release();
$lock->acquire();
sendInvoice();
$lock->release();

Refactored

function withLock(Lock $lock, callable $callback): void {
    $lock->acquire();

    try {
        $callback();
    } finally {
        $lock->release();
    }
}

7. Knowledge Duplication

Duplicate Code

const PASSWORD_MAX_LENGTH = 32;
$validator->maxLength('password', 32);
VARCHAR(32)

Refactored

class PasswordRules {
    public const MAX_LENGTH = 32;
}

8. Representation Duplication

Duplicate Code

class UserDTO {
    public string $name;
    public string $email;
}
class UserApiModel {
    public string $name;
    public string $email;
}
class UserViewModel {
    public string $name;
    public string $email;
}

Refactored

class UserData {
    public function __construct(
        public string $name,
        public string $email,
    ) {}
}

9. Behavioral Duplication

Duplicate Code

function isActive(User $user): bool {
    return !$user->disabled && $user->confirmed;
}
function canLogin(User $user): bool {
    return $user->confirmed && !$user->disabled;
}
function canAccessDashboard(User $user): bool {
    return !$user->disabled && $user->confirmed;
}

Refactored

class UserStatus {
    public static function isActive(User $user): bool {
        return !$user->disabled && $user->confirmed;
    }
}

10. UI Duplication

Duplicate Code

<input type="text" name="first_name" class="form-control">
<input type="text" name="last_name" class="form-control">
<input type="text" name="city" class="form-control">

Refactored

function renderInput(string $name): string {
    return sprintf(
        '<input type="text" name="%s" class="form-control">',
        htmlspecialchars($name)
    );
}

11. Configuration Duplication

Duplicate Code

redis_timeout: 30
redis_retries: 3
cache_timeout: 30
cache_retries: 3
queue_timeout: 30
queue_retries: 3

Refactored

shared_defaults:
  timeout: 30
  retries: 3

12. Test Duplication

Duplicate Code

$user = UserFactory::create();
$this->actingAs($user);
$response = $this->get('/dashboard');
$response->assertOk();
$user = UserFactory::create();
$this->actingAs($user);
$response = $this->get('/settings');
$response->assertOk();

Refactored

function authenticatedGet(string $url): TestResponse {
    $user = UserFactory::create();
    $this->actingAs($user);

    return $this->get($url);
}

13. Query Duplication

Duplicate Code

$db->query("SELECT * FROM users WHERE deleted = 0");
$db->query("SELECT * FROM admins WHERE deleted = 0");
$db->query("SELECT * FROM customers WHERE deleted = 0");

Refactored

function selectActive(PDO $db, string $table): array {
    $stmt = $db->query("SELECT * FROM {$table} WHERE deleted = 0");
    return $stmt->fetchAll();
}

14. Protocol Duplication

Duplicate Code

$response = $client->get($url, [
    'headers' => ['Authorization' => 'Bearer ' . $token],
]);
$response = $client->post($url, [
    'headers' => ['Authorization' => 'Bearer ' . $token],
]);

Refactored

class ApiClient {
    public function request(string $method, string $url, array $options = []) {
        $options['headers']['Authorization'] = 'Bearer ' . $this->token;

        return $this->client->request($method, $url, $options);
    }
}

15. Copy-Paste Duplication

Duplicate Code

$total = $subtotal + $tax;
$formatted = number_format($total, 2);
echo $formatted;
$total = $subtotal + $tax;
$formatted = number_format($total, 2);
echo $formatted;

Refactored

function renderTotal(float $subtotal, float $tax): void {
    $total = $subtotal + $tax;
    echo number_format($total, 2);
}

16. Logic Duplication

Duplicate Code

if ($user->role === 'admin' || $user->role === 'manager') {
    grantAccess();
}
if (in_array($user->role, ['admin', 'manager'])) {
    showDashboard();
}

Refactored

function hasElevatedAccess(User $user): bool {
    return in_array($user->role, ['admin', 'manager']);
}

17. Validation Duplication

Duplicate Code

if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    throw new InvalidArgumentException();
}
if (!filter_var($customerEmail, FILTER_VALIDATE_EMAIL)) {
    throw new InvalidArgumentException();
}

Refactored

function validateEmail(string $email): void {
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        throw new InvalidArgumentException('Invalid email');
    }
}

18. Error-Handling Duplication

Duplicate Code

try {
    syncUsers();
} catch (Throwable $e) {
    logger()->error($e->getMessage());
}
try {
    syncOrders();
} catch (Throwable $e) {
    logger()->error($e->getMessage());
}

Refactored

function safely(callable $callback): void {
    try {
        $callback();
    } catch (Throwable $e) {
        logger()->error($e->getMessage());
    }
}

19. State Duplication

Duplicate Code

$user->balance = 100;
$cache['balance'] = 100;
$_SESSION['balance'] = 100;

Refactored

class BalanceService {
    public function set(User $user, float $balance): void {
        $user->balance = $balance;
    }
}

20. Documentation Duplication

Duplicate Code

// Max upload size: 20MB
Maximum upload size is 20MB.
upload_limit: 20MB

Refactored

class UploadConfig {
    public const MAX_SIZE_MB = 20;
}

21. Dependency Duplication

Duplicate Code

"monolog/monolog": "^2.0"
"monolog/monolog": "^2.1"
"monolog/monolog": "^3.0"

Refactored

"monolog/monolog": "^3.0"

22. Schema Duplication

Duplicate Code

'name' => 'required|string|max:255'
#[Assert\Length(max: 255)]
VARCHAR(255)

Refactored

class UserSchema {
    public const NAME_MAX_LENGTH = 255;
}

23. Mapping Duplication

Duplicate Code

$userDto->name = $user->name;
$userDto->email = $user->email;
$payload['name'] = $user->name;
$payload['email'] = $user->email;

Refactored

function mapUser(User $user): array {
    return [
        'name' => $user->name,
        'email' => $user->email,
    ];
}

24. Permission Duplication

Duplicate Code

if (!$user->isAdmin()) {
    abort(403);
}
if (!$user->isAdmin()) {
    throw new AuthorizationException();
}

Refactored

function requireAdmin(User $user): void {
    if (!$user->isAdmin()) {
        throw new AuthorizationException();
    }
}

25. Workflow Duplication

Duplicate Code

validateOrder();
chargeCard();
sendReceipt();
validateSubscription();
chargeCard();
sendReceipt();

Refactored

function executePurchaseWorkflow(callable $validator): void {
    $validator();
    chargeCard();
    sendReceipt();
}

26. Security Duplication

Duplicate Code

$password = password_hash($password, PASSWORD_BCRYPT);
$pin = password_hash($pin, PASSWORD_BCRYPT);

Refactored

function hashSecret(string $secret): string {
    return password_hash($secret, PASSWORD_BCRYPT);
}

27. Resource Lifecycle Duplication

Duplicate Code

$file = fopen($path, 'r');
$data = fread($file, filesize($path));
fclose($file);
$file = fopen($otherPath, 'r');
$data = fread($file, filesize($otherPath));
fclose($file);

Refactored

function readFileContents(string $path): string {
    $file = fopen($path, 'r');

    try {
        return fread($file, filesize($path));
    } finally {
        fclose($file);
    }
}

28. Boilerplate Duplication

Duplicate Code

class UserController {
    public function __construct(private Logger $logger) {}
}
class OrderController {
    public function __construct(private Logger $logger) {}
}

Refactored

abstract class BaseController {
    public function __construct(protected Logger $logger) {}
}

29. Template Duplication

Duplicate Code

<h1>User Report</h1>
<p>Total: <?= $total ?></p>
<h1>Sales Report</h1>
<p>Total: <?= $total ?></p>

Refactored

function renderReport(string $title, float $total): void {
    echo "<h1>{$title}</h1>";
    echo "<p>Total: {$total}</p>";
}

30. Concurrency Duplication

Duplicate Code

$mutex->lock();
updateStats();
$mutex->unlock();
$mutex->lock();
updateCache();
$mutex->unlock();

Refactored

function synchronized(Mutex $mutex, callable $callback): void {
    $mutex->lock();

    try {
        $callback();
    } finally {
        $mutex->unlock();
    }
}

31. Monitoring Duplication

Duplicate Code

$metrics->increment('users.created');
$metrics->increment('orders.created');
$metrics->increment('tickets.created');

Refactored

function trackCreated(string $entity): void {
    metrics()->increment("{$entity}.created");
}

32. Serialization Duplication

Duplicate Code

json_encode([
    'id' => $user->id,
    'name' => $user->name,
]);
json_encode([
    'id' => $admin->id,
    'name' => $admin->name,
]);

Refactored

function serializeIdentity(object $entity): string {
    return json_encode([
        'id' => $entity->id,
        'name' => $entity->name,
    ]);
}

33. Integration Duplication

Duplicate Code

$mailchimp->subscribe($email);
logger()->info('Subscribed');
$sendgrid->subscribe($email);
logger()->info('Subscribed');

Refactored

function subscribe(NewsletterProvider $provider, string $email): void {
    $provider->subscribe($email);
    logger()->info('Subscribed');
}

34. Policy Duplication

Duplicate Code

if ($invoice->amount > 10000) {
    requireManagerApproval();
}
if ($purchase->amount > 10000) {
    requireManagerApproval();
}

Refactored

class ApprovalPolicy {
    public static function requiresManagerApproval(float $amount): bool {
        return $amount > 10000;
    }
}

35. Domain Rule Duplication

Duplicate Code

if ($account->balance < 0) {
    throw new RuntimeException('Overdraft not allowed');
}
if ($wallet->balance < 0) {
    throw new RuntimeException('Overdraft not allowed');
}

Refactored

class BalanceRules {
    public static function ensureNonNegative(float $balance): void {
        if ($balance < 0) {
            throw new RuntimeException('Overdraft not allowed');
        }
    }
}