My Fusebox 2005 Presentation + Sample App

Rather than take the time to write up documentation on the sample app that accompanied my Head First Mach-II presentation, I thought I’d just make these materials available and deal with any aftermath in due course 😉 So here’s the goods! Enjoy!

Comments

good presenttaion. you are good presenter and information is complete and useful.

Posted by Marishi Matawan @ 4/17/07 3:04 PM

Linux Torvalds on programming”

“The power and flexibility of a programming language is inversely proportional to the number of development frameworks that surround it. Note that in traditional [C/C++] programming, there are almost no extant frameworks, while many of the newer, more stylish languages spawn frameworks in a never-ending stream, hoping to someday overcome the inherent weakness and impotence of the language itself.” (From the Helsinki LUG, 08/2004)

’nuff said.

Posted by Irving Goldstein @ 4/17/07 3:04 PM

“Linux” (I assume you meant Linus) has also said that he doesn’t believe in specs. Do you subscribe to that philosophy as well?

Posted by Matt Woodward @ 4/17/07 3:04 PM

The lady dost protest too loudly. If CF did everything it was supposed to do, you wouldn’t need to bolt on a panolpy of ersatz frameworks in a vain struggle to make a weak system ready for prime-time.

’nuff said.

Posted by Irving Goldstein @ 4/17/07 3:04 PM

The lady? Interesting. OK, so apparently by your argument (and by extension “Linux’s” as well), Java is a weak language and not ready for prime time because many Java developers find a huge amount of value in using something like Spring?

Posted by Matt Woodward @ 4/17/07 3:04 PM

Well, the thing is, the ONLY reason we have CF is for web application development. You don’t write standalone apps, embedded apps, desktop GUIs, or distributed enterprise systems in CF.

The main reason CF exists is to provide a tag-based way to program web pages, and if you need to select from a buffet of frameworks to get the job done, that’s a defeciency in the language.

Not knocking your frameworks, mind you, but hopefully suggesting that CF has fallen down on the job just a little bit…

Posted by Irving Goldstein @ 4/17/07 3:04 PM

Then apparently Java has as well, because many of the Java frameworks are specifically designed for Java web app development. I humbly suggest that you don’t understand what frameworks are all about and what problems they solve if this is your opinion of frameworks.

Posted by Matt Woodward @ 4/17/07 3:04 PM

Well, using Java as a point of comparison is unfair to CF, since Java does a heck of a lot more (and in a wider variety of situations) than CF does. If Java needs a X framework to function well in environment Y, so be it.

CF, however, is generally ONLY used for web development applications, and the vast majority of the framework smorgasbord deal with rectifying its shortcomings in that very area–supposedly its area of greatest strength (you said as much yourself, with the key phrase, “what problems they solve.”)

With that decided, the question becomes: Why the variety of frameworks? I mean, come on people…”Model Glue?”

Posted by Irving Goldstein @ 4/17/07 3:04 PM

First, you clearly don’t know much about ColdFusion and the associated frameworks. It’s not about rectifying CF’s shortcomings (of which it has precious few in the web development arena), it’s about … aw heck, not sure why I’m even bothering. Go back to your framework-free C++ development and feel superior to we lowly web developers if that’s what makes you happy. And tell Linux I said hello.

Posted by Matt Woodward @ 4/17/07 3:04 PM

Well, I have to admit I’m a little embarassed. I took some time to read your blog and your comments, and more about some of the great things people are doing with frameworks (including Match-II) and I have to admit I’m impressed.

Sorry for wasting your time–I stand corrected–Carry on!

Shalom!

Posted by Irving Goldstein @ 4/17/07 3:04 PM

Matt, I just read through the presentation ppt, and my impression is that you must be an awesome presenter 😀

Unfortuneatly distance, time and finances prevents me from attending all the cool conferences over there, but I have a goal to be at Scotch on the Rocks next year, and I will bug Andy about trying to get you there 😉

And I really look forwards to the new m2 release and the new documentation. Knowing you had a hand in it creates expectations.

Keep up the good work.
Regards from Norway.

Posted by Trond Ulseth @ 4/17/07 3:04 PM

Thanks Trond–we’re looking forward to the Mach-II release as well, which should be VERY soon. I’d love to come to Scotch on the Rocks!

Posted by Matt Woodward @ 4/17/07 3:04 PM

Matt,

A lot of your previous threads on OO development helped me get started in understanding theories that I later applied to Mach-II and CFC based Fusebox4.1 development. I like your teaching style.

That being said I also wanted to thank you for posting your Fusebox Conf Presentation. Time/Distance/$$ have always prevented me from attending all the various CF conferences and I have always looked forward to viewing the various presentations. I wish many of the other presenters whom I greatly respect would have made the presentations available to those of us that couldn’t catch them.

Thanks again!
-A

p.s. What happened to cfopenbb? Is it dead?

Posted by Ali @ 4/17/07 3:04 PM

Matt,

I downloaded the sample code you provided, but the app didn’t work as-is.

I had to modify the mach-ii.xml, and add the tag, and a closing tag for things to work.

Another thing is that the event-handlers that do ‘s don’t work.

Do I need to install the redirect filter for those to work?

Thanks,
Ali

Posted by Ali @ 4/17/07 3:04 PM

Ali–chances are this is because this was built for Mach-II 1.1.0. Sorry about that. 1.1.0 is scheduled for release later this month.

Posted by Matt Woodward @ 4/17/07 3:04 PM

Thanks Matt.

The only other change I had to make was changing “redirect” to “announce” and then all works perfectly.

Ali

Posted by Ali @ 4/17/07 3:04 PM

Right–redirect is a new feature of 1.1.0. I’ll have a lot more to say about that very soon!

Posted by Matt Woodward @ 4/17/07 3:04 PM

Fusebox and Frameworks 2005 Wrap-Up

The Fusebox and Frameworks 2005 Conference was this past week and as always, Michael and all the folks at TeraTech put on a first class event. It was fantastic to get the opportunity to talk to attendees about Mach-II and the exciting stuff we put in the 1.1.0 release (available very soon!) as well as what we have planned for future releases. There’s a ton of very exciting stuff going on with CF frameworks in general so here’s my roundup of what I found most interesting at the conference.

 

Mach-II:I gave my Head First Mach-II presentation twice (PowerPoint and sample app code available soon), led a Mach-II Birds of a Feather session, and Ben Edwards gave a Mach-II Under the Hood presentation, so Mach-II had a strong presence at the conference. I got comments from lots of attendees after my presentation that they were now no longer “afraid” of Mach-II, and current Mach-II users were very excited to see all the activity going on in the Mach-II community these days, so this was fantastic. With the 1.1.0 release we’re going to have a lot more and a lot better documentation, and when I have time I’m going to do my presentation as a Captivate demo, so you should have some excellent resources in the very near future.

I think the thing to remember about Mach-II is that if you put in the time to learn OO (which is a MUST these days!) then Mach-II is actually VERY simple to learn. It’s based on some very basic principles and once you get the hang of those it’s off to the races. Mach-II is a mature, stable framework that’s proven itself in numerous very large applications so it’s definitely worth a look if you haven’t checked it out yet.

Spring, ColdSpring, IoC, and AOP: I know, lots of acronyms in there, and I’ll be saying a lot more about all of this in the future. Max Porges gave a GREAT presentation about using Spring with a Java model in ColdFusion applications. At its most basic level, Spring is a framework built on the idea of Inversion of Control (IoC), aka Dependency Injection, and also supports Aspect Oriented Programming (AOP). This is extremely powerful stuff based on the simple idea that your model should be completely unaware of your framework, and also that each object in your model should be as unaware of other objects in your model as possible.

If that sounds great but you’d prefer to build your model in CFCs instead of Java, you’ll definitely want to check out Dave Ross’s ColdSpring as well as Chris Scott’s ColdSpring AOP. Dave and Chris are working together (and quite obsessively, I might add!) on both of these initiatives and coming up with some amazing results. I talked with them pretty extensively at the conference and really like where they’re going with things. I’m going to be using ColdSpring on an upcoming project so I’ll have a lot more to say about it in the not-too-distant future.

Fusebox: Fusebox is of course alive and kicking, and even though I was never a fan in 3.0 days, Fusebox 4.1 has a lot of nice features and is definitely worth checking out, particularly if you don’t have much OO experience. The very cool thing about Fusebox is that you can build extremely well-organized, easy to maintain applications using procedural principles, then move into using an OO model with Fusebox, and at that point if you’re looking for something more purely OO, you’ll more or less have the skills you need to move into something like Mach-II. I also love all the fantastic tools available for Fusebox, and the fact that you can very easily farm out discrete portions of the application development to people who don’t need to have any idea about the application as a whole. This is powerful stuff for team development, particularly for a geographically disbursed team.

Model-Glue: Joe Rinehart gave some great presentations on his Model-Glue framework, which has been described by many people (to me anyway) as a kind of hybrid between Fusebox and Mach-II. It uses many of the same principles as Mach-II but could be a bit more approachable if you’re coming from a non-OO background. Model-Glue is getting a ton of attention these days, Joe’s an extremely sharp guy who works very hard on it, and given the adoption as of late you’ll have plenty of help getting into it. The 1.0 version was just released and is definitely worth a look.

Tartan: Paul Kenney’s Tartan Framework is a ColdFusion framework designed around Service Oriented Architecture (SOA). The basic idea between SOA is that components of your applications should be extremely loosely coupled (always a good thing!), and to achieve this SOA is based on a service layer to which your application components make requests and from which your components receive responses. If you’re thinking “web services” at this point you’re on the right track. Tartan can be an extremely powerful addition to other frameworks such as Mach-II, particularly if you want to do something like create a Mach-II application and put a Flash or Flex front-end on it, which Mach-II wouldn’t really be able to accommodate on its own.

The onTap Framework: S. Isaac Dealey’s onTap Framework has been around for quite some time, and I had the opportunity to hear him present on it several times back when he was a member of the DFW CFUG. My own take on onTap is that it’s based on the idea of automatic execution of filepaths, and it’s not entirely dissimilar to the way Fusebox approaches things, albeit with less explicit configuration of things. (Isaac, please correct me if I’m totally off-base here!) The most powerful aspect of onTap is the huge API/function libraries Isaac has included in the framework; think Ruby on Rails for ColdFusion. Automatic database tie-ins, automatic form generation and validation, really slick HTML libraries that make building slick DHTML interfaces dead simple … there’s lots of stuff in here to make your life easier.

Other Frameworks, Methodologies, and “Non-Frameworks”: As always conferences get extremely busy, so in some cases I found myself caught up in conversations and missing some presentations I initially wanted to attend. Neil Ross presented on his framework TheHUB but unfortunately I missed that session. John Paul Ashenfelter presented on Ruby on Rails, which was admittedly a bit bizarre given that this was a CF conference. I missed the presentation but from what I heard it was full of the superlatives that seem to be part and parcel of the Rails community. Not that I think Rails is a bad idea necessarily, but it certainly isn’t the silver bullet they make it out to be, and regardless of anything else it’s still Ruby at a language level which I think would be a hard sell in a corporate environment. (Just my opinion.)

Since it’s been discussed to death in other blogs I’ll leave my comments about the “non-framework” contingency of one that was at the conference to a minimum. Let’s just say I had an Emperor’s New Clothes moment or two during discussions and presentations of this ilk.

All in all it was a GREAT conference, and definitely shows that the ColdFusion community is at a tipping point. The days of CFers not knowing what OO is and being aware that they need to gain these skills are coming to a close, and with the wealth of world-class tools that are in the works, we’re soon going to have a set of enviable tools at our disposal to build powerful, flexible, maintainable ColdFusion applications in ways we never thought possible even as recently as three years ago. It’s an exciting time to be a ColdFusion developer!

Comments

(Isaac, please correct me if I’m totally off-base here!)

Nope, you’re pretty well on-target. That’s the angle I’ve been promoting for a while now.

Although I do also like to think that there’s a measure of flexibility in display, data access (persistence) and in the controller that’s not generally available with other frameworks — i.e. in Mach-II or Fusebox, an event-handler or a fuseaction must be explicitly told about any “plugin” applications which might affect the page-view (or functionality) of that request (xml config).

I guess you could say that the onTap framework uses a form of IOC (because it turns that config on its head/side) — if a plugin affects views or events (as opposed to simply adding a service), it must be at least moderately aware of the events for which controller code is injected, but not vice-versa. The blog for instance deletes a blog when its owner/author is deleted.

Posted by ike @ 4/17/07 3:04 PM

How Much Should Objects Know About Themselves?

This question came up in our CFUG meeting last month when I gave a CFC-101 presentation, but I was reminded of it again today while reading this article about Service-Oriented Architecture. Here’s the pertinent quote that caught my attention:

“The idea of SOA departs significantly from that of object oriented programming, which strongly suggests that you should bind data and its processing together. So, in object oriented programming style, every CD would come with its own player and they are not supposed to be separated. This sounds odd, but it’s the way we have built many software systems.”

In the context of the discussions we had at our CFUG meeting, this specifically came up when I was discussing the bean objects in the sample application I built. Several people thought they seemed too simple, and that I was leaving a bunch of methods out of the beans for the purposes of illustration. The beans actually were relatively “real-world” examples albeit limited in the number of attributes they contained. Some people were wondering where the view() or display() methods were, and how the data in the beans would actually get displayed, which is a rather fundamental error in logic (IMO anyway) with respect to how much objects should really know about themselves.

 

This debate actually ties in directly with the quote from the SOA article. While on the surface the quote may seem correct, there is something a bit off about it to me. In OOP we of course say that an object’s methods and its data are both contained within the object; this is a hallmark of OOP and one of the features that most distinguishes OOP from procedural programming. What isn’t so cut-and-dry, however, is exactly *which* methods should be contained within the object. Where does it make sense to start taking methods out of the object and create another object to act as a service layer?

Using the example from the article, should a CD object know how to play itself? Some would say yes, citing the self-contained mantra of OOP. I, on the other hand, would likely say no, a CD shouldn’t know how to play itself, any more than I would say a Person bean should know how to display itself.

Why would I say that? Because to me if you take the notion of self-contained objects too far, you’re breaking two of the other tenets of OOP, namely tight cohesion and loose coupling. If a CD knows how to play itself, that may be taking things one step too far because while all CD objects get played the same way, what if you want to feed your CD object to a different type of player in the future? Now obviously in other cases you *do* want to have polymorphic methods to handle things like this, so in the classic Shape object example, you might have a draw() method that gets implemented differently for a circle than it does for a square.

Let’s think about the CD again for a minute. Should a CD, LP, and cassette object each inherit from a single parent and have polymorphic play() methods? Or would it be better to have the media objects be just a bit more ignorant of themselves and have a service-type object, such as a Player, handle the play() method based on the media given to it?

As with so much in OOP, the answer is “it depends.” In the case of something like a Person bean, if you have a display() method within the bean itself you’re severely limiting its usefulness and the overall flexibility of the bean. Better to have a slightly more dumbed-down bean that can be used by multiple front-ends through a service architecture of sorts.

At any rate, this thought came back to me while reading this article, and it’s something we have to be mindful of as we build object-oriented systems. There are no hard-and-fast rules but certain ways of doing things make more sense than others, and we should always be mindful of making our objects as reusable as possible. If you want to display a Person in more than one way, or you want to play a CD on more than one type of player (e.g. standard player vs. computer drive), then consider dumbing down your objects a bit and creating a service object to handle things. This can make for a far more flexible system than can more easily be expanded in the future.

Comments

I don’t think a CD should know how to play itself. I want to be able to transfer it from my home stereo to my car. I want be able to rip it into MP3s. But the purpose of a metaphor, as Martin Fowler says, is not to give you the answers, but to help you figure out what questions to ask. A CD can be heard through headphones or a car stereo. Can your bean be viewed different ways? Can its data be extracted and reencoded in a new format?

Posted by Patrick McElhaney @ 4/17/07 3:04 PM

Thanks Patrick. The way I think of beans is no different than what you’re saying about CDs. The beans hold the information, but what’s done with it is not prescribed by the bean itself. So long as the bean provides methods to get at the data it contains, it doesn’t know or care what’s using it and how it’s getting displayed, which in my mind is the best way to keep it flexible. If the bean is generic I can drop it into an HTML front-end, a Flash front-end, or even drop it into a Flex application without any changes to the bean itself.

Posted by Matt Woodward @ 4/17/07 3:04 PM

That SOA quote is absurd and terribly misleading! Even in the purist OO world, we should recognize that a CD player exists and has many variants. Our "real-world" model should lead us to somehow inserting a CD object into a CD player object with the knowledge that a CD does *not* know how to play itself – that’s the job of the CD *player*. It’s exactly this sort of nonsense that can get OO a bad name because it’s used as (bad) justification of why OO doesn’t "work"…

Posted by Sean Corfield @ 4/17/07 3:04 PM

Thanks Sean, that’s why I posted the quote–seemed to me to be at best a misunderstanding or at worst a misapplication of OO principles as a means of attempting to illustrate an absurdity of OO that doesn’t exist. If there actually is a system designed as the SOA quote outlines I’d argue it’s not a *well*-designed system and certainly shouldn’t be taken as an example of OOP.

Posted by Matt Woodward @ 4/17/07 3:04 PM

CFC-101: An Introduction to OOP in CFMX

Here’s a presentation (and the accompanying little application I built) that I gave to the Dallas/Fort Worth ColdFusion User Group last night. We had a good turnout and a lot of people are wanting to get into OOP in ColdFusion, so this is highly encouraging.

Caveats on the app:

  • It uses the new cfgrid and cfform in CFMX 7, so you’ll have to run it on CFMX 7
  • The “Cancel” and “Delete” buttons on the cfforms don’t do anything yet because I didn’t have time prior to the presentation to figure out how to use the onClick ActionScript stuff
  • I cranked it out pretty quickly–a.k.a. “Standard Disclaimer” 😉

As always, feedback is greatly appreciated. If you have questions, see something weird, think something could be explained better, etc. please feel free to let me know. That’s how we’re all going to learn this stuff and make every app we write in CFMX 7 OO!

Comments

Sorry, I forgot to put the database script in the application zip. I’ll repost another one later today.

Posted by Matt Woodward @ 4/17/07 3:04 PM

Matt, this is great stuff. I’ve already put a link to it in our reference section and will make sure all of our developers that aren’t experts on OOP w/CFMX view it, which is pretty much all of us. Thanks very much.

Posted by Jim @ 4/17/07 3:04 PM

Thanks Jim, glad to help. I’ll get the version of the application zip with the database script up here shortly.

Posted by Matt Woodward @ 4/17/07 3:04 PM

I just posted the updated cfc101_app.zip file (same link as before). This contains a cfc101.sql file that’s a dump from MySQL but should be usable (it’s plain text SQL commands) to create this database on another RDBMS or in Access. Let me know if you have any problems.

Posted by Matt Woodward @ 4/17/07 3:04 PM

Matt, Fantastic presentation. I especially like the work you’ve done with Data Access Objects and gateways. I might have to go back and look at some of my code (crud <— muttered comment, not an acronym). I thought you were pretty strong in your discussion of using the var scope inside components. When you talk about variables leaking out of the function, are you referring to some bug? I’ve been using the variables scope regularly to set up private variables. It seems to be pretty predictable so far to me. You do have to be careful with querries, though. It would be nice if they were private by default. I had a bigger problem with the resolution of the unnamed scoped variables and the arguemnts scope. That one caused me a bunch of headaches until I found out what the problem was. Funny how a simple order of operations issue can really blow apart your application when you and your computer don’t agree on how to do the math. 🙂

Posted by Mike Rankin @ 4/17/07 3:04 PM

Mike–not talking about a bug, this is just the way things work and if you’re not aware of it, it can bite you in the kiester. Specifically I’m talking about using var to declare variables within functions, which is a different situation than using variables within your CFC to make your variables private to that CFC. Hopefully the difference between the two wasn’t a point of confusion. var scoped variables will stay within a function, while variables scoped variables are accessible throughout the CFC (but only within the CFC).

Posted by Matt Woodward @ 4/17/07 3:04 PM

CFHibernate

In order to “put my money where my mouth is” about open source ColdFusion software, today I registered a new project at cfopen.org called CFHibernate. If you’re familiar with Hibernate for Java, what I’d like to do is give ColdFusion users the tremendous capabilities that Hibernate has to offer. If you’re not sure what Hibernate is, read on …

 

Hibernate is an object-relational mapping (ORM) persistence framework for Java. What this means is that you define XML mapping files that describe your objects to Hibernate, and Hibernate creates your relational database model for you as well as many of your business objects (beans). Then in your application code, you literally don’t ever have to write any SQL code. That’s right, no SQL code. You make calls to the Hibernate service and it handles the database interaction for you. Being able to pass objects to Hibernate and not worry about all the “junk” that we typically have to concern ourselves with when persisting objects in an RDBMS is extremely powerful and very cool stuff.

The CFHibernate project is obviously in the pre-planning stages. I’ve been messing with Hibernate for Java for a little over a week now is all, but I’m extremely impressed and would absolutely love to be able to use this same functionality in my CF applications. Maybe it was the tedium of writing a bunch of DAOs that brought this on. 😉 At any rate, if you’re interested in this effort and want to help, please consider registering on cfopen.org and signing up for the project. It’s a big undertaking but I think it would be a huge benefit to OO CFers, and since the Hibernate code is in Java it might even be relatively leverageable (if that’s even a word).

Comments

I wouldn’t say that hibernate "creates" your business objects for you… although it will instantiate them. It doesn’t create your DAO’s either… something has to TELL hibernate what to do, and that’s usually a "DAO"-type class/cfc/whatever. I’d actually say it would more likely be called a "service", that extends hibernateDAOSupport, and thus can get() save() and find() objects of the proper type for you. The beauty of hibernate is the abstraction of the storage "medium". Is it a database? Is it xml? What if it’s just an in-memory cache? Who cares! Disclaimer: everything I just said was provided w/ my "limited experience" with Hibernate.

Posted by Dave Ross @ 4/17/07 3:04 PM

Well, actually Hibernate does create your business objects for you if you want it to. You can create an XML mapping and Hibernate will generate all your Java code for your business objects (by "business objects" I’m talking beans here) for you, complete with getters, setters, the appopriate datatypes, etc. This is based on what I’ve been doing with Hibernate anyway–I didn’t have to write a single Java bean by hand, I just had to write the Java classes that use the beans (the application itself, in other words). Also based on what I’ve been doing, it doesn’t create your DAOs for you either, but then again you don’t really need any DAOs. Once you set up all your mapping files those tell Hibernate what to do when you call the various methods on Hibernate and pass it the objects you want persisted in your database. To me that’s one of the big advantage of Hibernate. Yes, it also abstracts the storage mechanism, and this is another huge advantage. You want to switch from MS SQL to MySQL, or to Oracle, or HSQLDB, or whatever … all you do is change a single properties file to tell Hibernate to use a different "dialect", give it the new driver and connection info, and you’re literally done. That means changing about 4 lines of code in one file and seriously, that’s all there is to it. I’m admittedly pretty new to Hibernate as well, but it definitely can generate a lot of code for you if you want it to. Yes, you still have to create XML files that it can use so it knows what you’re wanting to do, but that’s a lot simpler than writing the objects by hand, and these mapping files are also used to generate your database schema.

Posted by Matt Woodward @ 4/17/07 3:04 PM

ahh yes… I remember reading that it could do that (create your "beans"), but never having seen it set up that way in practice, it must have slipped my mind. I will be trying my best to contribute to the project, but as I said last night, it’s quite a large undertaking.

Posted by Dave Ross @ 4/17/07 3:04 PM

Yep, most definitely a large undertaking, but I think it’s a worthwhile one, and hey, better too much ambition than not enough. 😉 Even if this project gets part-way to the full Hibernate feature set I think we’ll get some darn useful tools out of it.

Posted by Matt Woodward @ 4/17/07 3:04 PM

Matt, This is a great idea. I don’t know how much time I have to contribute but I would like keep in the loop. Can I suggest you create a RSS-capable mailing list for the project so folks can monitor via their favorite newsreader? I find google groups works fine for the CFE list (topica doesn’t do RSS). -Phil p.s. Want to help me win a Mac Mini 😉

Posted by Phil Cruz @ 4/17/07 3:04 PM

Thanks Phil–I’ll check into the RSS thing. It would be cool if cfopen had this built in but I’m not sure if it does. It has mailing list functionality I see but I haven’t looked any further. I’m not sure how much time I’ll have to contribute myself ;-), but I’m going to do what I can because I’m really excited about the possibilities this would offer. I need to do an even deeper dive into Hibernate itself to make sure I understand it really thoroughly but even after a week of working with it I think I have a decent handle on the functionality at a high level and how it works on the surface. The hard part will be digging into the technical side of how it does what it does, where the cutoff point between what Java code can be leveraged and what can’t is, etc. It’s going to be interesting if nothing else! As for the Mac Mini, I’m not sure I can help since I’ve already registered. My wife said she’d sign up on someone’s if they can get someone who isn’t registered to return the favor on mine, but since we’re in the same household I’m not sure that would work either. If you know how they check, etc. and what’s legit and what isn’t, send me an email and I’ll see what I can do.

Posted by Matt Woodward @ 4/17/07 3:04 PM

I have a base DAO that I started uses a cf structure to map tables to a bean. This could easily be changed to use XML like Hibernate does. I would be happy to share it as a part of this project if people think it would help.

Posted by Kurt Wiersma @ 4/17/07 3:04 PM

Excellent–we’ll take all the help we can get! Thanks Kurt!

Posted by Matt Woodward @ 4/17/07 3:04 PM

Matt some people have got hibernate working with coldfusion over on the flex yahoo group http://groups.yahoo.com/group/flexcoders/message/7801?threaded=1 It takes a fair amount of modification to coldfusion as the cf log4j.jar is an old version. Maybe blackstone will provide easier integration.

Posted by Mike Shaw @ 4/17/07 3:04 PM

Thanks Mike–I found some references to that but didn’t ever see the message that they got it working. I’ll have to look into that because I’m curious exactly what they’re doing with it, how they’re persisting things, etc. My goal would be to use CFCs as my objects and be able to pass those into Hibernate, which I don’t believe you can do. Now of course you could use Java objects as your beans within CF (which I’ve done before with Mach-II), but I really don’t want to go that route because then it’s a hybrid Java/CF application instead of a CF application that happens to use parts of the Java version of Hibernate or alternatively has its own CF-based ORM. Thanks a lot for the link though–I’ll follow up with these folks and see exactly how they’re approaching this.

Posted by Matt Woodward @ 4/17/07 3:04 PM

Great stuff, Matt. I was just talking with Hal Helms earlier this evening about the problem of getting old RDBMS-heads (like me) to see the world in something other than a relational model. A project like this would go a long way to reinforce the "database last" attitude that we encourage in FLiP, and stress the application model instead of the storage model.

Posted by Jeff Peters @ 4/17/07 3:04 PM

Thanks Jeff–I must admit when I first started reading about Hibernate I was a bit doubtful about how well it would handle the database schema generation piece. It’s actually quite amazing–in the applications I’ve been playing with so far Hibernate does pretty much what I’d do myself, it sets up indexes, primary and foreign key relationships, and is pretty darn adept at handling one-to-many and many-to-many relationships. As with any of these sorts of tools you have to know a little about how it "thinks" to get the results you want, but it’s amazingly straight-forward, and as you said it takes the emphasis off the database model and puts us completely in the object realm. I think (as Hal’s said 100 times) that’s another hangup we all have as we switch from procedural to OO; there’s still that pesky database we have to deal with that doesn’t quite think in objects. With ORMs you can let the computer worry about all that stuff! I’ll admit that I’m probably still in the honeymood period with Hibernate, but I think I’ve dug semi-deep so far and I don’t see any glaring annoyances yet. It does a great job of mapping objects to an RDBMS and has huge advantages when it comes to switching an application from one datastore to another as well. It’s going to be challenging getting this going in ColdFusion but I think it’s something that would make a lot of the repetitive stuff we all do on a daily basis a whole lot less tedious.

Posted by Matt Woodward @ 4/17/07 3:04 PM

Don’t forget the advantage of managed lazy loading. Let hibernate handle all the caching. Hibernate has a performance impact, like any other persistence layer, so use it wisely. 🙂

Posted by M. Schopman @ 4/17/07 3:04 PM

I was part of the group that is mentioned in the Yahoo group. Basically, our goal was slightly different than your stated goal here. We wanted to have all of our business logic in one place (Java), and be able to use ColdFusion (using Mach-II) for a public site, and Flex for an internal order-entry site. We were able to get Hibernate to work correctly with Flex without any real problems (other than understanding Hibernate and how it works). And I must say that we’ve been nothing short of amazed at how well Hibernate seems to work. However, we were unable to get ColdFusion to work correctly with Hibernate for any length of time. We ran into several issues, and most of them seemed to stem from JRun itself (mostly the classloader). We would be able to get it to work with an instance based version of CFMX, but then it wouldn’t work with a standalone version of CFMX. We also ran into cross compatability issues between the Mac and PC, where something would work on the Mac, but not on PC. In looking around the internet, we were unable to find anyone else who had broached the subject of Hibernate for CF, or even JRun. Because of a project deadline, we had to essentially scrap the Hibernate for ColdFusion concept. We do plan on picking it up though in a couple months. It’s a very daunting task, but I think it’s possible and should definitely be explored!

Posted by Rob Schimp @ 4/17/07 3:04 PM

Yep Micha, everything’s a tradeoff and there are defintely some performance issues that you have to be aware of with Hibernate. By that I mean (based on what I’ve done with it so far) you just have to be very aware of how you’re using it, when things get loaded, etc. etc. Luckily the Hibernate folks are well aware of what the gotchas are and it’s documented quite well. I’ll be curious to see how all this translates over to the CF side and I begin working on all of this.

Posted by Matt Woodward @ 4/17/07 3:04 PM

Thanks for the follow-up Rob. Based on what I could tell from the flexcoders list I thought that’s what you were doing. It’s an option I considered but I’d really like to see a more CF-centric solution that wouldn’t force people to use Java objects. Not that it’s a bad solution necessarily, but it’s one level removed from CF and would required CFers to learn enough Java to build their beans in Java. Simple enough really, but it’s not CF. 🙂 I definitely think it’s possible to get this rolling in CF, but you’re right, pretty daunting. I’m just going to take it one step at a time and see how it all plays out. Thanks much for the feedback.

Posted by Matt Woodward @ 4/17/07 3:04 PM

Good to see someone else trying this. I have NOT been able to get this working so far. I am primarily a JAVA/J2EE developer doing back end work for presentation layers done in CF. I love Hibernate for my JAVA projects and I am trying to implement it in the CF environment for my team. I’m registered at CFOpen.org but I am unsure of how to sign up for the project development.

Posted by Troy Harris @ 4/17/07 3:04 PM

Excellent Troy–just e-mail me your cfopen.org ID and I can add you to the project.

Posted by Matt Woodward @ 4/17/07 3:04 PM

Matt, I am running JBoss and Bluedragon. Having some trouble with the datasource configuration. Hibernate docs point you to put the config in conf/server.xml for Tomcat. BD doesnt have this file.. instead has bluedragon.xml. Do you know how to set the datasource setting for JBoss + BD? Thx Joe

Posted by Joe @ 4/17/07 3:04 PM

I could not make work Hibernate and Flex, could someone help me?

Posted by Miguel Angel Romero Cornelio @ 4/17/07 3:04 PM

Miguel–there was some discussion on this quite a long time ago over on the Flex Coders list at Yahoo! Groups. If you search the Yahoo! Groups you should be able to find it, then search within that group for Hibernate and there’s some information available.

Posted by Matt Woodward @ 4/17/07 3:04 PM

I am hoping to implement a ColdFusion / Java hybrid application that uses POJOs and Hibernate in

the model, and coldfusion for the view and controller.

I’ve been thinking about the issues with running hibernate on CF for a while and have come up with

the following idea.

Part 1
——————
1. Download the source for the Commons Logging package
2. Create an Eclipse project for it
3. Refactor the base package for commons logging to be:
cf.org.apache.commons.logging instead of
org.apache.commons.logging
4. Build a jar. cf-commons-logging.jar

Part 2
——————
1. Download the souce for Hibernate
2. Create an Eclipse project for it
3. Refactor the base package for Hibernate to be:
cf.org.hibernate instead of
org.hibernate
4. Buidl a jar. cf-hibernate.jar

Part 3
——————
Place the 2 jars you created above, along with all other supporting jars where CF can pick them up

and start/restart ColdFusion

Posted by Kurt @ 4/17/07 3:04 PM

I forgot one of the most important steps in my post above!!!

In part 2, before you build the cf-hibernate.jar, there should be an additional step:

** Do a search and replace in the entire hibernate source and update all references to: org.apache.commons.logging
to instead point to: cf.org.apache.commons.logging

Posted by Kurt @ 4/17/07 3:04 PM

Actually, now that I think about things, Step 3 under Part 2 should be eliminated. There is no need to change hibernate’s package name.

So ignore the following instruction:
3.) Refactor the base package for Hibernate to be:
cf.org.hibernate instead of
org.hibernate

and instead do the following:

3.) Do a search and replace in the entire hibernate source and update all references to: org.apache.commons.logging
to instead point to: cf.org.apache.commons.logging

Posted by Kurt @ 4/17/07 3:04 PM

Beware. i tried to follow these steps today. i agree they seem like they should work & probably will in the end, but much labor! I followed build instructions carefully. Using Eclipse 3.1.

i tried building hibernate versions 2.1.2, 2.1.3, and 3.0CR2.
In each case the source files are missing this package
org.hibernate.hql.antlr

i can find nothing about this through extensive searching. building commons logging with the renamed packages went smoother.

See my post to the hibernate forum (perhaps a solution will come)
http://forum.hibernate.org/viewtopic.php?p=2306368

Posted by Dado @ 4/17/07 3:04 PM

It looks like you actually have to build hibernate using the build.xml file that comes with it to generate this package. Then you’d have to do the refactoring..

See the notes at the bottom of the page:

http://www.hibernate.org/hib_docs/v3/api/org/hibernate/hql/antlr/package-summ…

And checkout this line in the build.xml file.

….

Man, I’ve got to spend some time and get this working. Back to work…

Posted by Kurt @ 4/17/07 3:04 PM

Here’s a re-pose with the stuff that was between tags having it’s tags removed so you can acutally see what I was posting.

It looks like you actually have to build hibernate using the build.xml file that comes with it to generate this package. Then you’d have to do the refactoring..

See the notes at the bottom of the page:

http://www.hibernate.org/hib_docs/v3/api/org/hibernate/hql/antlr/package-summ…

And checkout this line in the build.xml file.

property name=”parser.src” value=”${generated.src}/org/hibernate/hql/antlr”/

target name=”init.antlr” depends=”init”
description=”Check ANTLR dependencies.”
uptodate property=”antlr.isUpToDate”
targetfile=”${parser.src}/.antlr_run”
srcfiles dir=”${grammar.dir}” includes=”*.g”/
/uptodate
/target
….

Man, I’ve got to spend some time and get this working. Back to work…

Posted by Kurt @ 4/17/07 3:04 PM

I got CFMX 7.0.1 and Hibernate 3.1.3 working!!!! I don’t know how far other people got CF and Hibernate to work, but this is totally working!! I’m doing full CRUD functionality!!

I followed the steps I outlined in my prevoius posts, which was pretty much refactoring the commons-logging and log4j packages to be “cf.org.apache…” instead of “org.apache…” and then I updated any references in the Hibernate source code to the commons-loggging and log4j packages to now point to my new “cf.org…” packages.

So after that I had 3 jar files
cf-commons-logging.jar
cf-log4j.jar
cf-hibernate.jar

I then put these files in:
__cfinstall__/wwwroot/WEB-INF/lib
and restarted MX

(I also put in the MySQL connector JAR and a JAR that my application uses – my app is a cf/java hybrid)

I created a simple test CFM template which executed a number of business actions (Java Classes) which handle all my hibernate access, and detaching objects…. and I could do everything, with NO complaints from CF!!

Posted by Kurt Bonnet @ 4/17/07 3:04 PM

Why to write cfhibernate you can use hibernate…

Posted by @ 4/17/07 3:04 PM

Hi Kurt,
Can you publish the modified .jar files somewhere, so anybody can use these files?

Thanks,
-dipak

Posted by Dipak @ 4/17/07 3:05 PM

DAOs and Composition

In the spirit of what Joe Rinehart and a few others have been doing so far in this the “year of OO for CFers,” I thought I’d share what I’ve been working through this week. Specifically I’ve been grappling with Data Access Objects (DAOs) and how best to use them when composition is involved with the objects. I’ve done this several times before but I’m using a rebuild of our CFUG site to dig deep and try and figure out the best way to handle this (I’ll stop short of saying “the right way to handle this”). For example, let’s say I have a Person bean and an Address bean, and the Person bean has an Address bean in it. What’s the best way to handle this situation in the DAOs?

 

Let’s focus on the create method specifically since it’s the most messy. If we’re dealing with a Person and an Address, let’s assume we have a form on which a person enters their basic personal information (name, email, etc.) and also their address information. When they submit this form, on the backend we need to create a Person object and an Address object, populate them with the form data, and pass them to a DAO to run the create method. There are a few different scenarios I’ve mulled over, and I’ve come up with my preferred way of doing this, but I’d be curious to get your feedback.

Scenario One: Handle Person and Address Separately

Because these are separate objects and each have their own DAO, one way of handling this would be to handle the Person and Address objects separately. In other words, after the form submission, in whatever component is handling the logic of processing the form, populate a Person, populate an Address, then call personDAO.create(person) and addressDAO.create(address) in sequence.

The Issues

This may seem like the simplest way to handle things, but there are a few issues that arise. First, there is a bit of chicken and egg stuff going on with the relationship between Person and Address on the RDBMS side. Since the person and address tables are separate and related through a key (address_id in the person table), the Person really should have an Address id before personDAO.create() gets called. So we could reverse the order of the calls above and call addressDAO.create() first, then grab the address id from the result of that call and put it in the Person object, then call personDAO.create().

This isn’t necessarily a bad way to do things, and would certainly work in this situation, but what happens when you get into more complex scenarios with multiple instances of composition (which in my application is the case)? In some cases the relationships and chicken-and-egg stuff gets even more complex, so you end up making multiple calls to your DAOs (create first to get the ids needed, then update later to put the ids in the necessary spots). Also, in my opinion you end up really muddying up things in the component that’s handling the logic of the form submission (which in Mach-II is done in the listeners). So in my mind I scratched this option off as not the way to go about doing things.

Scenario Two: Put Address in Person and Have Separate Queries in the PersonDAO

It doesn’t take but a few lines of typing the code for this scenario to realize what the faulty logic here is. It may seem like a decent idea at first, and you can even put the person and address queries in a nice tidy transaction on the database side, but you end up completely duplicating the code that’s in the Address DAO, which is a big, big, big no-no. I must admit in some cases for deletion I have done this, but delete queries are typically extremely simple and likely wouldn’t change over time. Something like a create might change in the future (if you add a field, for example), so you’d end up having to maintain the create logic in two places. Clearly not the right solution.

Scenario Three: Leverage the Address DAO Within the Person DAO

We’re using composition in our beans, so why not use composition of sorts (this isn’t strictly composition, but bear with me …) in our DAO as well? When we instantiate the Person DAO, why not just instantiate an Address DAO inside the Person DAO so we can call things that way? Then after the form submission we’re instantiating the Person bean, the Address bean, putting the Address bean in the Person bean, and just calling personDAO.create(person).

At this point, after much pacing and pondering, this is what makes the most sense to me. That isn’t to say there aren’t downsides here as well, which is why I’m posting my thoughts to get some feedback from others on this. I’ve seen plenty of examples of Java code that do this, so I’m assuming it’s not flat-out “wrong,” it seems to work well, and I really like the fact that it keeps things self-contained by only necessitating one call to the Person DAO (even if behind the scenes the Person DAO is actually calling the create method of the Address DAO as well).

There are still some chicken-and-egg situations when you do things this way. Those are relatively unavoidable in any of these scenarios. But what this gains you is A) complete reuse of the DAO code (no duplication of code as in scenario 2 above), and B) it keeps the logic of the form processing component a lot cleaner because you’re just instantiating some objects and passing a single object to its DAO for the create action.

So am I on the right track? Is there a fourth option I haven’t considered? Should I find a new career? Let me know your thoughts.

Comments

I’m glad you posted this. I have the same personal debates and haven’t been able to fully commit to any one solution as being the "best". Maybe you have an object UserAddressDAO that you call to create and it instantiates the UserDAO and the AddressDAO – so the "chicken egg" logic is handled in that one place where the id relationship is handled at a data abstracted location (as opposed to in your business object)? (I guess this is kind of a facade) I am anxious to hear what others think. I am currently debating the inclusion of some deletion code in a DAO as you glossed over "I must admit in some cases for deletion I have done this, but delete queries are typically extremely simple and likely wouldn’t change over time." on the cfc-dev mailing list and can’t really come to a "feels right" answer on that either. I currently do just what you mention – i’m just not sure its the best way.

Posted by Bill @ 4/17/07 3:04 PM

I think it makes sense… I do this type of thing all the time. It makes sense that if person HAS A address then personDAO has a addressDAO. In fact, I even have DAO’s that contain gateways for another type. Just the other day I had a "student" object that had a property like "previous schools attended" (an array). So, my studentDAO received an instance of a schoolGateway via. dependency injection (rather than creating it on it’s own), and during it’s read() operation, it placed a result from the schoolGateway.getPreviouslyAttendedByStudentID(id) into the student instance. All the merits you mentioned are valid… in fact I use this same instance of the schoolGateway elsewhere. I know I’m starting to sound like a broken record, but you should take a look at what I’ve done w/ the spring -> CFC port. It makes managing these situations a hell of a lot easier.

Posted by Dave Ross @ 4/17/07 3:04 PM

Matt, This is a GREAT post. I think you’re right on track, and you did a great job explaining why Scenario Three is probably the the rig — erm, a Very Good way to handle this problem. Patrick

Posted by Patrick McElhaney @ 4/17/07 3:04 PM

Thanks for the thoughts Bill–the issue I see with the UserAddressDAO situation is that you wind up with a class explosion of sorts. If we throw a Company object into the mix, do you then build a UserAddressCompanyDAO? That could get ugly real quick. 😉 When I’m thinking through this stuff I try to talk through all the scenarios, no matter how unlikely they seem at first, just to make sure I understand *why* something isn’t a good solution. Then I can feel like I’ve covered all my bases. There’s someone who posts on one of the CF lists with the tag line, "I haven’t failed. I’ve found 10,000 ways that don’t work" (or something along those lines), which I think is attributed to Edison. That’s definitely how I feel doing all this OO stuff. I often spend more time thinking through all the options than actually implementing the one that makes the most sense, but this isn’t necessarily a bad thing! Better to spend a lot of time thinking through everything than building a bunch of stuff you have to throw out when you realize you’ve coded yourself into a corner.

Posted by Matt Woodward @ 4/17/07 3:04 PM

Thanks Dave–I’m really interested in checking out the Spring port you’ve done. I’ve read quite a bit about Spring on the Java side of the world and it’s pretty impressive, particularly in contrast to something like Struts. Can you post a link here or email it to me? I definitely want to check that out.

Posted by Matt Woodward @ 4/17/07 3:04 PM

Thanks Patrick–given the brief feedback so far at least I know I’m not way off the mark. That will allow me to sleep better at night. 😉

Posted by Matt Woodward @ 4/17/07 3:04 PM

Though I find myself using the third scenario most often, here’s a fourth scenario to throw out there for discussion: Scenario Four: Drop the AddressDAO In this scenario, all the DB functions for managing Addresses would be handled through the PersonDAO. I’m sure there are alarms going off in your head, thinking "What?! I’ll have to rewrite the code to manage Addresses for any other business object that has an Address!". That’s more than likely correct… the Person-Address example isn’t really a good one for this scenario. Instead, consider this example of composition (as opposed to aggregation or association): a Worm is composed of Segments. Since Segments cannot exist without a Worm (and don’t make sense outside the context of a Worm), Worm manages the lifecycle of its Segments. Similarly, we can have WormDAO manage all the DB functions for Segments, since no other DAO will ever have to work with Segments (no danger of duplicate code). One big plus of this approach is that you can take advantage of the DB’s joining capability (and grab the Worm and all its Segments in one, optimized query). Of course, if WormDAO starts getting bloated, you can factor out the Segment functionality into a SegmentDAO.

Posted by Doug Keen @ 4/17/07 3:04 PM

nice post. How to handle multiple addresses per person with your scenario three? I suppose have person.address be an array of address type, eh? Now, what I am really stuck on is how to wrap these creates into a DB transaction? what happens if the person.create is successful but the address.create is not? Doug

Posted by Douglas Knudsen @ 4/17/07 3:04 PM

Definitely true Dough–if there is no need for a separate Address object (or Segment object in your example), then you wouldn’t need and really shouldn’t have a separate DAO unless there’s some other driving need. I actually thought about not having the Person and Address have a separate DAO, but in the end I decided to keep the two separate so I could expand in the future as needed. Great point though–don’t create objects just for kicks; make sure you need them and it makes sense to have them be separate entities.

Posted by Matt Woodward @ 4/17/07 3:04 PM

Douglas, I’d likely handle multiple addresses as you outline, namely with an array of objects. As for your other comment concerning the transactions, I’m still messing with that myself so I’d be curious to hear what other folks have done. What I usually do (at this point anyway) is have the create() methods return some sort of indication of whether or not they were successful, and that way I can proceed or not based on the success of each step. That doesn’t address the rollback issue, however, so if the first step fails I’m ok, but if the last step fails I’m in a bit of trouble. I haven’t quite thought through the best way to handle that other than something like keep track of whether the last step fails, then you can go back and run deletes as needed on the previous steps. Not particularly pretty but it does the trick, although then you get into what happens if the deletes fail …

Posted by Matt Woodward @ 4/17/07 3:04 PM

good post Doug. I think what you say about the Segment/Worm makes alot of sense and will probably apply to the problem I am having. I hadn’t thought to have one "big" dao that takes care of a Parent Element and its subordinate objects (that can only exist if the parent exists). Then pull out those subordinate objects that end up needing to be in their own DAO. I was guess I was under (the false?) impression that a DAO would only deal with one objects interface to the datasource.

Posted by Bill @ 4/17/07 3:04 PM

I think this was my impression when I first started learning all this as well Bill, that a DAO would only deal with one object. The more code samples I looked at (which are largely in Java, which is one of the reasons I’m trying to make this big charge for CF-specific OO materials this year), the more I saw that this wasn’t necessarily the case, and it started to make more sense as well as simplify the code overall, which is always a good goal to have. The CFUG site I’m working on is turning into a bit of a beast, but once it’s done I think it should be a relatively decent example of a lot of these concepts as well as a good semi-large Mach-II sample application. I’ve gotten a lot out of studying Phil Cruz’s mach-ii.info site as well as several of the examples that Joe Rinehart, Scott Barnes, and others have put on their blogs.

Posted by Matt Woodward @ 4/17/07 3:04 PM

in regards to the rollback it seems like I remember reading that a transaction will work across components in CF 6.1 now. So, it seems to me that having a "transaction" object that calls you various methods for you – a facade i guess since it simplifies the interface while still giving you full access to the power behind it – the facade woudl call the various methods for you – and in the facade you would wrap those method calls in a cftransaction. Now, something I have never tried is havinga cftransaction wrapped around these generic factory /execution combinations so that the cftransaction is in place as needed if my datasource is a db that supports transactions – but if my datasource is something else – with no queries for instance – that the code won’t blow up. Now I’ll have to confirm with my memory if that is a valid scenario – cftransaction wrapped around code that contains no queries. It seems like it would be OK but would have a slight performance hit. hrm. Of course, you could have a facade factory i guess that returns the correct facade based on your datastore and the xml based facade wouldn’t have the cftransactions in it but the sql based one would. I guess the merged DAO thing that Doug mentioned would work here – in the same regards a merged "facade" could exist to handle an object and all of its subordinate objects (those that wouldn’t exist without it). So you could have FacadeFactory -> Facade_xml || Facade_odbc the facade_odbc would be responsible for instantiaing whatever objects it needed then wrapping those object method calls in a cftransaction. this way you get the rollback, the separation of methods to their reusable components (DAOs and so forth) and an easy to access interface for your application to deal with. What do you think? Does this seem like a huge stretch?

Posted by Bill @ 4/17/07 3:04 PM

That gives me a lot of very cool ideas to try out Bill–thanks! As with most of this OO stuff, there’s a million different ways to go with things, so I’ll have to experiment, particularly with the transaction stuff. If there’s a way to get that going without necessarily involving database queries that would be very cool, I’ve just never tried it. One of those things I just assumed wouldn’t work so I never messed with it.

Posted by Matt Woodward @ 4/17/07 3:04 PM

I always use a service object which has my DAO called inside of this. This helps with the situation you talk about above because I would have a personService that has a getPerson() and savePerson method. savePerson knows to call save using the personDAO and then to call save using the addressDAO each address inside my person. This service layer also works great when Flash remoting and/or web services are involved. I would be happy to do a blog post on my method to get more feedback if people are interested.

Posted by Kurt Wiersma @ 4/17/07 3:04 PM

Thanks Kurt, that would be cool. It sounds like that’s similar to what I’m doing (as far as calling the person DAO method and then that in turn calls the address DAO method), only with the addition of the service layer in the picture. I’m always happy to see details on what other folks are doing with all of this.

Posted by Matt Woodward @ 4/17/07 3:04 PM

Best stuff I read today. Thanks for the inputs. DK

Posted by Douglas Knudsen @ 4/17/07 3:04 PM

This is great Matt ! This blog (and all the comments) just answer my previous problem posted on CFCDev about an Article objects with multiple properties in it. I didn’t know it, but what I meant was _multiple composition_, it’s hard when you don’t know the terminology of what you need. Now I can have my _ContentObjectClass_ DAO managing all _ContentObjectClassProperty_ DB queries, like Doug Keen segment and worm example. Or maybe I can have simply the _ContentObjectClass_ DAO calling the _ContentObjectClassProperty_ DAO, but anyway, things area getting better all trhe time, thank you guys.

Posted by Marcantonio Silva @ 4/17/07 3:04 PM

I think I saw the discussion on CFCDev Marcantonio which is what got my wheels turning on all of this as well. I’m getting a lot of great ideas from the discussions as well.

Posted by Matt Woodward @ 4/17/07 3:04 PM

Excellent discussion! I ran into the same issue, but with a header/detail object scenario. I used the same idea as Kurt and created a Service. That allowed the service to contain the logic that knows how to deal with the interaction of the DAO objects and I can keep the DAOs as "pure" as one can. For the batch header and detail row issue, I used a UUID to solve the chicken and egg issue. It requires 32 more bytes per rows to store a char(36) vs. an integer, but our main tables will only have up to 1,000,000 rows. We archive to a data warehouse scenario and those tables use identity columns for smaller storage. I have built and torn apart my objects and services 3 times now in the past 2 weeks, but they keep getting better. And don’t get caught up in the *best* process – it will never be good enough. I have been at this for more than 16 years and the idea of *satisficing* is best practiced. No matter how good you build it this time, you will rebuild in the future to take advantage of new technologies and methods. That’s the price of progress. And you can’t let the new folks take advantage of new ideas/technologies while you stay connected to your old *best* methods. Things move too fast for that to be successful. Excellent conversation!

Posted by Paul Carney @ 4/17/07 3:04 PM

Thanks for the thoughts Paul–you know, I thought about using UUIDs and then "just decided not to" (no rhyme or reason to it), but now that I’ve thought through this stuff 100 times I think I may rework my database and all my CFCs to use UUIDs instead. I’ll think through all my scenarios to make sure it’ll get me what I’m after, but you’re right, that would definitely avoid the chicken-and-egg situation with the IDs. Thanks for bringing up something that makes me want to do yet more rework! 😉 Excellent thoughts on refactoring as well. It’s nice to hear from someone with a lot more experience than myself so I know I’m not just bad at this stuff! I’m a big enough dork that I’m having a great time thinking about all these OO design issues, reading all the books I can get my hands on, experimenting, reworking, etc. Sometimes I feel like I’m spending tons of time thinking and not a lot of time doing, but as I think I said before, better to do that and make well-informed decisions than just slap something together and hope it’s maintainable. Thanks again–now off to see about using UUIDs …

Posted by Matt Woodward @ 4/17/07 3:04 PM

You need not use UUID’s to beat chicken-and-egg; you could use a Sequence. In a current project I have a MS SQL Server db table named ‘Sequence’ with columns ‘SequenceName’ and ‘SequenceId’. My DAO’s all extend a GenericDAO.cfc which has a getNewId() method, that calls a stored procedure to get the next integer id in a specified (named) sequence. In this app my table has 3 rows, with ‘SequenceName’ = ‘UserGroup’, ‘NodeItem’ and ‘ValueObject’, and SequenceId for each row is the next integer id that will be returned. My UserDAO and GroupDAO both use a ‘UserGroup’ sequence, so each sets variables.sequenceName = "UserGroup". getNewId() calls the stored procedure like this: EXEC nextVal @sequenceName=<cfqueryparam cfsqltype="CF_SQL_VARCHAR" maxlength="50" value="#variables.sequenceName#"> We adapted the stored procedure from one by James Thornton ( http://jamesthornton.com/software/coldfusion/nextval.html ) — ours looks like this: CREATE PROCEDURE nextVal @sequenceName nvarchar(50), @sequenceId int=NULL OUTPUT AS — return an error if sequence does not exist — so we will know if someone truncates the table set @sequenceId = -1 UPDATE Sequence SET @sequenceId = SequenceId = SequenceId + 1 WHERE SequenceName = @sequenceName Select @sequenceId as sequenceId GO So if you want, each of your DAOs can have its own sequence of integer ids or all can use the same one. My DAOs use getNewId() within their create() methods to grab an id just before inserting the new record, but you could just as well call getNewId() as a public method up front, set it in your User bean and do it again for your Address bean. Now each can know the other’s id before you persist them. Hmmm, I guess for flexibility the create() method should use check for a non-zero id in the incoming object and use that if present; if the id is zero (as set by the constructor) then call getNewId() for the id to use in the INSERT query. There’s your 32 bytes per record back, at the expense of calling the stored proc once per id (instead of using CreateUUID() in CF). Also, integer ids are nice if you have to move things between (say) Oracle and SQL Server, heaven forbid…

Posted by lars-o-matic @ 4/17/07 3:04 PM

lars: I understand your approach, but there are 3 issues for us: 1. We would have to incorporate into the sproc a check for uniqueness. We are going to key off that new ID and the Sequence table row for a given SequenceName can be reset without any db constraints validating it. This only pertains if you care about uniqueness, which we do in our case. 2. This solution will have a difficult time scaling as every item in the application will now depend on this one DAO and sproc to handle all new rows. That could cause a very large logjam. 3. UUIDs offer one more benefit: they do not have to be created on your system. For instance, in our solution, our own application will be calling the Service and DAO objects from within our app, but there is also a Web service that uses the same ojbects. Other systems can pass in their chunk of information, using their own UUID, but we can also use it since it will be unique not only in our system, but the world. UUID pretty much guarantees us uniqueness from any system. In this manner, all of the disparate systems have their own unique key (the UUID), but we are able to link them together without having to map our internal ID in a row to the UUID in order to speak with other systems regarding this chunk of data. The CreateUUID() CF function also saves us a trip to the db server. Every little bit counts (pun intended) when looking at large volume transaction systems. For us, storage is cheap and network bandwith is a bigger concern. But that may differ in other scenarios, in which your solution handles the tasks with ease.

Posted by Paul Carney @ 4/17/07 3:04 PM

Matt, I think your chicken and egg issue is due to the DB design. Instead of putting the address_id in the person table, you should have a separate table to join the two. person_addresses { person_id address_id } That would actually more closely model the separation of objects if that is your goal. It also allows for a person to have more than one address (which is a very likely scenario). Using this method, you no longer need worry about which gets created first – you simply create each one, presumably retrieiving the new ids from each operation, then you perform an insert those new ids into the person address table.

Posted by Roland Collins @ 4/17/07 3:04 PM

Matt, I think your chicken and egg issue is due to the DB design. Instead of putting the address_id in the person table, you should have a separate table to join the two. person_addresses { person_id address_id } That would actually more closely model the separation of objects if that is your goal. It also allows for a person to have more than one address (which is a very likely scenario). Using this method, you no longer need worry about which gets created first – you simply create each one, presumably retrieiving the new ids from each operation, then you perform an insert those new ids into the person address table.

Posted by Roland Collins @ 4/17/07 3:04 PM

Paul: yes, UUID vs Sequence is not a one-size-fits-all discussion! Your point #1 (Sequence id’s must be unique) would suggest table-level security on the Sequence table. Your point #2 — you could have many DAOs but yes, they’d all call the same stored procedure. Throw enough traffic at it and I guess anything bottlenecks. There must be stopgap solutions (e.g. 2 independent Sequences and sprocs — one produces odd numbers, the other even ones… or do it with N greater than 2). Come to that, the Sequence could live on a different box than the main db. Not arguing with you, just "thinking aloud". Your point #3 — yes, I _love_ UUIDs for being GLOBALLY unique, and they can come from a whole other process. I hate that not all platforms I use support UUID / GUID as native types — I’m sure casting them to 36-character strings and having to index them as text primary keys in, say, Oracle, incurs a wee performance hit that might add up at very high volume. Thanks for the reply.

Posted by lars-o-matic @ 4/17/07 3:04 PM

Roland–thanks for the thoughts. The reason I’m not using a join table for addresses is because, in this current app anyway, people will always only have one address. I also have companies who have addresses, however (again they’ll only have one), so that’s why I separated the addresses out. In other cases in this app I do have linking tables (person_skill for example) but not for the addresses. I’m just not sure that if there really wasn’t a need (in this case there might be, but in other cases not) for a join table that it’s worth having the extra table, but it’s worth considering I suppose. Good point about avoiding some problems with this though. In the interest of incorporating this and allowing for the possibility of multiple addresses for people and companies (total overkill for this app, but what the heck!) I’ll probably rework this as well. Thanks!

Posted by Matt Woodward @ 4/17/07 3:04 PM

Lars–thanks for the info on sequences. Yet another option to consider! And thanks to everyone for all the discussion on this point, it’s really helping a lot of people I think. There’s a lot of ins and outs to some of this stuff so bouncing these ideas around is really great.

Posted by Matt Woodward @ 4/17/07 3:04 PM

I agree, Matt. Some great ideas from everyone. It’s nice to see that people can share thoughts in a way that we all learn how other people approach problems. Lars’s comments got me thinking down another road…but I will test some things out and we will have another discussion on another day! Good Luck!

Posted by Paul Carney @ 4/17/07 3:04 PM

What’s an Object?

What started as a simple blog entry quickly became quite lengthy, so I’m posting what I hope will be the first in a series of introduction to object-oriented programming for ColdFusion programmers articles as a PDF.

Please feel free to comment, correct, scrutinize, and ask questions as needed!

whats_an_object.pdf
Download this file

Comments

Thanks for writing this piece and I look forward to any future ones!

Posted by Freddys @ 4/17/07 3:04 PM

Ben Forta blogged this. that’s how I found it.

Posted by john ivanoff @ 4/17/07 3:04 PM

Excelent Matt, While this was not new to me, this is the first time I gained a real understanding of it. You have a great way of explaining. Really looking forward to the future "follow ups".

Posted by Trond Ulseth @ 4/17/07 3:04 PM

Thanks everyone–appreciate the feedback!

Posted by Matt Woodward @ 4/17/07 3:04 PM

I was looking for a OO explanation in a CF way… and this is it… (and like Trond… I’m really looking forward for more.) Thank you

Posted by Steini Jonsson @ 4/17/07 3:04 PM

Hi Matt, Good show on the article! I am looking forward to seeing this blog in Flex calling CFCs through Flash Remoting. 🙂

Posted by Mike Kollen @ 4/17/07 3:04 PM

Thanks Mike–getting that up and running is definitely on the roadmap! The code’s done, just have to find the time to clean it up a bit and get Flex installed on this server. I’m putting it on Tomcat so I’m sure I’ll have some tales to tell going through that experience …

Posted by Matt Woodward @ 4/17/07 3:04 PM

I too would like to express my congratulatory remarks on a well written article. I am definetely looking forward to your next one, just don’t wait too long to release it! 🙂

Posted by noname @ 4/17/07 3:04 PM

Great article, I look forward to more in the future. I have been trying to get my head aroung CFC’s and OOP in general for some time. Your first article reienforce what I have picked up todate, and added some depth to what an Object is. What I look forward to hopefully in a future article is something along the lines of "OK, now you know what an object is, here is how you find them in the requirements for an application and get them to work together to acomplish said applications goals."

Posted by Ian Skinner @ 4/17/07 3:04 PM

Thanks for all the nice feedback. Ian, what you’re discussing, specifically OO design, is probably the hardest part of OOP. I’ll definitely be addressing it, but a very, very firm foundation needs to be in place first, so it will come late in the series of articles I have planned. As a preview, the next article (no timing on it yet) will likely be along the lines of "OK, now I know what an object is … how do I use one in the context of an application?" This will be really simple stuff but will help build a foundation so everyone can start seeing objects in their apps as Ian points out. It’s fantastic to see so many CFers interested in this!

Posted by Matt Woodward @ 4/17/07 3:04 PM

Nice job, Matt!

Posted by Hal Helms @ 4/17/07 3:04 PM

Great introductory article. I’m glad to see that you are not stuffing all your bean properties in to the "this" scope like I’ve seen so many other people do.

Posted by Mike Rankin @ 4/17/07 3:04 PM

Matt, Thanks for writting this article!

Posted by Ray Buechler @ 4/17/07 3:04 PM

Great article Matt! I know Im late to the table, but this has actually helped me see that I’ve been going about OOP all wrong. 😉 Now I know how to start looking at it. I’ve always tied my DAO’s and my BO’s to my databases like there was some sort of magical mystical invisible binding between them (Procedural Programmer stuck in an OOP world). I now see how I should be looking at it and have found a new excitment for trying. 🙂 Thanks again!

Posted by Jeff Lester @ 4/17/07 3:04 PM

Hal Helms Newsletters – OO Primer

If you’re new to OO or want to solidify what you already know (or *think* you already know …), you’re going to want to check out Hal Helms’ latest series of newsletters:

http://halhelms.com/index.cfm?fuseaction=newsletters.detail

Hal has a real gift to explaining OO concepts in a way that makes them very easy to understand and is very passionate about getting people to start thinking in OO, so his latest two newsletters (and the upcoming ones he’s hinted at) should be considered “must read” materials for CFers looking to make the transition to OO. And that should be each and every one of you!

I’m going to be covering an intro to OO thinking, principles, etc. at our February CFUG meeting as well so I should have some thoughts over the next month or so. This will be a good way for me to get started on the series of OO blog entries/articles I have planned for the new year.

I hereby declare 2005 to be “the year of OO” for all CFers! 🙂

Exercises in Design Patterns

I had a really eloquent version of this post all worked out, but for some reason it choked when I submitted it, so this will be a less eloquent, abbreviated version.

Apologies that I’ve been in a cave lately. I’ve had the typical end-of-the-year project pileup to dig out from under, but in the course of working feverishly on some of these projects, I’ve taken the opportunity to take a much closer look at some design patterns, specifically in my case DAOs and how to use them better and more effectively.

 

I’ve been using DAOs in Mach-II projects for quite some time now, and although it’s been working great I realized I’ve been using them a bit prescriptively without *really* digging down deep and understanding all the surrounding issues, gotchas, and possibilities. So I’ve been reading, researching, and reading some more over the past few weeks and I’m starting to have some revelatory insights on some things.

The purpose of this post isn’t to share any insights–they’re far too half-baked at this point, but you better believe I’ll be sharing in the very near future. I’ll be thinking out loud and talking to myself a lot over the coming weeks, so please don’t be alarmed. I’m not insane, I’m just obsessed. 🙂 I do think it’s appropriate for me to make a few general comments at this point, largely brought on by the introspective season we’re in.

First, always be challenging yourself. I’m at the point now with a lot of more advanced OO concepts that I feel like I’m at least starting to “know what I don’t know,” and it’s really inspiring me to go nuts with learning this stuff. I’ve already looked back and stuff I’ve written over the last year and seen how much better I could have done things had I known then what I know now.

Second, I’m a bit surprised at the lack of comprehensive CF-specific code samples and literature about OOP and design patterns. It’s starting to emerge on some really great blogs (I’ll post links later–it’s late and I’m beat), but I’m going to do what I can in the coming year to contribute to this area, which I feel is pretty lacking. Since I have a Java background I’ve been getting a lot out of reading the Java materials, but if we as CFers are going to take our craft to the next level and bring others along with us (kicking and screaming if necessary!), then I think we need our own set of knowledge and literature.

Finally, I’m in the process of rebuilding the Dallas/Fort Worth ColdFusion User Group web site, and I’m going to apply as many of these concepts as I can to this project. For the purposes of the site a lot of it may be overkill, but these sorts of projects are perfect for applying theories I may not have put into practice yet. Once I get the site in a better state of completion I’ll share the code so others can learn from it (or rip it to shreds as the case may be!).

Happy Holidays CFers, and if you haven’t made the commitment to start doing OOP yet, make 2005 the year in which you do it. Seriously. Not only is it a necessity from a career standpoint, it will make your development life easier and more fun, I guarantee it.

Comments

Can’t wait to see your interpretation on the patterns with CFMX ( I mean that in a good way). I also think the reason you don’t see OOP Patterns discussed in the context of CFMX, is because its regarded as a "Nice Object approach to procedure code". Thats what a lot of the purists have worded to me about anyway, saying its not even *REAL* OO – debatable. So yeah, J2EE seems to be a main source of mirrored conceptulizations which sux as you kind of need to know Java in many ways to understand it. I think we should all (blogs I mean) finalize one big uber blog-fest for 2005 on the subject, and PDF for the future CF’ers heeheheh…

Posted by Scott Barnes @ 4/17/07 3:04 PM

Thanks Scott–I’ve certainly gotten a lot out of your conversations in Sean’s Breeze room as well as from your blog. I definitely agree with the notion that we need to ban together and blog the heck out of this stuff, and I’ve already thought about a series of articles (instead of just blog posts) for distribution as PDF (or FlashPaper! go MM!) so it’s a bit more easy for folks to take it along, print, etc. Once we all reach a consensus on everything (or even have 2-3 "best practices" for each of these areas) I think it will prove to be a great resource for CFers. Blog posts and subsequent comments (great place for us to hash out the details) can serve as great fodder for more formalized documents, tutorials, etc. (And let’s not forget those who are OO newbies, because these are numerous with CF; OO-101 stuff would be extremely valuable in addition to more advanced topics.) On that point, the other thing I think CF literature does a poor job of is indocrinating people into OO from the start. Yes, CF is intended to be easy to learn, etc. and I don’t think CF should lose that strength, but I think a lot of CFers don’t get into OO because it’s presented as "advanced" or "that weird other thing that a handful of people do." Once people get their feet wet with CF syntax, etc., OO should be presented as "the way you should be building things." In my opinion it’s not gaining traction because it’s seen as unnecessary or esoteric. Opening people’s eyes to the huge advantages and presenting it as how you do CF will help in this regard. As for whether or not CF is "real OO," you’re right, that’s debatable. I don’t typically engage in that debate because there’s no denying CF is missing some hallmark features of true OO, but in my mind nitpicking kind of misses the point. (Not saying you do this, but some folks do.) Let’s push things and do as much as we can with what we’ve got rather than not doing OO at all because this or that can’t be accomplished in CF.

Posted by Matt Woodward @ 4/17/07 3:04 PM