Adding PHPStan to existing projects: Sell the dream, manage the expectations

June 23rd 2023

Do you want start using PHPStan on your projects, but are unsure if your team will be on board?

This article is inspired by @ediar's tweet: "Any advice to get my coworkers into static analysis? They think it requires too many type comments for just defensive programming, and is not worth it."

I thought I'd share my experience of introducing PHPStan to existing projects.

I've broken this series into 4 articles, they are the steps I'd recommend taking:

  1. Sell the dream but manage expectations (This article)
  2. Initial scan
  3. Soft launch
  4. Full launch

Aim of article

By the end of this article you should some ideas for talking to your team about adding PHPStan to your development process. There are some suggestions for dealing with people who might object to the idea.

Sell the dream but manage expectations

I find that when trying to introduce new tools or processes, the main difficulty is not the technology, it is the people. Some people don't like change. Others don't understand, or dispute the value of something new.

For those who need a bit of convincing, it is important that they understand the eventual benefits and for you to acknowledge there will be a few bumps along the way. No tool or process is a silver bullet. There will be pain points adding them into your workflow. However, the benefits should outweigh the pain.

Benefits of static analysis

When trying to persuade people to do something, in this case use PHPStan, it's always better if they come to the same point of view on their own. One way to do this is to reflect on current wins and problems of the existing development process.

It is worth asking questions that illustrate benefits of static analysis your team might already be experiencing (e.g. by using an IDE). You can then illustrate how PHPStan will amplify these benefits:

  • Does using an IDE speed up development? If so, how?
  • How does your IDE prevent you from introducing bugs?
  • How does your IDE help you to safely refactor?

It's also worth asking questions that might pull out problems that PHPStan can help solve.

  • What problems as a team have we been having recently?
  • What recent bugs have we had?
  • What difficulties refactoring have we had?
  • Does it feel too difficult to refactor safely?

To help you with framing how PHPStan can increase the benefits, or help solve problems, here are some of the benefits I found.

Finding bugs

The most apparent benefit is that PHPStan will find bugs before they make it to production. Using PHPStan for a few weeks is often enough to convince people. That's how I got hooked. PHPStan also changes how you code, IMO, for the better. You'll make fewer mistakes and your code is more robust.

Safer refactoring

After a few weeks of PHPStan use I realised that I got even greater value from it when I was refactoring code. If I made a change to a bit of code (e.g. method signature), PHPStan can show me all other places I need to update too. Sometimes a change will ripple through a codebase; I update a method signature, then I need to update all the callers, this in turn causes more changes. All of which PHPStan can me identify.

On code bases with high type coverage but with low or no test coverage, it is still possible to safely refactor code with PHPStan.

PHPStan still helps on projects with high test coverage. Often the issues found by PHPStan are easier to understand and fix, than interpreting the failed tests. I make PHPStan happy, before running tests.

Custom language features

PHPStan gives you generics out of the box. You can also use PHPStan extensions to give you features that other languages have. E.g. PHP Language extensions

Probably the biggest benefit of all is that you can write your own PHPStan custom rules to enforce your own project's conventions automatically. This is very powerful, especially for larger projects with many developers.

Challenges of introducing PHPStan

Adding PHPStan to your workflow is similar to adding a new member to your team. It is worth framing it as such, so that your colleagues understand that initially things will slow down a bit, but in the long run it will be worth it. In fact there are well established phases in team development: forming, storming, norming, performing.

In the depths of the storming phase, remember that this an essential part of the journey to a better development process. Appreciating of the end goal should help everyone through the difficult times.

There issues I've had adding PHPStan to a project include:

You must add type information to everything

To get the most accurate results out of PHPStan, all member data, method parameters and returns need type information. We'll see why the next article.

Type information can either be provided as a type declaration. E.g.

function getPersonByEmail(string $email): Person {
  // Implementation

Or by type hints (docblocks):

 * @param string $email
 * @return Person 
function getPersonByEmail(string $email): Person {
  // Implementation

Sometimes you might need both, e.g. when specifying the types in arrays:

/** @return array<int,Person> */
function getPeople(): array {
  // Implementation that returns an array:
  // The array keys are integers
  // The array values are of type Person.

As it happens I believe that adding type information improves readability of code.

If you're working with someone who is against type information then you can ask them for their views on clean code.

With luck, they'll say something along the lines of... "Clean code is very important. Code should be self documenting. It's intention should be clear. Etc, etc." In which case you can ask them, what is more self documenting and intention revealing than type information?

You don't need to fix all the issues or add type information before we can write new code?

Developers might worry that they need to fix existing code or add type information to everything before they can start writing new code.

Thanks to PHPStan's baseline feature, it is not necessary to fix all the issues before you can start writing new code. All new code will have to pass static analysis, but existing code can be fixed as and when it is touched.

You might have to change how you code

Some code can be problematic for static analysers to understand. You might get errors reported that are not actually errors, however in many cases the code can be refactored to keep that static analysis tool happy. Often the refactored code is easier for humans to understand too. We'll look at examples of this in later articles.

Let's get started...

Hopefully you're closer to getting people onboard with using PHPStan. What kind of conversations did you have? What were the objections? How did you overcome them? Let me know on Twitter or Mastodon.

The second part of this series will look at your type coverage to decide the best approach.