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

Reply via email to