Since I added Hibernate support to CF Groovy, I've been using that for pretty much all new development. Oh, how nice it is. The perm-gen issue is still lingering, but if after a few projects, I've realized that you don't actually end up touching your persistent entities that much, so it's not as big a deal as it seemed it would be. Most of the work on those is done up front, laying out properties, relationships, and various helper methods and psuedo-properties.
Yes, my apps suffer from what Fowler has dubbed an "anemic business model", but I don't have great issue with that. It's a concious design decision, not an anti-pattern that has cropped up without my knowing. It's specifically driven by the non-CFML nature of the persistent entities, and as such they're not really full-fledged business objects. Instead, they're more just value objects (or data transfer objects) both inside the app and between the app and the database. I'm also a big fan of simple, and while I'm definitely not following the all powerful "best practices", I tend to weight simple as a higher priority than a lot of people.
I've also seen a signficant shift of Groovy code from the service layer up to the web layer, which is something I wasn't expecting. My initial thoughts were that the web layer would stay almost entirely CFML, and the Groovy would be used for the backend code and interfacing with Hibernate. The views are still all CFML, but my controllers are growing Groovy snippets all over the place, while the service layer is mostly just interfacing with CFML APIs from the Hibernate plugin, actually using Groovy for very little.
One little piece that I have't posted yet is a "port" of my TransactionAdvice CFC for use with the Hibernate functionality of CF Groovy. The logic is exactly the same as the original, just no ability to set an isolation, and it requires a reference to the Hibernate plugin instance. Download here: HibernateTransactionAdvice_b4173.zip.
I'm curious: given that Groovy is slowly infecting the upper layers of your applications, why not write richer business objects in Groovy, i.e., instead of adding Groovy logic in the service and controller tiers, why not push that down into the business objects themselves?
Like you, I'm liking Groovy more and more (and I'm only halfway through the Groovy Recipes book!).
Sean,
Because I'm still figuring out where everything best fits. ;) Writing whole classes in Groovy precludes the use of CFML, which is a significant ramification. CFMAIL's really handy compared to managing a JavaMail interface manually, for example. Much of what I'm using Groovy for is more akin to using CFSCRIPT – an alternate/simpler/richer syntax for non-CFML-specific programming tasks. Even simply things like ["one", "two", "three"].each{ /* do something */ } can be quite handy, and with the lack of overhead entering and leaving the Groovy runtime, there's little reason not to use that stuff, even if it wasn't the real point of the implementation. Another problem is that while CF can call Groovy, Groovy can't call CF. So once you cross into Groovy-land, you're stuck there.
The "Groovy logic" in the service and controller tiers is really service and controller logic. It's not that I'm spreading my business logic up the levels, more just that I'm using it in places I hadn't really expected to initially. When I was first building the whole framework, I was really envisioning a all-CF web/controller layer, a CFC-with-embedded-Groovy service layer, and then a Groovy-based persistence layer. But in practice I'm finding CF-with-embedded-Groovy web/controller, CFC service layer, and Groovy-based persistence.
At this point, I don't think implementing the service layer in Groovy is the right choice. Sure, I'm using bits of Groovy (both snippets and classes) to accomplish things, but the apps are still CFML apps, and I don't want that to change. If I were doing more of a JEE-style of development, using Spring, Hibernate, and Groovy together to build backends would definitely be something to consider, but at this point, I want my CFML. I'm lazy, I don't always have a full IDE (emacs over SSH, anyone?), and the "problems" that CFML has aren't nearly as big a deal with Groovy for the entities. If I were working on "real" projects where there was budget, timelines, resources, etc., I'd undoubtedly make different decisions.
This is something I have been pondering for a while, as I've been toying with the idea of enabling Transfer to generate Java and/or Groovy objects.
What would be very handy is some transparent means to enable you to write your services in CFCs, but keep your business objects in Java/Groovy, and still be able to inject those CF CFCs into your Groovy/Java business objects, (Hopefully) in a very seamless manner, through the use of CFCProxy.
I haven't worked out all the details, but that way you could keep the RAD nature of CF, but still be able to push it into your Business Objects (much like I do now in CF)
Mark,
With CFCProxy, you'll have to invoke some facade CFC that then delegates back to the "real" CFC instance, right? It's been a while, but I don't recall being able to create a proxy for an existing instance. I supposed if it's all generated it's not as much of a deal, but there's still performance implications.
I'd love to see a good way to write more with Groovy, but not lose the CFML nature of the application. Both have great strengths, but CF rather bastardized the many languages/one JVM model, which makes it hard. To be fair, Groovy's done some of the same thing with it's MetaClass infrastructure, but if you don't use it (i.e. declare normal methods, fields, etc.) your Groovy objects are "normal" Java instances at runtime. With CF you don't have that option.
Yeah.. the way to have some sort of generated dynamic proxy would be ideal (that was the thought I was having), rather than having to invoke CFCProxy directly.
There are performance implications, but I guess you have to pay a price somewhere if you want to hook CF into it.
Barney,
Do you work alone, or with a very small team? I ask because one of the implications I'd see here is a divergence among team members and their ability to maintain these applications. Without a strongly led effort to having the appropriate people learn groovy, I can see how you'd quickly get stuck in a situation where you're the only one who can maintain the apps. And that's no fun. In addition, politically, what happens when you introduce this and you hit a lot of resistance from other team members who simply have no interest/need at all to learn this new language? On top of that, there's the director/VP level to deal with. So you're selling up and selling down.
On smaller teams with really agile people and leadership, this sounds great. In larger IT departments with the whole gamut of skills… yikes.
Again, I'm asking only because I'm curious if you're yet in a position where you're trying to introduce this and I'm wondering how you're doing so, or if this is just a one-man-show at this point.
Thanks!
marc
marc,
I'm only using CF Groovy and Hibernate for personal projects, where I, surprise, work alone. ;) The framework was developed solely on personal time as well, and with basically zero hope of any at-work integration, at least where I work now.
At work we do a lot of interfacing with Java, and the CF Groovy integration would be very valuable, but the boss doesn't want to adopt any Groovy. So we hack together all kinds of interesting stuff in CF, and occasionally shell out for some real Java (and all the compile, restart, etc. fun it brings). One really good example is getting a java.util.List of content objects back from the CMS and wanting to sort the list. You need a Comparator. So instead of dropping a <g:script> tag with a one-line Comparator in there, we build a Java class, compile it, create a JAR, add it to the application's classpath, restart the container, and then see if it works. It's retarded.
So we use CF (RAD, dynamic, no compile, limited in scope) and Java (non-RAD, static, compile, virtually unlimited). Groovy (RAD, dynamic, no compile, virtually unlimited), on the other hand, is off the table. It's a silly political distinction, but such is life. But more to your point, I work on a team of 11, 7 of which are full-time developers (the rest are operational support people who write a lot of the view layer based on customer needs, and generally help the customers use the applications), and we all write both CF and Java. So Groovy would not be anything of a stretch from a technical side.
My team are mostly CFers from the ground up with some folks having more Java experience than others and some folks having more Flex experience than others. So far, everyone is liking their exposure to Groovy and building the entire backend for some AIR applications in Groovy and Java, leveraging Spring and Hibernate, is proving to be a fun and interesting experiment that will guide our technical decisions moving forward.