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

Reply via email to