This post is the first in a series about Poka-yoke Design - also known as encapsulation.

A common problem in API design is temporal coupling, which occurs when there's an implicit relationship between two, or more, members of a class requiring clients to invoke one member before the other. This tightly couples the members in the temporal dimension.

The archetypical example is the use of an Initialize method, although copious other examples can be found - even in the BCL. As an example, this usage of EndpointAddressBuilder compiles, but fails at run-time:

var b = new EndpointAddressBuilder();
var e = b.ToEndpointAddress();

It turns out that at least an URI is required before an EndpointAddress can be created. The following code compiles and succeeds at run-time:

var b = new EndpointAddressBuilder();
b.Uri = new UriBuilder().Uri;
var e = b.ToEndpointAddress();

The API provides no hint that this is necessary, but there's a temporal coupling between the Uri property and the ToEndpointAddress method.

In the rest of the post I will provide a more complete example, as well as a guideline to improve the API towards Poka-yoke Design.

Smell Example #

This example describes a more abstract code smell, exhibited by the Smell class. The public API looks like this:

public class Smell
{
    public void Initialize(string name)
 
    public string Spread()
}

Semantically the name of the Initialize method is obviously a clue, but on a structural level this API gives us no indication of temporal coupling. Thus, code like this compiles, but throws an exception at run-time:

var s = new Smell();
var n = s.Spread();

It turns out that the Spread method throws an InvalidOperationException because the Smell has not been initialized with a name. The problem with the Smell class is that it doesn't properly protect its invariants. In other words, encapsulation is broken.

To fix the issue the Initialize method must be invoked before the Spread method:

var sut = new Smell();
sut.Initialize("Sulphur");
var n = sut.Spread();

While it's possible to write unit tests that explore the behavior of the Smell class, it would be better if the design was improved to enable the compiler to provide feedback.

Improvement: Constructor Injection #

Encapsulation (Poka-yoke style) requires that the class can never be in an inconsistent state. Since the name of the smell is required, a guarantee that it is always available must be built into the class. If no good default value is available, the name must be requested via the constructor:

public class Fragrance : IFragrance
{
    private readonly string name;
 
    public Fragrance(string name)
    {
        if (name == null)
        {
            throw new ArgumentNullException("name");
        }
 
        this.name = name;
    }
 
    public string Spread()
    {
        return this.name;
    }
}

This effectively guarantees that the name is always available in all instances of the class. There  are also positive side effects:

  • The cyclomatic complexity of the class has been reduced
  • The class is now immutable, and thereby thread-safe

However, there are times when the original version of the class implements an interface that causes the temporal coupling. It might have looked like this:

public interface ISmell
{
    void Initialize(string name);
 
    string Spread();
}

In many cases the injected value (name) is unknown until run-time, in which case straight use of the constructor seems prohibitive - after all, the constructor is an implementation detail and not part of the loosely coupled API. When programming against an interface it's not possible to invoke the constructor.

There's a solution for that as well.

Improvement: Abstract Factory #

To decouple the methods in the ISmell (ha ha) interface the Initialize method can be moved to a new interface. Instead of mutating the (inconsistent) state of a class, the Create method (formerly known as Initialize) returns a new instance of the IFragrance interface:

public interface IFragranceFactory
{
    IFragrance Create(string name);
}

The implementation is straightforward:

public class FragranceFactory : IFragranceFactory
{
    public IFragrance Create(string name)
    {
        if (name == null)
        {
            throw new ArgumentNullException("name");
        }
        return new Fragrance(name);
    }
}

This enables encapsulation because both the FragranceFactory and Fragrance classes protect their invariants. They can never be in an inconsistent state. A client previously interacting with the ISmell interface can use the IFragranceFactory/IFragrance combination to achieve the same funcionality:

var f = factory.Create(name);
var n = f.Spread();

This is better because improper use of the API can now be detected by the compiler instead of at run-time. An interesting side-effect by moving towards a more statically declared interaction structure is that classes tend towards immutability. Immutable classes are automatically thread-safe, which is an increasingly important trait in the (relatively) new multi-core era.


Comments

Scott #
Great insight again in to core principles that often get over looked even by big names in software development.

Looking forward to the rest of the series.
2011-05-24 16:02 UTC
juan agui #
Have you ever considered renaming your blog to programming 101? It's amazing how most my colleagues are still writing procedural code and violate each and every OOP principle. Fortunately there are blogs like yours that explain brilliantly and concisely these topics. Keep up the good job!


2011-05-24 17:28 UTC
Although, I agree with the fact that temporal coupling must be avoided, when possible, I find the solution you propose quite overkill (as always with that dependency injection jazz, IMHO). With the initial design, at least, as a developer, the problem I had were simple to solve (ie: add the Initialize call). Now with DI, as a user of the Small API, I may have to deal with all sort of runtime problems, just because I didn't "read" the API, or the documentation properly :-) Plus, now I have 4 types instead of 1 loaded in my domain. A simple design may not be the most elegant, but it bears simple problems.
2011-05-25 05:50 UTC
So, suppose I want my FragranceFactory to return a Fragrance that implements ISmell (as you have it above) instead of an IFragrance--perhaps because I can't change ISmell). I should just have FragranceFactory return initialized Fragrances wherein the Initialize method does nothing, right? This would accomplish all our goals, although ISmell would still be confusing to the consumer.
2011-05-25 17:27 UTC
Simon, exactly the opposite is true. With the Fragrance API you wouldn't have to deal with any runtime problems, because as soon as you can compile, the design of the code makes it very likely that it's also going to work at run-time (except for null values, which you can't escape no matter what you do).

Getting feedback sooner is betting than getting feedback later. I much prefer getting a compiler error over a run-time exception.

The number of types is hardly a measure of the quality of the code, but if it is, the more the better. The Single Responsibility Principle favors many small classes over a few God Classes.

However, even if you don't agree, then comparing one type against four doesn't make sense. In the absence of interfaces there'd be one class in each alternative (Smell versus Fragrance). When you add interfaces into the mix, you have two types (Smell and ISmell) in the temporally coupled API against four types in the safe API.
2011-05-25 18:19 UTC
Patrick, yes, that might be a possible variation, although perhaps a bit exotic... In which scenario would that be the case?
2011-05-25 18:21 UTC
Not sure to follow you on the number of types. Initially, I had 1 Smell class, and in then end I have 2 classes and 2 interfaces. Or maybe I missed something.
In a real world project, multiply classes by 2, 3, 4 or more (lets add some WCF interfaces to this!) is indeed an issue, unless you generate some or all of it.
I'm not saying what you propose can't be done, or is inelegant. It is exactly the opposite, it's clever and smart, and is the style of code that can be taught in classes or blogged about, but the generalization of these principles can lead to bloated code and huge assemblies if applied massively.

About maintenability, I pretend your code is harder to extend. Initially, I had one class that I could easily extend and the JIT helps me a lot here. I can create a new Spread(arguments) methods easily without breaking any of my existing clients (and without changing the semantics coupling). It's less easy with interfaces, do I need one new ISmellxx interfaces for every new method? New types again? Classes are extensible, interfaces are carved in stone forever - in fact, most people *do* change their interfaces, but that's another story :-)
2011-05-26 07:08 UTC
This blog post discusses two scenarios. The first scenario is that you have only the Smell class. In that scenario, you can replace the Smell class with the Fragrance class (minus the IFragrance interface). No new types are necessary, so you start out with one type and end up with one type.

The second scenarios is when you have a Smell class implementing an ISmell interface. In that case you'd need to go from two to four types.

When it comes to maintainability, I find that the SOLID principles are some of the best guidelines around. The Open/Closed Principle explicitly states that classes should be closed for modification, but open for extensibility. In other words, we extend code only by adding new classes.
2011-05-26 18:24 UTC
_ikke_ #
Just to be sure:

The factory class is allowed to create concrete instances without using a DI container? And any dependencies that the concrete class needs will have to be passed to the factory class?

2011-05-27 10:49 UTC
Use of a DI Container is IMO orthogonal to the issue.

Conceptually it's best to think about any such factories as concrete classes. If they need to pass dependencies to the objects they create, they can do so by requesting them by Constructor Injection. In other words you are correct that "any dependencies that the concrete class needs will have to be passed to the factory class" (excluding those that are passed as parameters to the Create method).

On a practical side, you can always consider implementing the factory as an infrastructure component based on a container. Essentially, the factory would be an Adapter over the container. However, if you do this, you must be sure to place the Adapter in the Composition Root of the application, as otherwise you risk that the container reference leaks into your application code. This means that the concrete class and the factory will end up being implemented in two different assemblies. If you use Castle Windsor, you can go all the way and not even implement the container at all because instead you can leverage the Typed Factory facility.
2011-05-28 21:52 UTC
Mohammed #
All of our code is full of temporal couplings. You can not prevent it because we solve our problems in doing first step1, followed by step2, and so on and so forth. So I don't think you can create code where there is no temporal coupling. What you can do on the other hand, and what I think this blog should have addressed, is to always create valid objects. The design of the class Smell makes it possible creating the object of type Smell without a name. Right after you issued the keyword new() your object is invalid. Any method you call after that will operate on an invalid object (Initialize(...) tries to remedy that). Your solution on the other hand is the right one.
2011-06-17 13:07 UTC
Daniel Hilgarth #
Mark, thanks for this and the other articles in this and other series.
I have one question however:
FragranceFactory.Create checks name for null. Why?
I see the following problems with it:
1) Code duplication:
As Fragrance can be instantiated without the use of the factory, the null check can't be removed from the constructor of Fragrance.
2) Knowledge of implementation details of Fragrance:
The FragranceFactory knows that Fragrance can't work with a name that is null. This is not implicit, this is explicit knowledge. Another implementation of IFragrance could simply assign a default value if null is passed. As FragranceFactory is coupled tightly to Fragrancy, that is not such a big problem. Still I think it is not correct
3) No benefit whatsoever:
Adding the null check in the Create method brings no benefit at all. On the contrary: If we were to change the constructor of Fragrance to allow null and to assign a default value, but would forget to change FragranceFactory.Create accordingly, the semantics of the object creation would differ, depending on how the object is created.

Can you please explain what I have missed and why you decided to put the null check into the Create method?
2011-07-21 12:34 UTC
Daniel, thank you for your insightful comment - you are completely correct.

I just added the Guard Clause out of habit, but your arguments are valid and I will in the future be more careful with my Guard Clauses. It only makes sense that one should only have a Guard Clause if one uses the argument in question. That's not the case when it's just being passed on, so it should not be there.

Thanks for pointing that out.
2011-07-21 15:03 UTC
Mark, thanks for your answer. I hope I didn't sound like I was nitpicking. I simply was a bit puzzled about it.
2011-07-21 15:25 UTC
Not at all - I'm happy that you pointed out something I hadn't properly considered. I learned something from it :)
2011-07-21 15:28 UTC
Hey Mark,
What about fluent interfaces? They completely rely on temporal coupling by design:

var query = new QueryBuilder().WithField("dressing").NotNull().Containing("bacon");

Do you consider this an edge case, or do you actually dislike fluent interfaces in general?
2011-08-02 17:50 UTC
Not at all (to both statements). A Fluent Interface doesn't rely on Temporal Coupling at all - I frequently implement Fluent APIs with immutable types.

See this blog post for a very simple example. For a very complex example, see AutoFixture's Ploeh.AutoFixture.Dsl namespace, which is kicked off by the fixture.Build<T>() method.

In any case, Temporal Coupling doesn't disallow mutability - it just states that if you have mutating methods, the order in which they are invoked (if at all) mustn't matter.
2011-08-02 18:23 UTC
Emanuel Pasat #
Offtopic question: striving for immutability on the domain model is a good practice (or only value objects should be immutable)?
2011-09-16 14:32 UTC
The most common approach is certainly to model Entities as mutable objects while Value Objects are kept immutable.

When you use 'classic' CRUD-style Repositories or Unit of Work, that may also be the best match to that style of architecture. However, my more recent experience with CQRS and Event Sourcing seems to indicate to me that an immutable domain model begins to make a lot more sense. However, I've still to gain more experience with this before I can say anything with confidence.

It has been my general experience over the last couple of years that the more immutable objects I can define, the easier the code is to work with and reason about.
2011-09-16 19:18 UTC
Luis #
Quick noob question, why the IFragranceFactory interface? Your code factory.Create("name") which i imagine would be preceded by "var factory = new FragranceFactory()" does not use the interface, does it?
2012-09-11 14:12 UTC
An IFragranceFactory instance can be injected into any client that needs it, freeing it from having to create the tightly coupled instance itself.

The IFragranceFactory instance can be created in the Composition Root, potentially far removed from any clients. At this point it could be created with the 'new' keyword, or by a DI Container.
2012-09-11 15:43 UTC
Luis #
i came to this blog post with the specific intention of reading about temporal coupling, but after reading your reply to my message and feeling utterly confused i decided to go and read your book, maybe after reading it i'll actually understand what you're saying, and gather some knowledge about DI in the process, obviously this DI is a thing
2012-09-21 12:45 UTC
Sorry, I didn't mean to confuse you...
2012-09-21 13:15 UTC
James Wheeler #
Hi Mark, this is an old post now but it's still very relevant for me. What about the case when initialization is a time consuming process?

For example, at my company we work with a lot of devices and we often end up writing initialization methods for some Type, let's call it 'FooDevice,' that provides functionality for that kind of device.

Let's say our FooDevice implements an interface very similar to ISmell:
IFooDevice
{
    Task Initialize(string comPort);
    int DoSomething();
}
This particular initialization method accepts as input parameter the COM port on which the device is connected to and through which we send serial commands to control the device.

So the initialization method may then create a serial port object for that port, configure the device in various ways (such as disabling physical buttons, since we're now controlling it programatically) and so forth.

The initialization may be a time consuming process that can potentially take in excess of a few seconds or longer.

Following your advice, we should apply a refactoring here. The constructor for FooDevice should accept the COM port instead. Though that seems to imply that initialization should be done in the constructor:
class FooDevice : IFooDevice
{
    public FooDevice(string comPort)
    {
        // Initialize(comPort);
    }
    
    private void Initialize(string comPort) { /* ... */ }
}
Yet that becomes problematic, because now we've lost the ability to return a Task. But of course if we have our IFooDeviceFactory, it can provide the Task:
IFooDeviceFactory
{
    Task<IFooDevice> Create(string comPort);
}
Now, if I understand your example correctly, then the whole purpose of providing an Abstract Factory is to satisify the requirement that the client be in control of when the object is created. Or else the client could just directly accept an IFragrance and no factory would be needed. Another client could feasibily skip the factory and invoke the Fragrance constructor directly.

But if we allow the same behavior with my above example, we're back in the same awkward situation with the constructor.

What can we do then? Should we make the constructor private, and instead provide a static factory method like the following?
class FooDevice : IFooDevice
{
    private FooDevice() { }

    public static Task<FooDevice> Create(string comPort)
    {
        var device = new FooDevice();
        await device.Initialize(string comPort);

        return device;
    }

    private Task Initialize(string comPort) { /* ... */ }
}
2021-06-07 22:22 UTC

James, thank you for writing. Based on what you describe, I find the last option, the one with a static factory method, preferable.

You may want to consider calling it something like Connect instead of Create, but then again, perhaps this isn't much of an improvement. The most important information is in the return type. Since the method returns a task, it's a strong signal that this could take some time.

What about closing the connection? Is that a concern? If so, you may want to make the object implement IDisposable. These days, various code analysers will tell you to dispose of such an object once you're done with it.

You write:

"the whole purpose of providing an Abstract Factory is to satisify the requirement that the client be in control of when the object is created"

Not quite. The main purpose of such a design is encapsulation, guaranteeing that an object can never be in an invalid state.

2021-06-09 12:42 UTC
James Wheeler #

Thanks for the reponse Mark. I too would consider calling the static factory method Connect but I stuck with Create for the sake of consistency with the example.

I'm not sure I follow your comment about encapsulation. With your example, FragranceFactory merely delegates its work to the Fragrance constructor--the Fragrance class already achieves encapsulation by requiring name as a constructor argument.

If you had instead introduced a SmellFactory that behaved like the following, then I would agree it encapsulates the required initialization protocol:

			class SmellFactory : ISmellFactory
			{
				ISmell Create(string name)
				{
					var smell = new Smell();
					smell.Initialize(name);
					return smell;
				}
			}
			

So the only usage I can see for keeping a factory around after improving the design with IFragrance is to allow the client to lazily create an instance of Fragrance without tightly coupling the client via the constructor. Otherwise, an already valid instance of IFragrance could be passed to the client.

Indeed, you preface the introduction of the Abstract Factory improvement with, "In many cases the injected value (name) is unknown until run-time..."

As for disposal, yes, we almost always need to implement IDisposable, since the supplier's managed API for the device usually implements IDisposable as well.

However, wouldn't using an Abstract Factory like this be undesirable? IDevice would need to implement IDisposable so that the client could invoke Dispose on the device instance created by the factory. But as you and Steven point out in your book on dependency injection, an abstraction that implements IDisposable is a leaky abstraction. Or would that not apply in this case?

2021-06-14 19:25 UTC

James, thank you for writing. There are two separate concerns here:

  • Guaranteeing that an object is in a valid state (encapsulation)
  • Enabling polymorphism
What valid state means is specific to an implementation; i.e. a concrete class. Thus, if FooDevice can only be initialised like shown above, that's an implementation detail.

The other concern is polymorphism. Your original definition of the IFooDevice interface had two methods: Initialize and DoSomething. In order to retain both of these capabilities, you're going to need to put both of these functions somewhere. In order to address the sequential coupling implied by that version of the interface, you'll have to distribute those methods over two different polymoprhic types:

IFooDeviceFactory
{
    Task<IFooDevice> Create(string comPort);
}

IFooDevice
{
    int DoSomething();
}

This prevents programmer error. With the original design, a client developer could call DoSomething without first calling Initialize. With the new design, this is no longer possible. You can't call DoSomething unless you have an IFooDevice instance, and you can't get an IFooDevice instance unless you call the Create method.

Is the factory required? Not necessarily. That depends on where the responsibility to create the object lies. If client code is the only code in possession of the comPort value, then you'll need the polymorphic factory in order to intialise a polymorphic object. On the other hand, if the comPort value is available to the application infrastructure (e.g. via a configuration value or environment variable) then you may not the the abstract factory. In that case, any client code that needs an IFooDevice object can receive it via the constructor, and the application's Composition Root can create the object using the concrete Create method.

As to the observation about interfaces inheriting from IDisposable, I still consider that a leaky abstraction. There's usually a way to avoid it, but it tends to depend on the details of the application architecture. Thus, it's difficult to give general advice on that topic without knowing more about the actual circumstances.

2021-06-17 10:50 UTC


Wish to comment?

You can add a comment to this post by sending me a pull request. Alternatively, you can discuss this post on Twitter or somewhere else with a permalink. Ping me with the link, and I may respond.

Published

Tuesday, 24 May 2011 14:00:42 UTC

Tags



"Our team wholeheartedly endorses Mark. His expert service provides tremendous value."
Hire me!
Published: Tuesday, 24 May 2011 14:00:42 UTC