The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Object Creation Style

I had an engaging discussion yesterday with a co-worker centered on the best way to handle object creation.  Option 1 was the simple free-for-all method where anyone that needs a certain kind of object just invokes the appropriate constructor and gets an instance.  Option 2 is building a Factory object and equipping it with methods to return objects of various sorts.  Finally, option 3 is the approach that is/used to be common with many of the Microsoft object models - basically identify parent object types and/or "Collections" and put Add methods on them to create child or member objects.

I thought it would be interesting to see what approach other folks favored.  I tend to prefer the Factory approach for a number of reasons (don't tell Benji Smith :P), while my friend likes the Microsoft collection  approach.  Any other votes?
Franklin Send private email
Friday, March 02, 2007
 
 
It can't be answered generically, it goes to purpose. Why use a factory when there's no intelligence needed in the creation? Should a string object be created by a factory just because?

The collection approach makes sense when you are using a framework that is managing the object and knows which object to create and how to configure it properly for the framework. It's in essence a factory that controls scope. Again, a string collection shouldn't be made just to create a string object.
son of parnas
Friday, March 02, 2007
 
 
Do The Simplest Thing That Works for each situation. For simple objects, just use constructors. For complex creation logic, use a Factory class. The collection methods are just a convenient short-cut for create and then add.

It's good to be aware of the different options, but the value comes from applying the right approach to each situation, not from picking a favorite and mis-using it.
Mike S Send private email
Friday, March 02, 2007
 
 
In the interest of being brief, I left out the context of our discussion, which probably makes a pretty big deal.  We were talking about implementing the Domain Object Model, so the objects we're talking about creating would be domain objects.  Certainly I wouldn't want to have to use factories to instantiate strings and other basic stuff like that.

One of the reasons I tend to lean towards the factory, all else being equal, is because the factory allows me to make the client code depend on an abstraction/interface and keep the concrete class hidden.  This has been a boon to me when it comes time to do testing because I can simply swap in a different factory to return instrumented versions of the classes, or even mock objects, without modifying the client code.
Franklin Send private email
Friday, March 02, 2007
 
 
I agree - in that situation, a factory makes sense.
Mike S Send private email
Friday, March 02, 2007
 
 
For what you're talking about a Factory makes sense, the factory returns interfaces instead of objects.

Alternatively you can do a data object pattern where your domain objects are essentially structures (or in the case of Java, JavaBeans) that are passed to business objects that operate on them, and to data layer objects for persistence management.

In this case, your data layer creates the objects and fills them (which is a factory of sorts), passing them to your business layer, which then passes them to a display layer that renders them.


It really does depend on what you're doing and the nature of the objects.  It is very possible to over-Factoryize things.
Dan Fleet Send private email
Friday, March 02, 2007
 
 
If you have multiple classes extending from one common class, that's a good indicator a factory might make sense.  Clarification: that is for objects of classes like orders, customers, etc., not Stringy thingies.
OneMist8k
Friday, March 02, 2007
 
 
"It is very possible to over-Factoryize things"

That's for sure.  That's why I mentioned Benji Smith above.  He wrote an excellent post a couple years back on the subject:

http://discuss.joelonsoftware.com/default.asp?joel.3.219431.12

Excellent read if ya haven't read it before.

This is really an instance of a more general problem - too many levels of indirection.  I was fiddling with those Enterprise Application Blocks and they are a lovely example of that problem.  It's maddening trying to track down any specific behavior in that mess - everything is forwarding responsibility to something else.
Franklin Send private email
Friday, March 02, 2007
 
 
I don't quite like having a lot of constructors to differentiate varients of an object. If I find myself with 3 or more constructors, I may...
 - Use a static factory method (aka creation method)
 - Remove convenience versions and instead use null or NullObjects to differentiate.
 - For many parameters, refactor to a parameter object.
 - Use factories and interfaces for complex object creation or to provide different implementation strategies.

I really, really hate it when people create a bunch of constructors for abstract objects and force you to implement each to comply with their framework. Most of the time they are simply convenience versions that could easily be done away with.
Manes
Friday, March 02, 2007
 
 
!!!
BenjiSmith Send private email
Friday, March 02, 2007
 
 
That's a great thread Franklin.  Thanks.
Dan Fleet Send private email
Saturday, March 03, 2007
 
 
Strange that no one mentions dependency injection in this discussion.  For those not familar, take a look at the Spring Framework or the Spring Framework.NET.

The basic idea is that you leave the instantiation of your objects to the external framework (which creates them according to some configuration specified by you .. but not in code).  Thus, if an object needs to make use of another object, it receives this object via a setter method or via the constructor.  ie, you avoid creating object on the fly.

One of the biggest advantages of this is that when properly done, it improves greatly improves your ability to unit test your object.  Say you have an object A which makes use of objects B and C.  Object A might contain setter methods for objects B and C so that object A doesn't need to worry about creating them.  Therefore, when you write a unit test of object A, you can pass 'mock' or 'stub' objects to those setter methods so that your unit test is testing ONLY the functionality of object A.

When using dependency injection approaches, you don't need to worry about writing code for factories or singletons as the framework takes care of that for you.  Of course you still have complete control over how things get created, eg, you can specify that a particular object is non-singleton and is 'lazy' loaded.

It's certainly a different approach to OO however many large scale enterprise projects use this to great effect.  Worth considering.
Dev
Saturday, March 03, 2007
 
 
+1 for inversion of control and dependency injection. We prefer the Castle framework for .NET to Spring.NET, but that's just a personal preference.

That said, I don't like DI by setter / property. Constructor is better but only if the constructor is not available to the consuming assembly (ie it's hidden within the IoC framework). This is hard to do in some languages that don't have a way to allow a class in one assembly to access a class in another assembly in a privileged (ie non-public) manner without requiring inheritance.

Castle can get around this by using Reflection, which - while relatively costly - is an effective way of keeping your private stuff private while still allowing the IoC framework in to do DI.
.NET Guy
Saturday, March 03, 2007
 
 
(Forgot to mention that Castle does all of this through NHibernate and its own DynamicProxy which is now part of the standard NHibernate distribution. +1 for OR mappers too!)
.NET Guy
Saturday, March 03, 2007
 
 
I must be the only person on the planet who hates Inversion of Control. In my opinion, IoC is the epitome of obfuscation for enterprise Java projects.

I won't dive into that particular tirade right now, but you can read my most recent rant here:

http://discuss.joelonsoftware.com/default.asp?joel.3.432868#discussTopic434815
BenjiSmith Send private email
Saturday, March 03, 2007
 
 
Nice rant, Benji! Lots of good points there.
John Topley Send private email
Sunday, March 04, 2007
 
 
Yeah, I see your point too. Your NHibernate mapping files suddenly become a critical resource. That said, with NHibernate there are extensions which allow you to specify your mappings as attributes on your mapped classes, which then generate the mapping file at compile time. That's a good deal more transparent.

Thing is, re-compiling your code is not a major problem is the code is just used by you. As soon as you release code to be used by others as a binary dependency - even within your own company or group - then you have a major incentive not to re-compile, because without an efficient distribution mechanism you suddenly have umpteen versions of your code out there which you have to support all at the same time. That's why 'pluggable' systems with config files are so attractive to some people.

For me, modern OO programming is a continuous struggle of the concrete vs the abstract. There's a kind of instinctive pull a lot of people feel to make everything as non-specific as possible - to never hard-code in anything if you could make it configurable and pluggable and generic instead. It's definitely the road to architecture astronautics if you don't control it. As the saying goes, 'every program attempts to expand until it can read email'.

As always, it's a question of finding the right balance. If you took the IoC/DI/OR mapping/code generation route to its logical conclusion, your program would be a set of config files and rule templates and the actual code would just be generated automagically at runtime. I suspect some people would find that idea curiously attractive, if it were practical.
.NET Guy
Sunday, March 04, 2007
 
 
> For me, modern OO programming is a continuous struggle
> of the concrete vs the abstract.

Nicely put.


> your program would be a set of config files and
> rule templates

That's really the idea of MDA and it makes sense there. It's the inbetween that's always hard.
son of parnas
Sunday, March 04, 2007
 
 
Benji: Read your rant in the other thread ... you state that the purpose of DI is to avoid having to recompile code.  That is completely missing the point of DI.  Using DI improves code reuse and testability by ensuring that code within an object is not concerned with the creation of other objects. 

I agree its not the be all and end all .. but have you actually used it on a decent sized application?
Dev
Sunday, March 04, 2007
 
 
Dev:
"Using DI improves code reuse and testability by ensuring that code within an object is not concerned with the creation of other objects."

I guess I just don't agree that moving the creation of all objects out of the semantically well-defined language of your application and into a morass of configuration files contributes, in any way, to code reuse or testability.

When I'm working with a java source code file, I can glance up at the top of the file, at all those 'import' statements, and get a clear picture of the class's dependencies. If I don't like the dependencies, I can refactor. If I don't like an object creating its own dependant objects, I'll create a Factory class to manufacture them for me.

I just really really hate that inversion of control requires defying the semantics of the language. When I see an object that's never instantiated in code, I see a programming error. And the java compiler agrees with me.

The fact that an external tool rewrites the bytecode at runtime doesn't ameliorate the problem, in my book, because the pervasive invisible dependencies are still very difficult to decypher when you're authoring code in a large project. Maintainability goes completely out the window, because if anyone else works on the project, they won't be able to find the dependencies without digging through a nightmare of XML.

If it's really necessary to wire objects together outside of compiled code, I propose the following:

// Normal imports
import java.util.Map;
import net.benjismith.Whatever;

// Configuration imports
import org.spring.MyInsaneConfig.xml

class MyClass {

  // Instead of leaving an invalid null object
  // here, explicitly declare that an IoC container
  // will be responsible for object construction.

  private Whatever myObject = BindAtRuntime(
    MyInsaneConfig.MyClass.myObject.ClassType
  );

  // ... class body...

}

Doing something like that would still allow the construction of objects (and the specification of which classes belong where) to be deferred until runtime. But at least the dependencies would be explicitly defined inline with code.

And when I'm writing code my favorite IDE, I could simply CONTROL-click on the configuration binding to read its definition.

Then again, we already have .properties files, and you could do the exact same thing with a ResourceBundle and reflection.

I honestly don't see the benefits of IoC containers, when Factory classes and ResourceBundles already provide a solution to the problem, without having to defy the semantics of the language to do so.
BenjiSmith Send private email
Sunday, March 04, 2007
 
 
> The fact that an external tool rewrites the bytecode at runtime doesn't ameliorate the problem,

Definitely agree. Being able to build a mental model of what is happening from the actual source code is crucial to development. The more magic the more faith we need instead of hard science.
son of parnas
Sunday, March 04, 2007
 
 
This has been an extremely educational thread. 

There are some aspects of frameworks that I like, but I too struggle with the concept that the behaviour of my system is not specified in the code, but in XML files scattered through an application.

The applications I work with don't require extension at runtime, if I need to fix a mapping, I will be recompiling the application for deployment anyway.  So I'm not sure what the joy in being able to tweak a bean mapping in an XML file gets me vs mapping it in code and having it validated.

Once again, both sides of this discussion have been enlightening to me.  Thank you all.
Dan Fleet Send private email
Sunday, March 04, 2007
 
 
I don't know what Dependency Injection is, but the second I saw a post endorsing it, I knew there would be another one admonishing it further down.
Greg Send private email
Monday, March 05, 2007
 
 
As I soon as saw a post saying they don't know I major concept like DI, I knew I would see a post like this.
son of parnas
Monday, March 05, 2007
 
 
I've never worked with Spring, but it sounds like the same sort of stuff I ran into when using the .NET Enterprise Application Blocks.  These things all have configuration files filled with specifications that essentially map various roles/interfaces onto implementaiton classes.  At runtime, some assembler class reads the configuration file(s), converts the various specifications into instantiated objects, and then stitches them all together. 

Maybe this works great if you are following one of the recipes that comes pre-packaged with the system, but I can tell you from experience that it's zero fun trying to walk through the code to see where you need to patch in to make something custom happen.  I'm on the "don't do it" side of this issue.

Why not just encapsulate your creation policies into a single factory class.  When you need to change policies, it's easy enough to just swap the .class or .DLL file for a new one with the new policies in it.  This let's you have all the benefits of working within the programming language and also the benefits of being able to deploy new policies at will.  What's the allure of the XML configuration file for stuff like this?
Franklin Send private email
Monday, March 05, 2007
 
 
"I've never worked with Spring, but it sounds like the same sort of stuff I ran into when using the .NET Enterprise Application Blocks.  These things all have configuration files filled with specifications that essentially map various roles/interfaces onto implementaiton classes.  At runtime, some assembler class reads the configuration file(s), converts the various specifications into instantiated objects, and then stitches them all together."

Well, yes, sort-of. But, critically, Spring is actually decent code and a good design. The Application Blocks look like they were put together by someone whose idea of good architecture is ADO. Shudder.
.NET Guy
Tuesday, March 06, 2007
 
 
"The Application Blocks look like they were put together by someone whose idea of good architecture is ADO."

Heh, that's an insightful comparison.  I think I'll borrow it for future use, if you don't mind :)  Always wanted a nice concise way to express my horror at some of the slop that passes for production code at work.
Franklin Send private email
Tuesday, March 06, 2007
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz