I-prefixes disappear from interface names
In Nette, interfaces were named with the letter I
at the
beginning (e.g. IRequest
). A couple of years ago, an extremely
slow and long term process began, which quietly while maintaining backwards
compatibility is getting rid of these prefixes. How exactly is this happening
and why?

The Conventions Around Us
Nette has used the convention of prefixing interfaces with the letter
I
since its inception. It has never made any distinction in
abstract class names. In other frameworks (e.g. Symfony, CakePHP, Zend or PSR)
you may see a different convention, using the Interface
suffix
(e.g. Psr\Cache\CacheItemInterface
) together with the
Abstract
prefix for abstract classes (e.g.
Psr\Log\AbstractLogger
). Finally, there are libraries (e.g. Laravel
or the PHP system library) that do not distinguish interfaces or abstract
classes in any way (e.g. the Throwable
or Iterator
interfaces, or abstract class FilterIterator
).
If we were to look outside the PHP world, the I
prefix is used
for example by C#, whereas in Java or TypeScript the names are not
distinguished.
About a decade ago, when the Nette DI, the heart of all modern and cleanly designed applications was created, I fully realized that distinguishing interfaces and abstract classes, whether by prefix or suffix, was a huge mistake. But at that time, the framework was already celebrating 5 years of existence and it was impossible to change the interface names without causing a colossal BC break. To maintain consistency, I continued to use prefixes for Nette, but abandoned them for all other projects. (Nette was still a monolith at that time, but e.g. Nette Tester was a separate project and you won't find the prefix for interfaces there).
However, I was still looking for a way to painlessly drop the I
prefix. I see the differentiation of interface names as such a significant
mistake that it was worth putting a lot of effort into correcting it. Especially
since the framework is taken by programmers as a example of clean design.
The reasons are the subject of a separate article Prefixes and Suffixes Do Not Belong in Interface Names.
How to Say Goodbye to the I-names?
After a few years I found a way to give I
away. Quietly and
with full compatibility. It was a process planned many years in advance, which
started with the release of Nette 3.1.
Usually, it was enough to simply rename the original interface (e.g.
Nette\Mail\IMailer
to Mailer
) while creating an alias
(IMailer
) to make both versions work. Along with this, I added
“hidden” code to the source file that only the IDE and Composer can see. It
makes autoloading work for the alias as well, and forces the editor to strike it
as deprecated in the code with a note that the non-prefixed version
should be used. So all existing code works unchanged, while the programmer is
led to prefer the new version.
In some cases, I did not rename the interface because the plan was to change
it (e.g. the new Nette\Security\UserStorage
is different from the
old Nette\Security\IUserStorage
and both can be used at the same
time as part of the transition), or because I am planning a different solution
(e.g. Tracy\IBarPanel
).
In some cases, removing the prefix was not possible because the name was
already taken. This is for example the case of
Nette\Security\IIdentity
and Identity
. Here,
SimpleIdentity
needs to be taken first as a successor to
Identity
and the name will be freed. Such a thing has to be spread
over several major versions and thus many years to be truly painless. But there
is no hurry.
So in Nette 4 only Nette\Http\IRequest
and
IResponse
will remain prefixed, as a reminder of a former time. And
also Nette\ComponentModel\IComponent
and IContainer
,
but I'm not sure if their existence is useful at all. Aliases will continue to
work, of course.
Sign in to submit a comment