Hello everybody ! We are done with a final draft, document attached. I'll post an implementation document first draft tomorrow morning.
I also want to thank two very special and talented persons whom have higly contributed : Kore Nordmann and Tobias Schlitt. This document would have never met such a high-quality (to my opinion) without the experience and time that you have shared ! Cheers, James. -- James Pic
eZ Component: MvcTools, Requirements ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :Author: James Pic, Tobias Schlitt :Revision: $Revision$ :Date: $Date$ Target and scope ================ The scope of this document is to describe the requirements for a component providing classes to implement a MVC_ architecture for a web application. This document does not describe the design of the named component, but only summarizes the requirements for it as discussed on the developer mailinglist. Where suitable, design related topics will be touched, but a dedicated design document will follow later, defining APIs, classes and the architectural structure of the component. Note that if you don't understand a term, you should have a look at the section `Clarification of terms`_. Introduction ============ Model-View-Controller (MVC) is a common architecture pattern to implement all kinds of applications using the object-oriented design paradigm. The goal of the MvcTools component is to give users a basis for such architectures for web applications written in PHP 5. The component shall not provide a full-featured implementation of the MVC architecture, but should help users to easily create their own, custom implementation. A good starting point to learn more about MVC is the Wikipedia article: http://en.wikipedia.org/wiki/Model-view-controller Component integration ===================== eZ Components already provide some components that are useful when implementing an MVC. However, one basic goal of eZ Components is to keep each component as independent as possible and to realize dependencies through so-called tie-in components. Therefore the mechanisms realized in an MVC component should be that far abstracted, that other components can be tied in and provide only very basic implementations on its own. This also allows users to implement their own mechanisms. The following components have been identified as possible tie-ins: - Template_ (view) - UserInput_ (routing) - Url_ (routing) - PersistentObject_ (models) - EventLog_ (error-handling) - Mail_ (error-handling, view) .. _UserInput: http://ezcomponents.org/docs/tutorials/UserInput .. _Url: http://ezcomponents.org/docs/tutorials/Url .. _PersistentObject: http://ezcomponents.org/docs/tutorials/PersistentObject .. _EventLog: http://ezcomponents.org/docs/tutorials/EventLog .. _Mail: http://ezcomponents.org/docs/tutorials/Mail For each of these components a tie-in component could considered to be implemented at a later stage. This should be kept in mind when desigining the classes/interfaces for the MvcTools component. Design requirements =================== This section summarizes the requirements regarding the later following design document. I/O abstraction ---------------- Modern applications often require to deal with different input and output protocols and formats (for example HTTP-GET, HTTP-POST, SOAP for the input part and HTML, PDF, ReST-webservices for the output part). Therefore, protocols input and output formats should be abstracted into dedicated objects, which are not specific to a certain protocoll or format. Controllers will only receive these abstracted data objects without knowledge of the used format/protocol, to allow the re-use of 1 controller with severl different input/output sources. A benefic side-effect relates to controller-testing: Creating input and output mocks and fixtures allows straight-forward TDD. Summary ^^^^^^^ - Controllers should not know about the input and output environment but work on abstract objects only. Layers ------ The MvcTools component should distinguish certain layers to allow users to easily adjust and replace certain functionality. Therefore, the following requirements have been specified. Controllers process and respond to events, typically user actions, and may invoke changes on the model. In our case, controllers run an action using a single argument: An input-object. A controller returns an output-object, after being run. Another different layer is responsible to select the controller to run and the action to call on it. To create the input-object it requires the so-called input-router. After the controller has been run, the output object is send to the view-manager, which is responsible to select the correct rendering mode for the output protocol/format. Those two layers should be able to use any number of controllers per-request. They handle the client-protocol, so that the controller doesn't have work on raw input data (e.g. GET/POST/...) and does not have to generate any specific output format (e.g. HTML, XML, plain text,...) or anythingng that is protocol-specific. The two layers abstract I/O from the controller as described in the specific section. Summary ^^^^^^^ - Any number of controllers and actions can be run in 1 request. - Controllers may neither work on raw input directly, nor create a specific kind of output, but may only work on abstracted I/O objects. - It should be straight forward to test any action. Ideas ^^^^^ A PersistentObject_ tie-in could be supplied to easily realize Crud_ controllers. .. _PersistentObject: http://ezcomponents.org/docs/tutorials/PersistentObject .. _Crud: http://en.wikipedia.org/wiki/Create%2C_read%2C_update_and_delete Routing ------- Several controllers can be run to serve a single request. Those controllers should be runnable within different requests in different mixtures. A controller returns an abstract value that should be usable with any output formats and protocols. The input-router is responsible to filter the incoming request and to extract all relevant data into the input abstraction object. The router also selects the controller(s) to run. After running the controllers the router selects the view-manager to use with the controller's return values (output-objects). Controllers can call the routers re-routing method with redefined input data to redirect processing to a different controller. Routers must also provide a mechanism to create URLs from input-objects, that may be used to access a certain controller and action with a certain view-manager and defined parameters. This method must be accesable from the controllers and the view-manager. Summary ^^^^^^^ Routers are responsible for: - Filtering and abstracting input data - Creating an abstract input object - Selecting controllers based on the input - Running the controllers and collecting abstract response objects Routers may be asked by a controller to re-route the request to another controller and must therefore be accessible from any action. Tie-in components for the Url_ and UserInput_ components should be provided to realize routers. The design of these components should be considered important while designing the MvcTools component. .. _UserInput: http://ezcomponents.org/docs/tutorials/UserInput .. _Url: http://ezcomponents.org/docs/tutorials/Url View-management --------------- Controllers return a value that cannot be send directly to the client (abstract output object). Another layer uses the return value and processes it into a specific response. This layer is called the view-manager. The view manager receives the output object and the abstract request object an can decide on the base of both of them which view handler to use. The view handler is responsible for rendering one or several output-objects into a proper response. Only 1 view-handler can be used to generate a certain output. It can receive any number of abstract output objects. A view-handler is responsible to render a certain output format for a certain protocol. The view-handler to use is determined by the used view-manager, and the view-manager to use is determined by the router. For example, the view-handler that generate HTML/HTTP-responses is separated from the view-handler that generates XML/HTTP-response. Summary ^^^^^^^ View-manager role: - Receives abstract input object - Builds the concrete response and sends it to the client A tie-in for the Template_ component should be provided with the first release of MvcTools. .. _Template: http://ezcomponents.org/docs/tutorials/Url Error-handling -------------- During debugging it must be possible to present helpful error messages to the developer, but on a production system no errors from the MVC should be shown to the user, but the developer should be able to handle them gracefully. Some failures should be reported to the administrator in a technical manner; allowing him to fix the problem or to handle the client's request manually. Errors may occur during each step of the request handling, like the following examples: - Router cannot parse request - Configured / requested controller could not be found - The view can't be rendered because of incompatible data or some template parse error Those errors cannot be handled by the controller, because they happen outside of it. A configurable default controller will be called for all error messages, so the application developer may decide to send messages, show or log the occured error. An error during the execution of this default controller will cause a "501 - Internal Server Error". As none of the given errors is meant to be displayed to the user of the application (but only to the developer) no translation possibilities for the errors need to be provided. TieIns for this default controller using the EventLog and / or Mail component for error logging would be useful. Summary ^^^^^^^ Actions should be able to cast an error specifying, at once : - the verbose error message, - the non-verbose error message or id, - the target action to bundle the error with, - wheter actors should be notified or not. An EventLog_ + Mail_ tie-in should be supplied by another component. .. _EventLog: http://ezcomponents.org/docs/tutorials/EventLog .. _Mail: http://ezcomponents.org/docs/tutorials/Mail Testing ------- Testing a controller is the key to quality development. Testing manually each controller can lead to disasters: It's boring to do and therefore humans cannot cover all controllers manually after each bugfix. The solution is test-automation in PHP (e.g. using PHPUnit). Controllers run with a single argument: An abstract input object. Controllers return a single value: An abstract output object. Running a controller with an input-object fixture and asserting that the result matches an output-object fixture is the procedure to test a controller. Summary ^^^^^^^ Requested process to test a controller: - Create an input-fixture (abstract input object) - Create an output-fixture (abstract output object) - Run the controller against the input-fixture - Assert that the controller-result equals the output-fixture Conventions ----------- Convention is the key for this component. Even though tie-ins will be supplied to allow the usage of other eZ Componets, all layers should be adjustable and replaceable by the user. The only classes that should be common to every projects are the input and the output abstractions. All other classes should be defined through interfaces and only very basic implementations will be shipped with the component. Advanced implementations can be added at a later stage, be provided via tie-ins or can be implemented by the user himself or be installed through 3rd parties. Special Considerations ====================== We should keep testing capabilities for the extensions to this component and the applications build upon it in mind during the design and implementation phase. We cannot provide the testing environment itself: - Does not fit into the component - Our test "component" is not an official component and can only be used to test eZ Components themselves. However, we could provide detailed information and possibly some helper classes for the testing of applications build on this component. The later application configuration layer (meaning to read configuration from config files and configuring the parts of the MVC accordingly) should be part of a potential "Framework" component. But this should not be part of this document nor the MvcTools component. In addition, this component should neither provide any automation facilities (e.g. code generation, deployment) nor integration with components that are not explicitly needed by it (e.g. Configuration, Authentication or Database). Integration with such components could: - Be build using a tie-in - Be part of a potential "Framework" component/package stuff that might be created in future. Clarification of terms ====================== MVC_ Model-View-Controller (MVC) is an architectural pattern to separate data (model) and user interface (view) concerns, so that changes to the user interface will not affect data handling. Model The domain-specific representation of the information that the application operates on. Domain logic adds meaning to raw data (e.g., calculating whether today is the user's birthday, or the totals, taxes, and shipping charges for shopping cart items). The PersistentObject component provides a persistent storage mechanism (such as a database) to store data. MVC does not specifically mention the data access layer because it is understood to be underneath or encapsulated by the model. View Renders the action into a form suitable for interaction, typically a user interface element. Multiple views can exist for a single model for different purposes. The Template component provides a syntax-light language for non-programmers to design the views. Therefore a tie-in with the Template component should be provided. Controller Processes and responds to events, typically user actions, and may invoke changes on the model. Action Controllers can provide one or several actions. Each action has a specific process that can be called by the router. InputOutput_ In computing, input/output (I/O), refers to the communication between a program and the outside world - possibly a human or another machine. Inputs are the data received by the system, and outputs are the data sent from it. The term can also be used as part of an action: "To perform I/O" is to perform an input and/or output operation. For example, a browser such as Firefox is able to send input to the website and to render it's output (HTML). I/O Stands for Input/Output. Router Routers are the first layer hit by input and the last layer that processes the output. That is why it handles routing requests to the appropriate action and abstracts the request/response protocol. Fixture_ Fixtures are objects that are set to an arbitary state for testing purposes. Abstraction_ It is the process or result of generalization by reducing data, typically in order to retain only information which is usable by any router for any protocol. .. _MVC: http://en.wikipedia.org/wiki/Model-view-controller .. _InputOutput: http://en.wikipedia.org/wiki/Input/output .. _Fixture: http://en.wikipedia.org/wiki/Test_fixture .. _Abstraction: http://en.wikipedia.org/wiki/Abstraction Credits ======= Thanks to the persons who gave feedback on this and previous versions of this document *on the eZ Components developer mailinglist*. I did my best to compile our requirements. - Tobias Schlitt - Gaetano Giunta - Tobias Struckmeier - Derick Rethans - Kore Nordmann - James Pic .. Local Variables: mode: rst fill-column: 79 End: vim: et syn=rst tw=79
-- Components mailing list [email protected] http://lists.ez.no/mailman/listinfo/components
