Discuss/clarify the use of @throws tag in interfaces, and contract enforcement

Created on 25 February 2016, about 9 years ago
Updated 6 February 2025, 2 months ago

Currently in Drupal 8, we do have @throws annotations on interfaces, which look quite reasonable so far.
E.g. try a grep -R throws . | grep Interface, which shows some existing @throws blocks.

However, the documentation pages are not very detailed about the need of implementations to comply with this interface contract.
https://www.drupal.org/node/608166
https://www.drupal.org/coding-standards/docs#throws

And:
- There are cases where we call interface methods and neither catch nor document the exception. Just look for code that calls methods which throw "PluginException".
- The documentation does not tell if this is required.

We should agree on something, and document it.

And btw, maybe the agreement will be that being 100% consistent by requiring try/catch/wrap at package boundary is too much effort, and we accept to be inconsistent. Or that this is the goal, but we will only slowly get there.

Background

The @throws tag can have three purposes:
1. Inform about possible exceptions thrown directly by the same function/method.
2. Inform about possible exceptions thrown indirectly by methods called down the line.
3. Inform about possible exceptions thrown by interface implementations or subclasses.

The second is only possible, if we actually know about the exceptions thrown by functions/methods we call.
If we purely depend on abstractions (interfaces), not implementations, the only way to know is if the interface itself has a @throws tag. Which in PHP is usually not reliable.
And if we rely on hooks and callbacks, we are completely lost.

In Java, only "checked" exceptions have to be declared with a "throws" statement.
I think some people want PHP to behave in an equivalent way. "RuntimeException" and "LogicException" (and descendants) would be considered "unchecked", whereas custom exceptions that directly derive from "Exception" would be considered as "checked". E.g. in PhpStorm there is an option to disable the inspection for "missing throws statement" for runtime and logic exceptions.

The concept of checked exceptions in Java is controversial.

The idea in Java is that interfaces declare specific types of checked exceptions, that implementations are allowed to throw.
To comply with this requirement, implementations need to catch and wrap ("re-brand") exceptions of called functions/methods, if they have the wrong exception type. This introduces the need for a lot of try / catch logic, which some consider as meaningless/noisy/redundant.

Some suggest to solve this by using a smaller set of reusable exception types (per package, or globally) for @throws statements. But this still leaves a lot of need for try / catch / wrap, if we are serious about contract enforcement.

Another approach is to have only one exception type (per package, or globally).
I think Drupal is following a similar direction (per "package" or "subsystem").

And some may argue that even the per-package or per-subsystem distinction is too much, because it still requires try/catch/wrap on package boundary.

Please note that this is all about the @throws statement in interfaces / contracts. Implementations may still throw dedicated exception classes, that inherit from the more generic exception type.

📌 Task
Status

Postponed: needs info

Component

Coding Standards

Created by

🇩🇪Germany donquixote

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024