You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@isis.apache.org by "Oscar Bou (JIRA)" <ji...@apache.org> on 2018/01/08 12:57:00 UTC

[jira] [Comment Edited] (ISIS-1807) Wrap Domain Entities by default

    [ https://issues.apache.org/jira/browse/ISIS-1807?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16316256#comment-16316256 ] 

Oscar Bou edited comment on ISIS-1807 at 1/8/18 12:56 PM:
----------------------------------------------------------

Hi, Dan.

Yes, all our codebase is plenty of "wrapped" calls. It's mandatory according to our internal standards to always invoke inside a "wrap" call any setter and action invocation.

Fully agree that what we are trying to guarantee are those trust boundaries, but assuming they're directly related (and defined, scoped) to a given Domain Entity and associated sub-entities (i.e, Aggregated Root in DDD terms).
So every invocation from one Service or Domain Entity to actions on another Domain Entity or Services (or setters from a Domain Entity) are always wrapped to ensure invariants protection through the domain logic embedded:
* on the action implementation
* the "modifyXXX" method from the default programming model
* or the domain event handlers.
basically ...

Regading, View Models, it's a related case that it's worth considering. Wrapping invocations could be a way to ensure its immutability. For example, invoking a setter would throw by default an Exception if not invoked inside a "WrapperFactory.wrapSkipRules(...)" call. 


was (Author: oscarbou):
Hi, Dan.

Yes, all our codebase is plenty of "wrapped" calls. It's mandatory according to our internal standards to always invoke inside a "wrap" call any setter and action.

Fully agree is that my intent is to guarantee those trust boundaries, but assuming they're directly related to a given Domain Entity and associated sub-entities (i.e, Aggregated Root in DDD terms).
So every invocation from one Service or Domain Entity to actions on another Domain Entity or Services (or setters from a Domain Entity) are always wrapped to ensure invariants protection through the domain logic embedded:
* on the action implementation
* the "modifyXXX" method from the default programming model
* or the domain event handlers basically.

Regading, View Models, it's a related case that it's worth considering. Wrapping invocations could be a way to ensure its immutability. For example, invoking a setter would throw by default an Exception if not invoked inside a "WrapperFactory.wrapSkipRules(...)" call. 

> Wrap Domain Entities by default
> -------------------------------
>
>                 Key: ISIS-1807
>                 URL: https://issues.apache.org/jira/browse/ISIS-1807
>             Project: Isis
>          Issue Type: Improvement
>          Components: Core
>    Affects Versions: 1.15.1
>            Reporter: Oscar Bou
>             Fix For: 2.0.0
>
>
> This way, all hide/disable/validate constraints, and other constraints/invariants forced through actions, are always ensured by default.
> This will require to wrap by default:
> * New Domain Entity instances / objects (ie, changes on FactoryService).
> * Domain Entities returned by queries (ie, changes on RepositoryService).
> Users might disable this new default behaviour through configuration, as some projects can prioritize performance (avoiding wrapping invocations) vs Domain constraints/invariants enforcement.
> ~~~~
> Dan's notes:
> I'd like to refine the concept of wrapping while implementing this ticket.
> The idea of wrapping was originally to allow the UI to be simulated within integration tests.  The intent of this ticket is to formalize the idea of the same set of validations being done automatically between programmatic interactions from one service/entity to another service/entity.  
> So, the more general concept (common to both UI/domain interactions and domain-to-domain programmatic interactions) is one of _trust boundaries_.  If there is no trust from the calling client to the supplying service/entity, then that interaction should be wrapped.
> However, the wrapping model as it currently stands is a little bit too UI/domain oriented, in that it has both hidden AND disabled as well as validate phases.  From the perspective of a programmatic domain-to-domain interaction there's no meaningful distinction between the hidden and disabled constraints: they both mean: "that object isn't in a state to be called".  In other words its a pre constraint that is not satisfied.
> The other aspect here is that I can imagine that there are actions that we would like to allow to be made programmatically (ie through a wrapper) but which shouldn't be part of the UI.  In other words these actions form part of the programmatic API of a module, just not part of its UI.
> Putting all this together, I propose that we slightly change the meaning of wrapping (though we'll keep the current implementation too for backwards compatibility), namely that by default wrapped object will check the disable and validate phases only, ie it will _not_ check the hidden phase.  This allows such actions to be indicated as hidden (probably using @ActionLayout or .layout.xml or security) but still able to be called programmatically.  The disable phase = pre check.
> We could define the following terminology:
> - "default" wrapping : as described above, checks only disable and validate, not hidden
> - "strict" wrapping - for backward compatibility, also checks hidden first
> We could define a configuration property:
> isis.runtime.wrapping=default | strict | none
> with "default" wrapping being the default if not specified.
> In terms of the programming API, the WrapperFactory#wrap(...) will obviously be less important than it was, because by default objects will be wrapped.  For backward compatibilty, I think this should continue to create strict wrappers
> The wrap(...) method is also overloaded, with wrap(ExecutionMode).  We can extend this enum:
> - EXECUTE - (existing) returns a strict wrapper
> - SKIP_RULES - (existing) skips applying the hidden/disable/validate rules
> - NO_EXECUTE - (existing) applies hidden/disabled/validate, but does not execute
> - DEFAULT - (new) returns a "default" wrapper, applies only disable/validate but not hidden
> (new:) if the object passed in is already wrapped, then it should be replaced with a wrapper with the specified mode.  Prevoiusly this was a no-op, I think.
> The unwrap(...) method is unchanged.



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)