4

It is about More Than Just Code

Wouldn’t describing PHP: Hypertext Preprocessor (PHP) as a programming language be a bit reductive when you think about it? We must face the facts: PHP is not a simple programming language. It’s a complete ecosystem, with a gigantic community, thousands of contributors, and new features being proposed and released regularly. But not only that: millions of libraries and application programming interfaces (API) are written and launched thanks to PHP. Even many command-line tools are entirely developed thanks to the PHP language. PHP is a whole world on its own. Let’s start by looking at the reasons why PHP is not just a language for writing a website.

These are the topics we will cover in this chapter:

  • PHP as an ecosystem
  • Choosing the right libraries
  • A word about semantic versioning
  • Stability versus trends

PHP as an ecosystem

This can be seen in several things that we can list together, as follows:

  • PHP is, still in the early 2020s, the most used server-side language for web application development. When you know the predominant (not to say overwhelming) place of web applications in our everyday use, this is a genuinely nice award!
  • The language continues to evolve very strongly, especially in recent years. It went through a slump during the development of PHP 6 (which was never released) before experiencing a real explosion of its popularity starting with version 7. Version 7 defined the foundation of the future of PHP with highly demanded features such as strong typing, as well as incredible performance and speed improvement. Benchmarks comparing PHP 5 and 7 were just crazy when they first came out. Developments continue strongly, with new features being proposed very regularly.
  • PHP has an exceptional dependency manager named Composer. Simple, open source, and devilishly efficient, it is often recognized by its users as the best dependency manager on the market, all programming languages included. Although this may be a subjective opinion, we can’t take away its reliability.
  • Speaking of dependencies, you only have to visit the Packagist site (the repository where Composer takes dependencies) to realize the exceptional community that PHP has at its disposal to make available so many libraries, each one more incredible than the other, with the vast majority being free of charge and with no usage restrictions. If you have a need, there is an external library available that will certainly solve your problem.
  • PHP extensions are a real goldmine for extending the language. The extensions, unlike the libraries that you install with Composer, are written in C and plug directly into the source code of the PHP interpreter. This gives us the possibility to extend the language with impressive performance. This also means that the default installation of PHP can be extremely minimal and needs almost nothing to work. We can then install extensions unitarily according to our needs. This is especially useful if our application must run on a server with limited resources.
  • Multiple conferences around the world show a strong commitment to PHP. Equally incredible and renowned tools such as the Symfony, Drupal, and Laravel frameworks show a real desire to push the language as far as it can be taken. These frameworks themselves organize international conferences and are used by multinational companies (Airbnb, Spotify, TheFork, and so on). For the record, Symfony is still in 2022 one of the open source projects with the largest number of contributors to the framework and documentation, among all existing open source projects.
  • The development of the PHP core is still in full swing today, and more than ever. Proposals for new features and requests for comments (RFCs) (the first step in proposing a change to the language) are emerging at a rapid pace and are implemented just as fast. Many contributors are involved, and a renewal of the main contributors is also observed. Older and more important contributors, such as the well-known Nikita Popov, are leaving the ship while new contributors are coming to the project. The community is in perpetual effervescence.

PHP is a language that has a proven reputation. Its robustness and efficiency have made it the language of choice for some of the world’s largest sites. Where alternatives have been implemented in the past or currently, such as Python (which is used by around 1.2% of all websites at the time of writing) for some Google sites, PHP is in the majority. Obviously, many attractive technologies are emerging and taking market share from PHP, such as Node.js or C# and the .NET Framework. PHP still has a good future ahead of it. Knowing how to write a website in PHP ensures that you’ll know how to read the source code of the overwhelming majority of existing sites in the world.

For all these reasons, PHP is an ecosystem. Pushing the reflection a little further... if PHP is not just a programming language and if PHP is not just code, why should we limit clean code to code?

The clean code could also contain, by extension, the right choice of external dependencies and libraries to install on your project. Let’s see why you should choose your dependencies wisely and how to choose them well to limit the risks.

Choosing the right libraries

Choosing the right external library to install can be a real challenge. It’s a challenge we’ve all faced or will all face one day. The reason is simple: there is no point in reinventing the wheel. The reason we want to install an external library is usually the same. We have a specific problem that we want to solve as cleanly as possible. Here, two situations arise:

  • We know how to solve the problem, but we don’t want to have to rewrite everything when tools already exist to solve our problem simply
  • We have no idea how to solve the problem because we lack theoretical or practical knowledge

It is then interesting to call upon an external library whose role is to bring us a very specific solution to our case. The advantages are multiple, as outlined here:

  • The person(s) who develop(s) the external library may have thought for several days or weeks about the best way to provide a solution. It may even be their day job. Whatever time they have spent on it, it is often more time than we will allow to think calmly and cleanly about the solution.
  • The maintenance of the dependency, if it is still actively in development, is managed by someone else than you. This means that you will regularly receive bug fixes and new features thanks to these volunteers who offer you their most precious asset: their time.
  • If the external library you are using is open source, then you are exposed to additional benefits, as follows:
    • The source code is visible to everyone. This means that anyone, such as other developers or even security researchers, can analyze the source code in order to strengthen it and fix security flaws (or at least notify the author). Don’t get me wrong: open source is not bad for security. In fact, it is quite the opposite. Security by obfuscation (understand this as hiding things such as source code to ensure “security”) is the worst thing that can happen. Security must be achieved by other means. There is no lack of evidence: the most used encryption and ciphering algorithms in the world are known, and their functioning is perfectly explained in 1,001 places on the internet. This does not compromise their security.
    • If the open source project is abandoned, then initiatives (called “forks”) can follow. Forks are, to put it simply, people who have copied the source code of a project and developed it on their own, independently of the developments of the original project. This can ensure, in theory, infinite longevity of a project.
    • If the main maintainer of the project no longer has time to take care of the project but developers wish to do so, the source code being open to all, they can do so.
  • If you are curious, you can dig into the source code and understand how the problem was solved by the library!

We can clearly see that the choice of open source dependencies is quite inevitable. If you want the insurance to not end up with an unusable tool unavailable overnight, open source is made for you because you can store a copy of the source code as long as you want without fear. This is the first excellent way to choose an external library.

A second factor to consider is the frequency of updates to the project. Obviously, if a project is open source but has not been updated for several months or even several years, beware: it may be an abandonment. In this case, it means that the project may not support the next versions of PHP, for example, or that the bugs and security flaws will not be fixed anymore. There are two effortless ways to know if a project is still maintained or not, as set out here:

  • First, you can check the date of the last version of the library. Be careful again, as some projects have (very) slow-release processes, and it is advisable to combine this technique with the second one.
  • Here’s the second technique. Look at when the last modifications of the source code were made. This can be done very easily, especially if the source code is hosted on a site such as GitHub. By browsing through the files, you can see when the last modifications of a folder or a file were made. This can be an excellent indication of the development dynamics of the project.

A third factor to consider is the documentation of the library. You’ll probably want to make sure that the project has minimal and sufficient documentation to set up the basics. If no documentation is provided, you can be sure that using the external library will be a systematic pain. Indeed, all code maintenance will become a battle to remember how the project works, without documentation to help you or to share knowledge. Moreover, this can also be very much related to the community around the technology you want to use. If very few people use the project you want to integrate into yours and the community is quite inactive, or even non-existent, nobody will be able to help you in an optimal way. This can be an effective way to decide whether to use this or that dependency in your code.

A fourth factor is the number of dependencies that the library itself depends on. Generally speaking, we prefer a library that has very few dependencies. Fewer dependencies mean fewer packages to update and fewer third parties, so there is less chance of problems in one of those parties.

Finally, many projects have continuous integration (CI) badges on their main page. These badges allow you to know at a glance the test coverage (as a reminder: the proportion of code covered by tests), the number of tests, the latest version, and so on. Obviously, it is better to choose a project with as many tests as possible and with a high test coverage to limit problems during updates.

A word about semantic versioning

Speaking of updates, let’s talk about versioning and—especially—semantic versioning. If the external library you want to use follows the rules of semantic versioning, this could have an incredibly positive and reassuring impact on your developments and updates. Let’s take a look at what this means exactly.

What is semantic versioning?

Versioning is simply putting a number on a version of the source code. We are all familiar with versions such as 1.0, 1.5.0, 2.0.0, and so on. The semantic versioning adds a semantic—that is to say, precise meaning to each of these numbers. Let’s take version 2.3.15 as an example. Here is how semantic versioning breaks down this version number:

  • The “2” indicates a major version. A major version can introduce new features, bug fixes, and—most importantly—changes that break backward compatibility. This last point is the most important. Indeed, from one major version to another, method signatures or even complete class names can change, and some may also disappear. So, you have to be extremely careful when you move to a major version higher than the current one, and you have to test that everything still works. Often, the release changelogs provide the changes you need to make to be compliant with the new major release.
  • The “3” indicates a minor version. As with major releases, minor releases can bring new features as well as bug fixes. The main difference is that minor releases cannot make changes that break backward compatibility. This means that you can upgrade a dependency to the next minor version to take advantage of all the new features and bug fixes without worrying that your code will break when you upgrade. However, it will never be superfluous to run all your tests afterward at the time of the minor update. You never know. Often, minor releases trigger code deprecation messages. These messages tell you which methods you should not use anymore because they will certainly be removed in the next major release. By taking into account the deprecation messages as you develop, you save yourself a lot of work when it comes to updating the dependency to the next major release.
  • The “15” indicates the patch number. A patch contains only bug fixes and security fixes. It does not contain new features. You should consider always installing the new patches of your dependencies in your project.

We can see the advantages of semantic versioning: serenity, logic, and consistency. There are obviously other variations such as Alpha, Beta, Release Candidate, and Golden Master. But these are rarer.

How to deal with semantic versioning

Semantic versioning also includes a particular notation that allows your dependency manager to know how to install new versions and when to update your dependencies. Let’s take as an example this extract of the file that Composer uses to install dependencies (and this is the same principle for many dependency managers out there):

{

    "require": {

        "php": ">=7.3",

        "symfony/dotenv": "3.4.*",

        "symfony/event-dispatcher-contracts": "~1.1",

        "symfony/http-client": "^4.2.2"

    }

}

This snippet describes four dependencies: a minimal version for PHP, as well as three external libraries. It doesn’t really matter what these libraries are. We can note here four separate ways to define the versions we want to accept in our dependencies. Let’s see what they are.

The first way to write the version we observe is by using the >= operator. This one is one of the easiest to understand: we want to accept all versions greater than or equal to the one specified. Here, our application accepts all versions of PHP higher than version 7.3, as well as version 7.3 itself. Of course, dependency managers accept other such operators: =, <, >, and <=. You can also combine these operators to get very precise version constraints—for example, by writing “>=1.2.0 <2.0.0”.

The second operator is quite well known because it is used in many other contexts. It is the wildcard, denoted *. This symbol simply represents the fact that you can replace it with whatever you want. In the preceding example, we accept all the patch versions of the 3.4 version of the dependency. This allows it to benefit only from bug fixes, without updating the minor version. This wildcard can be placed anywhere in the version number. For example, the notation 3.* will benefit from all minor versions of the major version 3.

The following notation is the use of the tilde operator, ~. This operator means that you will only benefit from the patches of the given version. In the example, we will then benefit from all the patch versions of version 1.1 of the dependency (that is, 1.1.0, 1.1.1, 1.1.2, and so on). This is remarkably similar to the wildcard operator, except that the wildcard operator cannot be placed anywhere in the version number and only concerns patches. Also, it is worth noting that Composer interprets the tilde a little differently: it also allows minor versions, not just patches. If you are using Composer and you want to benefit only from the patch versions without the minor versions, you will have to use the wildcard operator.

Finally, the last operator we will see is the caret operator, denoted ^. In the preceding example, the caret operator allows all patch versions as well as minor versions of major version 4 (that is, 4.2.2, 4.2.3, 4.4.0, and so on). If you want to define a minimum version of a dependency while accepting new patches and minor versions but refusing major versions (which may bring breaking changes) automatically during the update of external libraries, this is a particularly good choice. That’s why it’s one of the most popular operators.

The possibilities are endless, and once you have mastered this notation, you can be confident about updating the dependencies of your project. As far as good practices are concerned, it is always a clever idea to accept all new patches and minor versions of a dependency. You should never lock a dependency to an extremely specific version without any conditions or possibility to update. Indeed, if an external library scrupulously respects semantic versioning, you will have no conflict with your existing code. Breaking changes are reserved for major versions. Therefore, you should not automatically accept major versions when updating your dependencies: chances are that you will have to adapt your code to make it work properly.

Stability versus trends

Let’s finish this chapter with a few words about the most recent versions, but also about trendy external technologies and libraries.

First, let’s talk about the latest versions of external libraries. Of course, we might be tempted to use the latest ones, the ones that were just released a few hours ago. It is worth remembering that bugs may appear, and a new patch version may be released in the near future if this is the case. Or not. And in this case, the bug could persist for a while. So, it’s particularly important to write tests. Imagine the comfort: you update all your dependencies, you run your test suite, and if all the lights are green (and your application is properly tested), you can be fairly sure that everything is fine.

That said, if any tests turn red because you’ve updated an external library, you’ll have to investigate to find out where this is coming from. In any case, you shouldn’t think that you are safe from any problem if your dependencies are well fixed and constrained or you only accept patches and/or minor versions. Patches could also bring bugs—you never know.

As far as Alpha versions are concerned, let’s be clear: these versions are not made for production applications. The different libraries are clear on this point: the code can change from one day to the next, bringing breaking changes without warning. In short, you must be incredibly careful. That said, if you want to evaluate these versions to see for yourself, the developers of the libraries will be delighted to receive your feedback. The Beta versions are supposed to be more stable and not bring any more breaking changes. You should still be incredibly careful when using them.

As a general rule, only use the final, stable versions in production. Reserve the Alpha and Beta versions for development and test environments if you want to be ready on the day of the stable release for production deployment. New features are always exciting things, but they are never worth sacrificing the stability of your application. Your users don’t care about the new features of the external libraries you use: only stability matters—the fact that it just works.

Now, let’s talk about trendy technologies (an external PHP library, a new tool, or even a new programming language). You hear everyone around you talking about a particular technology. This technology is spreading like wildfire, you hear about it everywhere on the internet, huge companies are getting into it, and tech conferences are all about it. You must be wary of this kind of thing. Even if the promises of these technologies can be exciting and revolutionary, think first about what is important: your users.

Will this technology make a real difference to your end users? Is it really worth training on it and taking weeks or even months to figure out how it works? You need to be sure that it will have a real positive impact on your project. You also must keep in mind that innovative technology will have a small community. The impacts are immediate, as outlined here:

  • You will have to train all the people who arrive on your project
  • The documentation may not be complete, which may make it difficult to understand
  • You may find yourself alone in front of your screen without finding a solution to your problem: you are one of the first to use this technology, and therefore one of the first to face the obstacles encountered with it

Finally, you must make sure that the project is robust so that you don’t end up with a recent technology abandoned without warning. This happens more often than you think, and much (if not all) of your work will have been for naught. So, beware of the latest unproven technologies, and be sure of the robustness and seriousness of the project. Wait until you’ve had some time to think about it. Again, your users will surely be able to do without this technology (which they will not be aware of) until it is mature.

Summary

Limiting PHP to the programming language is reductive. We have just seen it—it is a real ecosystem with a rich and active community, and extremely far from burying its favorite language. The developments around PHP are countless, and the language itself has evolved in the most beautiful way in recent years. The contributions of functionalities gave a real second wind to this one, allowing it to claim—still today—first place among the most used programming languages on the server side for a web application.

All this would be nothing without the explosion in the number of external libraries available for the language. You have a problem; there is a solution. We are fortunate that most external libraries are open source. Thousands of developers make available, voluntarily and free of charge, the fruit of hours, weeks, or years of work.

Making a choice from among these libraries can be difficult and challenging. It is important, even mandatory, to do real research work beforehand to be sure to make the right choice. We are not immune to obstacles and incidents, but this chapter has provided you with tools and ready-to-use solutions to limit the risks. Above all, don’t rush into the most fashionable technologies. If you want to attract users and have them continue to use your application more than another, the key words are “robustness” and “stability”!

We have talked a lot about other people’s work, but we should not forget our own achievements. How can you manage to develop good habits to find your way in your code as you manage to find your way effortlessly in the source code of your favorite external libraries when you need to understand its internal workings? We come back to what we said in the first chapters: by having the same habits, we understand each other more easily. This obviously applies to the organization of a project, in the naming of files, the structure of folders, and so on. And this is exactly what we will see in practice in the next chapter.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset