Hey guys,
We ran into some serious code tangle issues in StreamFlow with regard to
our entity code, and as I analyzed the issue using Structure101 I think
I found why, and what to do about it.
Basically, entities have structure. Yeah, we already know they have
mixins, which assumes internal structure, but there's more to it than
that. The DCI paradigm suggests that we think of objects from two
perspectives: what-the-system-is (passive) and what-the-system-does
(active). The first is a structural concern (nouns) where the latter is
an interaction concern (verbs).
In the first category you will find concrete things (Organization, User,
Project, Task in my case) whereas in the latter you will find roles and
how they relate (Assignable, Assignee, Authentication, Delegatable,
Delegatee in my case). Mixins in the first category also tends to have
methods like "create","add","remove", which are used to build a
structure of entities. They don't "do" anything, apart from creating
structures. Modifying associations, mostly.
The category contains mixins with all interactions, with objects being
represented by roles. Interaction methods will rarely change the
structure of an existing object graph, just "do something" with it.
Dependency-wise, the structure, what-the-system-is, may only refer to
concepts within the structure. An Organization may refer to a Project,
but a Project may not refer to an Assignable, since that would be mixing
structure and interactions. The consequence of this is that interactions
can be used on any object graph that fulfills the roles, and may have
nothing at all to do with Organizations, Projects and Tasks, as is the
case in my project. Also, as DCI predicts it becomes possible to "read"
an interaction algorithm without looking everywhere in the code. If I
want to find out everything there is to know about "assignment" I can
read that interaction+roles, and I'm done. I don't have to look in the
entity structure that "implements" this interaction. Similarly, the
interactions may only refer to interaction concepts, even though
structure and interactions both coexist within an actual entity. An
interaction refers to "Assignable" instead of "Task", and "Assignee"
instead of "User". The Task entity Composite interface refers to both
Assignable and Task interfaces though, as it is the "glue" between the
structure and interactions. For example:
interface TaskEntity
extends Task, Assignable, Delegatable.
{
}
If an interaction requires an entity to implement a role that needs
access to the structure, then this is done in the "glue" layer (same
package as TaskEntity above). So structure refers to structure,
interactions refers to interactions+roles, and then actual entities bind
things together, including implementing interaction roles using the
structure. Then there is no tangle, as structure and interactions are
separated yet coexisting without explicitly knowing about each other.
Compared to current "best practices", the structure would be comprised
of our anemic POJO domain model (the create/add/remove methods), and
then the interactions would be implemented by transaction scripts that
work on these graphs. They would most likely be completely meshed
together though, with interactions referring to "Task" instead of
"Assignable", so there's no way to read the algorithms, and no way to
compose algorithms. There would also be no logical place to handle
polymorphism.
To me this is a big step forward, and shows just how important it is too
have mixins as a conceptual tool, and how to use them properly for
different things.
/Rickard
_______________________________________________
qi4j-dev mailing list
[email protected]
http://lists.ops4j.org/mailman/listinfo/qi4j-dev