Interface suffix: take it or leave it?

In the recent RFC: New Validation Component topic emerged an argument that I think deserves one of its own.

The article points out good questions about the conventionts used today in PHP world, and I agree with most of them, somewhere fully, somewhere only in the idea of questioning habits.

However I fully disagree on the first point, and in a big project like ZF I think it deserves at least public discussion.

Talking about habits, we need to split the topic in two part:

  1. whether or not a convention is good
  2. impacts of a convention change

The idea

The misunderstanding and misusing of interfaces and implementations cited in Naming chapter are real, but they are only an evidence of the bad habits cited in the paragraphs that follow.

Of course having a TranslatorInterface and a Translator confuses people on what should be typehinted, but thatā€™s not an issue with naming, itā€™s an issue of a Default implementation and having no reason to create an interface.

zend-cache\Storage is a good example: there is no default cache storage, so there is no Storage class, but it makes sense to have an interface with the abstract concept of storage named StorageInterface

The article also say that typehinting against something with Interface suffix is superfluous:

The interface [ā€¦] is the essential concept, the thing that clients use. They donā€™t care whether [the typehint] is a concrete class or an interface, and they donā€™t care how itā€™s implemented. The client wants to be decoupled from all those details.

Well, I think that isnā€™t always true, sometimes there is a need for a strict coupling with a specific implementation.

When I read the Interface part on a typehint I think ā€œOk this object uses an external API, but it isnā€™t coupled to a specific implementation, I can understand this object aloneā€.
When I donā€™t see it I think ā€œIf I need to know what this object is doing, I have to read the dependency behaviour firstā€.

These thoughts have huge impacts on the easiness of comprehension of external libraries.

For example Doctrine (used to) use only EntityManager class typehints because complex database behaviours are coupled strictly coupled with results, and the implementation can be only one; for an advance usage of Doctrine, a developer must read some of its code.
In the other part different zend-cache\Storages can be switched without caring much the code because the expected behaviours are the same across storages.
And all this can be immediately known by just a single suffix.

If there would be no Interface suffix, I will have to open the typehint to know what to expect in term of coupling.

Regarding the suffix making interfaces first-class citizen, I disagree: classes donā€™t have Class suffix not because they are or arenā€™t special, but just to be less verbose.
I would find it right to use Class suffix, we donā€™t do it because implying it saves us a lot of words to write and read.


The impacts

Zend Framework Naming Conventions speed up a lot the comprehension of the library.

Consistency across the whole project is a mandatory requirement for a developer in order to trust the framework, otherwise the learning curve would be infinite.

If the maintainers or the community agree to change a convention, I expect it to be a breaking change, and so bumping a major version.

As said the suffix change was seen in the RFC: New Validation Component topic. The current zend-validator version is 2, and I suppose the RFC proposal is for v3.

There already are some components of Zend Framework bumped to v3. Even if now the components are splitted, If Iā€™m using only v3 components I would be very, very, very confused to see the Interface suffix somewhere, and not seeing it somewhere else.

If new conventions are going to be adopted, I would expect, or at least hope, to see them only in v4.


Comments to the original article worth the reading.

What are your thoughts?

2 Likes

I donā€™t follow your reasoning here; why does it makes sense that the abstract concept is named with the Interface suffix, exactly?

You go on to say:

Thatā€™s exactly the point Mathias is making: sometimes you will typehint against an abstraction, sometimes a concrete implementation. The question at hand is how should those be named?

Next, you say the following:

When it comes down to it, in both situations, you need to lookup the class or interface to determine what the public contract is. Knowing that youā€™re typehinting against an interface versus a class is no different; I need to look at the public signatures to see what I can or cannot do. When I look at a class, I might also need to look and see what functionality it inherits, but thatā€™s the only difference. Considering interfaces can inherit from other interfaces, this difference is mainly one of class ... extends ... implements ... vs interface ... extends ...; itā€™s simply one less level of indirection.

If youā€™re using an IDE, it will typically even give you tooltips to allow you to select these methods, making lookups unnecessary.

My point is: any coupling implied by a typehint relates to that typehint and what it extends from, regardless of whether itā€™s an interface or a class, and how you determine what can be done based on typehint does not differ based on that distinction.

I think the main argument you present that we should be looking at is consistency between components. That said, weā€™ve made different decisions between different components throughout the development cycle of Zend Framework all along. Some components create collection or aggregate types, some use arrays; some components use value objects, some use arrays; some use known design pattern names for naming, others use semantic naming; and so on. The question I have here is

Does naming interfaces with an Interface suffix provide enough benefit to consumers and/or maintainers to continue using that paradigm?

Iā€™m on the fence, and strongly leaning to no, but Iā€™m curious if others besides @Slamdunk has an opinion.

I came to PHP from Java world and Interface suffix was barely used there. I agree with the consistency argument, framework should stick to one naming convention across whole project.

But stillā€¦ there is no such a thing like StorageInterface - it should be just a Storage that have multiple implementations, RedisStorage, DummyStorage, PersistentStorage. Modern IDEā€™s mark interfaces, I see no point of doing that explicitly.

I would like to keep Interface suffix. I understand code faster when I read StorageInterface not Storage also in some cases when you see a name like MemoryStorage is it interface or implementation? Maybe itā€™s implementation of Storage interface or maybe is interface for RedisStorage and MemcachedStorage not all people good at making clear names but Interface suffix helps a lot and you donā€™t even have to think what it is.

also sometimes you have nested interfaces as an example would be:
Psr\Http\Message\ServerRequestInterface
Psr\Http\Message\RequestInterface

I understand that you should not care about what it is but well If I know that Request interface then I expect ServerRequest implementation. Oh but wait Zend\Diactoros\ServerRequest is an implementation how this would be different from Psr\Http\Message\ServerRequest.

So I vote to keep Interface suffix.

I think the interface suffix is just personal taste. Leaving it away is something you might get used to if you are open to it.

I havenā€™t read the article that was linked with the reasoning. I can do without the interface suffix:

  • For dependency injection and getting services from the container I donā€™t care if it has Interface behind a class name or not. Iā€™m injecting an object and my IDE knows what methods it has available with typehinting. It can be from typehinting against a class or interface.
  • If Iā€™m reading / editing a class you can easily tell if it extends an interface (implements vs extends).

If new conventions are going to be adopted, I would expect, or at least hope, to see them only in v4.

There is no Zend Framework v3 or v4 anymore. New possible conventions and other bc breaks will be introduced in new major versions. For new components it will be v1, and existing components it could be v2, v3 or even v4. It really depends on how fast the development is of the specific components.

There is a difference:

  1. Interface typehint ā†’ go reading Methods, DocBlocks
  2. Implementation typehing ā†’ go reading Methods, DocBlocks and Methods content / Code

In an ideal world where every library developer is perfect at naming things, abstracting ideas, segregating behaviours and minimizing complexity, maybe Iā€™ll start avoiding reading external code.
At the time of writing, my experience on working with hundreds dependencies tells me this is far from being real, and Zend Framework was and is no expection in my daily usage.

Seeing an Interface typehint makes me skipping opening the dependency; looking and the IDE suggests is enough.

Iā€™m ok with this, but I would consider compulsory a wiki/doc that superseeds GitHub - zendframework/zendframework: Official Zend Framework repository for ZF > v2.
Following dozens of libraries each with its particular standards is already tough enough.
A library that doesnā€™t even have and document them is a no go.

Ping @ocramius: you already wrote a reply to the original topic 4 years ago; I would really appreciate your recent point of view (not because you were more on my side, but because you are a good thinker and a ZF maintainer)

I find article too idealistic (and its not just Microsoft that puts ā€œIā€ in front of names). In code chunks dealing with difficult corner cases, his quote ā€œThe interface Translator is the essential concept, the thing that clients use. They donā€™t care whether Translator is a concrete class or an interfaceā€ does not always apply. It applies well to very removed from dirty details of business logic components, like Service Manager Factories which indeed do not care what implementation of ContainerInterface is, they just want to grab next dependency with $container->get(). Look around Zend\Db code generator and you will quickly want to know what is guideline vs what is a battle against engine differences.

There is a comment mentioning classes can potentially become interfaces in future. This is a warning sign about something many do not want to admit: we do often code with bias towards implementation. In his translator example, give most people Translator paramter, and they will treat it like something they own, preventing easy override in the future. Give them interface, and they will think multiple times against assuming whats inside.

To me, interface stronger suggests strategy pattern. When I see SomethingInterface, I know it can be substituted with my own version. Take SessionManager that takes in StorageInterface. Right there, based on patterns I have seen throughout frameworks, I know SessionManager is capable of working with multitudes of Storage options. It gives me option to use default one or I am welcome to make one myself by implementing the interface. If consumer of interfaces does not specify that it is comfortable with ANY implementation, not just SessionStorage so long as signatures aling, and I am not satisfied with defaults, I have little way to know whether manager was tightly coupled to implementation requiring some specific behaviour of default SessionStorage to function, whether implementation of signature is not enough alone. Those cases are not uncommon both in libraries and real world. In that case, to substitute with own implementation tend to override implementation class, and methods that want customized end up being copy pasted, because I have very little indication whether this substitution will be handled cleanly when I inject it to manager.

There is also browsing. I can quickly grasp my available options by looking in a directory for files named ā€œinterfaceā€. Gives me a way to determine what I am capable to override. I can use those to get inspiration for what I am capable of customizing, how can I take advantage of those customizations, or what am I stuck with as is.

That said, @xtreamwayz has a point that IDE will ideally take care of this. If I do ctrl+N and search for factory I get green icon. That is good enough. But I do not get that indicator in method signature.

I donā€™t understand your second point; why do you look at the method content, and not just the signature? The signature should be all youā€™re worried about as a consumer.

You are right: should. This is of course true for a good part of cases, but false for another good part. Developers that typehint against implementations use to couple their code not only to signatures, but also to the deep behaviour of the dependency. In the other part, developers typehinting against interfaces put efforts in abstracting what they need and their coupling.

Interface suffix suggests two extremely different efforts Iā€™m going to put in understanding the code, and naming strategies has exactly this role: make code understandable just by reading words before reading code. It is the same reason $array variable costs 1 minute to the brain, while $usersDbResultset costs 1 second.

1 Like

Very well put. Also do not forget that I write code to be consumed, not always being the consumer myself. When I override components using strategy patterns that are all over ZF, I become the one consumed. I need very clear indication where that is possible or not. Current convention of SomeComponentOptionInterface lets me know precisely what can be overridden, how can my custom code become consumed by the framework.

  1. Making style decisions because ā€œthe IDE tells us anywayā€ seems like a dangerous dependency and crutch. Not only are there many different IDEs, but I think code should communicate well on its own - on a sheet of paper even (gasp!).

  2. Decorating names will almost always convey more informationā€¦ the question really is, is it worth the clutter? I say yes:

    a) A single .php file can be one of several major ā€˜thingsā€™ (Class, Interface, Trait, ??), and since we donā€™t suffix with ā€œClassā€, I think itā€™s valuable and clarifying that we suffix the other ā€œthingsā€ to differentiate them.

    b) At a glance, I can see if something is depending on an interface or an implementation.

2 Likes

Good first point.
Second point is mostly good, except that this is what the maintainers are trying us NOT to do. The argument is that the fact you have to know what the ā€œthingā€ is, is in itself sign of bad design, that you should not care what type of file it is at all. Can you provide more weight on how realistic, whether it is too ideological or not from your experiences?

I thought that was similar to your point? If I can tell at a glance that something depends on an interface, that tells me immediately that I can inject my own implementation.

I do not think it addresses Matthewā€™s question ā€œwhyā€ in the first reply. We are telling him we want to see it, but we have not convinced him the ā€œwhyā€ we care about knowing if its tight implementation or not, and according to article if we have to care, its bad design. So personal experiences to support the claim would probably help more.

FWIW, Iā€™ve found myself on both sides of this argument.

This issue has been cause of a very long, and often duplicated, thread of discussion in the PHP-FIG mailing list, being the FIG a producer of contracts delivered as interfaces.

At that time, I advocated for keeping the Interface suffix primarily for consistency: since PSRs cannot be changed, Iā€™d rather have every standard ever produced follow the same convention, rather than having that convention change at some random point in the org history, opening the possibility of having to deal with both conventions in the same codebase (i.e. if a consumer used various PSRs for different purposes, some older, some newer).

Having said that, I think that the ZF community, as a framework/library producer, is in the more favourable position of being able to adequate its entire codebase to a different convention, and this would address the consistency issue: for example, at some point every zend-* package could be released under a 4.x version number (possibly even skipping some majors: yes, it can be done, it has been done) and it would be clearly stated that ā€œevery package starting from version the 4.x uses X coding style conventionā€. Iā€™m suggesting this because dealing with the change with different versions on a per-package basis would be frankly a bit of a nightmare.

Talking about the convention itself, I generally agree with Mathias Verraes, and in this instance Iā€™m actually very much in favour of dropping the Interface suffix. In fact Iā€™d drop any language related suffix (i.e. Trait too).

Lately, Iā€™ve been doing this in my new projects via heavy usage of the use statements: I religiously aliased every single import to get rid of any non-semantic name.

To anybody against this change, I suggest trying this and see.

Itā€™s initially a little boring to write, but IDEs help with that, and the resulting code is, in my opinion, much clearer, expressive and self documenting.
PHP is becoming increasingly heavy in its syntax, and striking the right balance between conciseness and verbosity is something we should all strive for.

For the record, some colleagues who initially were against, came around and admitted that the code reads more easily. If you followed a different convention for you whole career, it obviously takes some time to get accustomed to a new one.

Is it worth going through the hassle of a big rename effort throughout every zend-* package? Maybe, but I wouldnā€™t bet on it. If you have to go through a massive refactor anyway, though, then I think itā€™s definitely worth taking the chance to also update the naming convention.

But again, style is very subjective, and we all know the adagio that tells how naming things is one of the two hardest problems in computer programming. :wink:

Cheers.

Should there be a difference in mentality between writing domain code vs framework code? I can very well see the reason not to have UserInterface, CommentInterface followed by Advisor implements UserInterface, Client implements UserInterface. My opinions are directed strictly at library code, where there is no self-explanatory or widely known domain language.

@stefanotorresi the PHP FIG mailing list topic you are referring is https://groups.google.com/forum/#!searchin/php-fig/interface$20suffix|sort:relevance/php-fig/Potawlu2CrQ/DLdnd_MJCQAJ isnā€™t it?

Arguments and voters seem to be the same and alike ditributed.

I donā€™t think we can come to an agreement, so the only point I would like to underline again is my hope that, after a decision is chosen, a simple and clear wiki will be redacted about new conventions, and if these are going to be different from v2 ones, a new major version will be bumped.

The last time I checked, natural numbers were infinite; mixing different styles and conventions behind the same major version is insane.

In my view, having a type in an identifier (like variable names, class names, interfaces et cetera) is old-school PHP3 where you have variable names like $foo_string or $bar_int. With PSR-3, this old [and entirely out-dated] style is being brought back to live.

There is absolutely no need for a suffix Interface in an interface (and surely no where else) as an interface is indeed an interface. Better naming is like Converter, Validator, Logger, Throwable (very nice, you have it) but never FooableInterface or SomeBarInterface. That is plain double-redundant.

So my vote is leave it out.

Thereā€™s a lot thatā€™s been said on this so Iā€™ll keep mine short: Keep the Interface suffix. Applications are built around Interfaces and giving it this title is paramount to calling It King. Dropping the suffix does not promote its rank but rather demotes it to as common as a class. Interface is King.

2 Likes