Static Factory Method Testing

115 views
Skip to first unread message

Daris

unread,
Aug 17, 2016, 4:52:27 PM8/17/16
to Growing Object-Oriented Software
Hi,

I have a question about static factory method. 

Within value objects creating factories as separate classes is big overhead for the code.
But using it, doesn't expose collaborators for class directly.

For example (This can be done much better way, but to keep it simple):
OrderedProduct -> is VO.
------
class addProductToOrderService {
   
    add(string orderId, string productType, int count) {
          
          order = this.repository.getOrder(orderid);
          order.add( OrderedProduct::create(productType, count) );
    }
   
}

I can test this situation, by checking if value object with specific values was passed to order.add(), mock. But it doesn't seems right. 
Here we can make collaborator explicit by using injecting OrderedProductFactory. But when you have many Value Objects it becomes problematic to create so many factory classes for it.

So my question is how you handle this kind of situations? 



Steve Smith

unread,
Aug 17, 2016, 7:37:46 PM8/17/16
to growing-object-o...@googlegroups.com
To be sure I understand, your factory is returning a subsclass of OrderedProduct, based on the productType string provided?

If that's not the case, I would ask why you don't just instantiate the VO directly. If it is the case, are these different VO types adding value, or could they be represented by a single type (e.g. OrderedProduct)?

If the current design is optimal from that standpoint, I would probably inject the factory as you suggest. If there get to be many of them, I would try to refactor the responsibilities of the class that uses them (into smaller classes that don't each use all of the VO factories).

Steve


--

---
You received this message because you are subscribed to the Google Groups "Growing Object-Oriented Software" group.
To unsubscribe from this group and stop receiving emails from it, send an email to growing-object-oriented-software+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--

Matteo Vaccari

unread,
Aug 18, 2016, 4:17:01 AM8/18/16
to growing-object-o...@googlegroups.com
My 2 cents:

if the service you're developing is this simple, it would probably be sufficient to test it from the outside in a functional/acceptance test.

If there's a hint of complication in how the strings coming from the outside are used to create domain objects, I would delegate that work to a unit-tested factory object.

The easy strategy is to move complication to objects that you can TDD easily, and leave the correctness of calls to those objects to broader integration tests.




Luca Minudel

unread,
Aug 18, 2016, 4:53:35 AM8/18/16
to Growing Object-Oriented Software
Daris

when you write and design code using TDD, it is common to push up as far as possible the code that composes objects, that define the system structure.
I started to do this, to keep together the creation of all objects that needs to be replaced to run integration and acceptance tests in the test environment, to mock external system. This is the type of flexibility I needed for testing.
This gave me also the flexibility in terms of changing and evolving the system: it enables you
- to make the system easily configurable,
- to make components easily replaceable with techniques such as 'branch by abstraction'
- to aggressively refactor compositional code to remove duplication and express intent, and thereby raise the abstraction level at which program so less and less code is needed to write more and more functionality as the system grows.

When you do like that, it become possible to create the factory in just one place of the system, at that point it does not need to be static any more, it's simply instantiated once and passed around using an interface.
No one except the instantiation code, and the test code, needs to know what's the concrete class.
 

To get there, it can take time and meanwhile you need to deal with static methods and variables that are already present in the system.
For this, you find few useful refactoring in the WELC book.

And here you find one example of how reduce the dependency from a static class and make the code testable. Until you reach the situation described initially and then you can get rid completely of the static.
1- the initial code here: https://github.com/lucaminudel/TDDwithMockObjectsAndDesignPrinciples/tree/master/TDDMicroExercises/CSharp/TurnTicketDispenser
2- a proposed solution: https://github.com/lucaminudel/TDDwithMockObjectsAndDesignPrinciples/tree/master/TDDMicroExercises.ProposedSolution/CSharp
3- the description of the code an #3 here:https://github.com/lucaminudel/TDDwithMockObjectsAndDesignPrinciples/blob/master/TDDMicroExercises/README.md

HTH, Luca
Reply all
Reply to author
Forward
0 new messages