Hi Brian, So if I understand: A Staff member has-many Projects A Project has-many Staff And fwiw, this is probably implemented in the db with a StafftoProjects (or ProjectstoStaff) join table.
A couple of comments. Firstly, from a pure object model, relationships are uni-directional (unlike in a relational db), but you *can* have two unidirectional relationships, so it is perfectly ok for Staff to have many projects and projects to have many staff. If you're using service classes (StaffService and ProjectService) you just need to use setter (not constructor) injection in ColdSpring or LightWire to handle the fact that each service relies on the other. If I want a list of staff and their projects, the simple (ignore performance) approach would be: StaffListBO = StaffService.getStaffList() Then you'd output StaffListIBO.getName(), StaffListIBO.getEmail(), and you'd call (for each Staff member in the loop) StaffListIBO.getProjects() that would return an IBO collection of the project beans, you'd then loop over those to display ProjectListIBO.getName() for each project. If you implement this, you're probably going to have an n+1 query issue (20 staff members = 21 queries). Hibernate is often smart enough to handle this kind of stuff intelligently, but I don't think any of the native CF ORMs are. You can solve a lot of this with caching, but if I was expecting a high traffic site, while I don't want to get into premature optimization, I'd still be concerned about this. My solution is a custom data mapper I wrote which is like an ORM, but allows me to describe some more SQL like requirements, so I could ask for StaffList with a propertynamelist of Name,Email,AssociatedProjectNames. I describe AssociatedProjectNames as a aggregate virtual field based on a "Staff has-many Projects" relationship and it generates SQL with the appropriate aggregation clause so I get back just the data I want in a single, performant SQL query. It's not OO, but it's a good fit to the use case. Personally I'd start by writing the query you actually want, I'd use that to load the IBO (add a property to the Staff IBO called ProjectNameList and just load that from your query) and you'll still be able to use any custom business logic related to the staff without worrying about what could become a real performance issue. But the truth is the best solution will depend on the details of your use case, non-functional requirements, and what you're most comfortable doing! Best Wishes. Peter > 2009/8/31 Brian H. <[email protected]> > > Thanks Matt and Peter. Responses greatly appreciated. > > I agree with both of you, and I am seriously looking into IBOs to > circumvent CF's performance penalty. > > If you don't mind me pushing my point forward a little more, I think > that the nature of my secondary question (aside from "should I use an > array of beans") is how to represent some of these relationships. > Let's please asume for the moment that we're talking as if we were > working in pure J2EE with native objects. > > Let's say that Projects and Staff are first class citizens in my > application (both have DAOs, Beans). Staff can be assigned to > projects, I would expect that my Project bean would be composed of > Staff beans (staff which are assigned to this project), and my Project > bean would have a "getStaff()" method. So, I could easily produce a > listing page like this by looping over a collection of Project beans > (then looping over the Staff beans inside of it): > > Project Name Start Date Staff > abc proj 2009-09-01 Brian, Remi, George > 123proj 2009-04-01 Remi, Frank > > But what if I want to do the other way around, and on the staff > listing page, list all projects that a staff happens to be currently > assigned to: > > Staff Name Email Currently Assigned Projects > Brian [email protected] abc proj > Remi [email protected] abc proj, 123proj > Frank [email protected] 123proj > > That is, I am looping over my staff beans (or using an IBO) and > calling a "getProjects()" and looping over each Project bean in the > Staff bean to output all of the project names. So now when creating > "abc proj" my ProjectDAO needs to call my StaffService (which calls > the StaffDAO) to grab the Staff bean "Brian", but in the process of > doing so, the StaffDAO would have to call the ProjectService (which > calls the projectDAO) to get the project bean "abc proj"! I have a > cyclical relationship here. > > Sorry to dump this all on you guys but I am scratching my head here > trying to figure out how to pull this off in a real application. > > -Brian > > On Aug 29, 8:50 am, Peter Bell <[email protected]> wrote: > > And just to pipe in, this is *exactly* what an Iterating Business > > Object was designed to solve. If you have dumb lists, use queries. > If > > you have collections of business objects with meaningful business > > logic, use an IBO to encapsulate that. That way you use the same > logic > > for 1 bean or 1,000 but are only instantiating one object so > > performance is never an issue, > > > > Best Wishes, > > Peter > > > > On Aug 29, 2009, at Sat Aug 29, 12:34 AM, Matthew Woodward wrote: > > > > > To answer the question in the subject: it depends. > > > > > Brian H. wrote: > > >> It always seemed to me that if you went through all the trouble > of > > >> writing beans and DAOs, that you should be able to grab an > array of > > >> beans and use those objects in the “listing” page. > > > > > You can certainly do this. > > > > >> Let’s forget any CF object instantiation performance concerns > for the > > >> moment and focus on core patterns. > > > > > Ah, but you can't forget performance. Doesn't mean you CAN'T do > > > this, but you need to always be aware of how much data your app > will > > > eventually be dealing with. > > > > > Short answer is that in Java you don't have to worry about this > > > because Java is so insanely fast compared to CFML when it comes to > > > objects. > > > > > That being said, it really just depends on how much data you're > > > talking about, and the performance impact weighed against a > > > realistic assessment of how your application handles data will > > > determine what you can and can't get away with. > > > > >> Here’s my problem. Let’s say that I > > >> am on a user listing page, and I want to loop over an array of > user > > >> beans, outputting values by calling “getter” methods. Along with > > >> simple Name and contact info, I also want to pull the names of > all > > >> projects this user is assigned to. This is obviously not > something > > >> typically stored in user bean. I obviously don’t want to have to > > >> instantiate whole project beans and compose them within the > user bean > > >> every time that I load up a user since that is pretty wasteful. > > > > > But if we're forgetting about performance concerns and just > looking > > > at it from an object modeling standpoint that scenario makes > perfect > > > sense. > > > > >> Have I totally lost my mind in wanting to use arrays of beans > instead > > >> of queries for my listing pages? Especially since my beans do all > > >> kinds of wonderful formatting for me like “getPhone()” and > > >> “getPhoneFormatted()”. > > > > > You haven't lost your mind, but you have to make the right > decision > > > on a case-by-case basis. If it's not much data we're talking > about, > > > great; I built an entire app this way and since it wasn't much > data > > > it worked great. Until the client called a year later and said, > "You > > > know those collections I told you would never consist of more than > > > 4-6 objects? Well now we have one with 130 objects and it's > running > > > kind of slow." :-) > > > > > Point being there's your ideal object model, and there's reality, > > > and reality can bite you a lot more quickly in CFML because of the > > > overhead associated with instantiating objects. > > > > >> I expect that the responses I’ll get here are going to be > “well, that > > >> is WHY you are supposed to use a gateway to return the listing > as a > > >> query, so you can pull all this cross-referenced data from the DB > > >> directly”. Yes I know, but doesn’t it seem like an awful waste > of all > > >> that bean/DAO programming? > > > > > Well, yes and no--again, depends on the app. Would I write a > > > reporting application using objects? Heck no--queries are great > for > > > reporting-type data, so it likely wouldn't make sense to use a > bunch > > > of objects in that case. Would I write a banking app and not use > > > objects? Again, heck no--having an "Account" object and a > "Customer" > > > object just makes way too much sense. > > > > >> I love the fact that my bean can have a “getPhone()” and > > >> “getPhoneFormatted()” method. I can even pass my bean a > > >> “PhoneFormatter” component to do the formatting. Now it feels > like > > >> that I have to repeat all of this work when pulling “listings” as > > >> simple CF queries. > > > > > Well there's are some happy mediums here. The reality of life in > > > CFML is queries are fast, huge collections of objects are slow. > > > That's life. If you want wicked fast performance with tons of > > > objects, you need to write your model in Java. > > > > > The other thing to remember is that listings are what query > objects > > > are for, so if you're avoiding them for some weird sense of "but > I'm > > > not 'doing OO'" (whatever that means), then don't. Smart > programmers > > > use the right tool for the job as opposed to blindly following > some > > > arbitrary set of so-called rules they think they should be > following. > > > > > So stepping off my soap box, you want object-like functionality > but > > > need speed for large collections? Use structs. In most of my > beans I > > > have a getMemento() method that returns the variables scope so I > get > > > the data from my beans without all the overhead. It's a great > > > compromise. > > > > >> Anyway, sorry for the long winded post. Just feeling a bit > > >> frustrated > > >> here at seeing what feels like an elegant architecture go to > waste. > > > > > I don't think it's a waste--even if you use it rather sparingly in > > > your application it leads to a much more maintainable app in my > > > opinion. Otherwise I would have ditched objects long ago. > > > -- > > > Matthew Woodward > > > [email protected] > > >http://www.mattwoodward.com/blog > > > > > Please do not send me proprietary file formats such as Word, > > > PowerPoint, etc. as attachments. > > >http://www.gnu.org/philosophy/no-word-attachments.html > > > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to Mach-II for CFML list. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/mach-ii-for-coldfusion?hl=en SVN: http://greatbiztoolsllc.svn.cvsdude.com/mach-ii/ Wiki / Documentation / Tickets: http://greatbiztoolsllc.trac.cvsdude.com/mach-ii/ -~----------~----~----~----~------~----~------~--~---
