Jeff Wild had a few comments about my Jakarta Commons post. Good stuff. It got me thinking though. The Jakarta Commons Collections library allows you to combine predicates, transformers, and closures via utility classes. And that's where my head was because my problem at work needed to have the predicates combined in different ways and I didn't want to pollute the public API of my class unneedlessly with each special case. But, Jeff made an excellent point. Do I want the clients of my code to have a dependency on the Jakarta Commons Collection library? What's a developer to do?
Then, it occurred to me. I should just make my collection of objects it's own domain specific object that I can then send the proper messages to. Thus, instead of a Collection object, you have an AccountCollection object that wraps around an ordinary collection. And this is where I can stick the "active" method. It's not static and reads so much better.
But, what about being able to combine predicates, transformers, and closures? I didn't discuss that in the original post. My post was inspired by a problem at work where I needed to combine different predicates on in-memory objects. So, it would be nice to have a "where" method that selects a subset of my new AccountCollection. I could even make the "where" functionality available in an abstract collection so that future domain specific collections could enjoy its benefits. But, to combine predicates, it's still ugly with all of the static utility method calls. Yuck. OK, what if I write my own abstract predicates, closures, and transformers that can chain themselves? For instance, you could have "and" and "or" methods to predicate; "then" for closures; and "as" method for transformers. Underneath the covers, could simply call all of the static utility methods. I get readability back (getUser().getAccounts().active() and getUser().getAccounts().where(Account.BY.olderThan(DAYS_90).and(Account.BY.active())).
I like this approach better and it keeps the knowledge shared. You could put the most frequent queries in the the domain specific collection, but still leave it open for future extension of less used queries or transformations.
Yet, again, this approves the more you move functionality down and spread responsibilities around, the easier your code becomes to read. Thanks to Jeff for making me thinking of where my solution was ugly.