Skip to main content
Ben Nadel at cf.Objective() 2012 (Minneapolis, MN) with: Shawn Slaughter and Scott Stroz
Ben Nadel at cf.Objective() 2012 (Minneapolis, MN) with: Shawn Slaughter Scott Stroz ( @boyzoid )

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

By on

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

22 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?

31 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.

15,640 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 :)

22 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.

15,640 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).

22 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.

15,640 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.

96 Comments

@Dominic

"Thankfully, ColdFusion isn't Java"

You'd probably be quite surprised if you decompile d ColdFusion to see how it really works ...

ColdFusion is a Java application ...

96 Comments

@Ben ...

All in all DTO's, VO's are supposed to be 'dumb' their sole purpose 'should' be to pipeline model objects around an application. Here's a colorful example.

"Hey Shop Factory Go Make Me a Pizza Shop :: Okay"

"Hey Pizza Shop Go Make Me a Pizza Delivery Boy :: God Responsibility"

"Hey Pizza Delivery Boy Go Make Me a Pizza Shop :: Shop Factory Responsibility"

"Hey Pizza Shop (CALL) Me a Pizza Delivery Boy :: Okay"

:-)

96 Comments

@Ben ...

Sorry for the delayed response ... I've been pretty busy...

Basically a DTO is simply an object that doesn't hold state ... it's typically a 'dupe' object used to transfer data. I.E.

@Entity
public class Pizza{ String name, int age... }

//pizza delivery boy
public class PizzaDTO {String name, int age... }

That being said... In my example I 'attempted' (poorly it seems ;-) ) to illustrate the correlation between a transferer ~ The Pizza Boy.

With all due respect to those hard-working pizza guys ... They have a simple responsibility ~ to transfer pizzas ... They go to and from the pizza shop(domain) to the customer(client)...

Sorry... if my example misses the mark...

Petri Kainulainen has a pretty good example of DDD using the DTO pattern...

http://www.petrikainulainen.net/programming/spring-framework/integration-testing-of-spring-mvc-applications-rest-api-part-two/

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel