View Source

<p>This is not a hard and fast rule, but more of a guide to naming such that we can build more consistent API's in the various components in Zend Framework. By now, we've had a significant amount of time to work with namespaced and PHP 5.3 code, I think it's time to talk about some of our previous decisions to ensure they were indeed the right ones.</p>

<h3>Previous arguments</h3>

<p>Previous arguments that have been put forth have drawn inspiration far and wide from various programming language communities and various programming language code bases. Ultimately, I think this is a bad idea. When it comes to THIS decision, we should look directly at the communities and languages that are most like our own. Our own is object-oriented with an implementation that is single inheritance / multiple interfaces. What that means is our direct inspiration should be language communities like this, which is primarily C# and Java, but maybe Pascal and a few others.</p>

<p>On of the larger previous arguments has been that by adding &quot;abstract&quot; and &quot;interface&quot; to a class name is another form of Hungarian Notation. In all my research, I've seen very few texts say that apply the term Hungarian Notation to the naming of &quot;types&quot;; I've only seen this terminology applied to variables. Saying it's a form of Hungarian Notation seems incorrect to me, and thus should not be used as an argument.</p>

<p>Another argument is that with IDE's, the behavior of a type is known since the IDE will know if a name is a concrete class, abstract class or interface name. While I, being an IDE user, can understand this argument; it is both that the greater PHP community might not be a user of an IDE but also that type support and hinting in major IDEs is still not 100%. Thus, in my mind, this argument can be dismissed too.</p>

<p>Yet another argument is that the PEAR standards for 2.0 have been set and that we should follow these recommendations. While we've traditionally seen PEAR as the standards group (some say &quot;gold standard&quot;), it is clear they are embarking into PHP 5.3 at the same time as us and are identifying the same problems as us. At this point, their research is as old as ours and it would be an injustice to our group to simply default to the PEAR group for direction here. So again, in my mind, this argument too is not solid.</p>

<p>Finally, we have to admit that the SPL is not perfect and over time has been produced by many developers that have varying and differing opinions on what names should be used. The PHP Group does not go into the same depth as we should when it comes to namings (they have an altogether different set of goals and perspectives that rank naming and refactorings lower). One of the major reasons for a PHP frameworks existence is that frameworks are built by a smaller group of developers that share a common set of goals, perspectives and coding standards. For us and our success; consistency, cohesiveness and clarity of our API are what make ZF a more successful project moving forward.</p>

<h3>What are the Problems At Hand?</h3>

<ul>
<li>Name collisions</li>
<li>Too much creativity required on behalf of a developer (this is a bad thing)</li>
<li>Unclear API, hard to distinguish consumption vs. extension API (this is important!)</li>
<li>Lack of purpose and intent in type names</li>
</ul>


<p>First, we are seeing more <strong>name collisions</strong>, that is, places where we actually want to create a class now has an interface in it's place. Since we've banned the usage of the suffix &quot;Interface&quot;, we've had to find new names for things that are interfaces (which, in ZF2 we will have more of since we've rightfully adopted the <a href="http://en.wikipedia.org/wiki/Solid_(object-oriented_design)">SOLID</a> &amp; <a href="http://en.wikipedia.org/wiki/Design_by_contract">Design-by-contract</a> approaches.) Without the suffix of &quot;interface&quot;, we now have to become <strong>more creative</strong> in naming when it comes to finding a home (in both name and filesystem location) for our interfaces. This is a bad thing. Too much creativity from too many people will create too many variances in the ZF2 API. As a consequence,&nbsp;we will diverge from consistency in the naming of classes - a bad thing. Instead of ZF2 becoming more a more cohesive API to interact with, it will remain the same or worse than ZF1 in the fact that it is ultimately looks and feels like code written build by lots of developers each with their own programming nuances.</p>

<p>Ultimately, we need our class names to immediately identify their <strong>purpose and intent through their name</strong>. What this will allow is for both new developers and seasoned ZF2 developers the ability to glance over a components classes and be able to distinguish between what is part of the <a href="http://ralphschindler.com/2011/01/18/php-component-and-library-api-design-overview"><strong>consumption API</strong> and what is part of the <strong>extension API</strong></a>.</p>

<h3>How Have Others Like Us Solved This Problem</h3>

<ul>
<li>.NET (C#) &amp; Pascal community has traditionally (dominantly) prefixed classes with &quot;I&quot; for interface</li>
<li>The Java Community has traditionally (dominantly) suffixed classes with &quot;Interface&quot;</li>
</ul>


<p>The PHP OO type system is not really so different from .NET/C# and Java. That said, perhaps we should have a hard look at these communities. After all, these happen to be two of the <a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html">most popular programming languages on earth</a>. Their audience tends to be more enterprise centric, but is that one of our core audiences too?</p>

<h3>Visual Demonstrations</h3>

<p>The following imagery will help to explain my position as it relates to the API, its clarity &amp; cohesiveness, and ultimately, the first impressions it gives off.</p>

<p>This is an example of an early, but mostly complete Zend Framework 2.0 component. It currently follows the existing naming conventions we've setup over the past year.<br />
<ac:image ac:border="true"><ri:attachment ri:filename="naming1.jpg" /></ac:image></p>
<hr />
<p>One of the first questions a new developer (to this component) might ask is &quot;How do I use this component, where do I start&quot;. This component answers this question very well...<br />
<ac:image ac:border="true"><ri:attachment ri:filename="naming1-entrypoint.jpg" /></ac:image></p>
<hr />
<p>Beyond identifying the initial use case or &quot;entry point&quot; for this new API, a question might be either of the following: &quot;What other classes can I interact with immediately&quot;, &quot;How do I extend this code base for my use case&quot;...<br />
<ac:image ac:border="true"><ri:attachment ri:filename="naming1-where-extension-points.jpg" /></ac:image></p>
<hr />
<p>Without examining all the files, what might we assume about the intent and purpose of each class..<br />
(blue is correct assumptions, red is incorrect assumptions),<br />
<ac:image ac:border="true"><ri:attachment ri:filename="naming1-assumptions-of-purpose.jpg" /></ac:image><br />
(Yes, these are my assumptions, perhaps yours would be closers to the purpose/intent of the class. But, my point ultimately is that there is less a chance that two developers can make the same assumption about the same classes purpose/intent)</p>
<hr />
<p>In this screenshot, in order to identify all the interfaces, we've had to explore each file. This screenshot is in an IDE, but without an IDE, the process is still the same. The developer will have to explore each and every class to get the &quot;full picture&quot;...<br />
<ac:image ac:border="true"><ri:attachment ri:filename="naming2.jpg" /></ac:image></p>
<hr />
<p>Now that we've opened or examined all the files, we can identify what's what:<br />
<ac:image ac:border="true"><ri:attachment ri:filename="naming2-identify-by-expansion.jpg" /></ac:image></p>
<hr />
<p>Here is an alternative naming scheme. Yes, the namings of interfaces are far less creative than previously, and yes, they add a little bit of length (Interface vs. Manager - 2 characters), but the length problem has already been solved with the PHP namespace implementation. More importantly though this boring conventions does reduce the need for creative names. And that is ultimately a good thing because creative leads to divergence and variance whereas convention leads to consistency and cohesiveness...<br />
<ac:image ac:border="true"><ri:attachment ri:filename="naming-alt-highlight-types.jpg" /></ac:image></p>


<h3>Code Review Consideration</h3>

<p>When looking at code others have produced, having an 'Interface' suffix allows the reviewer to be able to distinguish if the code under review is coupling classed based on a particular contract (interface) or a specific implementation (concrete implementation / abstract implementation).</p>

<p>For example:</p>

<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
public function someMethod(Bar $bar) { // is Bar a class, abstract or interface?
// ...

if ($baz instanceof Baz) {} // is Baz a class, abstract or interface?

// ...
}
]]></ac:plain-text-body></ac:macro>

<p>as oppose to:</p>

<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
public function someMethod(BarInterface $bar) { // this class just wants an object that satisfies a particular interface
// ...
if ($boo instanceof BooInterface) {} // definitely an interface
if ($bam instanceof AbstractBam) {} // definiately expecting something that has a based abstract impl. of AbstractBam
if ($bax instanceof Bax) {} // definitely a concrete implementation
}

]]></ac:plain-text-body></ac:macro>

<p>The latter code (above) makes it easy for anyone consuming the above code to see what kind of type expectations there are without having to have full knowledge of all the types in a particular namespace. This gives a consumer a better understanding of where possible extension points more immediately than having to fully understand all the code in the codebase.</p>

<h3>Conclusion &amp; Proposal</h3>

<p>Just as the prefix &quot;Abstract&quot; helps us identify incomplete implementations, &quot;Interface&quot; helps us distinguish useable classes from contracts (ie: interfaces). This proposal is not to change anything as it releates to the prefix &quot;Abstract&quot;, which has been accepted and is in use. This proposal suggests two things only:</p>

<ul>
<li>Suffix contracts with &quot;Interface&quot;. Contracts will <em>generally</em> consist of more than a single method, but not always.</li>
<li>Suffix object capabilities with 'able' or some other kind of representation of capability. While it's not a hard and fast rule, capability interfaces should generally be single method interfaces.</li>
</ul>


<h3>References</h3>

<ul>
<li><a href="http://zend-framework-community.634137.n4.nabble.com/Proposal-to-update-Abstract-Interface-Naming-Conventions-tt1755544.html#none">Super Old Discussion &quot;Proposal-to-update-Abstract-Interface-Naming-Conventions&quot;</a></li>
<li><a href="http://zend-framework-community.634137.n4.nabble.com/Poll-Interfaces-Abstract-class-naming-conventions-tt1755142.html#none">Old Discussion &quot;Poll-Interfaces-Abstract-class-naming-conventions&quot;</a></li>
<li><a href="http://framework.zend.com/wiki/display/ZFPROP/Naming+conventions+for+2.0+-+Matthew+Ratzloff">Old Proposal By Matthew Ratzloff</a></li>
<li><a href="http://en.wikipedia.org/wiki/Solid_(object-oriented_design)">SOLID principle</a> &amp; <a href="http://en.wikipedia.org/wiki/Design_by_contract">Design-by-contract</a></li>
<li><a href="http://ralphschindler.com/2011/01/18/php-component-and-library-api-design-overview">Ralph's Article on API Design</a></li>
</ul>