I've been tempted to respond to a lot of the recent threads about
factories, as I see a lot of blind following and not a lot of analysis
of the solution. Let's start with the problem: our CFCs have external
dependencies, there's no way around it. A datasource name (dsn from now
on) is great example of such a dependency. 

First attempt at solving the problem is directly referencing dsn, e.g.
lots of #application.dsn#. We all know this is bad for a number of
reasons, the most important being that your CFC is now dependent on some
arbitrary variable in an external scope. I might want to repurpose your
CFC for an app that doesn't even USE the application scope!

Ok, then we move on to "passing in the dsn". This is much better, we've
established a way to supply the CFC with its dsn, and now the code is
more reusable because we can always create the CFC, pass in a dsn, and
be done... the CFC doesn't care about "where" it lives or whether an
application scope even exists.

Ah but wait, we now made creating the CFC more complex, a necessary
burden, but one that can mitigated by several strategies, one of which
is the factory pattern. If we make a CFC that's responsible for creating
CFCs, then we can move the complexity of creating that CFC into the
factory and hide it from the "calling code" (anyone who needs to
use/create our CFC). Hmm... but how will the factory know what dsn to
pass into the CFCs that it creates? You have to supply that somehow, or
maybe the factory goes and reads it from somewhere? Either way, now the
factory itself has become more complex to create, which diminuishes its
benefits a bit. The factory is still better because you can use it to
create multiple types of CFCs, which more than likely have common
dependencies like a dsn.

However, that's where the benefits of hand-coding factories stop. They
are rather inflexible... what if I have a "DAOFactory", which is
responsible for creating/configuring 10 different DAOs, and one day I
decide that the dsn which DAO #7 needs a different dsn than all the
others. You are now going in your factory to add a special case, which
is confusing because your factories should be pretty generic. Factories
are a good way to hide creational complexity, but they aren't the
end-all-be-all.

So, we move on to the two new kids on the block... one is known as the
Service Locator pattern. The way this works is that your CFCs use the
Service Locator to "look up" their dependencies. So when your DAO needs
a dsn, it asks the Service Locator for the value. It's actually not
typical for a Service Locator to contain simple strings, more likely
your DAO obtains a "service" from the service locator, which itself can
give the DAO that dsn value - but either way the concept is the same.

The problem with implementing the Service Locator pattern in CF is that
we don't have static classes, meaning we must supply a real instance of
the service locator to each and every CFC that needs to use it. So,
instead of supplying your DAOs with a dsn, you supply them with a
service locator (or you create a new service locator within every
component that needs it). That's why I don't like to use the service
locator pattern w/ CF, you are tying all your cfcs to a single instance
of something, and you lose the self-documenting nature of describing
your CFC's dependencies (meaning having a "dsn" argument to an init()
method tells me that this CFC needs a dsn... passing in a service
locator hides those dependencies).

Lastly we have what's known as Dependency Injection / Inversion of
Control. IoC containers are really just factories on steriods. That's
why ColdSpring's core class is called the "BeanFactory". It's an
all-knowing factory that's externally configurable. Primarily, it
resolves your CFC's dependencies by injection, either thru setter
methods or contructor arguments. The CFC you wrote that needs a dsn to
be passed in can be configured inside the ColdSpring BeanFactory in
about 3 lines of xml. You'll never hand-code a factory again. You won't
waste time dealing with creational patterns. Your components are easier
to test because you don't have to test the component and it's respective
factory at the same time. ColdSpring's core is essentially a
"factory-framework".

I hope that sheds some light on the differences between the more common
approaches to assembling a CFC-based model.

-Dave Ross

-----------------------------------------
CONFIDENTIALITY NOTICE: This email and any attachments may contain
confidential information that is protected by law and is for the
sole use of the individuals or entities to which it is addressed.
If you are not the intended recipient, please notify the sender by
replying to this email and destroying all copies of the
communication and attachments. Further use, disclosure, copying,
distribution of, or reliance upon the contents of this email and
attachments is strictly prohibited. To contact Albany Medical
Center, or for a copy of our privacy practices, please visit us on
the Internet at www.amc.edu.



----------------------------------------------------------
You are subscribed to cfcdev. To unsubscribe, send an email to 
[email protected] with the words 'unsubscribe cfcdev' as the subject of the 
email.

CFCDev is run by CFCZone (www.cfczone.org) and supported by CFXHosting 
(www.cfxhosting.com).

An archive of the CFCDev list is available at 
www.mail-archive.com/[email protected]


Reply via email to