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.
