Persistance CFC Generators

Last week a couple friends (Sim and Chris) and I were taking about persistence mechanisms and the benefits of each.  Obviously there's the inline SQL route, which is the more performant, and the most cumbersome to maintain.  At the other end are abstract persistence frameworks such as Arf! or Reactor which are designed for ease of use and maintenance, but not necessarily for speed or complex operations.  In the middle is the concept of ra static generator, which is basically a tool that'll write all your persistence code for you, based on your DB schema, but once written, it performs no management.  You have to write the generator to begin with, of course, but you can also customize the generaated code to match your application.

The question was what's the right solution.  Between the three of us, we decided that all three were.  The main app I work on uses a generator because performance is important.   Sim, on the other hand, did some prototyping with Arf! and decided that he'd just keep the backend for the production app, since it was performant enough.

It's an interesting puzzle, because the maintainability of a managed persistence layer is very attractive, but balancing that against performance can be difficult.  But there's a way to make the static generator method a lot friendlier that I wanted to discuss, because it's a little "weird", and can easily be overlooked (as I did for over a year).

Basically, what you do is use your generators as if they're a third party code source, and generate your CFCs into a vendor branch in your version control system.  Then you can easily maintain custom modifications to the generated CFCs (as almost invariably needs to happen), without it getting in the way of regenerating at a later time.  A good example is adding a field to an entity.  Add the field to the schema, regenerate to the vendor branch, and then merge the mods into your real codebase.

With a setup like that, the gap between a generator and a persistence framework is narrowed considerably, because you can effectively regenerate as often as you like (though it still requires a manual step).  But you needn't pay the run time cost of a framework, which can be important for heavily loaded applications.

Just wanted to throw that all out there as an idea to consider, and as another reason to make sure you're using some kind of version control for all your apps.

7 responses to “Persistance CFC Generators”

  1. Chip Temm

    I like the generated route myself and think that you raise an important concept in using SCM tools to manage merging manual changes to generated files into files generated after changes to the base templates. I have been working on a system to slurp UML diagrams and generate a persistence layer. You can find it at http://cfopen.org/projects/openmodel/ Unfortunately I haven't found much time to work on it of late as I have recently started a new job. What I need to do is to think about re-doing the templates in order to generate something with more momentum- maybe ARF as Joe is getting a lot of press these days.

  2. Kurt Wiersma

    From what I know doesn't Reactor generate code right when it starts up so it won't have a huge performance hit on your application after it starts up? If so that might make it more of a production solution then ARF (not that ARF is bad).

  3. Mike Kelp

    One thing I have considered that could pretty much work for any object based platform would be to generate objects into a set of base CFCs with an empty CFC that inherits the base and is where you would put customized code.

    Obviously the idea has a long way to go, but it does allow regeneration without needing as much merging work and keeps the developer in absolute control. There are a lot more pros and cons as I keep thinking about it, but I have considered implementing it on a small scale to see how powerful it would be.

  4. Barney

    To answer both Kurt and Mike, yes, Reactor does generate code once, and then use it until regenerated. It also generates empty CFCs for you to modify that extend the CFCs that actually contain the generated code. Upon regeneration, only the base CFCs are overwritten, leaving any custom code intact.

    The main problem with this is you can only tweak stuff at the method level. I.e. if you need to change behaviour of the generated code, you can only do it by wrapping or replacing a method. No finer-grained control is available. In many cases, that's sufficient, but not always. An example would be a entity property that has a different type than the field in the DB. No big deal to override the get/set pair, but the UPDATE and INSERT statements don't need to be totally rewritten, just that one fields needs modification.

  5. Doug Hughes

    Barney –

    Just so I understand, the only complaint you really have with Reactor is the inaccessibility of the base generated objects? My real answer to that is that Reactor is not intended to keep you from having to code stuff. It’s whole purpose is to reduce the amount of tedious, repetitive coding you’d otherwise be doing.

    Regarding speed, reactor shouldn’t have much more overhead in production mode than a typical factory CFC. There is a little overhead related to making the core CFCs database agnostic, but I’m working on that.

    Anyhow, I’d love any feedback you might have. Reactor’s not for everyone (nor for every project), but I’d like it to be as good as it could be.

  6. Barney

    Doug,

    My point was more that if you start mucking with the generated code that a framework produces then you lose a lot of the benefits of the framework (because you're invading the framework's black box). At that point, you're basically using the framework as a static generator, which is fine, but reduces the utility of having the framework to begin with.

    In PIER, I happen to tweak a lot of generated SQL, simply because machines are horrible about dealing with every edge case, so I don't even bother trying to program the generator to handle them. As such, any kind of automated solution would be more cumbersome than it's worth, but a static generator is perfect. Combined with vendor branches, it makes for a very easy to work with setup. That was my main point.

    Basically what I've got is a custom Reactor-like product that doesn't have the ability to do anything dynamically. It generates only when I tell it to, never automatically. It's also tuned to do some PIER-specific generation. I could easily have started with Reactor and customized (and saved myself a lot of work, no doubt, judging from the digging around I've done in Reactor), but unfortunately Reactor came a few years too late.

    I think Reactor (and Arf, etc.) are great products to have available to CF developers. They're just no a be-all end-all answer to persistance issues, and there are ways to make other techniques approach the ease of use those frameworks offer.

  7. mihaimm

    This is an excellent idea. And with SVN it actually works.