Creating Service Objects And Value Objects In A Dependency Injection (DI) Framework

Posted May 10, 2012 at 11:19 AM by Ben Nadel

Tags: ColdFusion, Javascript / DHTML

For the last couple of months, I've been thinking a lot about my level of programming and my architectural understanding. Currently, I feel like I know enough to get most things "done." But, with the increasing complexity of my applications, especially those that require robust, modular client-side JavaScript, I'm filled with anxiety that I won't be able to create code that is easily maintainable and augmentable. As such, I've been putting a lot of time into reading up on Object-Oriented best practices and trying new exercises like Object Calisthenics in JavaScript.

This morning, I found a very interesting article by Misko Hevery on the use of the "new" operator for object instantiation. In his article, Hevery lays out some guidelines that can help keep your code cohesive and easy to test.

First, he asserts that you should try to avoid calling the "new" operator as much as possible within your code. Every time you call the "new" operator, you make your code harder to test because you have object-creation logic encapsulated in such a way that your testing framework cannot easily manipulate it. When possible, the "new" operator should be deferred to some sort of Factory that can use a Dependency Injection (DI) framework.

That said, there are types of objects that the dependency injection framework simply can't know about. He refers to these objects as "Newables." For this blog post, I'll refer to them as "Value" objects. And, I'll refer to the other objects (the ones the DI framework can know about) as "Service" objects. These Value objects must be created inline using the "new" operator.

In this context, Hevery lays down the following guidelines:

  • A Service object can ask for other Service objects in its constructor.
  • A Service object can never ask for a Value object in its constructor. This is because the dependency injection (DI) framework will not know how to create the required Value object.
  • A Value object can ask for other Value objects in its constructor.
  • A Value object can never ask for a Service object in its constructor.
  • A Value object can be passed a Service object as part of a method call; however, that Service object cannot be stored in the state of the Value object. In other words, the Value object cannot retain a reference to the Service object.

I don't know enough about Object Oriented Programming (OOP) to know whether or not these guidelines make complete sense. I can understand that removing dependencies will probably make your classes more cohesive as the potential for "responsibility" has been limited. There are probably situations where these guidelines must be broken; but, like the Object Calisthenics exercise, leaning on these guidelines for "advice" will probably have beneficial effect on how you think about your code.

If nothing else, running into a situation that violates these guidelines might just give you pause to ask the question, "Is there a cleaner way to wire this together?" And, the more we question our status-quo, the more likely we are to find better ways of doing things.




Reader Comments

May 10, 2012 at 12:29 PM // reply »
19 Comments

I think we should always be a little weary of taking advice straight out of Java. Thankfully, ColdFusion isn't Java and the fact that CFCs don't have an automatic constructor means that we *can* use object factories for our VOs.

The calling code can get an uninitialized object from your object factory and call the VO's init() method with the arguments that it only it knows about. So:

var myVo = voFactory.getVo( 'myVo' ).init( foo=bar );

I believe that there should then *never* be a need to use the new operator in ColdFusion if you are using object factories.

Thoughts?


May 10, 2012 at 12:42 PM // reply »
13 Comments

Odd that I'm currently working through much the same issue while developing some standards for Unit Testing. And with much the same recommendations: heavier reliance on DI and factories while avoiding objects instantiated within a method using the "new" keyword.

As a result, though, our unit tests are getting much more accurate and we have a solid foundation to begin TDD.


May 10, 2012 at 1:58 PM // reply »
11,241 Comments

@Dominic,

As far as the ColdFusion or JavaScript vs. Java, I can say that Hevery does do a lot of JavaScript and loves it. But, he does draw some comparisons / contracts. From his blog, here's what he says about Dependency Injection in JavaScript:

"All of the things which I have talked about in my blog is still true. Dependency Injection is a must and JavaScript's dynamic nature does not make go away. Anyone who claims that DI is only for Java and that his language somehow makes it exempt form the rules of managing your dependencies, needs to lear more about DI. Similarly global state is a bad idea, and JavaScript is extra bad here, as global is the default and you have to do extra typing to get propers scoping, same goes to functions and their default affinity to global state. Bad JavaScript, Bad! Separation of wiring from logic still holds true and no amount monkey patching, will keep you sane in the long run."

... However, he says that due to the nature of JavaScript, "duck-typing" can replace most inheritance situations:

"I have written 10,000's of lines of JavaScript and I am yet to come across a need for inheritance. Where did it go? Proper use of inheritance == polymorphic behavior but one can get that with duck typing just by implementing the right kind of methods."

As far as the validity of much of this, I simply don't have the experience to say. All I can say is that I don't know enough and I'm willing to do a lot of experimenting.

As far as the Value Objects and the DI framework, I don't get the sense that he was talking about serving up the class definition via the DIF. I think it was more like the DIF cannot init() the class.

@Matt,

Very cool to get some ColdFusion / real-world points of view. I'm excited to be challenging myself to think differently. I really should also start getting into TDD - I don't know much about tests yet :(( shameful :)


May 10, 2012 at 1:59 PM // reply »
11,241 Comments

@All, the two quotes above came from this blog post:

http://misko.hevery.com/2010/04/07/move-over-java-i-have-fallen-in-love-with-javascript/


May 10, 2012 at 3:29 PM // reply »
19 Comments

@Ben, I *think* that he was very much saying that you can't serve up your VOs through the DIF. I believe his reasoning being that you cannot create an object without invoking its constructor in Java (folk correct me if I am wrong), so that a DIF wouldn't automatically know how to create the VO and you couldn't do the example I gave in Java.


May 10, 2012 at 6:01 PM // reply »
11,241 Comments

@Dominic,

That could very well be what he was saying - I am in no place to argue for or against it. That said, having the class definition encapsulated in the DI / factory would make the embedded instantiation more testable (as far as I can see).


May 11, 2012 at 4:01 AM // reply »
19 Comments

@Ben, yeah more testable + more controllable in terms of how you decorate objects and how you switch in different implementations, etc.

I'm sure if he could, he'd never use 'new', just that given the language constraints he is somewhat forced to.

I probably came over a bit rude with my we're not Java comment (unintentionally) but I think its something we should always keep in mind - we can avoid all the things that make coding in Java a PITA.


May 11, 2012 at 8:00 AM // reply »
11,241 Comments

@Dominic,

Absolutely no "Attitude" detected! We're just having a good conversation about awesome programming stuff. You think I have any idea what I'm talking about on this matter?! I'm just trying to wrap my head around it.


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 22, 2013 at 11:47 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Dana, Awesome - so it looks like this bug was fixed in ColdFusion 10. Thanks so much for double-checking that. ... read »
May 22, 2013 at 11:37 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
When I c&p and run on cf10, I get: Selected User IDs: 1,4 User 1 selected: YES - YES User 2 selected: NO - NO User 3 selected: NO - NO User 4 selected: YES - YES User 5 selected: NO - ... read »
May 22, 2013 at 11:27 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Tom, Good thought, but no dice. Both of these still exhibit the same behavior: users.id[ users.currentRow ] users[ "id" ][ users.currentRow ] It's just something whacky happening with ... read »
May 22, 2013 at 11:07 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
Could your problem be that "users.id" is actually an ARRAY, not a single value? Perhaps try it again with "users.id[1]" (I only have CF8 here at work). ... read »
May 22, 2013 at 7:52 AM
Nested Views, Routing, And Deep Linking With AngularJS
Hi, Just a quick thank you. As it happens, for my own purposes, the pending ui-router work being done in native angular is likely the one I'll adopt, but your exploration, code and documentation of ... read »
May 22, 2013 at 4:43 AM
How Do You Use The ColdFusion CFParam Tag?
'<cfparam>' or 'isDefined()and <cfset>' performs the same task.Is there any difference? ... read »
May 21, 2013 at 7:46 PM
Using Plupload For Drag & Drop File Uploads In ColdFusion
No luck. At least I have uncovered the cause, URLScan 3.1. Here is what I see in the IIS log when a file is over 30mb. 2013-05-21 23:29:05 10.105.45.128 GET /plupload/assets/jquery/jquery-1.8. ... read »
May 21, 2013 at 6:12 PM
Using Plupload For Drag & Drop File Uploads In ColdFusion
Ben, I did not see you after Pete Freitag's Lockdown session at cfObjective but he said that IIS sets file size limits at 30MB by default which just happened to be the threshold for file size when ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools