doc/book/en/development/entityclasses/application-logic.rst
branchstable
changeset 5394 105011657405
parent 5393 875bdc0fe8ce
child 5395 e0ab7433e640
--- a/doc/book/en/development/entityclasses/application-logic.rst	Fri Apr 23 17:07:55 2010 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-How to use entities objects
----------------------------
-
-The previous chapters detailed the classes and methods available to
-the developper at the so-called `ORM`_ level. However they say little
-about the common patterns of usage of these objects.
-
-.. _`ORM`: http://en.wikipedia.org/wiki/Object-relational_mapping
-
-Entities objects are used in the repository and web sides of
-CubicWeb. On the repository side of things, one should manipulate them
-in Hooks and Operations.
-
-Hooks and Operations provide support for the implementation of rules
-such as computed attributes, coherency invariants, etc (they play the
-same role as database triggers, but in a way that is independant of
-the actual data sources).
-
-So a lot of an application's business rules will be written in Hooks
-(or Operations).
-
-On the web side, views also typically operate using entity
-objects. Obvious entity methods for use in views are the dublin code
-method like dc_title, etc. For separation of concerns reasons, one
-should ensure no ui logic pervades the entities level, and also no
-business logic should creep into the views.
-
-In the duration of a transaction, entities objects can be instantiated
-many times, in views and hooks, even for the same database entity. For
-instance, in a classic CubicWeb deployment setup, the repository and
-the web frontend are separated process communicating over the
-wire. There is no way state can be shared between these processes
-(there is a specific API for that). Hence, it is not possible to use
-entity objects as messengers between these components of an
-application. It means that an attribute set as in `obj.x = 42`,
-whether or not x is actually an entity schema attribute, has a short
-life span, limited to the hook, operation or view within which the
-object was built.
-
-Setting an attribute or relation value can be done in the context of a
-Hook/Operation, using the obj.set_attributes(x=42) notation or a plain
-RQL SET expression.
-
-In views, it would be preferable to encapsulate the necessary logic in
-a method of the concerned entity class(es). But of course, this advice
-is also reasonnable for Hooks/Operations, though the separation of
-concerns here is less stringent than in the case of views.
-
-This leads to the practical role of entity objects: it's where an
-important part of the application logic lie (the other part being
-located in the Hook/Operations).
-
-Anatomy of an entity class
---------------------------
-
-We can look now at a real life example coming from the `tracker`_
-cube. Let us begin to study the entities/project.py content.
-
-.. sourcecode:: python
-
-    class Project(TreeMixIn, AnyEntity):
-        __regid__ = 'Project'
-        __implements__ = AnyEntity.__implements__ + (ITree,)
-        fetch_attrs, fetch_order = fetch_config(('name', 'description',
-                                                 'description_format', 'summary'))
-
-        TICKET_DEFAULT_STATE_RESTR = 'S name IN ("created","identified","released","scheduled")'
-
-        tree_attribute = 'subproject_of'
-        parent_target = 'subject'
-        children_target = 'object'
-
-        def dc_title(self):
-            return self.name
-
-First we see that it uses an ITree interface and the TreeMixIn default
-implementation. The attributes `tree_attribute`, `parent_target` and
-`children_target` are used by the TreeMixIn code. This is typically
-used in views concerned with the representation of tree-like
-structures (CubicWeb provides several such views).
-
-It is important that the views themselves try not to implement this
-logic, not only because such views would be hardly applyable to other
-tree-like relations, but also because it is perfectly fine and useful
-to use such an interface in Hooks.
-
-In fact, Tree nature is a property of the data model that cannot be
-fully and portably expressed at the level of database entities (think
-about the transitive closure of the child relation). This is a further
-argument to implement it at entity class level.
-
-The `dc_title` method provides a (unicode string) value likely to be
-consummed by views, but note that here we do not care about output
-encodings. We care about providing data in the most universal format
-possible, because the data could be used by a web view (which would be
-responsible of ensuring XHTML compliance), or a console or file
-oriented output (which would have the necessary context about the
-needed byte stream encoding).
-
-The fetch_attrs, fetch_order class attributes are parameters of the
-`ORM`_ layer. They tell which attributes should be loaded at once on
-entity object instantiation (by default, only the eid is known, other
-attributes are loaded on demand), and which attribute is to be used to
-order the .related() and .unrelated() methods output.
-
-Finally, we can observe the big TICKET_DEFAULT_STATE_RESTR is a pure
-application domain piece of data. There is, of course, no limitation
-to the amount of class attributes of this kind.
-
-Let us now dig into more substantial pieces of code.
-
-.. sourcecode:: python
-
-    def latest_version(self, states=('published',), reverse=None):
-        """returns the latest version(s) for the project in one of the given
-        states.
-
-        when no states specified, returns the latest published version.
-        """
-        order = 'DESC'
-        if reverse is not None:
-            warn('reverse argument is deprecated',
-                 DeprecationWarning, stacklevel=1)
-            if reverse:
-                order = 'ASC'
-        rset = self.versions_in_state(states, order, True)
-        if rset:
-            return rset.get_entity(0, 0)
-        return None
-
-    def versions_in_state(self, states, order='ASC', limit=False):
-        """returns version(s) for the project in one of the given states, sorted
-        by version number.
-
-        If limit is true, limit result to one version.
-        If reverse, versions are returned from the smallest to the greatest.
-        """
-        if limit:
-            order += ' LIMIT 1'
-        rql = 'Any V,N ORDERBY version_sort_value(N) %s ' \
-              'WHERE V num N, V in_state S, S name IN (%s), ' \
-              'V version_of P, P eid %%(p)s' % (order, ','.join(repr(s) for s in states))
-        return self._cw.execute(rql, {'p': self.eid})
-
-.. _`tracker`: http://www.cubicweb.org/project/cubicweb-tracker/
-
-These few lines exhibit the important properties we want to outline:
-
-* entity code is concerned with the application domain
-
-* it is NOT concerned with database coherency (this is the realm of
-  Hooks/Operations); in other words, it assumes a coherent world
-
-* it is NOT concerned with end-user interfaces
-
-* however it can be used in both contexts
-
-* it does not create or manipulate the internal object's state
-
-* it plays freely with RQL expression as needed
-
-* it is not concerned with internationalization
-
-* it does not raise exceptions
-
-