Hi Chris,

On Feb 1, 2:21 am, Chris McDonough <[email protected]> wrote:
> On Tue, 2012-01-31 at 15:09 -0800, papagr wrote:
> > Hello everyone,
>
> > >From the object-oriented point of view, a Pyramid View (instance of a
> > callable class) depends on the context and the request. Pyramid,
> > correctly injects those dependencies into the view, during a view's
> > class instantiation (while processing a Request).
>
> > Assuming that a view depends on other objects to do its job, is there
> > a preferred or suggested way of injecting other services
> > (dependencies) in a Pyramid view? By "injecting", I do not mean to use
> > the Service Locator design pattern, i.e. let the view find its
> > dependencies using a registry.
>
> If you mean inject stuff into a *view*, you can cause the request to be
> decorated with arbitrary objects on every request using
> config.set_request_property (see
> <http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/api/conf...>).

config.set_request_property(...) seems very useful and I will consider
it. However, I will have to register this way many Domain Model
services and then a Request will act like a service locator. I.e. A
view X will call request.server_foo() and a view Z will call
request.server_bar() i.e. the views know how to find their
dependencies. I would like the Request object to have as few
responsibilities as possible. In addition, in order to test a view I
will have to inspect the code and find out which of the registered
services are used and register Mock Services to a DummyRequest.

The design of the web application that I am envisioning is based on
Domain Driven Design building blocks (http://en.wikipedia.org/wiki/
Domain-driven_design#Building_blocks_of_DDD), like a Repository. E.g.
the Domain Layer of a project management application will consist of a
Project, a ProjectRepository and a ProjectFactory. The Pyramid Views
will "coordinate the application activity and contain no business
logic" (http://www.infoq.com/articles/ddd-in-practice). I.e. Pyramid
views will form the Application Layer (although this is not the strict
DDD approach, it just convenient for me).

It is better explained by an example:

class ProjectListView(object):
    def __init__(self, request, project_repository, project_factory):
        self.request = request
        self.project_repo = project_repository
        self.project_factory = project_factory

    @view_config(route_name='project_list', request_method='GET',
renderer="templates/project/list.pt")
    def get(self):
        query_criteria = ... process the request here ...
        if query_criteria is not None:
            self.project_repo.filter(query_criteria)
        return self.project_repo.get()

    @view_config(route_name='project_create', request_method='POST',
renderer="templates/project/create.pt")
    def create(self):
        data = ... process the request here ...
        new_project = self.project_factory(data)
        self.project_repo.add(new_project)
        return new_project

As you notice the ProjectListView is easily testable, it declares at
the constructor what it needs and does not depend on the
implementation of the ProjectRepository. When the view is being tested
I could simple pass an instance of an InMemoryProjectRepository and
when I actually run the server I pass an instance of a
SQLAlchemyProjectRepository. In case I decide to change the underlying
ORM I will only have to code a new ProjectRepository and I will not
have to look into each view that uses DBSession to freely query the
DB. Of course, for simple projects this is overkill but for bigger
projects I would like to have objects with as few responsibilities as
possible.

It would have been great if Pyramid offered a way to do the following:

class ProjectListView(object):

    @view_inject(project_repository=ProjectRepository,
project_factory=ProjectFactory)
    def __init__(self, request, project_repository, project_factory):
        self.request = request
        self.project_repo = project_repository
        self.project_factory = project_factory

config = Configurator(settings=settings)
config.view_provide(ProjectFactory, SimpleProjectFactory)
config.view_provide(ProjectRepository, SQLAProjectRepository)  #
(interface/abstract class or a simple string, concrete implementation)

I.e. the framework knows how to instantiate a ProjectRepository and
when a view declares that a ProjectRepository is required then
SQLAProjectRepository is instantiated.

I welcome all objections :-)

Nikos.

-- 
You received this message because you are subscribed to the Google Groups 
"pylons-discuss" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/pylons-discuss?hl=en.

Reply via email to