RE: [coldbox:17842] [Coldbox 3.5.3] - Wirebox Question about OO models and how they get populated.

83 views
Skip to first unread message

br...@bradwood.com

unread,
Mar 18, 2013, 1:07:35 PM3/18/13
to col...@googlegroups.com
> I don't see how wirebox could choose which type of address object to use and I'm not sure where the responsibility for populating that address object lies.

WireBox wouldn't choose.  Your code would decide what it wanted and ask Wirebox for an instance of whatever object you need.

> I've seen the UserService objects created in samples. Would I also have an Address Service object?

You can if you want.  I wouldn't though (see personal practices below)

> Would the UserService object have to know all about the the address service?

I don't know what you mean by "all about", but ideally the user service would only "know" about the public methods (or API) of the address service.  The userService can easily get a reference to the addressService by annotating itself so WireBox will autowire the address service in when it creates the userService.

userService.cfc
component singleton {
    property name="addressService" inject;
}

>  I dont' see the difference between an userservice object and an UserFactory object.

Frankly, I don't know that there is a difference other than the name. 

I think you're looking too much at ColdBox MVC to tell you how to do your models.  The real answer is, "However you want."  I know that might not be a useful answer, but the reality is that ColdBox provides support for doing just about anything you want, but it is very un-opinionated when it comes to forcing you down one path or another.  Many people are using ColdBox and everyone probably handles their models (and what they call them) a little differently.  Now, you're likely to get lots of good advice on this list about how your models behave, but know that it's just the good advice of what's worked for us-- not any sort of mandate from ColdBox-land.

---- Begin random non-ColdBox biased advice :) ----
  • I'm not using ORM-- mostly because I started building my app at work before CF ORM came out. (I kind of wish I were though)
  • I would avoid having a service, bean, and DAO for every table in your database or you'll wind up with an anemic domain model. 
  • I typically have a DAO and bean for MOST tables (those that represent entities, which excludes pure-xref "relationship" tables)
  • I group together related beans and have them all fall under a single service.  This also makes sense since my services exist to handle behaviors of my application that involve more than one bean.  I also call my services to create any new instance of beans (which then in turn delegate to WireBox to create the autowire the transients), but that's just the way I do it.
  • I handle object composition (has-a relationships) with some hand-built lazy loading.  So, the user object loads and persists the address object via a service method the first time it's requested.
  • I don't do inheritance (is-a relationships) as much as I'd like, but that's because we use Peter Bell's IBO pattern which requires a collection of entities are stored as an array in a single object which makes polymorphism harder.  (I kind of regret doing that now though) 
  • When I do inheritance, the service makes the call as to what object it's going to create when it's asked to create something.
  • If it's SQL (except QofQ) put it in the DAO. 
  • If it's a behavior of a single object, try very hard to put in the bean over the service.  (fat beans, thin services)
  • If it's a behavior of several related objects, put it in the service, but still keep the service code as thin as possible (delegate to beans where possible)
  • The most important piece of advice, is your app should live entirely in your models.  ie, if you have a shopping cart-- you should be able to do everything you need to create and populate that shopping card in a test page without hitting a handler.  Keep business logic out of the handlers, and just let them push form fields around and set views.
---- End random non-ColdBox biased advice :) ----

Feel free to ignore as much as the above as you want-- it's just how I prefer to do things.
If you have questions about what I do, please ask. 
More importantly, if you have questions about how to accomplish what you want to do, please ask.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: br...@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com 


-------- Original Message --------
Subject: [coldbox:17842] [Coldbox 3.5.3] - Wirebox Question about OO
models and how they get populated.
From: Keo_74 <kenneth....@gmail.com>
Date: Mon, March 18, 2013 11:08 am
To: col...@googlegroups.com

Hello, I am new to Coldbox but have been programming Coldfusion 7+ years. I am new to using MVC in the coldfusion world, so some of what i'm looking for may not be coldbox specific.

I have been going through the online documentation and the videos, but honestly have grown somewhat frustrated because of how every document seems to be for a different version of coldbox.

I have looked at the sample apps but they too seem out of date.

So enough of my I'm a frustrated newbie disclaimer. 

My company is looking at using coldbox in their next project. What I am trying to reconcile in my brain right now is how complex models would work in the Coldbox MVC world. 

I do not want to use ORM at this time.  

In the presentations videos I've watched it has been said that Coldbox Wirebox DI replaces the whole object factory pattern.  But it seems to me that most of what the object factory was doing is just moved to a service object. So I'm not sure if I'm missing something. 


Take the following models for example. 

  • Model : User
    • First name
    • Last Name
    • User Name
    • User ID
    • Address 
  • Model :Address
    • Address_1
    • Address_2
    • City
    • State
    • Country
    • Zip
  • Model : GalaticAddress  
    • Extends Address
    • Solar System
    • Sector
    • Planet
So in the Object Factory world I would have something like an object called UserFactory. Which would have a method getUser (ID). The factory would connect to an UserDAO object, pull back the data, create a new user object, insert the data from the UserDao,  Then the Factory would use AddressDAO and pull back the address and based on the type create either a Address or Galactic address and insert the resulting address object into the User object which is returned.

How would I do this in the ColdBox MVC world. I understand that I can have an user model that has a address model injected vi wirebox DI but I don't see how wirebox could choose which type of address object to use and I'm not sure where the responsibility for populating that address object lies.

I've seen the UserService objects created in samples. Would I also have an Address Service object? 

Would the UserService object have to know all about the the address service?

 I dont' see the difference between an userservice object and an UserFactory object.




--
--
You received this message because you are subscribed to the Google Groups "ColdBox Platform" group.
For News, visit http://blog.coldbox.org
For Documentation, visit http://wiki.coldbox.org
For Bug Reports, visit https://ortussolutions.atlassian.net/browse/COLDBOX
---
You received this message because you are subscribed to the Google Groups "ColdBox Platform" group.
To unsubscribe from this group and stop receiving emails from it, send an email to coldbox+u...@googlegroups.com.
To post to this group, send email to col...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Keo_74

unread,
Mar 18, 2013, 2:04:57 PM3/18/13
to col...@googlegroups.com
Thank you for your insight.

I guess I'm trying to come up with best practices and guid lines. My company is new to Coldbox and I was asked to look into the Coldbox way of doing things when it came to handling objects. 

Your non-coldbox advice is really helpful. My fear is that we are going to have a coldbox framework but everything inside custom coded, which defeats the purpose of using a frame work.

I was kind of looking at the basic bean as just a object for storing data. In a normal OO environment the Factory would handle all of the population of it to keep things loosely coupled.
Having fat beans simplifies it but it does tighten the coupling.

If I think of the service objects as factories I can make it work, but whats the point then in using wire box. I can see how it makes doing singletons easier, but when it comes to more complex objects I don't understand.

I'm going to work on some test apps. Either things will fall into place for me or it might help my questions become more specific as I try to get it to work.

Thank you for your help.

Jason Durham

unread,
Mar 18, 2013, 4:05:34 PM3/18/13
to col...@googlegroups.com
I think you'll find many folks prefer that their model remain portable between MVC frameworks. As such, my service layer doesn't not make use of any Coldbox-specific awesomeness.  For example, I've created abstract classes to handle populating simple values and I manage relationships directly in my service methods.  As Brad said, my model can be called directly from a CFM.

It doesn't sound like that's something you're looking for.  The good news is.. Coldbox also provides many helpful bits that help you generate services (see VirtualEntityService) and also contains many helpful utility methods (populateModel()) that will give you functionality not found in most MVC frameworks.  I suggest starting from scratch on the documentation to learn what Coldbox _will_ do for you, rather than make assumptions of what you think it should do.  

Jason Durham

Keo_74

unread,
Mar 19, 2013, 10:08:02 AM3/19/13
to col...@googlegroups.com, ja...@durhamcons.com
Thank You for your response.,

I've read through the documentation and watched as many of the videos that I could find. I have made no assumptions other than I want to use coldbox as the framework. The documentation is good at showing the technical side of the functions but doesn't really give you the why or how.

Also depending on what page you are reading so much of it seems out of date or you just get snippets, no offense entended.

I started by creating my own object factory and models but I was asked to look into using wirebox. I think there may be a misconception on the part of my company that wirebox is this one method solution to OO. In other words that wirebox replaces the traditional object factory pattern.

It sounds like the truth is somewhere in between and wirebox works with the object factory pattern. I'm sure that as I delve more into it that I will find more uses for it. I just didn't want to go down the path of setting up my own factories or services to find out that it was not the perferred wirebox way and then have to re-write everything. But if there is no preferred way then it doesn't matter.

I have a feeling we will end up with something similar to what you are describing. 

Matt Quackenbush

unread,
Mar 19, 2013, 10:11:16 AM3/19/13
to col...@googlegroups.com
Wirebox is not a bean factory, per se. Wirebox *is*, however, an IoC / DI solution.

http://en.wikipedia.org/wiki/Inversion_of_control
http://en.wikipedia.org/wiki/Dependency_injection

HTH

Sana Ullah

unread,
Mar 19, 2013, 10:45:27 AM3/19/13
to col...@googlegroups.com
Hi Keo,

The "request life cycle" is most important aspect of any framework. Rest of implementation is up to developer's understanding and choice.

For example service, dao layer could be 100% independent from framework.  
Developer can also take advantage of framework tools using domain layer and speed up development work.

Here is list of documentation which will help you in understanding more about framework and tools

Step 1: ColdBox Request Life Cycles

Step 2: ColdBox Configuration CFC

Step 3: Model Integration Guide

Step 4: WireBox: The Enterprise Dependency Injection Framework

-- 
Warm Regards
Sana

br...@bradwood.com

unread,
Mar 19, 2013, 1:58:30 PM3/19/13
to col...@googlegroups.com
I'm not entirely sure what your company is expecting WireBox to do so I can't address that too specifically, if someone thinks it's magic pixy dust that creates everything for you, there mistaken.  :) That being said, WireBox is incredibly useful and I can't imagine not using it.  (We have 300 model CFCs between our Services, Beans, and DAOs)

Things WireBox can do for you:
  • It's an object factory.  I know Matt said it isn't, and to some degree it might not fit everyone's definition, but as far as a class responsible for abstracting the creation of objects, I'd say yes it fits that. http://en.wikipedia.org/wiki/Factory_%28software_concept%29
  • WireBox can create just about anything-- CFCs, java objects, web services.   It can also create them based on the full component path, or by mapping IDs of your choice configured ahead of time in the config.  You can explicitly configure the mappings or let Wirebox scan your model convention folders for you.
  • It's an ioc container.  Ioc stands for inversion of control which is basically a fancy word that means your code knows less and delegates to a framework that knows all the necessary details.
  • It is a DI engine.  DI stands for Dependance Injection.  If you have a User bean and it needs a reference to the userDAO, you could say the userDAO is a dependency of the user bean.  WireBox is capable of creating each user bean with a reference to the userDAO automatically if you configure it to (or annotate the user bean to signify that it requires it)
  • It does setter injection (calling setter methods to set dependencies after creation)
  • It does constructor inject (passing dependencies into the object constructor upon creation)
  • It does mixin injection (Using small amounts of of pixy dust to inject references to dependencies directly into private scopes after creating objects.
  • It does persistence.  This means you can specify an object to be persisted in any CF scope, as a singleton, or in any CacheBox provider.  Then you forget about it and just ask WireBox for the object and it will take care of creating OR retrieving that object from its scope.
  • It does AOP.  AOP stands for Aspect Oriented Programming and is too long to describe in a single bullet point.  In short, imagine if you could configure an arbitrary chunk of code to execute before and/or after any method(s) in your entire code base without every actually touching those methods.  This could let you enable, security, logging, or caching all across your application with just a few lines of configuration code.
  • There are a number of other things WireBox does, but these are the highlights. 
Things Wirebox will not do for you:
  • Automatically write SQL for you
  • Automatically create services or beans or accessors/mutators for you
  • Automatically load composite objects outside of the dependencies you have autowired
  • Save or load data from the database into your objects
  • Automatically decide what classes should inherit from what other classes (it does have some cool virtual inheritance that you can configure yourself though)
Hopefully that helps put in perspective what you'd use WireBox for.  Like I said, I can't imagine NOT using WireBox.  Most people don't even touch half the stuff on my list above-- they just use WireBox to persist their singletons and inject references to their dependencies and honestly that alone is worth it.  If you are wanting a framework to help with more, there are things like ORM that cover a lot of the bases in my second list and we can talk to you about what's available for that.

> Also depending on what page you are reading so much of it seems out of date or you just get snippets, no offense entended.

Can you send us links to pages that look out of date or confusing?  We'd love to fix them.  As a rule of thumb, the latest version of the docs are all on wiki.coldbox.org and have a note at the top that says something like "Covers up to version 1.6" (that's from the WireBox page).

Keo_74

unread,
Mar 19, 2013, 4:06:13 PM3/19/13
to col...@googlegroups.com
Well since you asked. Lets take the main wirebox page as an example. located here http://wiki.coldbox.org/wiki/WireBox.cfm

Section : Advantages of a DI framework
Second bullet point: "By giving WireBox DI responsibilities, you will stop creating objects manually or using custom object factories.'

It sounds like to me, based on that, I will be able to stop using custom object factories. So how do I do that? 

Looking a little bit further down the page I see. A primer to Wirebox injection.   This is where I kind of feel like you only get part of the picture. The coffeshop example shows the different ways to do injection which is great. But object factories are more than just that. They are about pulling in all the resources to return to you an instance of a object.  But the example never shows how that part would work with wirebox.  It doesn't really show you how you would stop using object factories as stated in bullet 2 up above.

After the short expresso example the page  jumps to mockbox integration and then binders and mappings and more advanced stuff from there. I'm sure that is great for when you have been using wirebox for awhile and need to lookup what the different scopes are, but for a person trying to learn what wirebox is and how the way you are used to working with objects translates to it.. it can be a little frustrating. 


Now this page is great : http://wiki.coldbox.org/wiki/Models.cfm

It does a great job of showing more of the components from start to finish and how they interact. I just wish that it showed some examples that didn't use populateModel () (other than the ORM examples) and maybe another model with a little bit more complex structure. For example if Contact.cfc contained a PhoneNumber object.  Where would the responsibilities lie for populating it and how does that work with Wirebox DI.

Anyway I'm not trying to nitpick, I like what I've seen of coldbox and wirebox. I'm just trying to figure out how it's going to fit into my environment and how we are going to get the most from it.

Mike Craig

unread,
Mar 19, 2013, 4:51:06 PM3/19/13
to col...@googlegroups.com
It gets better

Mike

br...@bradwood.com

unread,
Mar 19, 2013, 5:46:53 PM3/19/13
to col...@googlegroups.com
Thanks for the feedback.

> It sounds like to me, based on that, I will be able to stop using custom object factories. So how do I do that?

I'm not sure how to answer that question.  I think your confusion mostly comes from the fact that you call your services object factories.  At some level, I also interrogate my UserService when I want it to load an instance of a user object, but I don't consider it an object factory per se-- I think of it more as the API to my application.  Internally, the service method asks WireBox to provide it with a user object, which it then calls some methods upon to load data into that user.  Afterwards, the service method may consider implementing caching of that object for later use.  I see an object factory as a class that abstracts the creation of the object as well as the actual full component path and gives that object everything it needs to do its job.  My services do much more than that as they actually begin calling methods on my objects, loading them with data, giving then state and changing that state as well as interacting with the other moving parts of my application.  If I were to guess, you use the term object factory in a different light than our docs use it.

> The coffeshop example shows the different ways to do injection which is great. But object factories are more than just that. They are about pulling in all the resources to return to you an instance of a object.  

But that _is_ what the example does.  in that code sample, a CoffeeShop has a single dependency of an expressoMachine. 

> But the example never shows how that part would work with wirebox.  

Look at the property line of code at the top of the CoffeeShop class that looks like this:
property name="espressoMachine" inject="id:espressoMachine";

That is all you need.  Now, if you were to create an instance of the CoffeeShop like WireBox.getInstance("CoffeeShop"), that CoffeeShop object will contain a reference to the expressoMachine class in its variables scope.

> It doesn't really show you how you would stop using object factories as stated in bullet 2 up above.

Lol, I'm not sure what to tell you.  It also doesn't tell you how to not use PHP...  the code is what it is.  All that is shown is what is necessary to inject a reference of one object into another.

> but for a person trying to learn what wirebox is and how the way you are used to working with objects translates to it.. it can be a little frustrating.

I agree.  That's also why I wouldn't recommend trying to read the full docs to get started.  It would kind of be like reading the CFML language reference straight through to learn CF.  I'd recommend watching a couple presentations on getting started and checking out our sample apps.  Here's a couple recordings of Luis demoing WireBox that you may find helpful:

> I just wish that it showed some examples that didn't use populateModel ()

If it helps, replace calls to populateModel() in your head with a list of setter calls; one for each property.

> maybe another model with a little bit more complex structure. For example if Contact.cfc contained a PhoneNumber object.  Where would the responsibilities lie for populating it and how does that work with Wirebox DI.

Well, we do try to steer clear of getting too complicated in the docs-- then people will tell us they're too deep :)  That might be a good idea of a new sample app-- one that shows more interaction between models. I think one of the reasons we've stayed away from showing too much of that is because it's outside of the framework and up to the developer to decide.  If your models use composition (i.e., a contact object has a phoneNumber object) that's up to the developer to choose how they want to implement that.  WireBox doesn't dictate how you want to do it, it's just there to help create and autowire the phoneNumber object when you're ready for it.

For what it's worth, I can tell you how I do it-- but everyone on this list probably has their own favorite (and different) solution.

  1. Firstly, my models all extend a base bean class with a generic get() method. 
  2. When you get the phone number for a contact, it would look like this: contact.get("phoneNumber"). 
  3. Internally, the base class keeps a list of what properties have been loaded into the contact object. 
  4. The first time I call contact.get("phoneNumber") my base class looks for and automatically calls a lazyLoadPhoneNumber method.  This method asks the contactService (which has been wired in via mixin injection) to load up the phoneNumber object and does something like so:
  5. this.set("phoneNumber",contactService.getPhoneNumber(contactID = this.get("contactID")));
  6. The contactService has WireBox injected into it and calls something like WireBox.getInstance("phoneNumber").read(contactID = arguments.contactID)
  7. The phoneNumber bean has the phoneNumberDAO autowired into it and the read() method delegates out the DAO to get a result set, and then sets the data into the bean.
  8. After that, the phoneNumber object is saved in the Contact object as long as the Contact object is kept in memory.
Now, honestly I wouldn't want to put all that in the docs because it's just how I personally handle loading composed objects in my application.  There's sooo many things I could do differently and we don't even try to steer you down one path or the other in the ColdBox docs. 

As far as the feelings of frustration trying to figure everything out-- don't worry.  it will, as Mike Craig said, "get better" :)  OO and DI engines are not a simple matter and there is a lot to learn.  Much of what you learn is that there's many ways to do something and they all have advantages and disadvantages.  The best way I've found to take it is to dive in and start trying stuff and ask lots of questions. 

Mike Craig

unread,
Mar 19, 2013, 10:23:44 PM3/19/13
to col...@googlegroups.com
Just to chime in an additional comment that is purely experiential, personal and, I hope, relevant...and simply because I can.

Coldbox, the Coldbox Evangelists, Luis' team and Ortis Solutions have really pushed the envelope of what ColdFusion can really be capable of by capitalizing on what it already there.  I have often shared in the frustration of "getting started" and truth be told, this is probably the forth time I have tried to pick up this framework in the last two years...those frustrations kept me away.  

I might argue I was not ready, I might argue Coldbox was not ready.  For every kudo I can give that list above I can also tell you I have been pissed off, angry, disappointed in or about...the list is endless.  Humans have flaws, code has bugs, but the effort is the thing.  Most (if not all) frameworks are free, but the time to develop, the extensive documentation and the unbelievable support make it WORTH that effort.

But change is not a quick thing and is seldom comfortable or easy.  "I do it this way", "I think it should be this way", "Why the hell are you doing that", "This just doesn't make any sense"...do any of those sound familiar?  This, like many things  for me at least, is an exercise in patience, tolerance and cooperation.  It never helped that I consider myself to be pretty smart as it tends to fail me as a measure of anything meaningful.  I remember a paraphrase that even caveman though fire was magic at first.  

We can say start slow, don't read it all in one sitting, try and try again...and that would be very good advice...but don't do what I did and stop before you even get a chance to start.  In the end, the effort will make you a better developer, EVEN IF you decided not to adopt Coldbox.

It can still be frustrating, but it is amazing how the effort has paid off and I am still awestruck by how much flexibility some of the simplest things have offered.

[ end philosophy and opinion ]

Mike
Reply all
Reply to author
Forward
0 new messages