At the Boundaries, Applications are Not Object-Oriented

Tuesday, 31 May 2011 13:27:11 UTC

My recent series of blog posts about Poka-yoke Design generated a few responses (I would have been disappointed had this not been the case). Quite a few of these reactions relate to various serialization or translation technologies usually employed at application boundaries: Serialization, XML (de)hydration, UI validation, etc. Note that such translation happens not only at the perimeter of the application, but also at the persistence layer. ORMs are also a translation mechanism.

Common to most of the comments is that lots of serialization technologies require the presence of a default constructor. As an example, the XmlSerializer requires a default constructor and public writable properties. Most ORMs I've investigated seem to have the same kind of requirements. Windows Forms and WPF Controls (UI is also an application boundary) also must have default constructors. Doesn't that break encapsulation? Yes and no.

Objects at the Boundary #

It certainly would break encapsulation if you were to expose your (domain) objects directly at the boundary. Consider a simple XML document like this one:

<name>
  <firstName>Mark</firstName>
  <lastName>Seemann</lastName>
</name>

Whether or not we have formal a contract (XSD), we might stipulate that both the firstName and lastName elements are required. However, despite such a contract, I can easily create a document that breaks it:

<name>
  <firstName>Mark</firstName>
</name>

We can't enforce the contract as there's no compilation step involved. We can validate input (and output), but that's a different matter. Exactly because there's no enforcement it's very easy to create malformed input. The same argument can be made for UI input forms and any sort of serialized byte sequence. This is why we must treat all input as suspect.

This isn't a new observation at all. In Patterns of Enterprise Application Architecture, Martin Fowler described this as a Data Transfer Object (DTO). However, despite the name we should realize that DTOs are not really objects at all. This is nothing new either. Back in 2004 Don Box formulated the Four Tenets of Service Orientation. (Yes, I know that they are not in vogue any more and that people wanted to retire them, but some of them still make tons of sense.) Particularly the third tenet is germane to this particular discussion:

Services share schema and contract, not class.

Yes, and that means they are not objects. A DTO is a representation of such a piece of data mapped into an object-oriented language. That still doesn't make them objects in the sense of encapsulation. It would be impossible. Since all input is suspect, we can hardly enforce any invariants at all.

Often, as Craig Stuntz points out in a comment to one of my previous posts, even if the input is invalid, we want to capture what we did receive in order to present a proper error message (this argument also applies on machine-to-machine boundaries). This means that any DTO must have very weak invariants (if any at all).

DTOs don't break encapsulation because they aren't objects at all.

Don't be fooled by your tooling. The .NET framework very, very much wants you to treat DTOs as objects. Code generation ensues.

However, the strong typing provided by such auto-generated classes gives a false sense of security. You may think that you get rapid feedback from the compiler, but there are many possible ways you can get run-time errors (most notably when you forget to update the auto-generated code based on new schema versions).

An even more problematic result of representing input and output as objects is that it tricks lots of developers into dealing with them as though they represent the real object model. The result is invariably an anemic domain model.

More and more, this line of reasoning is leading me towards the conclusion that the DTO mental model that we have gotten used to over the last ten years is a dead end.

What Should Happen at the Boundary #

Given that we write object-oriented code and that data at the boundary is anything but object-oriented, how do we deal with it?

One option is to stick with what we already have. To bridge the gap we must then develop translation layers that can translate the DTOs to properly encapsulated domain objects. This is the route I take with the samples in my book. However, this is a solution that more and more I'm beginning to think may not be the best. It has issues with maintainability. (Incidentally, that's the problem with writing a book: at the time you're done, you know so much more than you did when you started out… Not that I'm denouncing the book - it's just not perfect…)

Another option is to stop treating data as objects and start treating it as the structured data that it really is. It would be really nice if our programming language had a separate concept of structured data… Interestingly, while C# has nothing of the kind, F# has tons of ways to model data structures without behavior. Perhaps that's a more honest approach to dealing with data… I will need to experiment more with this…

A third option is to look towards dynamic types. In his article Cutting Edge: Expando Objects in C# 4.0, Dino Esposito outlines a dynamic approach towards consuming structured data that shortcuts auto-generated code and provides a lightweight API to structured data. This also looks like a promising approach… It doesn't provide compile-time feedback, but that's only a false sense of security anyway. We must resort to unit tests to get rapid feedback, but we're all using TDD already, right?

In summary, my entire series about encapsulation relates to object-oriented programming. Although there are lots of technologies available to represent boundary data as ‘objects', they are false objects. Even if we use an object-oriented language at the boundary, the code has nothing to do with object orientation. Thus, the Poka-yoke Design rules don't apply there.

Now go back and reread this post, but replace ‘DTO' with ‘Entity' (or whatever your ORM calls its representation of a relational table row) and you should begin to see the contours of why ORMs are problematic.

P.S. 2022-05-02. See also At the boundaries, applications aren't functional.


Comments

Absolutely. I spend a lot of time in this space, an while I enjoy using (and maintaining) tools to make this transition simple, whenever there isthe first hint of a problem I always advise "add a dedicated DTO". A similar question (using interfaces in WCF messages) came up on stackoverflow last week. But ultimately, any boundary talks "data", not behaviour. It also emphasises why BinaryFormatter (implementation-aware) sucks so much for ***any*** kind of data exchange.
2011-05-31 14:53 UTC
Phil Sandler #
Arg, had a longer comment but it got eaten when I clicked Save Comment.

Anyway the gist of it: great post, I commpletely agree that data objects aren't domain objects, and thinking of them as structured data is very liberating. Using Entities/DTOs/data objects as a composible part of a domain object is a nice way to create that separation which still allows you to (potentially directly) use ORM entities while avoiding having an anemic domain model. So, for example, CustomerDomain would/could contain a CustomerEntity, instead of trying to add behavior to CustomerEntity (which might be a generated class).
2011-05-31 16:37 UTC
Phil, when you write 'Entity' I immediately think about the definition provided in "Domain-Driven Design". Those Entities are definitely Domain Objects which should have lots of behavior, but I'm getting the feeling that you're thinking about something else?
2011-05-31 18:22 UTC
Phil Sandler #
Hey Mark,

Yep, I meant "entity" more in the sense of how it is defined in some of the popular ORMs, like LLBLGen and Entity Framework. Essentially, an instance that corresponds (more or less) directly to a row in a table or view.
2011-05-31 22:09 UTC
Yes, we might compose real domain objects from DTOs, but I'm not sure that is the best solution. When we map non-object-oriented structures to objects, they tend to drag along a lot of baggage which hurts OO modeling.

For instance, generating DTOs from a database schema provides an entire static structure (relationships, etc.) that tend to constrain us when we subsequently attempt to define an object model. I rather prefer being able to work unconstrained and then subsequently figure out how to persist it.
2011-06-01 05:44 UTC
I like this article. As far as I undertand you for every entity you have (a domain object) you need a separate DTO for different representations (XML, SQL, etc.). So you need a third object which translates every DTO into a specific entity. Am I correct? If so, isn't that process too complex?
2011-06-01 08:29 UTC
Yes, that's what I've been doing for the last couple of years, but the downside is the maintenance overhead. That's why I, in the last part of the post, discuss alternatives. Currently I think that using dynamic types looks most promising.

Keep in mind that in most cases, a DTO is not an end-goal in itself. Rather, the end-goal is often the wire-representation of the DTO (XML, JSON, etc.). Wouldn't it be better if we could just skip the DTO altogether and use a bit of convention-based (and testable) dynamic code to make that translation directly?
2011-06-01 08:41 UTC
Florian Hötzinger #
I guess in WCF service scenarios there is really no other way than to create a DTO layer and compose our domain objects from those DTOs when passing them from/to the client. Since I'm doing a lot of Silverlight development at the moment, this came up quite early.
2011-06-01 09:13 UTC
@Mark: Yes, that would be quite a better way. Here comes the great article, you've mentioned, about the ExpandoObject and the dynamic way of dealing with json, xml and other representations of data. However, in case of SQL at this moment you still need some DTOs I guess. Maybe if we have some wrapper over the traditional IDataReader or some other mechanism to access the data, it will be possible again.
2011-06-01 10:13 UTC
Phil Sandler #
Hey Mark,

It's a difficult problem to solve perfectly--every solution had downsides. I have gone down the road of mapping DTOs (or data entities) via a translation layer and that can be painful as well. As you said, the tradeoff of using data objects as a composable part of the Domain Object is that you can't model your domain with complete freedom (which DDD purists would likely see as non-negotiable). The upside is that you have the potential for less maintenance.

2011-06-01 14:34 UTC
Florian, in WCF it is possible to drop down to the message-level and write directly to the message. Even so, I'm not sure I'd go that route, but it's good to know that the option exists.
2011-06-01 18:43 UTC
Boyan, I was specifically thinking about dropping down to IDataReader. For one example, please refer to Tomas Petricek's article Dynamic in F#: Reading data from SQL database.
2011-06-01 18:46 UTC
Hi Mark,

There is lots to argue about in this article (nothing "wrong", just semantics). The main point I would like to pick up on is about your point "What should happen at domain boundaries".

I would contest that rather than "translation" layers, its semantically better to think of it as an "interpretation object". When an app accepts input, there are very few assumptions that should be automatically attached to the unit of input. One of the fundamental ones and often the easiest to break is the assumption that the input is in any way valid, useful or complete.

The semantic concept(abstraction) that is wrapped around the unit of input (the object that encapsulates the input data) need to have a rich interface that can convey abstractions such as "Cannot interpret this input", "Can partially interpret the input but it contains some rubbish", "Input contains SQL injection attack", "Input is poorly formed and has a missing .DTD file" etc.

My argument is that the semantic concept of "translation" while obviously closely related to "interpretation" is semantically a "transformation process". A->B kind of idea, while "interpretation", at least in my head, is not so deterministic and seeks to extract domain abstractions from the input that are then exposed to the application as high level abstractions rather than low level "translated data/safe data/sanitized data".

Thanks,

hotsleeper
2011-06-02 02:37 UTC
Makes sense. I mainly used the term 'translation layer' as I assumed that most people would then immediately know what I meant :)
2011-06-02 06:51 UTC
Arved Sandstrom #
What's the processing error that is currently preventing comments? I can't get a usefully long one successfully submitted.
2011-06-02 09:50 UTC
Sorry about that. This blog is running on dasBlog which was last updated two years ago. Migrating the blog to a better engine is on my to-do list, but it'll be a couple of months at least before I get there.
2011-06-02 10:07 UTC
FWIW, the maintenance cost is effectively zero if the DTO types are codegened.

Dynamic types are also an option -- anyone who has used Rails/ActiveRecord is familiar with their upsides and downsides. In short, maintaining them is free, but using them costs more.

My preferred approach (for now) is to use EF entities as boundary objects for the DB. They cost almost nothing to maintain -- a couple of mouse clicks when we change DB schemata -- since we use "Database First" modeling for internal reasons.

You only get into encapsulation trouble with this if you try to use the EF entities as business objects -- something many people do. My $0.02 is that it's usually wrong to put any kind of behavior on an EF entity.
2011-06-04 15:51 UTC
I agree on the rule of never putting any behavior on an EF entity (although, still, I used to put a translation method on most of them: ToDomainObject(), but still...).

My personal experience with EF was that even with code generation, it was far from frictionless, but YMMV...
2011-06-04 21:13 UTC
Hi Mark,

Depends! If we're building a framework that is used by others then there is a big difference between the applications boundary to the "outside world" (DTO's) and persistence.

A quote taken from NHDay - Loosely Coupled Complexity - CQRS (see minute 2:10) What is wrong with a design with DTO's? "Nothing." End of presentation. But then continues into CQRS :)

Especially the translation-layer when requests come into our application, and we try to rebuild the OO model to help save new objects with an ORM can be cumbersome.

The point is that the database follows from the domain design, not other way round like EF or ORM class generators make you try to believe.
2011-06-05 11:18 UTC
The point being made here is that despite the name, DTOs aren't 'objects'. It's certainly possible to create a complex application entirely with DTOs - it's just not object-oriented.

There may be nothing wrong with that, but if you decide that you need object-orientation to solve a business problem, you must transform DTOs into proper objects, because it's impossible to make OOD with DTOs.
2011-06-05 11:45 UTC
The "everything is an ________" mantra gets us in trouble every time, whether it's strings in TCL, objects in Ruby, etc. Objects are a programming construct in practice, and the problem is we're trying to treat data as objects... which it really isn't. I echo your sentiments to "stop treating data as objects and start treating it as the structured data that it really is."
2011-06-05 18:59 UTC
Great article!

But why not think this further? What´s a boundary? Is a boundary where data is exchanged between processes? Or processes on different machines? Processes implemented using different platforms? Or is a boundary where data moves between .NET AppDomains? Or between threads?

The past year I´ve felt great relieve by very strictly appyling this rule: data that moves around is, well, just data.

That does not mean I´m back to procedural programming. I appreciate the benefits of object oriented languages.

But just because I can combine data and functions into one "thing", I should not always do it.

If data is state of a behavior, then data+function makes sense.

But if data is pushed around between "behaviroal objects" then data should be just data (maybe spiced with some convenience functions).

So what I´ve come to doing is "data flow design" or "behaviroal design". And that plays very nicely with async programming and distributing code across processes.
2011-06-08 14:14 UTC
Yes, we can take it further, but I don't believe that one approach necessarily rules out the other. However, it depends on how you decide to pass around structured data.

If you do it in a request/response style (even mapped into internal code), I'd say that you'd be doing procedural programming.

However, if you do it as Commands, passing structured data to void methods, you'd basically be heading in the direction of Pipes and Filters architecture. That's actually a very good place to be.
2011-06-09 09:47 UTC
Nice post (even though I'm a couple years late to it).
Wouldn't it be better if we could just skip the DTO altogether and use a bit of convention-based (and testable) dynamic code to make that translation directly?
I think technology is finally starting to get there. Most serializers still want a default constructor, but some also provide mechanisms for constructor injection — making immutable domain models possible again.
Now we just need to be able to validate the input appropriately; you made a point about validation being "a different matter" above that I didn't quite understand. It seems to me that, as long as the input is valid, we can use it to create a proper model object.
And if we can automatically return abstract errors like @hotsleeper suggested, then I think we have a full solution.
My most recent take on this problem has been to use a combination of Jersey, Jackson, and Hibernate Validator to translate from on-the-wire JSON representation to valid domain object.
Is there something I'm missing with this approach?
2013-05-07 10:45 CDT

The "different matter" of interpretation is that you need to be able to interpret and validate the incoming data, before you turn it into a Domain Object. An encapsulated Domain Object should throw exceptions if you attempt to create invalid instances, so unless you want to catch exceptions and surface them at the boundary, you'll need to be able to validate the input before you create the Domain Object.

There are various technologies where you can annotate your Domain Objects, in order to add such interpretation logic to them, but you should be aware that if you do that, you'd be conflating the interpretation logic with your Domain Model. Is that a problem? Only you can tell, but at least, you must be aware of this before you can make the decision.

What happens if you need to interpret XML as well as JSON? What happens if you need to interpret two mutually exlusive versions (v1 and v2) of XML into the same object? What happens if you need to interpret YAML in addition to JSON and XML? Etc.

2013-05-08 06:15 UTC

5 years have passed after original post date, but smart thoughts never get old i think.

I have a question, concerning "Currently I think that using dynamic types looks most promising."
Are you still think like that? I assume yes. But is it even "ethical" to use amorphous, general-purpose objects, like that?
It's bad to populate objects with property injection, but it's ok to give them method they didn't have? When I'm looking at this Expando I just see something like:
- take JSON file with object graph
- deserialize to "DTO" graph
- give arbitrary DTOs methods, so they now domain objects
- seems legit

Of cource, im exagerrating. But htat's why:
Right now we're starting a project. The only and last thing that bothers me now is exactly this: Client application receives JSON file with moderately large Scenes. While I'm satisfied with overal design I've achieved, there is this one "little" thing. As of now, i was planning to take this JSON, check it against schema (mb add some valitations later), "decompose" it to a number of DTOs and feed them to container in the process of object tree construction and for later use with Factories, that supply runtime objects with certain types and/or properties.
I don't like it, but I don't see a better way yet.

For example, how do I set up references? Using json's method is ofcourse not an option. Make repository and inject it everywhere? Yet, I don't see it is being Service Locator, I for some reason suspect it's bad. Who will register everyone there, for example? Though, it can be nimble visitor in both cases (but it will demand the addition of specialized interface to all objects just for this concern).
And now I recalled about this Expando. And now i fell myself even worse: earlier I was just seeing not-so-good solutions, but in fact acceptable if treated responsibly and carefully. But this expando.. I see how much easier it may make everything, but I don't know how to allow myself to use it (tho the problem may disappear by itself, as we may fall under constrait of useing .NET 3.5). But if you say using it is ok, I will surely do so. That's because I know that I can trust your opinion more, that my own in this context of software design.

All in all, I will be happy to hear your opinion on the matter of this article, but n years later. What is the answer to questions raised here by article and comments, ultimately? What transition from boundaries to inner OO paradise is the best in your opinion (and what is second, just in case)?
Also, concerning offtopic: can you give me a couple advices on setting up those references (that DI composition will not able to handle)? I think this will be needed only after object graph was builded, so may be do it in composition root right away during cunstruction? I was trying to do this pretty successfully, but i consider those method a "hack". Is it bad to have repository with almost all business objects?

2015-12-19 1:40 UTC

Dmitry, thank you for writing. This purpose of this post is mostly to help people realise that, as the title says, at the boundaries, applications aren't Object-Oriented (and neither are they Functional). Beyond that, the article is hardly prescriptive. While the What Should Happen at the Boundary section muses on ways to deal with input and output, I hope it doesn't suggest that there are any silver bullets that address these problems.

It's a subject not easily addressed here in a comment. A new article wouldn't even do the topic justice; a book would be required to truly cover all the ins and outs.

That said, I don't think I ever used the ExpandoObject-approach in practice, although I've used dynamic typing against JSON a lot with Integration Testing. Mostly, I use the Railway oriented programming approach to input validation, but it doesn't address all the other issues with parsing, implementing Tolerant Readers, etc.

"I know that I can trust your opinion more, that my own in this context of software design."
I don't think you should. All advice is given in a specific context. Sometimes, that context is explicit, but usually it's implicit. I don't know your context (and I confess that I don't understand your more specific questions), so I can only give advice from my own (implicit) context. It may or may not fit your context.

This is the reason I take pains to present arguments for my conclusion. While the arguments serve the purpose of trying to convince the reader, they also serve as documentation. From the arguments, the train of thought that leads to a particular conclusion should be clearer to the reader. If a reader disagrees with a premise, he or she will also disagree with the conclusion. That's OK; software development is not a one-size-fits-all activity.

2015-12-19 10:35 UTC

Design Smell: Default Constructor

Monday, 30 May 2011 13:02:02 UTC

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

Default constructors are code smells. There you have it. That probably sounds outrageous, but consider this: object-orientation is about encapsulating behavior and data into cohesive pieces of code (classes). Encapsulation means that the class should protect the integrity of the data it encapsulates. When data is required, it must often be supplied through a constructor. Conversely, a default constructor implies that no external data is required. That's a rather weak statement about the invariants of the class.

Please be aware that this post represents a smell. This indicates that whenever a certain idiom or pattern (in this case a default constructor) is encountered in code it should trigger further investigation.

As I will outline below, there are several scenarios where default constructors are perfectly fine, so the purpose of this blog post is not to thunder against default constructors. It's to provide food for thought.

If you have read my book you will know that Constructor Injection is the dominating DI pattern exactly because it statically advertises dependencies and protects the integrity of those dependencies by guaranteeing that an initialized consumer is always in a consistent state. This is fail-safe design because the compiler can enforce the relationship, thus providing rapid feedback.

This principle extends far beyond DI. In a previous post I described how a constructor with arguments statically advertises that the argument is required:

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;
    }
}

The Fragrance class protects the integrity of the name by requiring it through the constructor. Since this class requires the name to implement its behavior, requesting it through the constructor is the correct thing to do. A default constructor would not have been fail-safe, since it would introduce a temporal coupling.

Consider that objects are supposed to be containers of behavior and data. Whenever an object contains data, the data must be encapsulated. In the (very common) case where no meaningful default value can be defined, the data must be provided via the constructor. Thus, default constructors might indicate that encapsulation is broken.

When are Default Constructors OK? #

There are still scenarios where default constructors are in order (I'm sure there are more than those listed here).

  • If a default constructor can assign meaningful default values to all contained fields a default constructor still protects the invariants of the class. As an example, the default constructor of UriBuilder initializes its internal values to a consistent set that will build the Uri http://localhost unless one or more of its properties are subsequently manipulated. You may agree or disagree with this default behavior, but it's consistent and so encapsulation is preserved.
  • If a class contains no data obviously there is no data to protect. This may be a symptom of the Feature Envy code smell, which is often evidenced by the class in question being a concrete class.
    • If such a class can be turned into a static class it's a certain sign of Feature Envy.
    • If, on the other hand, the class implements an interface, it might be a sign that it actually represents pure behavior.

A class that represents pure behavior by implementing an interface is not necessarily a bad thing. This can be a very powerful construct.

In summary, a default constructor should be a signal to stop and think about the invariants of the class in question. Does the default constructor sufficiently guarantee the integrity of the encapsulated data? If so, the default constructor is appropriate, but otherwise it's not. In my experience, default constructors tend to be the exception rather than the rule.


Comments

Agreed.
My most common scenario for the default constructor is when some (probably reflection-based) framework requires it.
Don't like them, at all. There are always some dependencies, and excluding them from the ctor means you are introducing them in an uglier place...

Good post!
2011-05-30 16:24 UTC
martin #
So if I have a DTO class(only properties), all the properties should be provided in the contructor or the class should be contructed by some builder ?
2011-05-30 20:06 UTC
One caveat is the case of de- serialization.
2011-05-31 00:32 UTC
Loving this series Mark. Nice work :)
2011-05-31 01:14 UTC
Ken #
I would like to point out if you are using expression blend you need a default constructor on your view otherwise Blend can't open it. Something like this.

public ReturnPolicyManagementView(): base()
{
InitializeComponent();
}
public ReturnPolicyManagementView(ReturnPolicyManagementViewModel model) : this()
{
this.DataContext = model;
}

You can of course get away with this because WPF bindings fail without causing an exception.
2011-05-31 15:29 UTC
Martin, Bob, Ken, I wrote this postscript that essentially explains why such boundary code isn't object-oriented code. At the boundaries, encapsulation doesn't apply.
2011-05-31 18:17 UTC
You have such a unique way of looking at code & constructs, it's eye opening to say the least. I enjoy how you turn the widely accepted into a beast of evil :)

Attacking default constructors is either mad or madly genius.
2011-05-31 20:08 UTC
Nice series. This post reminded me of a painful realization I made lately, which is that by design, a struct must have a parameterless default constructor. Does this make structs evil in your book, except for cases where the parameterless constructor makes sense?
2011-06-05 07:39 UTC
structs aren't evil - as with most other language constructs, it's a matter of understanding when and how to apply them. Basically, a struct is (or should be) a specialized representation of a number. Int32, Decimal, DateTime, TimeSpan etc. all fall into this category, and if you have a similar domain-specific concept in you code base, a struct could be a good representation as long as 0 is a valid value. A hypothetical Temperature type would be an excellent candidate.

An example where a struct was inappropriately applied would by Guid, whose default value is Guid.Empty. Making Guid a struct adds no value because you'd always conceptually have to check whether you just received Guid.Empty. Had Guid been a reference type we could just have checked for null, but with this design choice we need to have special cases for handling exactly Guids. This means that we have to write special code that deals only with Guids, instead of code that just deals with any reference type.
2011-06-05 08:02 UTC

Design Smell: Redundant Required Attribute

Friday, 27 May 2011 13:21:06 UTC

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

Recently I saw this apparently enthusiastic tweet reporting from some Microsoft technology event:

[Required] attribute in code automatically creates a non-nullable entry in DB and validation in the webpage - nice […]

I imagine that it must look something like this:

public class Smell
{
    [Required]
    public int Id { get; set; }
}

Every time I see something like this I die a little inside. If you already read my previous posts it should by now be painfully clear why this breaks encapsulation. Despite the [Required] attribute there's no guarantee that the Id property will ever be assigned a value. The attribute is just a piece of garbage making a claim it can't back up.

Code like that is not fail-safe.

I understand that the attribute mentioned in the above tweet is intended to signal to some tool (probably EF) that the property must be mapped to a database schema as non-nullable, but it's still redundant. Attributes are not the correct way to make a statement about invariants.

Improved Design #

The [Required] attribute is redundant because there's a much better way to state that a piece of data is required. This has been possible since .NET 1.0. Here's the Poka-yoke version of that same statement:

public class Fragrance
{
    private readonly int id;
 
    public Fragrance(int id)
    {
        this.id = id;
    }
 
    public int Id
    {
        get { return this.id; }
    }
}

This simple structural design ensures that the ID truly is required (and if the ID can only be positive a Guard Clause can be added). An instance of Fragrance can only be created with an ID. Since this is a structural construction, the compiler can enforce the requirement, giving us rapid feedback.

I do realize that the [Required] attribute mentioned above is intended to address the challenge of mapping objects to relational data and rendering, but instead of closing the impedance mismatch gap, it widens it. Instead of introducing yet another redundant attribute the team should have made their tool understand simple idioms for encapsulation like the one above.

This isn't at all hard to do. As an example, DI Containers thrive on structural information encoded into constructors (this is called Auto-wiring). The team behind the [Required] attribute could have done that as well. The [Required] attribute is a primitive and toxic hack.

This is the major reason I never expect to use EF. It forces developers to break encapsulation, which is a principle upon which I refuse to compromise.


Comments

Seems like overkill if all you have is a piece of data that you want to display on a web page. Are you against using Entity Framework to fill Data Transfer Objects to be displayed?
2011-05-27 13:59 UTC
Agreed, I'd only use [Required] for validation on a view model
2011-05-27 14:35 UTC
You misstate the intended purpose of the attribute, because you cite a tweet instead of the documentation.

It is true that most code-to-schema-mapping-tools, including EF code-first, Fluent NHibernate, and others, will infer non-nullability from [Required] if it happens to be present on a type which is actually nullable. Why shouldn't they? I realize it's cool for the hip kids to flame EF at every opportunity, but good grief, it didn't cause the tornadoes in Memphis, and it didn't create (nor does it "require") [Required]...

The documentation makes the intended purpose of the attribute clear:

"The RequiredAttribute attribute specifies that when a field on a form is validated, the field must contain a value. A validation exception is raised if the property is null, contains an empty string (""), or contains only white-space characters."

Your "imagined" code example is indeed redundant even in the case where someone is trying to create a non-nullable DB field instead of using the attribute for its intended purpose, because integer properties, being value types, are always mapped to non-nullable fields, with or without [Required]. One must use "int?" to get a nullable DB field; [Required] has no effect on "int" at all. (Indeed, the MVC framework, e.g., treats [Required] and value types exactly the same.)

Now, let's consider the actual purpose of required, per the documentation, and see if it's redundant. Consider a view model with two "required" strings. The business requirement is that if either one or both of them do not contain a non-empty string, the web page should highlight the editors in red and display an appropriate message to the user. One could write a parameterized constructor and throw if they're not present, per your example, but you only get one chance to throw an exception, so you would have to handle three separate cases: The first field missing, the second field missing, or both fields missing. Better to use a validation framework which handles all of these cases for you -- which is exactly what [Required] is intended for.

I would argue that such a parameterized constructor with one or more throws is the wrong design in this scenario, because view models must be able to cope with the task of re-displaying invalid data entered by the user so that the user can correct her mistakes. In contrast to a business object, it must be able to hold and report on invalid states.
2011-05-27 15:19 UTC
Ben, if all you have "is a piece of data that you want to display on a web page" you're most likely in the CRUD application scenario. There are cases where this is indeed the correct solution to a business problem. It's perfectly fine, but it has nothing to do with object-orientation.

This whole series of posts about Poka-yoke Design are about encapsulation, which is an object-oriented principle. And yes: when it comes to OOD I'd never use EF (or any other ORM) if it requires me to break encapsulation.
2011-05-28 21:29 UTC
Craig, I agree that when it comes to user input validation, using an attribute on one or more properties with very loose invariants is the best solution. In general, when at the boundary of an application, it's always best to assume that input can be invalid in all sorts of ways. This is true for UI input as well as automated input (XML, CSV, JSON, etc.). Thus, any 'object' modeling an application boundary data structure is essentially not encapsulated.

However, it would be a grave mistake if we let UI concerns drive the design of our domain models. Thus, as soon as we know that we have a case of valid input data on our hands, we must translate it to a proper encapsulated object. From that point on (including db schema design) an attribute would certainly be redundant.

BTW, don't read to much into the tweet. Perhaps I chose the wrong example, and it was never my intention to thunder particularly at EF. So far, all I've heard about NHibernate indicates to me that it has similar issues with regards to encapsulation.
2011-05-28 21:42 UTC
I like what you said in above: "Thus, any 'object' modeling an application boundary data structure is essentially not encapsulated." That's an insight that many people miss.

My personal take on this is that data service interfaces are boundary structures themselves, and should be BOs in the same way that view models shouldn't be BOs, either.
2011-05-31 14:56 UTC
When you say 'BO', do you mean 'Boundary Object' or 'Business Object'? It seems to me that you might use both abbreviations in the same sentence... or I'm totally missing something :)
2011-05-31 18:19 UTC
Sorry, I meant business object, and "should" should have been "shouldn't." Not the clearest sentence I ever wrote!
2011-05-31 20:39 UTC
Gotcha! Agreed :)
2011-05-31 20:40 UTC

Code Smell: Automatic Property

Thursday, 26 May 2011 13:33:13 UTC

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

Automatic properties are one of the most redundant features of C#. I know that some people really love them, but they address a problem you shouldn't have in the first place.

I totally agree that code like this looks redundant:

private string name;
public string Name
{
    get { return this.name; }
    set { this.name = value; }
}

However, the solution is not to write this instead:

public string Name { get; set; }

The problem with the first code snippet isn't that it contains too much ceremony. The problem is that it breaks encapsulation. In fact

"[…] getters and setters do not achieve encapsulation or information hiding: they are a language-legitimized way to violate them."

James O. Coplien & Gertrud Bjørnvig. Lean Architecture. Wiley. 2010. p. 134.

While I personally think that properties do have their uses, I very rarely find use for automatic properties. They are never appropriate for reference types, and only rarely for value types.

Code Smell: Automatic Reference Type Property #

First of all, let's consider the very large set of properties that expose a reference type.

In the case of reference types, null is a possible value. However, when we think about Poka-yoke design, null is never an appropriate value because it leads to NullReferenceExceptions. The Null Object pattern provides a better alternative to deal with situations where a value might be undefined.

In other words, an automatic property like the Name property above is never appropriate. The setter must have some kind of Guard Clause to protect it against null (and possibly other invalid values). Here's the most fundamental example:

private string name;
public string Name
{
    get { return this.name; }
    set 
    {
        if (value == null)
        {
            throw new ArgumentNullException("value");
        }
        this.name = value; 
    }
}

As an alternative, a Guard Clause could also check for null and provide a default Null Object in the cases where the assigned value is null:

private string name;
public string Name
{
    get { return this.name; }
    set 
    {
        if (value == null)
        {
            this.name = "";
            return;
        }
        this.name = value; 
    }
}

However, this implementation contains a POLA violation because the getter sometimes returns a different value than what was assigned. It's possible to fix this problem by adding an associated boolean field indicating whether the name was assigned null so that null can be returned from the setter in this special case, but that leads to another code smell.

Code Smell: Automatic Value Type Property #

If the type of the property is a value type, the case is less clear-cut because value types can't be null. This means that a Null Guard is never appropriate. However, directly consuming a value type may still be inappropriate. In fact, it's only appropriate if the class can meaningfully accept and handle any value of that type.

If, for example, the class can really only handle a certain subset of all possible values, a Guard Clause must be introduced. Consider this example:

public int RetryCount { get; set; }

This property might be used to set the appropriate number or retries for a given operation. The problem with using an automatic property is that it's possible to assign a negative value to it, and that wouldn't make any sense. One possible remedy is to add a Guard Clause:

private int retryCount;
public int RetryCount
{
    get { return this.retryCount; }
    set
    {
        if (value < 0)
        {
            throw new ArgumentOutOfRangeException();
        }
        this.retryCount = value;
    }
}

However, in many cases, exposing a primitive property is more likely to be a case of Primitive Obsession.

Improved Design: Guard Clause #

As I described above, the most immediate fix for automatic properties is to properly implement the property with a Guard Clause. This ensures that the class' invariants are properly encapsulated.

Improved Design: Value Object Property #

When the automatic property is a value type, a Guard Clause may still be in order. However, when the property is really a symptom of Primitive Obsession, a better alternative is to introduce a proper Value Object.

Consider, as an example, this property:

public int Temperature { get; set; }

This is bad design for a number of reasons. It doesn't communicate the unit of measure and allows unbounded values to be assigned. What happens if - 100 is assigned? If the unit of measure is Celcius it should succeed, although in the case when it's Kelvin, it should fail. No matter the unit of measure, attempting to assign int.MinValue should fail.

A more robust design can be had if we introduce a new Temperature type and change the property to have that type. Apart from protection of invariants it would also encapsulate conversion between different temperature scales.

However, if that Value Object is implemented as a reference type the situation is equivalent to the situation described above, and a Null Guard is necessary. Only in the case where the Value Object is implemented as a value type is an anonymous property appropriate.

The bottom line is that automatic properties are rarely appropriate. In fact, they are only appropriate when the type of the property is a value type and all conceivable values are allowed. Since there are a few cases where automatic properties are appropriate their use can't be entirely dismissed, but it should be treated as warranting further investigation. It's a code smell, not an anti-pattern.

On a different note properties also violate the Law of Demeter, but that's the topic of a future blog post...


Comments

James Nail #
Hi Mark,
I'm enjoying this series, and you can be sure I'll be sharing it with my teammates.
I wanted to point out a typo that might confuse readers, though -- you used the term "anonymous properties" instead of "automatic properties" toward the end of the article, which threw me off at first.
Anyway, keep up the great work!
2011-05-26 14:07 UTC
Omer Katz #
What about NetworkStream's Connected property?
It has a private set and a public get and returns a boolean that indicates if the underlaying socket is connected.
Nothing wrong with that.

By your logic, any .NET ORM is bad because it uses properties and violates the Law of Demeter.
2011-05-26 14:09 UTC
Isn't the code smell "public setters" rather than automatic properties? Making the set protected or private solves this issue. E.g.

public decimal MyValue { get; private set; }

With such usages it is legitimate for the guard code to be in a state mutating method, constructor validation etc
2011-05-26 14:15 UTC
Good points, and I completely agree with the { get; set; } kind of auto-implemented properties - in fact I don't think I've ever checked one in.

However, I'm forever using the {get; private set; } kind of auto-implemented properties - what are your opinions on those? What about a hypothetical and confusingly named { get; readonly set; } auto-implemented property?
2011-05-26 14:25 UTC
James, thanks for pointing that out. I've now corrected the error.
2011-05-26 18:31 UTC
Omer, a boolean property falls into that rare case described during the discussion of value type properties. If the class exposing the property truly can accept any value that the type can possibly take, an automatic property is in order. A boolean value can only take one of two values, and both are legal. Thus, no Guard Clause is required. However, please notice that this scenario is not (or at least should not be) representative.

Regarding ORMs you are now jumping ahead of me :) I'll come to that in a later blog post, but yes, I genuinely believe that the whole concept of an ORM (at least in any incarnations I've seen so far) is a fallacy.
2011-05-26 18:39 UTC
Ben, you are correct that the issue is at least most prevalent when the setter is public. However, keep in mind that we should always treat protected as public, as anyone can always come by and derive from a class.

For private setters it's not so clear-cut. In most cases when I have read-only properties it tends to be because the property is being supplied through the constructor and subsequently treated as immutable. When that is the case, I much prefer a backing field because it can be declared as readonly.

In other words I rarely write code where the class itself can mutate the value of a read-only property, but I know that other people do. When this is the case, I could argue that I'd still prefer the setter to protect the invariants of the class, but that argument tends to become a little silly because with a backing field the class could always just mutate the value directly. In any case, if one has a class that needs that kind of protection from its own internals one probably has more serious problems :)

Keep in mind that this whole discussion about encapsulation relates to the public API of classes. Obviously, once you start poking around in the internals of a class, you're already looking at the source code and thus past the encapsulation perimeter.
2011-05-26 18:50 UTC
Alex, see my previous comment regarding { get; private set; }

Regarding { get; readonly set; } I would probably use something like this assuming this was something that could only be used from the constructor, because I'd still be able to add the appropriate Guard Clause in the constructor before invoking the setter.
2011-05-26 18:54 UTC
I totally agree with your post. However, there are some cases when you do not need to make checks for validity for reference types. If a class with such a property does not provide a default non-null value for it, then any other checks are redundant as the user may set or may not set a value to that property. This way it will still have its default value of NULL.

Using properties with public setters in really tricky. When you have a class with properties and methods, users do not know which properties should be set before a method is called which will result in a run-time exception. That's why required parameters should be provided directly to constructors and methods.
2011-05-27 07:52 UTC
If the value is optional a public setter is in order. However, allowing the field to be null is not, as it would require the rest of the class to have to check for null every time it uses the field. A Null Object is a better alternative, which again leads to the rule that a Null Guard is always appropriate for reference types. However, in certain cases, that Null Guard might not throw an exception, but rather replace the null with a Null Object.
2011-05-29 08:55 UTC
Theo Andersen #
Hi Mark,
I really like your design smell series posts, and i have a few questions.

I get and agree on your points about encapsulation and Automatic Properties, but as i see it a lot of frameworks forces you to break this encapsulation. An example is XML Serialization (ISerializable), which needs an empty constructor and then access to all the public properties to set them.

Couldn't this lead to both the automatic property and temporal coupling smells, as you need to have basic properties so the framework can set them, plus an empty constructor which then breaks your temporal encapsulation?
To adhere to the serialization interface you're forced to open up your code (or create a DTO).

2011-05-30 09:18 UTC
Theo, please see my latest post that touches on exactly that point.
2011-05-31 18:11 UTC
I wonder if there is a more elegant way to do this than creating guard clauses for every reference type property. It would have been nice to do this in a more declerative way. I posted a question on SO as well: http://stackoverflow.com/questions/6773189/auto-implemented-properties-with-non-null-check
2011-07-21 16:38 UTC
Ben Robinson #
Your points are arguments against using automatic properties inappropriately and are far from general cases. There are perfectly valid reasons to allow the setting of properties to null (e.g. using ORM how would you set a property mapped DB field to null) i think your example of a setter that throws a null reference exception is a code smell itself unless you have a specific reason for disallowing it. Your example of the RetryCount is simply an inappropriate use of an automatic property not at all an argument against automatic properties. Your example of temperature is an example of inappropriate type and has nothing to do with automatic properties at all, with the correct type an automatic property would make perfect sense as you could build the validation into the Temperature class. Automatic properties as just shorthand for simple field backed properties and where simple field back properties are correct then so are automatic properties. Simple field backed properties with no validation are sometimes used when they shouldn't be, but that has nothing to do with automatic properties.
2011-09-02 08:38 UTC
I agree with Ben's last point, I believe automatic property(or simple field backed property) is just a way to deal with how C# compiler does assembly linking, and using simple properties allows minor modifications to them without recompiling all dependent assemblies.

I somewhat agree to your Guard Clause argument, it's something I should pay more attention to instead of blindly implementing automatic properties. But I do have some doubts, in many cases, there is no proper default value, like Birth Date, Country, etc. In fact, I think that's the case most of the time, how would you deal with those situations?
2012-01-10 17:04 UTC
2012-01-15 16:40 UTC
Juliano Leal Goncalves #
Mark, have you considered revisiting this topic or adding some more info to this particular post after the introduction of automatic readonly properties? Most of what you discuss here is still applicable, but some of the newer constructs prevents a fair share of the problems associated with properties.
2018-03-20 14:15 UTC

Juliano, thank you for writing. You're right that after the publication of this post, C# got more features, at least one of which seems to relate to this article. When I write C# code today, I often use automatic read-only properties, combined with appropriate Guard Clauses in the constructor. I find that a useful language feature.

That particular later language feature (automatically implemented read-only properties) is, however, only tangentially related to the topic of this post. Did you have some other language construct in mind?

2018-03-20 16:12 UTC

Design Smell: Primitive Obsession

Wednesday, 25 May 2011 15:03:31 UTC

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

Many classes have a tendency to consume or expose primitive values like integers and strings. While such primitive types exist on any platform, they tend to lead to procedural code. Furthermore they often break encapsulation by allowing invalid values to be assigned.

This problem has been addressed many times before. Years ago Jimmy Bogard provided an excellent treatment of the issue, as well as guidance on how to resolve it. In relation to AutoFixture I also touched upon the subject some time ago. As such, the current post is mostly a placeholder.

However, it's worth noting that both Jimmy's and my own post address the concern that strings and integers do not sufficiently encapsulate the concepts of Zip codes and phone numbers.

  • When a Zip code is represented as a string it's possible to assign values such as null, string.Emtpy, “foo”, very long strings, etc. Jimmy's ZipCode class encapsulates the concept by guaranteeing that an instance can only be successfully created with a correct value.
  • When a Danish phone number is represented as an integer it's possible to assign values such as - 98, 0, int.MaxValue, etc. Once again the DanishPhoneNumber class from the above example encapsulates the concept by guaranteeing that an instance can only be successfully created with a correct value.

Encapsulation is broken unless the concept represented by a primitive value can truly take any of the possible values of the primitive type. This is rarely the case.

Design Smell #

A class consumes a primitive type. However, further analysis shows that not all possible values of the type are legal values.

Improved Design #

Encapsulate the primitive value in a Value Object that contains appropriate Guard Clauses etc. to guarantee that only valid instances are possible.

Primitives tend to not be fail-safe, but encapsulated Value Objects are.


Comments

Jon Wingfield #
What do you mean by this statement:

Encapsulation is broken unless the concept represented by a primitive value can truly take any of the possible values of the primitive type. This is rarely the case.

Should a Qty field that only takes positive integers now be represented by a separate class? You seem to be defining encapsulation as compile-safe or something.
2011-05-25 15:52 UTC
I would very much like to be able to represent a quantity as a specialized class. Unfortunately uint is not a CLS-compliant type - otherwise I would use that one a lot.

Keep in mind that I'm talking about a code smell. This means that whenever you encounter the smell it should make you stop and think. I'm not saying that using a primitive type is always wrong.

With a quantity, and given the constraints of C#, unfortunately there isn't a lot we can do. While we could encapsulate it in a PositiveInteger struct, it wouldn't add much value from a feedback perspective since we can't make the compiler choke on a negative value.

However, a hypothetical PositiveInteger struct would still add the value that it encapsulates the invariant in one place instead of spreading it out all over the code base.

Still, a positive integer is such a basic concept that it never changes. This means that even if you spread Guard Clauses that check for negative values all over your code base, you may not have much of a maintenance burden, since the Guard will never change. Still, you might forget it in a couple of places.

In any case I like the Temperature example above much better because it not only provides safety, but also encapsulates the concept as well as provides conversion logic etc.
2011-05-25 18:03 UTC
Thomas #
I try whenever possible to design that way my api especially in the domain layer. However I run into some corner cases with RESTful web services when it's more convenient for the client to provide a simple primitive than the complex object. Then on the server side the check is done to know if the provided value is correct. Would you bother to enforce it that case?
2011-05-31 22:38 UTC
Thomas, did you see my post on application boundaries? I think it ought to answer your question :)
2011-06-01 05:45 UTC
Thomas #
Not yet:) I'm catching up with the old one first. But I go to it:)
2011-06-01 06:29 UTC
Scott Peterson #
Hello Mark:

I am revisiting an old post in hopes you can shed some light on Value objects and their limits. I am currently trying to implement a Password class, which seems like a perfect example of something that should not be handled as a simple string. I modelled my Password object based on examples you've provided, in that I pass in a string to a constructor and then run an IsValid method to see if the string meets our business rules for passwords (length, types of characters, etc.). That's fine as it is, and I have unit tests to make sure all is well. But there are more business rules to a password. I need to have a privately set DateCreated field, and I need to store the number of days the password is valid, while providing a function to see if the password is still valid based on the DateCreated and the number of days the password is valid. However, adding these things to my value object seems like I'm polluting it. Plus, I want to pass in the number of days valid when the object is created, so now I have two parameters, which causes problems if I want to have an explicit operator. I thought about creating a PasswordPrimitive class and then a Password class that inherits the PasswordPrimitive class, but that seems messy.

If you have any thoughts and/or guidance, I'd appreciate the input.

Regards,
Scott
2015-02-26 21:04 UTC

Scott, thank you for writing. A Value Object can contain more than a single primitive value. The canonical Value Object example is Money, and you often see Money examples where a Money value is composed of an amount and a currency; one example in the literature is Kent Beck's implementation in Test Driven Development: By Example, which contains amount and currency.

Thus, I don't see any intrinsic problem with your password class containing both a string (or a byte array?) and an expiration time.

It's true that you can no longer have a lossless conversion from your Value Object to a primitive value, but that's not a requirement for it to be a Value Object.

(BTW, I hope you don't store passwords, but only the hashes!)

2015-02-27 7:29 UTC

Design Smell: Temporal Coupling

Tuesday, 24 May 2011 14:00:42 UTC

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

Poka-yoke Design: From Smell to Fragrance

Tuesday, 24 May 2011 13:57:39 UTC

Encapsulation is one of the most misunderstood aspects of object-oriented programming. Most people seem to think that the related concept of information hiding simply means that private fields should be exposed by public properties (or getter/setter methods in languages that don't have native properties).

Have you ever wondered what's the real benefit to be derived from code like the following?

private string name;
public string Name
{
    get { return this.name; }
    set { this.name = value; }
}

This feels awfully much like redundant code to me (and automatic properties are not the answer - it's just a compiler trick that still creates private backing fields). No information is actually hidden. Derick Bailey has a good piece on why this view of encapsulation is too narrow, so I'm not going to reiterate all his points here.

So then what is encapsulation?

The whole point of object-orientation is to produce cohesive pieces of code (classes) that solve given problems once and for all, so that programmers can use those classes without having to learn about the intricate details of the implementations.

This is what encapsulation is all about: exposing a solution to a problem without requiring the consumer to fully understand the problem domain.

This is what all well-designed classes do.

  • You don't have to know the intricate details of TDS to use ADO.NET against SQL Server.
  • You don't have to know the intricate details of painting on the screen to use WPF or Windows Forms.
  • You don't have to know the intricate details of Reflection to use a DI Container.
  • You don't have to know how to efficiently sort a list in order to efficiently sort a list in .NET.
  • Etc.

What makes encapsulation so important is exactly this trait. The class must hide the information it encapsulates in order to protect it against ‘naïve' users. Wikipedia has this to say:

Hiding the internals of the object protects its integrity by preventing users from setting the internal data of the component into an invalid or inconsistent state.

Keep in mind that users are expected to not fully understand the internal implementation of a class. This makes it obvious what encapsulation is really about:

Encapsulation is a fail-safe mechanism.

By corollary, encapsulation does not mean hiding complexity. Whenever complexity is hidden (as is the case for Providers) feedback time increases. Rapid feedback is much preferred, so delaying feedback is not desirable if it can be avoided.

Encapsulation is not about hiding complexity, but conversely exposing complexity in a fail-safe manner.

In Lean this is known as Poka-yoke, so I find it only fitting to think about encapsulation as Poka-yoke Design: APIs that make it as hard as possible to do the wrong thing. Considering that compilation is the cheapest feedback mechanism, it's preferable to design APIs so that the code can only compile when classes are used correctly.

In a series of blog posts I will look at various design smells that break encapsulation, as well as provide guidance on how to improve the design to make it safer, thus going from smell to fragrance.

  1. Design Smell: Temporal Coupling
  2. Design Smell: Primitive Obsession
  3. Code Smell: Automatic Property
  4. Design Smell: Redundant Required Attribute
  5. Design Smell: Default Constructor
  6. DI Container smell: Captive Dependency

Postscript: At the Boundaries, Applications are Not Object-Oriented


Comments

Perhaps it would be beneficial to elaborate on your focus here by describing when/where these "smells" are applicable. With the .NET community (as a whole) only recently coming on to topics like anemic models, I fear that they will take this advice and apply it to every scenario.

That's not to say that this is not relevant information but surely you're not implying that's applicable to scenarios like messaging, RESTful APIs, and other circumstances that need easily serializable objecst?
2011-05-30 15:03 UTC
Kurt Guntheroth #
You're still doing it wrong. Encapsulation means that, instead of exposing data, you expose an interface that exports exactly the operations and values that are defined for your class.

For instance, if a string name is used as a sorting key, it isn't appropriate to change the name. You can make the name string public, but that implies that changing the name is a valid operation, and might lead to bugs later. Providing a const getter, but no setter for the name says "You can't change this name".

If you have a setter and a getter for a piece of data, it should be because the class needs to expose that data for the purpose of changing it. That happens a lot, and it shouldn't be viewed as unreasonable that you have a private data member and a setter/getter. It's not a waste of time or code. It's a clear contract with users of your class that you intend to provide these operations no matter how the class evolves.

One important property of good encapsulation is that you are free to change the data representation of your class if the interface remains the same, and your changes will be limited to the methods of the class itself. Want to change from a 1-based count to a zero-based index? If you exposed a member called items, you're screwed. If you exposed a method called CountGet() you're ok. Just change CountGet()'s implementation from returning items to return items+1.
2011-06-01 16:22 UTC
One thing at a time... There's a reason I themed this series of blog posts around fail-safing. I agree that encapsulation involves more than just that, but I don't think I ever said anything else.
2011-06-01 18:52 UTC
Florian Fordermaier #
Interesting post. A few years ago I did some research on the "absence of proper encapsulation language features" in C# and Java. It's an interesting approach to advance from smells to fragrance, pointing out code snippets that potentially violate encapsulation in some way. But - to be honest - this will help only those people that are even aware of these problems.
You mentioned the compiler as the first and cheapest feedback mechanism, so the target should be to achieve automation of the process of enforcing proper encapsulation with (a) a better compiler or (b) static analysis or (c) runtime functionality that can be applied minimally-invasive.
See C++'s const qualifier, an excellent example of a language feature to support proper encapsulation, this would allow for e.g. auto-properties with a getter/setter when making the setter const. Of course this will itself impact your design, but it offers a language integrated fail-safe mechanism for encapsulation. What do you think?
I also may have an additional smell for you, a violation of the law of demeter breaks encapsulation in most cases.
2011-06-16 08:12 UTC
Florian, I agree with your statement about Law of Demeter, although Fowler calls it 'the occasionally useful suggestion of Demeter' (or some such thing).

I don't have any comment on the C++ const qualifier, as I have no idea what it does...
2011-06-18 18:00 UTC
Florian Fordermaier #
Mark,

first of all I have to correct my first comment, auto properties with a const setter is definitely non-sense.
The C++ const qualifier is effectively a statically checked and compiler-enforced construct to syntactically express your objectives regarding "permissions" to change an object's state.
If I e.g. declare a class A with a const method. Every caller calling the const method knows, that wahtever the method itself does, it will definitely not change the state of the object - imagine you have a immutable 'this' in your const method.
The same holds for e.g. a parameter that is passed to a method. If the parameter is declared const, the compiler will enforce that the parameter (be it a value or reference type) will not be changed.
But the real problem with every object that is owned by another object and exposed in some way(e.g. property getter), is, that when I return a reference to it, the caller that received the reference can change this object's state without me knowing it - this breaks encapsulation. The const qualifier comes to the rescue, when I return a const reference, the caller cannot change the returned object (compiler-checked!).

Although the const qualifier does not solve all the problems you mentioned in your blog, it can be of help. I actually only brought your attention to this C++ language construct to have an example in hand (I'm far away from a C++ expert) for what I meant with "automation of the process of enforcing proper encapsulation". I'm still interested in your opinion regarding efforts on automation of these things...


2011-06-21 11:30 UTC
Sounds useful. Currently, Microsoft is making an effort along the same lines with Code Contracts, but although it's actually a released technology it still seems a bit immature to me.

As I've been using TDD since 2003 I usually just codify my assumptions about invariants in the tests I write. A framework like Greg Young's Grensesnitt might also come in handy there.
2011-06-21 19:03 UTC

Tennis Kata with immutable types and a cyclomatic complexity of 1

Monday, 16 May 2011 11:01:00 UTC

Recently I had the inclination to do the Tennis Kata a couple of times. The first time I saw it I thought it wasn't terribly interesting as an exercise in C# development. It would basically just be an application of the State pattern, so I decided to make it a bit more interesting. More or less by intuition I decided to give myself the following constraints:

Now that's more interesting :)

Given these constraints, what would be the correct approach? Given that this is a finite state machine with a fixed number of states, the Visitor pattern will be a good match.

Each player's score can be modeled as a Value Object that can be one of these types:

  • ZeroPoints
  • FifteenPoints
  • ThirtyPoints
  • FortyPoints
  • AdvantagePoint
  • GamePoint

All of these classes implement the IPoints interface:

public interface IPoints
{
    IPoints Accept(IPoints visitor);
 
    IPoints LoseBall();
 
    IPoints WinBall(IPoints opponentPoints);
 
    IPoints WinBall(AdvantagePoint opponentPoints);
 
    IPoints WinBall(FortyPoints opponentPoints);
}

The interesting insight here is that until the opponent's score reaches FortyPoints nothing special happens. Those states can be effectively collapsed into the WinBall(IPoints) method. However, when the opponent either has FortyPoints or AdvantagePoint, special things happen, so IPoints has specialized methods for those cases. All implementations should use double dispatch to invoke the correct overload of WinBall, so the Accept method must be implemented like this:

public IPoints Accept(IPoints visitor)
{
    return visitor.WinBall(this);
}

That's the core of the Visitor pattern in action. When the implementer of the Accept method is either FortyPoints or AdvantagePoint, the specialized overload will be invoked.

It's now possible to create a context around a pair of IPoints (called a Game) to implement a method to register that Player 1 won a ball:

public Game PlayerOneWinsBall()
{
    var newPlayerOnePoints = this.PlayerTwoScore
        .Accept(this.PlayerOneScore);
    var newPlayerTwoPoints = 
        this.PlayerTwoScore.LoseBall();
    return new Game(
        newPlayerOnePoints, newPlayerTwoPoints);
}

A similar method for player two simply reverses the roles. (I'm currently reading Lean Architecture, but have yet to reach the chapter on DCI. However, considering what I've already read about DCI, this seems to fit the bill pretty well… although I might be wrong on that account.)

The context calculates new scores for both players and returns the result as a new instance of the Game class. This keeps the Game and IPoints implementations immutable.

The new score for the winner depends on the opponent's score, so the appropriate overload of WinBall should be invoked. The Visitor implementation makes it possible to pick the right overload without resorting to casts and if statements. As an example, the FortyPoints class implements the three WinBall overloads like this:

public IPoints WinBall(IPoints opponentPoints)
{
    return new GamePoint();
}
 
public IPoints WinBall(FortyPoints opponentPoints)
{
    return new AdvantagePoint();
}
 
public IPoints WinBall(AdvantagePoint opponentPoints)
{
    return this;
}

It's also important to correctly implement the LoseBall method. In most cases, losing a ball doesn't change the current state of the loser, in which case the implementation looks like this:

public IPoints LoseBall()
{
    return this;
}

However, when the player has advantage and loses the ball, he or she loses the advantage, so for the AdvantagePoint class the implementation looks like this:

public IPoints LoseBall()
{
    return new FortyPoints();
}

To keep things simple I decided to implicitly model deuce as both players having FortyPoints, so there's not explicit Deuce class. Thus, AdvantagePoint returns FortyPoints when losing the ball.

Using the Visitor pattern it's possible to keep the cyclomatic complexity at 1. The code has no branches or loops. It's immutable to boot, so a game might look like this:

[Fact]
public void PlayerOneWinsAfterHardFight()
{
    var game = new Game()
        .PlayerOneWinsBall()
        .PlayerOneWinsBall()
        .PlayerOneWinsBall()
        .PlayerTwoWinsBall()
        .PlayerTwoWinsBall()
        .PlayerTwoWinsBall()
        .PlayerTwoWinsBall()
        .PlayerOneWinsBall()
        .PlayerOneWinsBall()
        .PlayerOneWinsBall();
 
    Assert.Equal(new GamePoint(), game.PlayerOneScore);
    Assert.Equal(new FortyPoints(), game.PlayerTwoScore);
}

In case you'd like to take a closer look at the code I'm attaching it to this post. It was driven completely by using the AutoFixture.Xunit extension, so if you are interested in idiomatic AutoFixture code it's also a good example of that.

TennisKata.zip (3.09 MB)

Comments

It's a beautiful thing
2011-05-17 14:59 UTC
Thanks :)
2011-05-17 15:02 UTC
Klaus Hebsgaard #
Funny to see, I believe I created thi kata once upon a time ...
2011-05-19 15:31 UTC

Generic unit testing with xUnit.net

Monday, 09 May 2011 12:37:17 UTC

Generics in .NET are wonderful, but sometimes when doing Test-Driven Development against a generic class I've felt frustrated because I've been feeling that dropping down to the lowest common denominator and testing against, say, Foo<object> doesn't properly capture the variability inherent in generics. On the other hand, writing the same test for five different types of T have seemed too wasteful (not to mention boring) to bother with.

That's until it occurred to me that in xUnit.net (and possibly other unit testing frameworks) I can define a generic test class. As an example, I wanted to test-drive a class with this class definition:

public class Interval<T>

Instead of writing a set of tests against Interval<object> I rather wanted to write a set of tests against a representative set of T. This is so easy to do that I don't know why I haven't thought of it before. I simply declared the test class itself as a generic class:

public abstract class IntervalFacts<T>

The reason I declared the class as abstract is because that effectively prevents the test runner from trying to run the test methods directly on the class. That would fail because T is still open. However, it enabled me to write tests like this:

[Theory, AutoCatalogData]
public void MinimumIsCorrect(IComparable<T> first, 
    IComparable<T> second)
{
    var sut = new Interval<T>(first, second);
    IComparable<T> result = sut.Minimum;
    Assert.Equal(result, first);
}

In this test, I also use AutoFixture's xUnit.net extension, but that's completely optional. You might as well just write an old-fashioned unit test, but then you'll need a SUT Factory that can resolve generics. If you don't use AutoFixture any other (auto-mocking) container will do, and if you don't use one of those, you can define a Factory Method that creates appropriate instances of T (and, in this particular case, instances of IComparable<T>).

In the above example I used a [Theory], but I might as well have been using a [Fact] as long as I had a container or a Factory Method to create the appropriate instances.

The above test doesn't execute in itself because the owning class is abstract. I needed to declare an appropriate set of constructed types for which I wanted the test to run. To do that, I defined the following test classes:

public class DecimalIntervalFacts : IntervalFacts<decimal> { }
public class StringIntervalFacts : IntervalFacts<string> { }
public class DateTimeIntervalFacts : IntervalFacts<DateTime> { }
public class TimSpanIntervalFacts : IntervalFacts<TimeSpan> { }

The only thing these classes do is to each pick a particular type for T. However, since they are concrete classes with test methods, the test runner will pick up the test cases and execute them. This means that the single unit test I wrote above is now being executed four times - one for each constructed type.

It's even possible to specialize the generic class and add more methods to a single specialized class. As a sanity check I wanted to write a set of tests specifically against Interval<int>, so I added this class as well:

public class Int32IntervalFacts : IntervalFacts<int>
{
    [Theory]
    [InlineData(0, 0, 0, true)]
    [InlineData(-1, 1, -1, true)]
    [InlineData(-1, 1, 0, true)]
    [InlineData(-1, 1, 1, true)]
    [InlineData(-1, 1, -2, false)]
    [InlineData(-1, 1, 2, false)]
    public void Int32ContainsReturnsCorrectResult(
        int minimum, int maximum, int value,
        bool expectedResult)
    {
        var sut = new Interval<int>(minimum, maximum);
        var result = sut.Contains(value);
        Assert.Equal(expectedResult, result);
    }
 
    // More tests...
}

When added as an extra class in addition to the four ‘empty' concrete classes above, it now causes each generic method to be executed five times, whereas the above unit test is only executed for the Int32IntervalFacts class (on the other hand it's a parameterized test, so the method is actually executed six times).

It's also possible to write parameterized tests in the generic test class itself:

[Theory]
[InlineData(-1, -1, false)]
[InlineData(-1, 0, true)]
[InlineData(-1, 1, true)]
[InlineData(0, -1, false)]
[InlineData(0, 0, true)]
[InlineData(0, 1, true)]
[InlineData(1, -1, false)]
[InlineData(1, 0, false)]
[InlineData(1, 1, false)]
public void ContainsReturnsCorrectResult(
    int minumResult, int maximumResult,
    bool expectedResult)
{
    // Test method body
}

Since this parameterized test in itself has 9 variations and is declared by IntervalFacts<T> which now has 5 constructed implementers, this single test method will be executed 9 x 5 = 45 times!

Not that the number of executed tests in itself is any measure of the quality of the test, but I do appreciate the ability to write generic unit tests against generic types.


AutoFixture 2.1

Monday, 02 May 2011 18:34:52 UTC

Since I announced AutoFixture 2.1 beta 1 no issues have been reported, so I've now promoted the release to the official 2.1 release. This means that if you already downloaded AutoFixture 2.1 beta 1, you already have the 2.1 binaries. If not, you can head over to the release page to get it.

The NuGet packages will soon be available.

Update (2011.5.4): The NuGet packages are now available.


Page 63 of 76

"Our team wholeheartedly endorses Mark. His expert service provides tremendous value."
Hire me!