View Source

<h2>Overview</h2>

<p>This document covers general questions for <code>Zend\Tool</code> refactoring and applicability of <code>Zend_Tool</code> infrastructure in context of ZF2.</p>

<p>It also discusses the need for default providers (in ZF1 defined in <code>Zend_Tool_Framework_System_Provider</code>) and more importantly default code generating providers (defined in <code>Zend_Tool_Project_Provider</code>).</p>


<h2>Goals</h2>

<ul>
<li>Define what parts of <code>Zend\Tool*</code> ecosystem is reusable in context of ZF2 (what have been already refactored, what need to be removed)</li>
<li>Understand the need or the lack of support for code generating capabilities previously available via <code>Zend\Tool\Project</code> (but not limited to them)</li>
</ul>


<h2>Requirements</h2>

<h3>Zend\Tool\Framework</h3>

<ul>
<li><strong>MUST</strong> be simplified</li>
<li>All low-level components not <em>directly</em> involved in exposing providers' functionality <strong>MUST</strong> be either factored out or removed</li>
<li><strong>MUST</strong> integrate more tightly with <code>Zend\Console</code> (instead of custom CLI implementation)</li>
</ul>



<h3>zf2.php </h3>
<ul>
<li><strong>MUST</strong> co-exist w/o conflicts with ZF1 <code>zf.php</code> tool</li>
<li><strong>MUST</strong> support shared ZF2 installations (where ZF installed on some common path)</li>
<li><strong>SHOULD</strong> be able to create <a href="https://github.com/zendframework/ZendSkeletonApplication">ZendSkeletonApplication</a> - allowing to quick start <em>quickly</em></li>
<li><strong>SHOULD</strong> provide functionality on par with previous <code>zf.php</code> tool</li>
<li><strong>SHOULD</strong> expose providers previously found in <code>Zend\Tool\Project</code></li>
</ul>


<h3>Zend\Tool\Project:</h3>

<ul>
<li>No need to have it in framework's core, <em>providers</em> <strong>SHOULD</strong> be moved to separate module (<a href="https://github.com/farazdagi/ZendToolProviders">ZendToolProviders</a> during first implementation phase)</li>
<li><strong>MUST</strong> be simplified, just set of generators/providers easily consumable by <code>zf2.php</code> tool</li>
<li><strong>SHOULD NOT</strong> be stateful
<ul>
<li>Contrary to what is said in <a href="http://framework.zend.com/manual/1.11/en/zend.tool.project.introduction.html">docs</a>, when adding new action to existing controller no state is necessary - reflection capabilities of <code>Zend\Code</code> component should be enough.</li>
<li>General <code>modus operandi</code> should be KISS</li>
</ul>
</li>
</ul>


<h2>Current Status of Components</h2>

<p>At the moment <code>Zend\Tool</code> component and all of its sub-components were removed from master branch.</p>

<p>Partially, some functionality like one provided by <code>Zend\Tool\Client</code> is now available as a part of <code>Zend\Console</code> component (being developed).</p>

<p>Number of components originally found in <code>Zend_Tool</code> clearly smell of over-engineering: <code>Zend\Tool\Framework\Registry</code>, providers having state, client data storage capabilities, CLI client implementation itself. <br />
All these components either do not belong to the problem domain, or we have that domain defined very broadly.</p>

<p>So, the aim is to utilize previously created code, but the whole architecture should be more simple, decoupled and have fewer layers.</p>

<h2>Proposal</h2>

<p>Instead of having <code>Zend\Tool\Framework</code> + <code>Zend\Tool\Project</code> + <code>bin/zf.php</code> infrastructure will be amended to:</p>

<ul>
<li>have way more simple <code>Zend\Tool</code> component</li>
<li>have <code>ZendToolProviders</code> ZF2 module. It will contain set of default providers (providers found in <code>Zend\Tool\Project\Provider</code>).</li>
<li>providers found in <code>Zend\Tool\Framework\System\Provider</code> should remain w/i framework's core, so that they are available w/o <code>ZentToolProviders</code> module installation.</li>
<li><code>zf2.php</code> will be a rewrite of <code>zf.php</code> utilizing <code>Zend\Console</code></li>
</ul>



<h3>Zend\Tool Component</h3>

<p>Primary responsibility will be to provide utility functionality to any console-enabled modules.</p>

<p>While <code>Zend\Tool\Framework</code> was full-fledged framework, <code>Zend\Tool</code> in ZF2 will be a more light-weight solution delegating all of the leg-work to providers modules.</p>

<p>A good example of what might go into <code>Zend\Tool</code> component are marker interfaces, like <code>Provider</code> and <code>Pretandable</code> (aka dry-run). This will allow to have framework-defined standards for concrete providers.</p>

<h3>ZendToolProviders module</h3>

<ul>
<li>We may pick another name, I am not particularly good at naming</li>
<li>Will contain all basic code generation functionality, including:
<ul>
<li>modules</li>
<li>controllers</li>
<li>actions</li>
<li>views</li>
<li>unit tests</li>
<li>form</li>
<li>style and script assets (these can go into separate assetic module of course)</li>
</ul>
</li>
<li>It is probably good idea to have better integration for ORM entities (so that forms might be generated from them). This is a serious question though, requiring serious consideration.</li>
<li>Will play nicely with 3rd party console-enabled modules</li>
<li><code>Zend\Code</code> will be used for both parsing/scanning and code generation (where necessary)</li>
<li>It will be <em>standard</em> ZF2 module, to be installed into <code>vendor</code> folder</li>
</ul>


<p><code>Zend\Tool\Project</code></p>

<ul>
<li>No special treatment of projects, except for probably namespacing generators (to distinguish btw standard providers and imported)</li>
<li>Providers will be reworked to take into account changes occurred in <code>Zend\Code</code> and <code>Zend\Console</code></li>
</ul>


<h3>bin/zf2.php</h3>

<ul>
<li>It will heavily depend on <a href="https://github.com/Thinkscape/zf2/tree/feature/console/library/Zend/Console">Zend\Console component</a> developed by <ac:link><ri:user ri:username="joust" /></ac:link></li>
<li><strong>MUST</strong> be able to detect whether it is being run from ZF2 application, and if so detect available console-enabled modules</li>
<li><strong>SHOULD</strong> support both Active and Passive Generators</li>
<li><strong>MUST</strong> allow 3rd party plugin generators (so be extensible, 3rd party modules should be able to register with the tool and their providers become immediately available)</li>
<li><code>zf2.php</code> <strong>IS NOT</strong> 1:1 conversion of previous zf.php capabilities</li>
<li><strong>MUST</strong> support full scaffold generation (with separetely runnable steps - like controller creation, view creation etc)</li>
</ul>



<h2>Functional Segmentation</h2>

<p>Very important issue is separation by responsibility: for ex, Doctrine2 migrations or schema handling module may (and probably should) define its own providers. <br />
The aim is to standardize the way providers are created, and provide single point of access via which those providers will be used: that's via <code>zf2</code> script.</p>

<p>So, with wise utilization of refactored <code>Zend\Tool</code> (which will allow to mark classes semantically) + generic <code>zf2.php</code> script (which will rely on conventional <a href="http://framework.zend.com/wiki/display/ZFDEV2/RFC+-+Console+2.0">Zend\Mvc\ConsoleApplication</a>) we should be able to expose all console-enabled controllers easily.</p>

<h2>Active vs Passive Generators</h2>

<p>Ideally, both passive, and <a href="http://c2.com/cgi/wiki?ActiveCodeGeneration">active</a> code generation should be supported. </p>

<p>While passive code generation - where generated code is to be additionally edited by programmer - saves lots of typing, active generation will support on-fly or triggered re-compilation of artifacts/assets.</p>

<p>With this in mind, the primary focus of the module <strong>SHOULD</strong> be CLI-tool, and not the web-based interface (&agrave; la Yii's <a href="http://www.yiiframework.com/doc/guide/1.1/en/topics.gii">Gii</a> tool).</p>

<p>As module will be depended on <code>Zend\Console</code> which by itself is a good abstraction layer between framework's core and the rest of the world, extending code generator to support web-based interface should be relatively easy task. This is <em>beyond</em> the scope of current document though.</p>

<h2>Installation</h2>

<p><code>bin/zf2.php</code> tool will be available whenever ZF itself is available (being a part of installation).</p>

<p>System providers (like <code>zf2 show version</code>) will be available w/o any further configuration.</p>

<p>Code generators will be available on per project basis, and installable as any other ZF2 module i.e. <code>ZendToolProviders</code> module goes to <code>vendor</code> folder.</p>

<h2>ZF1 Compatibility</h2>

<p><code>zf2.php</code> tool:</p>
<ul>
<li><strong>SHOULD</strong> provide similar features original <code>zf1.php</code> provided (so that there's no huge learning curve)</li>
<li><strong>SHOULD NOT</strong> be aware of ZF1, meaning code generators will be ZF2-compatible ONLY</li>
<li><strong>MAY</strong> provide (out-of-box) some <code>migration</code> provider set, helping automating ZF1-&gt;ZF2 migrations.</li>
</ul>


<h2>zf2.php and module installation</h2>

<p>Good stress test for the whole idea of having separate modules for different sets of providers is module <a href="http://framework.zend.com/wiki/display/ZFDEV2/RFC+-+Module+Installation+and+Distribution">installation and distribution</a>.</p>

<p>It is expected that <code>zf2.php</code> is capable of installing/updating modules, so here is the question to anyone who have spent some brain-power analyzing best ways to install modules:<br />
Will it be feasible to create some <code>ZendToolModuleManager</code> module, which will be exposed via proposed <code>zf2.php</code> tool?</p>

<p>Will it be too much to ask end-user to install some standard modules in addition to core libs, to utilize framework in a more pleasant way?</p>

<h2>Roadmap</h2>

<ul>
<li>After gathering some input to confirm that the whole idea is sane, first step will be to implement <code>zf2.php</code> tool</li>
<li>Once done, <code>Zend\Tool\Project\Provider</code> need to be migrated to <a href="https://github.com/farazdagi/ZendToolProviders">ZendToolProviders</a> repo</li>
<li>Some docs on how to expose zf2 console-enabled controllers, so that any other modules may be updated:
<ul>
<li>Module management</li>
<li>Assets management</li>
<li>Doctrine2 integration (both schema and migrations tools)</li>
</ul>
</li>
</ul>


<p>NB: All development should be in sync with <code>Zend\Console</code> component - which is currently being updated.</p>


<h2>Alternatives</h2>

<p>When considering whether we need support for scaffolding/code generation it is worth looking at how others have tackled the same problem:</p>

<ul class="alternate">
<li>RoR has amazingly complete CLI tools (including code generators), Symfony2 follows the suit.</li>
<li>Django provides great admin application, but no code generation per se (although admin app + ModelForm + generic views still allow you to keep dev. process pretty DRY)</li>
<li>Yii has web-based generator (with preview), plus deprecated CLI tool</li>
<li>CakePHP has very rich CLI tools, including code generation, schema management, and i18n</li>
</ul>


<h2>References</h2>

<p><a href="http://framework.zend.com/manual/en/zend.tool.project.html">Zend Tool Docs for ZF1</a><br />
<a href="https://github.com/Thinkscape/zf2-console-sandbox">Artur Bodera's Console Sandbox on GitHub</a><br />
<a href="https://github.com/farazdagi/ZendToolProviders">ZendToolProviders</a><br />
<a href="http://framework.zend.com/wiki/display/ZFDEV2/RFC+-+Console+2.0">RFC Zend\Console 2.0</a></p>