DEV Community

Cover image for DRY (Don't Repeat Yourself)
Parzival
Parzival

Posted on

1

DRY (Don't Repeat Yourself)

Core Concept

DRY emphasizes that every piece of knowledge in a system should have a single, unambiguous representation.

Examples of Code Violating DRY

Example 1: Validation Logic

// WET (Write Everything Twice) Code
class User {
    public function validateUsername($username) {
        if (strlen($username) < 3 || strlen($username) > 20) {
            throw new Exception("Username must be between 3 and 20 characters");
        }
        if (!preg_match('/^[a-zA-Z0-9_]+$/', $username)) {
            throw new Exception("Username can only contain letters, numbers and underscore");
        }
    }

    public function updateUsername($username) {
        // Same validation repeated
        if (strlen($username) < 3 || strlen($username) > 20) {
            throw new Exception("Username must be between 3 and 20 characters");
        }
        if (!preg_match('/^[a-zA-Z0-9_]+$/', $username)) {
            throw new Exception("Username can only contain letters, numbers and underscore");
        }
        // Update logic
    }
}
Enter fullscreen mode Exit fullscreen mode

DRY Solution

class User {
    private function validateUsername($username) {
        if (strlen($username) < 3 || strlen($username) > 20) {
            throw new Exception("Username must be between 3 and 20 characters");
        }
        if (!preg_match('/^[a-zA-Z0-9_]+$/', $username)) {
            throw new Exception("Username can only contain letters, numbers and underscore");
        }
    }

    public function createUser($username) {
        $this->validateUsername($username);
        // Creation logic
    }

    public function updateUsername($username) {
        $this->validateUsername($username);
        // Update logic
    }
}
Enter fullscreen mode Exit fullscreen mode

Implementing DRY with Inheritance

abstract class BaseController {
    protected function jsonResponse($data, $status = 200) {
        header('Content-Type: application/json');
        http_response_code($status);
        echo json_encode($data);
    }
}

class UserController extends BaseController {
    public function show($id) {
        $user = User::find($id);
        return $this->jsonResponse($user);
    }
}

class ProductController extends BaseController {
    public function show($id) {
        $product = Product::find($id);
        return $this->jsonResponse($product);
    }
}
Enter fullscreen mode Exit fullscreen mode

Using Traits for DRY

trait Loggable {
    private function log($message) {
        $timestamp = date('Y-m-d H:i:s');
        file_put_contents('log.txt', "[$timestamp] $message\n", FILE_APPEND);
    }
}

class UserService {
    use Loggable;

    public function createUser($data) {
        $this->log("Creating new user");
        // User creation logic
    }
}

class PaymentService {
    use Loggable;

    public function processPayment($amount) {
        $this->log("Processing payment: $amount");
        // Payment processing logic
    }
}
Enter fullscreen mode Exit fullscreen mode

Using Constants

class Config {
    const DEFAULT_ITEMS_PER_PAGE = 10;
    const MAX_UPLOAD_SIZE = 5242880; // 5MB
    const ALLOWED_FILE_TYPES = ['jpg', 'png', 'pdf'];
}

class FileUploadService {
    public function validateFile($file) {
        if ($file['size'] > Config::MAX_UPLOAD_SIZE) {
            throw new Exception("File too large");
        }

        $extension = pathinfo($file['name'], PATHINFO_EXTENSION);
        if (!in_array($extension, Config::ALLOWED_FILE_TYPES)) {
            throw new Exception("Invalid file type");
        }
    }
}

class MediaController {
    public function index() {
        return $this->paginate(Config::DEFAULT_ITEMS_PER_PAGE);
    }
}
Enter fullscreen mode Exit fullscreen mode

These examples demonstrate how to apply DRY through various PHP features like inheritance, traits, constants, and proper method extraction. The goal is to maintain a single source of truth for any given functionality in your codebase.

Sentry blog image

How to reduce TTFB

In the past few years in the web dev world, we’ve seen a significant push towards rendering our websites on the server. Doing so is better for SEO and performs better on low-powered devices, but one thing we had to sacrifice is TTFB.

In this article, we’ll see how we can identify what makes our TTFB high so we can fix it.

Read more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay