The DRY principle: striking the delicate balance between code reuse and clarity

· Imen Ezzine · 3 minutes to read
Lego

This article explores the DRY (Don't Repeat Yourself) principle and its impact on code quality. While emphasizing its importance in avoiding repetition and facilitating maintenance, it highlights the risks of excessive application of this principle, which can be detrimental to clarity and project evolution. The aim is to strike the right balance between reuse and simplicity.

In this article, we explore the DRY (Don't Repeat Yourself) principle and its impact on code quality. While essential for avoiding redundancy and facilitating maintenance, its excessive application can sometimes complicate the understanding and evolution of a project. Let's find out how to strike the right balance between reuse and clarity.

The DRY principle: a double-edged sword

Recently, we put the finishing touches to the initial version of our current project, which will soon be launched in production. As the complexity of our code evolves due to the nature of the project, we're focusing on making it simpler and more streamlined. By implementing best practices such as the DRY (Don't Repeat Yourself) principle to avoid redundancy, we aim to maintain high quality.

This leads me to discuss a principle that I consider to be double-edged, and which should be used judiciously while remaining pragmatic.

Why apply the DRY principle?

The DRY “Don't Repeat Yourself” principle is a software development philosophy aimed at minimizing redundancy in source code. While this approach is widely praised for its effectiveness in managing code complexity, it is essential to understand how its rigid application can sometimes create confusion.

Example:

Let's take a case where we have two entities in a Symfony application: User and Admin. These two entities share common properties, such as firstname, lastname, and email. However, without normalization, we would be duplicating these properties in every entity, which violates the DRY principle. Here's an example of how it would look without normalization:

// src/Entity/User.php

namespace App\Entity;

class User
{
    private string $firstname;
    private string $lastname;
    private string $email;
    private string $job;
}
// src/Entity/Admin.php

namespace App\Entity;

class Admin
{
    private string $firstname;
    private string $lastname;
    private string $email;
    private array $roles;
}

In this case, the PhpStorm inspector or PHP Mess Detector would report a duplication of firstname, lastname and email properties in both entities. A classic suggestion would be to use inheritance to centralize these properties in a parent class, Account, to eliminate the duplication:

//src/Entity/Account.php

namespace App\Entity;

abstract class Account
{
    private string $firstname;
    private string $lastname;
    private string $email;
}

Next, we inherit User and Admin of this class Account, while adding properties specific to each of these entities:

//src/Entity/User.php

namespace App\Entity;

class User extends Account
{
    private string $job;
}
//src/Entity/Admin.php

namespace App\Entity;

class Admin extends Account
{
    private array $roles;
}

This approach centralizes shared properties in a base class. It improves readability and reduces the risk of duplication errors. However, it's important to bear in mind that this solution doesn't always have to be coupled with an ORM integration like Doctrine. Sometimes, working directly with a pure object model is better suited to keeping code independent of any framework. If Doctrine becomes necessary later on, you can always map these models with tools like MappedSuperclass or SingleTableInheritance.

When abstraction becomes excessive

However, this quest to reduce redundancy can sometimes lead to excessive abstraction. When developers seek to generalize too quickly, the code becomes harder to understand for those unfamiliar with the specific details of the project. Complex abstractions can create layers of indirection which, instead of clarifying the code, introduce additional levels of confusion.

Another aspect to consider is that persistence in strictly following the DRY principle can lead to generic code structures that are not optimal for each particular case. For example, when factoring a property such as a unique identifier (ID) for different entities, we may find that the associated rules vary according to the business context. Let's take the case of a system where users have simple numeric IDs, while customers require IDs with a regional prefix (e.g. EU-12345). In this case, centralizing ID management can complicate the code with additional conditions. Sometimes, intentional duplication of certain parts of the code, adapted to each entity, can improve readability and maintenance, especially when specific variations are likely to appear in the future.

DRY in the context of modern architecture

In modern architectures, particularly with microservices and Polyrepo strategies, it is sometimes encouraged to copy and paste between isolated services. As each service is autonomous and independent, a moderate duplication of code between different services can allow better management of local modifications and facilitate deployment without impacting other parts of the system.

Finding the right balance between code reuse and clarity is a constant challenge for developers. It's important to recognize that DRY is a guideline, not an absolute rule. Compromises may be necessary to maintain readable, understandable code while enjoying the benefits of reuse.

Conclusion

In conclusion, although the DRY principle is a valuable guide to improving code quality, its rigid application can sometimes lead to confusion. In the context of complex architectures such as microservices, developers may even be encouraged to duplicate code to guarantee service independence. The important thing is to remain aware of the project's context, and find the optimum balance between code reuse, readability and maintenance.

Are you looking to apply the DRY principle without compromising the readability and maintainability of your code?

At SensioLabs, our Symfony and PHP experts can help you structure your projects efficiently: intelligent code factoring, good development practices and scalable architecture.

This might also interest you

Fabien Potencier
Elise Hamimi

SymfonyCon Amsterdam 2025: Our Recap and the Highlights

After an iconic first edition in 2019, SymfonyCon made its big comeback to Amsterdam. From the start, you could feel the energy of a highly anticipated conference: more than 1,200 attendees, 39 nationalities, the biggest Symfony community reunion of the year, great discoveries... and a fun atmosphere. This year was extra special because it was the 20th anniversary of Symfony. SensioLabs was there: we'll tell you all about our experience there!

Read more
Chart going up
Silas Joisten

Why Tests? Explained for Management

For business leaders: why testing matters for ROI, risk reduction, and agility explained in management language with numbers and real case studies.

Read more
Code happy in lights
Imen Ezzine

Code Review: Types, Organization, and Best Practices

Code review is an essential step in the software development cycle. It improves code quality, reduces bugs, and encourages knowledge sharing within the team. GitLab and GitHub, two of the most popular code management platforms, offer advanced features to facilitate this process. This article covers the various types of code reviews, how to organize them, and how to use templates and checklists to make PRs (pull requests) more efficient.

Read more
Many Lego figurines on a white table with hands playing with them
Alexandre Nesson

Scrum Guide Expansion Pack (2025): Key Insights You Need to Know

A new building block has been added to the Scrum Guide to enrich it! Does it offer real value, or is it just window dressing? Read on to find out in this article written by one of our experts.

Read more
The SensioLabs team celebrating the 20th anniversary of Symfony with balloons
Jules Daunay

The Story Continues: SensioLabs Celebrates Symfony's 20th Anniversary

Time flies, especially when you're busy shaping the future of development! The SensioLabs team has just reached a milestone with the anniversary of the Symfony framework. We marked the occasion at the office, but the party isn't over yet. The date is already set for an XXL celebration at SymfonyCon Amsterdam 2025, from November 27 to 28.

Read more
PHP 8.5 URI extension
Oskar Stark

PHP 8.5's New URI Extension: A Game-Changer for URL Parsing

PHP 8.5 introduces a powerful new URI extension that modernizes URL handling. With support for both RFC 3986 and WHATWG standards, the new Uri class provides immutable objects, fluent interfaces, and proper validation - addressing all the limitations of the legacy parse_url() function. This guide shows practical before/after examples and explains when to use each standard.

Read more
Open in new tab
Silas Joisten

The Tab Trap: Why Forcing New Tabs Is Bad UX

We’ve all done it — added target="_blank" to a link to “help users” stay on our site. But what feels like a harmless convenience often creates confusion, breaks accessibility, and introduces hidden security risks.

Read more
3 dog heads
Mathieu Santostefano

Bring Your Own HTTP client

Break free from rigid dependencies in your PHP SDKs. Learn how to use PSR-7, PSR-17, and PSR-18 standards along with php-http/discovery to allow users to bring their favorite HTTP client, whether it's Guzzle, Symfony HttpClient, or another. A must-read for PHP and Symfony developers.

Read more
Image