Today, I got a talk with Nicolas about the relevance of the workflow
engine in Tryton.
We came to the conclusion that it will be perhaps better to drop it.
So here are the arguments:
- The Subflow which is indeed a key feature in the design of workflow is
never used in Tryton because by experience (on OpenERP) we knew that
it doesn't allow enough flexibillity. Most of the time, you need to
trigger the workflow in some other activities then the starting/ending
one.
- The flexibility. Normally the workflow engine must provide
flexibility but in the reallity, we have most of the time more
difficulty to modify it through modules (any standard module does it).
So we manage it by inheriting some methods.
- Simplicity. Just looking at the workflow of sale and you understand
that when you try to modelise complet life cycle of a document, the
workflow becomes very complex. But we can print a picture of it.
- Misunderstanding, most of the developpers (and users) think that the
workflow is linked to the status of the document but because of the
nature of the engine, it is not. And you can have inconsistency
between both.
- Speed, it is well know that the workflow engine is not very fast. Does
it deserve this sacrifice?
- Security, this is a point where it is good. The access right to go
througth a transition works well.
So by what could we replace the workflow engine?
The idea will be to have just simple method calls. Those methods will
replace the activities. The transitions will be replaced by different
way:
- buttons which are linked to methods
- methods that call other methods
- triggers? (not sure because they can be heavy)
The security will be replaced by capacities. So some method will be able
to check (via decorator?) if the user has a specific capacity to run the
method. The capacities will be defined in XML and they will be linked to
groups.
The workflow trigger will be replaced by overriding the right method of
the target model (it is already done like that with model without
workflow).
Optional advantage of such design is the traceback of calls will be more
clear.
So what do you think?
--
Cédric Krier
B2CK SPRL
Rue de Rotterdam, 4
4000 Liège
Belgium
Tel: +32 472 54 46 59
Email/Jabber: cedric...@b2ck.com
Website: http://www.b2ck.com/
You are talking about "Business Worfklow" which is different of the
"Model Workflow" of Tryton.
You are talking about "Business Worfklow" which is different of the
"Model Workflow" of Tryton.--
Cédric Krier
No or at least not in the common way to implement it.
Le 25 nov. 2011 à 19:10, Cédric Krier a écrit :
> Today, I got a talk with Nicolas about the relevance of the workflow
> engine in Tryton.
> We came to the conclusion that it will be perhaps better to drop it.
For those, like me, that don't have any experience with OpenErp, could you please point to a doc explaining how it currently works (or should) ?
Thks
Jean-Christophe Michel
--
Symétrie
livres et partitions, édition multimédia
30 rue Jean-Baptiste Say
69001 LYON (FRANCE)
tél +33 (0)478 29 52 14
fax +33 (0)478 30 01 11
web www.symetrie.com
There is not so much documentation about it.
We got:
http://doc.tryton.org/2.2/trytond/doc/ref/models/models.html#modelworkflow
And I find this about the OE workflow:
http://open-net.ch/ERP-CRM-OpenERP/User-Guide-OpenERP/Les-workflows
On 28/11/11 09:15 +0100, lists.j...@symetrie.com wrote:There is not so much documentation about it.
> Hi,
>
> Le 25 nov. 2011 à 19:10, Cédric Krier a écrit :
> > Today, I got a talk with Nicolas about the relevance of the workflow
> > engine in Tryton.
> > We came to the conclusion that it will be perhaps better to drop it.
>
> For those, like me, that don't have any experience with OpenErp, could you please point to a doc explaining how it currently works (or should) ?
We got:
http://doc.tryton.org/2.2/trytond/doc/ref/models/models.html#modelworkflow
And I find this about the OE workflow:
http://open-net.ch/ERP-CRM-OpenERP/User-Guide-OpenERP/Les-workflows
A Divendres, 25 de novembre de 2011 19:10:48, C�dric Krier va escriure:
I agree in all those points. Also, I'd add that we were discussing not the workflow engine, but the workflow and "state" of a document concept with Dominique from SISalp, and I think that needs some revision too. The same way subflows are not flexible enough, the "state" or "workflow" concept in a single document is sometimes not flexible enough, either. The advantage is that it is easy to understand but at the same time it is often used to impose some restrictions that make user's life a bit complicated. Although, maybe that discussion should go in another thread and with some specific examples, so will try to come back to this later.
> So by what could we replace the workflow engine?
>
> The idea will be to have just simple method calls. Those methods will
> replace the activities. The transitions will be replaced by different
> way:
>
> - buttons which are linked to methods
> - methods that call other methods
> - triggers? (not sure because they can be heavy)
>
> The security will be replaced by capacities. So some method will be able
> to check (via decorator?) if the user has a specific capacity to run the
> method. The capacities will be defined in XML and they will be linked to
> groups.
> The workflow trigger will be replaced by overriding the right method of
> the target model (it is already done like that with model without
> workflow).
> Optional advantage of such design is the traceback of calls will be more
> clear.
Again, I agree with the general design. The decorator can be an smart way to check capacities, but I ask myself how would those methods would registered in the system in the first place?
Maybe we should allow PYSON expressions that indicated when an action is possible and when not, the same way it is already done with 'required' and 'readonly' states in fields. Somehow that would define what currently is the previous state of a workflow state.
Ok. Just let me try to a proposal for discussion:
class Sample:
confirm = fields.Action('Confirm', Equal(Eval('state'), 'draft')),
def confirm_action(self, ids):
pass
I think that something like this has the advantage of:
- "Register" the action so we can assign user/group permissions to it.
- Clearly states what needs to be the previous "state" before the action can be executed.
- All the code is in the same file (no need to jump to XML for following the workflow).
- Can be overriden by other modules.
Opinions?
--
Albert Cervera i Areny
Tel: +34 93 553 18 03
This looks like the Button object I worked (before losing the work due
to crash disk) to allow to have xml view in separeted file [1].
So I think it should add some more parameters on it like the type
(action or method (no more workflow :-)).
One question I got is when should we test the access right/state.
For now, this design looks like it is only done on client side except if
there is some extra code in the method. Or as you said we could use a
decorator but the issue with decorator is the extension by other
modules where you lose the fact that the decorator is called first but
it is perhaps not a problem.
[1] https://codereview.appspot.com/3991046/
A Dimarts, 29 de novembre de 2011 09:48:27, C�dric Krier va escriure:
> On 29/11/11 08:59 +0100, Albert Cervera i Areny wrote:
> > A Divendres, 25 de novembre de 2011 19:10:48, C�dric Krier va escriure:
> >
> > class Sample:
> > confirm = fields.Action('Confirm', Equal(Eval('state'), 'draft')),
> >
> > def confirm_action(self, ids):
> > pass
> >
> > I think that something like this has the advantage of:
> > - "Register" the action so we can assign user/group permissions to it.
> > - Clearly states what needs to be the previous "state" before the action
> > can be executed.
> > - All the code is in the same file (no need to jump to XML for following
> > the workflow).
> > - Can be overriden by other modules.
>
> This looks like the Button object I worked (before losing the work due
> to crash disk) to allow to have xml view in separeted file [1].
> So I think it should add some more parameters on it like the type
> (action or method (no more workflow :-)).
What would be the advantage of distinguishing between action and method? What would be the differences?
> One question I got is when should we test the access right/state.
> For now, this design looks like it is only done on client side except if
> there is some extra code in the method. Or as you said we could use a
> decorator but the issue with decorator is the extension by other
> modules where you lose the fact that the decorator is called first but
> it is perhaps not a problem.
What about overriding __getattribute__ method or something like that in Model? Too much overhead, maybe?
>
action is running an ir.action like a report or a wizard.
method is calling a method on the model.
> > One question I got is when should we test the access right/state.
> > For now, this design looks like it is only done on client side except if
> > there is some extra code in the method. Or as you said we could use a
> > decorator but the issue with decorator is the extension by other
> > modules where you lose the fact that the decorator is called first but
> > it is perhaps not a problem.
>
> What about overriding __getattribute__ method or something like that in Model?
> Too much overhead, maybe?
Don't like too much. I prefer explicit.
>> > One question I got is when should we test the access right/state.
>> > For now, this design looks like it is only done on client side except if
>> > there is some extra code in the method. Or as you said we could use a
>> > decorator but the issue with decorator is the extension by other
>> > modules where you lose the fact that the decorator is called first but
>> > it is perhaps not a problem.
>>
>> What about overriding __getattribute__ method or something like that in Model?
>> Too much overhead, maybe?
>
>Don't like too much. I prefer explicit.
I have an idea about decorators (I like them they are a nifty syntax).
Maybe the decorator is used only to register the method as being
protected by inserting its name into an object specifying the access
rights. Then we doing the resolution of the request the first thing to
do would be to check this object to grant/refuse access to the method.
Something like:
1 import types
2
3 def grant(method):
4 method._protected = True
5 return method
6
7 def register_methods(klass):
8 for name in dir(klass):
9 attribute = getattr(klass, name)
10 if isinstance(attribute, types.MethodType):
11 if getattr(attribute, '_protected', False):
12 klass._protected[name] = 'protected'
13 return klass
14
15 @register_methods
16 class A(object):
17
18 _protected = {}
19
20 def toto(self, a):
21 print a
22
23 @grant
24 def tata(self, b):
25 print b
26
27 print A._protected
That way only the name is stored and the clash between inheritance and
decorators do not happen.
The issue with '_protected' being a class attribute is that when using
a multiple database set-up an installed module might change the
behavior of another behavior. This side effect has to be take into
account (I'll try to think about that after having done some
codereviews and GIS stuffs).
--
Nicolas Évrard
B2CK SPRL
rue de Rotterdam, 4
4000 Liège
Belgium
Tel: +32 472 54 46 59
E-mail/Jabber: nicolas...@b2ck.com
Website: http://www.b2ck.com/
I think such design works only for check at rpc level but I think for
workflow it must be done from any source.
Such design could be great to fill _rpc.
Anyway, I think decorator on function could work even with the
modularity because the idea is to protect the content of the method.
--
Cédric Krier
B2CK SPRL
Rue de Rotterdam, 4
4000 Liège
Belgium
Tel: +32 472 54 46 59