Hi,

Here my review of the mvc tools docs. Keep in mind that I have not
read _any_ of the discussions concerning this component before reading
the requirements and the design doc. I will probably comment on things
that have been discussed and things that are clear for everyone except
me :)

Here goes the requirements review:

> 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 mailing
> list.
> 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 implementations.
>
> 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:
>
> - EventLog_ (error-handling)
> - Mail_ (error-handling, view)
> - PersistentObject_ (models)
> - Template_ (view)
> - Tree_ (routing)
> - Url_ (routing)
> - UserInput_ (routing)
>
> .. _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
> .. _Tree: http://ezcomponents.org/docs/tutorials/Tree
>
> 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 designing
> the classes/interfaces for the MvcTools component.
>
> Design requirements
> ===================
>
> This section summarizes the requirements regarding the later following
> design document.
>
> 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 a case, controllers run an action using a single argument: an
> input-object, or a request object.
> A controller returns an result-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 request-object it requires the
> so-called request parser. After the controller has been run, the result
> object is send to the view-manager, which is responsible to select the
> correct rendering mode for the output protocol/format.
>
> The request object is responsible of generating an input object, which
> contains data that is not specific on the protocol; it can be used in
> protocol-independent controllers.
>
> Those two layers use one controller 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 anything that is
> protocol-specific. The two layers abstract I/O from the controller as
> described in the specific section.
>
> Summary
> ^^^^^^^
>
> - One controller and action can be run in one request.
> - Controllers should neither work on raw input directly, nor create a
> specific kind of result, but should only work on abstracted response and
> result objects.
> - Protocol dependent controllers may access the raw data.
> - 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
>
> Request parser
> --------------
>
> Requests should be parsed by the request parser.
> The request parsers are protocol dependent, and return a request object.
> The request object in question is responsible for generating an abstract
> input object, for controllers that are not protocol dependant.
Is this right? In the design doc I get the feeling that the request
object _is_ the abstract input. Or am I wrong?

> The request parser is the first layer in action, it's possible to run any
> controller with it's resulting request object, and protocol independant
> controllers with the input-object resulting from the request object.
> It handles input parsing and filtering, but delegates input validation to
> the controller.
Here is the first time filtering comes up but it is not explained.
What is filtering?

> Summary
> ^^^^^^^
>
> - The request parser is responsible to filter the incoming request and to
>   extract all relevant data into the request object.
> - The request object is responsible to produce an abstract input object.
If it is indeed three step (e.g request parser->request
object->abstract input object) why is this so? Why doesn't the request
parser generate the abstract input object right away?

> Multilevel 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, it should be possible to use abstracted input and output
> formats, into dedicated objects; which are not specific to a certain
> protocol or format.
>
> Controllers will however receive all the input data, besides the abstracted
> data that comes in from the request. It's up to the developer to make sure
> none of the protocol-specific data is used in case he wants a
> protocol-abstract controller. This allows protocol-specific controllers to
> access the raw request data.
>
> The request-object contains all the request data.
>
> A beneficial side-effect relates to controller-testing: Creating request
> and result mocks and fixtures allows straight-forward TDD.
>
> Summary
> ^^^^^^^
>
> - Some controllers should not know about the input and output environment
>   out work on abstract objects only.
> - Protocol dependent controllers should have access to all the request
> data.
>
> Routing
> -------
>
> Each request runs a controller.  A controller returns an abstract value
> that should be usable with any output formats and protocols.
>
> The router selects the controller to run.  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 request-objects,
> that may be used to access a certain controller and action with a certain
> view-manager and defined parameters. This method must be accessible from
> the controllers and the view-manager.  Protocol independent routers can use
> the input-object instead.
Why is this mechanism needed?

General questions I had about routers at this point:
- who decides which router to use?
- who calls the initial methods on the router?

> Summary
> ^^^^^^^
>
> Routers are responsible for:
>
> - Selecting controllers based on the input
> - Running the controller and collecting either the request object or the
>   abstract input object.
>
> 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
>
> Controller
> ----------
>
> Controllers provide the actions that implement the business logic of the
First mention of action? What is an action? (See comment on Action further down)
> application. The controllers accept the request object as input. Each
> controller implementation can provide two methods that provide filter
Why two?
> chains. These filter chains are run before - on the request object - and
> after - on the result object to implement application specific filtering.
I'm still not certain what this filtering is for.

> It is left to the user on how the interaction with the model happens. There
> are two basic options. One is where the model is directly used in the
> controller through f.e. the PersistentObjectSession's singleton pattern.
> The second possibility is to depend on a service interface. This service
> interface then uses the PersistentSession to query, and work on the model.
> This service interface architecture prevents the controller from being
> dependent on the model.
>
> Summary
> ^^^^^^^
>
> - Controllers are user-implemented
> - Controllers allow pre-run request filters
> - Controllers allow post-run result filters
> - There are two ways of dealing with a model
>
> View-management
> ---------------
>
> Controllers return a value that cannot be send directly to the client
> (abstract result 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 result object and the abstract request object
Is this the same as the abstract input object described earlier? I'm
slightly confused :)

> 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 result-objects
> into a proper response.
When can you have several result objects? How do you handle ordering?

> Only one view-handler can be used to generate a certain response. It can
> receive any number of abstract result 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.
How does the view-manager determine this?

>
> 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 the request object and the abstract result objects
> - 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 occurred error. An error during the execution
> of this default controller will cause a "500 - 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 Execution, 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,
> - whether actors should be notified or not.
>
> An EventLog_ and 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 bug fix. The
> solution is test-automation in PHP (e.g. using PHPUnit).
>
> Controllers run with a single argument: a request object.  Controllers
> return a single value: An abstract result object. Running a controller with
> an request-object fixture and asserting that the result matches an
> result-object fixture is the procedure to test a controller.

Very good. I like this.

> Summary
> ^^^^^^^
>
> Requested process to test a controller:
>
> - Create a request-fixture (which can have protocol dependent values)
> - Create a result-fixture (abstract output object)
> - Run the controller against the request-fixture
> - Assert that the controller's result equals the result-fixture
>
> Conventions
> -----------
>
> Convention is the key for this component.  Even though tie-ins will be
> supplied to allow the usage of other eZ Components, all layers should be
> adjustable and replaceable by the user.
>
> The only classes that should be common to every project are the request
> object, and the request and the result 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 party code.
>
> Special Considerations
> ======================
>
> HTTP-GET should not be allowed to invoke changes on the model because this
> would cause a violation of HTTP standards.
It's quite common to do though. Are you sure you want to "prohibit"
this? How will you enforce it?

> 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:
Yes, very good.

> - 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.
What is a process?

> 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 arbitrary 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.
>
> Request
>   The data that comes in through any protocol possible from the client to
> the server. The request data consists of headers, variables, files etc and
> is encapsulated in the ezcMvcRequest object.
>
> Result
>   The abstract result of a controller action that can be used by the view
>   manager to generate a response.
>
> Response
>   The data that is send from the server to the client that has been
> generated by the view manager from the abstract result object.

After reading all of this I still didn't really catch the general flow
of a request. Would it be possible to make a diagram of that? How are
the different parts supposed to interact.

Cheers,
Frederik
-- 
Components mailing list
Components@lists.ez.no
http://lists.ez.no/mailman/listinfo/components

Reply via email to