3

I'm employing TDD quite a bit these days and really enjoying myself - everything seems to flow better and be naturally better constructed and organized. However, while writing a bit of IO code, utilizing System.IO.Streams, and I was wondering - when is it ever worth not using a factory? Because in Streams case, it certainly seems better to not use a factory.

Generally, for more complex types that I have defined, such as a class that controls the authentication of something and interfaces with a database, you would probably use a dependency injection container and have this resolved at runtime without ever needing to actually create one.

However, in some circumstances, when you need to create a lot of these instances, you would create a Factory to construct that type - such as:

class Foo
  Foo(Bar bar, Foobar foobar, Fuzz fuzz)
  ...
end

Here, because you don't want to expose how to directly create this object to the clients that need it, you expose a Factory that will create them and inject that into the client instead. This has the benefit of allowing you to replace the factory at any time you want with something else and is generally used for creating instances of types which have derived types.

class FooFactory
   void Create(Bar, Foobar, Fuzz)
end

However, back to my Stream point - would it even be worth creating a Factory for a decorator around a Stream? For example, in my project I have BinaryDataStream, which reads my data from a Streeam. The BinaryData is in a custom format, and takes a Stream argument in it's constructor. Using new seems to violate everything I know that I've learned since I started using TDD, because I am giving the dependent in which it needs to know explicitly about how to get it's collaborator However a factory seems overkill.

Thoughts?

EDIT: I think I need to clarify. I don't mean avoiding new() all the time, as obviously it has it's use in tying up dependencies and the like. however, I meant in the following situation (copy-pasta from comments):

What I meant was that I have been told it is intrinsically evil to use the new() operator to a collaborator from inside the type that uses the collaborator, and that it is better to either a) pass an injected type or b) pass a factory (if you need to create an unknown number of those types). By using new() inside the collaborator you tie how to create that object and where to create it directly to the thing that requires it, and that it is better to inject a preconfigured instance into the constructor if you need one instance of it, or inject a factory into the constructor if you need to create multiple/undetermined number of instances

  • 5
    Using new seems to violate everything I know that I've learned since I started using TDD -- Why? Your DI container is using new to create the objects. What prevents you from doing the same? Factory methods are just an abstraction over new; you use the abstraction when you need what the abstraction provides. – Robert Harvey Apr 16 '14 at 17:49
  • 1
    In addition, it's unclear to me why you think using a constructor exposes unnecessary details. It is the judicious use of constructors that makes things like consistent instantiation of objects and immutable objects possible. The constructor only asks for what it needs, and nothing more. – Robert Harvey Apr 16 '14 at 17:52
  • Using new inside of a method intrinsically ties the implementation to that method. – Dan Pantry Apr 16 '14 at 17:53
  • If you need the ability to change out the implementation, you can do that with an interface. – Robert Harvey Apr 16 '14 at 17:54
  • @DanPantry So does calling non-virtual method on instance of different class. – Euphoric Apr 16 '14 at 17:54
18

Here, because you don't want to expose how to directly create this object to the clients that need it, you expose a Factory that will create them and inject that into the client instead.

  1. If clients know the object exists, it's usually fine for them to know how to make it. If you have an interface then maybe you need some factory to make the concrete instance, but for TDD you're just going to mock it anyways.
  2. Your example factory is just a passthru. Your client already knows everything needed to build the object, so replacing the factory is just as hard as replacing the constructor call.

When is it worth NOT using a Factory?

This is the wrong mode of thought.

You should default to not using factories. Factories are only necessary when you need to abstract away object creation. Since you should (in general) limit the creation of objects that require such abstraction, you should use factories sparingly. Instead, most of your objects will just take some interface and not care where it came from.

Only add complexity when it is necessary.

  • 1
    Sometimes an object needs some dependencies (like services) that the object who wants to create it really doesn't need to know about. In that case, a factory can create objects for you without the caller knowing or caring what those dependencies are. Then when the dependencies change, you only have one class to change (the factory). – Scott Whitlock Apr 17 '14 at 13:15
1

For any factory pattern to be usable, it needs a parameter to know what concrete instance to create. With Factory Method and Abstract Factory this "parameter" is type the creation method is on, which is achieved with polymorphism. With "plain" factory pattern, only way to achieve that is to pass the parameter into creation method. Also, this creation process should be complex, not just switch based on enum, if-else chain or something like that. It is also worth when there are multiple different places where the factory is used.

If you have Factory class that doesn't have method parameter, the creation logic is simple or is only used in single place, then I would consider it needless overengineering and needless abstraction. Simple method would be enough.

Also, just because the creation is in different class, doesn't mean it is decoupled. The calling code is still heavily tied to the Factory class. You would need to use abstract factory to have really decoupled code. Also, the whole "new is bad" mentality is dangerous, you should drop it. Creating objects is important part of OOP code. Trying to encapsulate even that will quickly result in overengineering and needless abstractions. Also note, that constructors themselves are sort of factories. They smake sure the instance is created in valid state base and to do that, they ask for required data.

  • 1
    Some object systems have new as being just a method on the relevant class object. (Java isn't one of those.) – Donal Fellows Apr 16 '14 at 22:28
  • @DonalFellows And how is that related to what I said? – Euphoric Apr 17 '14 at 4:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.