Drupal modern modules
It is the year 2020, with Drupal 9 recently released its time to establish a few points about what I consider good practices that replace old ways of writing code.
No more hooks
Writing hooks feels like crafting old procedural code. With Drupal 8 sailing away from the Drupal island and adopting other libraries and patterns we have now the event system from Symfony that can perfectly replace the hook system.
Many hooks can be replaced by events with the Hook Event Dispatcher module and if you find a hook that is not implemented is very easy to submit code needed by following the example of other hooks and proposed changes are usually accepted.
Subscribing to events allows for a nicer code structure with each of the listeners in its own class with a meaningful name, injection of services, subscription to an event multiple times and give priority to the event listeners so you control the order. One of the things I never liked of writing code in a file with the ".module" extension is that many tools like PHP Code Sniffer do not automatically understand that there is PHP code inside so the less code in the MYMODULE.module file, the better (ideally none).
Once the practice of writing services is more common and there is no more scattered helper functions (replaced by classes that group functionality) the task of configuring those services can be repetitive. Luckily Symfony has solution called autowiring that guesses the class that a service needs injected by reading the type hints.
I felt a bit of disappointment when I discovered that Drupal overrides some bits that come from Symfony and autowiring was not that easy implement. I rolled up my sleeves and released the Autoservices and autowiring module to add back some functionality so generally a MYMODULE.services.yml file is not needed. There is more information in the description of the module about how to bring that features into Drupal core.
Easy local environments and continuous integration
The people behind DrupalSpoons came up with a file structure and some configurations for composer that make spinning new development environments for each Drupal project effortless. A great example is the Devel module and the instructions to do local development, the Docker setup is recommended. That setup is also used for the continuous integration so anything that fails can be quickly checked locally with the same tools.
Separate user interface
This more a coding advise about the separation of the different functionalities of a Drupal module. When the parts of a module that face the user are not needed for the module to function on a production environment is better to split the user interface into a submodule so there more flexibility for the person building the site, less chances for unexpected changes on a production environment and an open door for different user interfaces to be implemented.
These are the four nice-to-have features that I advocate for modules to include and can shape the future of how modules are written. I'll probably compile more in the future but for the time being these are the ones that felt like a real improvement. An example for all of them can be found in the Libraries provider module that not only brings cool features but it is used as training grounds for introducing new concepts that other modules can rely on.