I was reading an InfoQ article on Composite Oriented Programming earlier on:
http://www.infoq.com/articles/Composite-Programming-Qi4j
I was interested in finding out whether anybody is currently using (or has used) the Qi4j framework at all?
How does it compares to using a traditional dependency injecti开发者_JAVA技巧on framework such as Spring for wiring classes together. Is the resulting object graph (based on mixins rather than classes) easier to deal with from a maintenance point of view?
Well, I've been using Qi4j myself for about a year now in a project. Once you get used to the power of mixins in your domain model, you'll be wondering how you ever managed without them before. In fact, I think the POJO method of creating domain models should be obsolete. It creates systemically unmaintainable code. Because the mixin/composite model is the important feature of Qi4j, rather than DI, there really isn't any comparison on the Java platform.
As for Bozho's concerns: when it comes to declaring mixins there are two separate cases. In entities, i.e. the domain model, an interface will typically only have one implementation, and you would in fact want to actively avoid having several implementations for maintenance and readibility reasons. So I declare the implementation straight in the interface. But, it is only a default, which can be overriden by the composite if you want to. I've so far never found a need to do so.
The other case is services, which is quite different. For many cases there will be only one implementation, and so declaring the implementation in the interface is again quite ok. But, there are far more cases with services that you want different implementations, and so for those cases you simply declare the mixin in the concrete composite type declaration instead. So both styles are possible, and recommended for various reasons.
As for casting, being able to cast an object is a bonus, not a problem. If you don't have casting from one role to other roles you're going to have to be quite inventive to get around it, which probably won't make your code simpler.
Kabram; Integration with JPA has been attempted more than once. If we have two overlapping but not fully compaible technologies, you will end up only with the intersection of possibilities. So, there are two basic approaches to integrate Qi4j with JPA.
To limit the JPA options, so that the much more flexible data structures that Qi4j needs can fully be used. Doing that makes no sense, as going directly to SQL is much more performant, and that is what we chose.
To limit Qi4j's data model to fit an existing JPA data model. Doing this will take away most of the advantages of why people choose Qi4j in the first place. We have therefor decided not to spend the cycles to do this. However, I think the extensibility of Qi4j is good enough to do such integration without hacking in the Core Runtime, and simply create an EntityStore.
Hopefully not too late on this discussion: But this is how I see it.
First of all I like the ideas(Composites, Mixins, Assemblies) behind Qi4j but am held back by the complexity of using it.
The concepts there should be part of wider umbrella such as a language(such as Java) than a framework, and should be easier to use.
I ran into a problem 2 years ago that left me wishing I had something like that then.
I wanted 3 different behaviors that could be reused on a set of beans. Some beans used all of them others any combination of two. I did not want to put all of them together in a class because it did not make sense. On the other hand I was constrained by the fact that I could not have multiple inheritance. The obvious solution: use an interface; which means implement the thing that many times. I remember complaining to a co-worker about the fact that I hope I had a way of providing a default implementation for an interface. This to me is a simple OO concept that allows one to reuse behaviors in a cleaner fashion. And if it is the case where you need something different than the default implementation than implement that one. That would make more sense and would not brake any natural law that I can see.
So to answer your question I think this Qi4j's concepts allow you to think OO in cleaner fashion, where Spring is more structural and not even comparable conceptually. You could be thinking dependency injection and not be thinking spring and be thinking Qi4j and not be thinking dept injection.
After reading the first part of the linked article, I didn't like two things:
- the implementations are defined in the interface (using
@Mixins
) - what if these should be mocked, or implementations changed? - requires casting
Having no experience with Qi4J, I can't say how this turns out in practice, but it doesn't feel good.
When I read through the Qi4j in 2 minutes, 10 minutes etc. tutorials (the last one is incomplete), the one obvious question that came to mind was how do I integrate this with JPA/Hibernate managed entities? I would like to see a solution that seamlessly integrates with JPA. No JPA implies no Qi4j adoption in my opinion. I'd love to see an article by the author(s) that shows integration with JPA and Spring, two things that have deep penetration in the Java Enterprise world. If the integration is straightforward, rapid adoption will follow.
Bozho; For you question about Mixins being declared on interfaces,
The Mixin implementations can be overridden, either in "higher" (i.e. sub-) interfaces, as the seek order for implementations happen "per method" and goes from the declared interface, left-to-right, and then to each of the super interfaces (also left-to-right in the extends clause). OR, you can override in the Assembly of a composite;
public void assemble( ModuleAssembly module )
{
module.entities( Account.class ).withMixins( LdapAuthenticatorMixin.class );
:
}
where the LdapAuthenticatorMixin may be abstract and only override a single method.
精彩评论