C++ The Modern Factory

Vintage car factory
We can do better.

I think I have architected, designed and implemented, what might be (a bit) better  Factory Pattern. Of course, I am pretty sure someone else has discovered the same variation.

Of all the patterns, very often, I was particularly bothered with “classical” aka legacy, Factory. Yes, once implemented, you can relatively easily make it create new “things”, but on the design and usability level, to me,  it does not look very flexible and expandable.

On the C++ level it requires code repetition and use of  smart pointers. In essence these two combined, somehow do not look to me like modern C++ at all.

[nextpage title=”Legacy Factory”]

Classical aka “Legacy” Factory Pattern. Looking at the diagram this seems very simple and obvious. For this post we will use the real life use-case of the “Car Factory”.  In particular to try and explain the architectural issues.

Now consider this.  Using the architecture above, how would you serve contemporary customers and offer them “build your own car” service?  Some on line page, where customers start with some half finished base of the car and then  pick and mix variety of engines, headlights, wheels, seats, sun roof etc … all the way to the details like in-car sound and vision, and a such.

Architecture above is made for factories that deliver ready made, possibly pre-built, finished cars. It is surely possible to re organize  the  internals of the factory to  make different variations to each model, but there is a practical limit. The more customers can pick-n-mix, the number of ever so different models raises exponentially.

The inherent flaw in this architecture is high level of abstraction granularity. Which in turn greatly lowers the level of architecture flexibility and resilience to change.

Implementation issues

I have come to the conclusion, in each Factory pattern variations, the actual factory method, class or whatever, is the focal point of quality issues, where one can feel the design on top of which the implementation resides.

Here is the factory method of the classical factory.

What is wrong with this code? Not much. It is only that this is almost C++98.

As the only modern thing, car_smart_pointer is usually implemented with  std::shared_ptr ; with us at least since C++11, which was standard since Aug 2011 (gasp!) But there where many quality smart pointer implementations before that. (Of course, I do not mean std::smart_ptr ).

We need to use the (smart) pointer here. It is not possible to return instance of Abstract Base Class. And this is how IAutomobile is implemented.

And then we implement our two car models by simply inheriting from this ABC.

class cabriolet from the diagram is almost the same. This is where we meet head-on, two things I do not like :

  • Inheritance
  • Code repetition

And then we invent clever design and then we “invent” coding idioms to mitigate the issues of these two.   If you are by now, standing in shock or are in hot disagreement, please refer to numerous on-line discussions on classical factory pattern implementation issues.

I particularly like Sean Parent’s  Inheritance Is The Base Class of Evil. It is about that and much more important things. Every minute is  full of quality c++ and quality design decisions. Not easy to follow but worth it.

[nextpage title=”Modern Factory”]

My variation  that I am calling “Swappable engines factory”. It is not just engines but this makes for a short title, which I think succinctly conveys the message.

Swappable engines factory
Swappable engines factory

Here the factory method is not the second fiddle. It is instead  the key player. The product (Car in this use case) is actually assembled (put together)  in the factory function. There is no such a thing as “finished car” in this architecture.

Let us discuss the factory method.

This is a proper modern C++ .  No smart pointers needed. We are enjoying the value semantics made much easier to use with the help of a modern C++ compiler.

Copy elision on return by value is now de-facto standard in all modern compilers. C++ 17 “Guaranteed Copy Elision”, very simple explanation.

Above is in C++17 and in essence compiled into: X x{} ;

But beware. It might be far from simple as that. This architecture will be easy to extend to offer the flexibility of composing the car, not before the customer (aka client) code requests a particular combination. For example.

“Swappable Engine Factory” architecture users do not have to worry about how many different models there are and will be. Implementation of it simply builds the car on the spot. Usage is rather simple.

There are few more important details that are making this design possible to implement into simple and resilient modern C++.   On the next page is the GitHub gist.[nextpage title=”The Implementation Details”]

This code is compiled and tested in Visual Studio 2017, with the latest MSVC as of 2018 June. This is not a “production code” it is more of a “proof of concept”. In case of bugs found, just wishing to comments or whatever please do not hesitate to contact me.

The eagle-eyed reader might jump on me using inheritance even in this modern factory.  And native pointer, gasp!  My answer: I know about Polymorphism without inheritance. It is not the focus of this post. It might be in the very near future in some future post on this same subject.

Also in this architecture, this is also an “implementation detail”. So do we use it and will we change it, is completely hidden from the client code, that will work unchanged, in case of changes.

https://gist.github.com/DBJDBJ/c4df39f5df2188de41dce6de260a7c58

I hope you will be able to apply this rather improved factory pattern to your use cases and projects. As ever, if in doubt, please contact me.