Technologies | March 2, 2022

Legacy code refactoring with Rector PHP

Working with “inherited” code or with code that has not yet been tested can lead to a great deal of concern. Getting rid of such code is not always possible – refactoring with suitable tools is often required. For over 15 years, PHP software developers have been able to utilize solutions to aid in the struggle with legacy code in their everyday work. But what exactly is legacy code and how can we learn to work with it? How can we get rid of technical debt? In this article, I would like to introduce you to a tool called Rector.

Legacy code

Legacy code – what is it?

Inherited code

Before I proceed to describe the capabilities of Rector, I would like to take a few sentences to outline what legacy code is and what the most frequently chosen ways of dealing with this problem are. There are numerous definitions of legacy code on the web. Literally translated, legacy code means nothing other than “inherited code”, or code that we de facto inherit from other software developers, for example when joining a new project. This code causes fear and concern – it works, but we do not know the intricacies of the logic behind it. Spaghetti code, which is particularly difficult to understand and harness, is especially feared.

The existing code

Legacy code is also code which we are in the process of writing, but it has not been tested yet, so it is not ready for future changes. In my opinion, each of the above definitions describes the essence of the problem.

Legacy code

Legacy code: refactoring or rewriting?

When working with legacy code, we have a choice of approaches that either minimize such code or get rid of it completely. We can therefore apply solutions such as code refactoring, or completely rewrite it. Code refactoring relates to the optimization of its small fragments, without changing the basic functionality, while the latter approach requires rewriting the entire application code from scratch, taking current standards into account.

Read also: Microservices architecture

Software code refactoring – tools to combat technological debt

As I mentioned in the introduction, we now have a variety of tools to combat technological debt in PHP code, among which are:

  • PHP_CodeSniffer,
  • PHP CS Fixer,
  • PHP-Parser,
  • PHPStan,
  • Psalm,
  • Rector.

Which tools should we choose? It all depends on what the development team needs at a given moment and whether the tool meets our expectations. The knowledge that members of the development team have of a given tool will also be a decisive factor. One of the above tools undertakes a static analysis of the code, another modifies it in accordance with the current standards, while others make it possible to do both – and Rector is part of the latter group.

Rector – a legacy code buster?

Rector was founded in 2017 by Tomas Votruba, and is an open source CLI (Command Line Interface) program based on Symfony components. It is a tool that, apart from analyzing static code, can also change it. The basic applications of Rector are efficient and fast updating and refactoring of the code, as well as changing the application architecture.

BigCTA MarekCzachorowski

Elevate Your Application Development

Our tailored Application Development services meet your unique business needs. Consult with Marek Czachorowski, Head of Data and AI Solutions, for expert guidance.

Schedule a meeting

Refactoring

When it comes to updating and refactoring, the possibilities include:

  • migration from PHP 5.3 to PHP 8.1,
  • migration from Symfony 2.8 to Symfony 4.4,
  • removing so-called dead code, i.e. code that will never be used,
  • changing the names of classes, methods, and parameters.
Legacy code

Changing the code architecture

In terms of architecture changes, they can involve changing the facade in Laravel to DI or transferring the application from TYPO3 to Symfony. Of course, modern IDEs allow for code refactoring, but they can be slow and complicated to use. When using regular expressions to search for code snippets, they may not find all occurrences or, by contrast, search for too many. Programmers who copy and paste the code may also make some errors due to fatigue or distraction.

Why Rector and not IDE?

Rector won’t do anything the software developer doesn’t let it do! It is based on rules (pre-defined, individual “rules” that make a single change in the code each), grouped into sets of rules that make changes with similar characteristics.

Individual rules:

  • ArrayKeyFirstLastRector,
  • IsCountableRector,
  • JsonThrowOnErrorRector.

Sets of rules:

  • PSR4,
  • Php70,
  • Php71, TypeDeclaration,
  • DowngradePhp71.

At the time of writing, Rector made approximately 660 rules available, collected in over 48 sets.


nearshore 2021.08.17 cover

Microservices, Java, Python and MongoDB in a project for an e-commerce giant

Find out how Inetum's specialists supported the project. Read the client's story!

Rector – configuration

The principle of how Rector works is very simple – we start by installing the tool and configuring it. Rector first searches for all files indicated by the programmer; then, after analyzing each of them separately, it builds an AST (Abstract Syntax Tree) for them. It applies developer-defined rules in the configuration file to each such tree. Once the entire process is complete, the console provides a report on the changes made. It is worth mentioning that Rector is not only based on default rules – the tool also allows you to create your own, more specialized ones.

/** @var SplFileInfo[] $fileInfos */
foreach ($fileInfos as $fileInfo)  {
    // 1 file => nodes
    /** @var Parser $phpParser */
    $nodes = $phpParser->parse(file_get_contents($fileInfo->getRealPath()));
    // nodes => 1 node
    foreach ($nodes as $node) { // rather traverse all of them
        /** @var PhpRectorInterface[] $rectors */
        foreach ($rectors as $rector)  {
            foreach ($rector->getNodeTypes() as $nodeType)  {
                if (is_a($node, $nodeType, true))  {
                    $rector->refactor($node);
                }
            }
        }
    }
}
return static function (
    ContainerConfigurator $containerConfigurator
): void {
    // get parameters
    $parameters = $containerConfigurator->parameters();
    $parameters->set(Option::PATHS, [
        __DIR__ . '/src'
    ]);
    // Define what rule sets will be applied
    $containerConfigurator->import(SetList::CODE_QUALITY);
};
ChangeArrayPushToArrayAssignRector
class SomeClass
  {
      public function run()
      {
          $items = [];
-         array_push($items, $item);
+         $items[] = $item;
      }
  }
CombinedAssignRector
-$value = $value + 5;
+$value += 5;
DateTimeToDateTimeInterfaceRector
class SomeClass {
-    public function methodWithDateTime(\DateTime $dateTime)
+    /**
+     * @param \DateTime|\DateTimeImmutable $dateTime
+     */
+    public function methodWithDateTime(
         \DateTimeInterface $dateTime
     ){
         return true;
     }
}
SimplifyArraySearchRector
-array_search("searching", $array) !== false;
+in_array("searching", $array);

Summary

Working with legacy code cannot be avoided – sooner or later every developer will come across it in a project. It is good to know the possibilities of code refactoring offered by tools such as Rector. I hope that I have persuaded you to find out more.

Consult your project directly with a specialist

Book a meeting

PHP developer with over 12 years of experience. He’s passionate about programming, focused on continuous development and learning about new, better solutions and technologies. In his private life, he loves sports and takes a keen interest in nutrition.

Exclusive Content Awaits!

Dive deep into our special resources and insights. Subscribe to our newsletter now and stay ahead of the curve.

Information on the processing of personal data

Exclusive Content Awaits!

Dive deep into our special resources and insights. Subscribe to our newsletter now and stay ahead of the curve.

Information on the processing of personal data

Subscribe to our newsletter to unlock this file

Dive deep into our special resources and insights. Subscribe now and stay ahead of the curve – Exclusive Content Awaits

Information on the processing of personal data

Almost There!

We’ve sent a verification email to your address. Please click on the confirmation link inside to enjoy our latest updates.

If there is no message in your inbox within 5 minutes then also check your *spam* folder.

Already Part of the Crew!

Looks like you’re already subscribed to our newsletter. Stay tuned for the latest updates!

Oops, Something Went Wrong!

We encountered an unexpected error while processing your request. Please try again later or contact our support team for assistance.

    Get notified about new articles

    Be a part of something more than just newsletter

    I hereby agree that Inetum Polska Sp. z o.o. shall process my personal data (hereinafter ‘personal data’), such as: my full name, e-mail address, telephone number and Skype ID/name for commercial purposes.

    I hereby agree that Inetum Polska Sp. z o.o. shall process my personal data (hereinafter ‘personal data’), such as: my full name, e-mail address and telephone number for marketing purposes.

    Read more

    Just one click away!

    We've sent you an email containing a confirmation link. Please open your inbox and finalize your subscription there to receive your e-book copy.

    Note: If you don't see that email in your inbox shortly, check your spam folder.