Autofixture: Creating a object tree where children reference parent for DDD design

Created on 1 Feb 2014  ·  14Comments  ·  Source: AutoFixture/AutoFixture

Hi there.

I wan't to be able to create a object tree where children reference parent.
For example a Car has Tires and a Tire references it's car.

So far I have been using OmitOnRecursionBehavior and assignin the reference manually, demo:

``` c#
var fixture = new Fixture();
fixture.Behaviors.Add(new OmitOnRecursionBehavior());
var car = fixture.Create();
foreach (var tire in car.Tires)
{
tire.Car = car;
}

What I wanted to do:

``` c#
fixture.Customize<Car>(composer => composer
.With(car => car.Tires, fixture.Build<Tire>().With(tire => tire.Car, car)
.CreateMany().ToList()));

What I also wanted to do:

``` c#
private class CarCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Behaviors.Add(new OmitOnRecursionBehavior());
fixture.Customizations.Add(new CarBuilder());
}
}

private class CarBuilder : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
var t = request as Type;
if (t != null && t == typeof(Car))
{
//Won't work, builder depends on it's self
var car = context.Create();
foreach (var tire in car.Tires)
{
tire.Car = car;
}
}

    return new NoSpecimen(request);
}

}

Here are the Car/Tire classes:

``` c#
public class Car
{
    public string Name { get; set; }
    public string Description { get; set; }
    public int Doors { get; set; }
    public List<Tire> Tires { get; set; }
}

public class Tire
{
    public int Size { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public Car Car { get; set; }
}

Can anyone help me solve this neatly?

Most helpful comment

The sample code provided by @moodmosaic is idiomatic, so that ought to be the way forward as a specific solution to a specific problem.

Regarding the appropriateness of using an ORM for DDD, I disagree. ORMs may seem powerful, but in fact, they are very constraining. The seem to solve a problem, but create many more problems.

When it comes to DDD, one of the most important tactical patterns described in the blue book is the concept of an _Aggregate Root_. All ORMs I've ever seen blatantly violate this pattern, because you can start at any given table and start loading rows of that table, and then walk various 'navigation properties' to load data from associated tables. This means that there are no roots, and thus, no clear ownership of data.

Add to this that everything's mutable, and you'll soon have a system on your hand, which is very difficult to reason about.

All 14 comments

I think you'll find that Tire should not have a reference to the parent Car. Circular references are considered bad (by autofixture, at least).

However, this is something I also need to solve. I am working with EF models that I cannot change, and they have circular references I cannot remove. Right now, I am avoiding autofixture, but I'd much rather put some effort into solving this generically (if possible).

Doing Domain Driven Design it is sometimes convenient as most logic is in the domain layer and some method on child might need the reference for cleaner implementations.

Eric Evans says in his book " Domain-Driven Design - Tackling Complexity in the Heart of Software":
Circular references logically exist in many domains and are sometimes necessary in design as well, but they are tricky to maintain.

Also, with popular persistence technologies like EF and Fluent NHibernate it is encouraged or at least more easy for the mappings.

Finding a convenient solution would therefore be helpful for me and others doing DDD, EF, or Fluent NHibernate.

I think @ploeh and @moodmosaic have made it clear in the past, that they don't like circular references and avoid them wherever possible (correct me if I'm wrong, I don't mean to speak for you, but this is my understanding).

However, both have been known to accept contributions to AutoFixture that they don't particularly find useful, provided it doesn't cause them maintainability and support issues (very fair, I think).

I'm very motivated to try and do something about this issue (assuming there is something that is generically useful that will work).

I like frameworks that encourage good design and I understand the problem with circular references but sometimes they are the logical thing to do. Maybe a solution can be found that does not encourage circular references but does not harm the beauty of AutoFixture.

Thank you for your answer and you positive attitude :+1:

Yes, _if_ we manage to come up with decent generic solution, it would not be the _default_ behaviour of AutoFixture.

From the CarBuilder above (the one that doesn't work), it looks as though what you really need is a Postprocessor<Car>. Have you tried that?

In general, the desire to use AutoFixture for ORM classes is a recurring theme, and as @adamchester notes, I have no problem making this work if it can be done in such a way that it doesn't cause maintainability or support issues.

On the other hand, not having used an ORM for more than three years, I have no personal interest in pursuing this feature, so it'd have to rely on someone else taking the lead on it.

Concerning the need for circular references, I agree that the concept is real, but that doesn't mean it's a good idea to use it in software design. Circular references will make code much more difficult to use and reason about. If it were unavoidable, then we'd have to live with it, but IME you can _always_ design an API in a way that avoids circular references; I don't know when I last created an API with a circular reference, but it's many years ago.

But what about ORMS, which require them?

Well, if you use an ORM, you're no longer working with object-oriented code; your code will be _relational_, with strong procedural elements. Don't let your choice of language (C#, etc.) deceive you.

Perhaps you can still do DDD in this way, but it'll be relational DDD, not object-oriented DDD. You'll end up with what Martin Fowler calls a Transaction Script.

Thanks for your answer, it is much appreciated :+1:

I have not heard of the PostProcessor but I gave it a try and could not get it to work, maybe I am missing something. It seems as if I use the PostProcessor then the type has not been initialized with values when it runs.

Here is my code:

``` c#
internal class DomainCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Behaviors.Add(new OmitOnRecursionBehavior());
fixture.Customizations.Add(
new Postprocessor(((Fixture)fixture).Engine, new CarCommand())
);
}
}

internal class CarCommand : ISpecimenCommand
{
public void Execute(object specimen, ISpecimenContext context)
{
var car = specimen as Car;
if (car != null)
{
//Null reference exeption here, no tires, no values in car sett
foreach (var tire in car.Tires)
{
tire.Car = car;
}
}
}
}
```

Martin Fowler is one of me heroes. In one of his posts he talks of the Anemic Domain Model which is exactly what I am trying to avoid. My entities have most of the logic in the application and not services(Transaction Scirpt). Since the entities have all the logic they may need some data related to them.

I always try to end with implementing the persistence layer after the domain model is completed so the database is a reflection of my entities not the other way around.

However the ORMS like EF/EF CodeFirst and NHibernate make you create relations not necessary for your entites and more circular references than needed by your original design making your design relational.

These ORMS are very powerful and justify this "uglyness".
I will have to live with these technologies for now and many others so a solution to this problem could be helpful to others.

Here is a passing test where the SUT is created with its _Tires_ filled and each Tire references its Car:

``` c#
[Fact]
public void Test()
{
var fixture = new Fixture();
fixture.Customize(c => c.Without(x => x.Car));
fixture.Customizations.Add(
new FilteringSpecimenBuilder(
new Postprocessor(
new MethodInvoker(
new ModestConstructorQuery()),
new CarFiller()),
new CarSpecification()));

var car = fixture.Create<Car>();

Assert.NotEmpty(car.Tires);
Array.ForEach(car.Tires.ToArray(), x => Assert.NotNull(x.Car));

}

private class CarFiller : ISpecimenCommand
{
public void Execute(object specimen, ISpecimenContext context)
{
if (specimen == null)
throw new ArgumentNullException("specimen");
if (context == null)
throw new ArgumentNullException("context");

    var car = specimen as Car;
    if (car == null)
        throw new ArgumentException(
            "The specimen must be an instance of Car.",
            "specimen");

    Array.ForEach(car.GetType().GetProperties(), x =>
    {
        if (x.Name == "Tires")
        {
            var tires =
                ((IEnumerable<object>)context
                    .Resolve(new MultipleRequest(typeof(Tire))))
                        .Cast<Tire>().ToArray();
            Array.ForEach(tires, tire => tire.Car = car);
            x.SetValue(car, tires.ToList());
        }
        else x.SetValue(car, context.Resolve(x.PropertyType));
    });
}

}

private class CarSpecification : IRequestSpecification
{
public bool IsSatisfiedBy(object request)
{
var requestType = request as Type;
if (requestType == null)
return false;

    return typeof(Car).IsAssignableFrom(requestType);
}

}
```

Sweet! Thank you @moodmosaic, I was missing a few pices of this puzzle.
Beautiful code :)

Also thanks to @adamchester and @ploeh for your thoughts.

I'll close this issue, this is enough for me. You can reopen this if you want to create a more generic solution.

The sample code provided by @moodmosaic is idiomatic, so that ought to be the way forward as a specific solution to a specific problem.

Regarding the appropriateness of using an ORM for DDD, I disagree. ORMs may seem powerful, but in fact, they are very constraining. The seem to solve a problem, but create many more problems.

When it comes to DDD, one of the most important tactical patterns described in the blue book is the concept of an _Aggregate Root_. All ORMs I've ever seen blatantly violate this pattern, because you can start at any given table and start loading rows of that table, and then walk various 'navigation properties' to load data from associated tables. This means that there are no roots, and thus, no clear ownership of data.

Add to this that everything's mutable, and you'll soon have a system on your hand, which is very difficult to reason about.

To create a true Aggregate Root with current ORMs is not possible. The Aggregate Root should be the only one able to change it's data...

ORMs create constraints like: parameterless constructors, setters for each property and it's navigational properties public. This has annoyed me very much.

With my current approaches I can't really trust that users of my library change data through it's Aggregate Root. Even if the Aggregate Root could enforce this it wouldn't prevent direct sql updates in the database...

Being stuck on SqlServer and relational databases hasn't helped me to find another way. Maybe I need to keep on looking for a better way.

Even so, I feel that applications I have created with DDD er more flexible to change and maintain. A part of that may also be the help of TDD and experience.

Thank you for your thoughts :+1:

I've noticed that if you have a .Customize call for the type being processed by the Filler that causes the filler to be ignored. eg fixture.Customize<Car>(c => c.Without(x => x.Doors))

I've tried to combine these like so:

var fixture = new Fixture();
            fixture.Customize<Tire>(c => c.Without(x => x.Car));
            ///fixture.Customize<Car>(c => c.Without(x => x.Doors));
            fixture.Customizations.Add(
                new FilteringSpecimenBuilder(
                    new Postprocessor(
                        SpecimenBuilderNodeFactory.CreateComposer<Car>().WithAutoProperties(!fixture.OmitAutoProperties)
                        .With(x=>x.Description, "Wee")
                        ,
                        new CarFiller()),
                    new CarSpecification()));


            var car = fixture.Create<Car>();

            Assert.Equal("Wee", car.Description);
            Assert.NotEmpty(car.Tires);
            Array.ForEach(car.Tires.ToArray(), x => Assert.NotNull(x.Car));
            Array.ForEach(car.Tires.ToArray(), x => Assert.True(x.Car == car));

So the Assert on the Description fails. Its being auto generated still, the customisations are ignored. Based on my strained understanding of things I would have expected the specimen passed to the filler to have been created using the Composer.

Edit I see now that the else x.SetValue(car, context.Resolve(x.PropertyType)) is auto generating the other properties. Cheers

Heres a more genericised version:

private class CollectionBackReferenceFiller<T, TElement> : ISpecimenCommand
            where T : class
        {
            private readonly string _collectionProperty;
            private readonly Action<TElement, T> _backReferenceSetter;

            public CollectionBackReferenceFiller(string collectionProperty, Action<TElement, T> backReferenceSetter)
            {
                _collectionProperty = collectionProperty;
                _backReferenceSetter = backReferenceSetter;
            }

            public void Execute(object specimen, ISpecimenContext context)
            {
                if (specimen == null)
                    throw new ArgumentNullException("specimen");
                if (context == null)
                    throw new ArgumentNullException("context");

                var typedSpecimen = specimen as T;
                if (typedSpecimen == null)
                    throw new ArgumentException(
                        "The specimen must be an instance of " + typeof(T).Name,
                        "specimen");

                Array.ForEach(typedSpecimen.GetType().GetProperties(), x =>
                {
                    if (x.Name == _collectionProperty)
                    {
                        var elements =
                            ((IEnumerable<object>)context
                                .Resolve(new MultipleRequest(typeof(TElement))))
                                    .Cast<TElement>().ToArray();
                        Array.ForEach(elements, e => _backReferenceSetter(e, typedSpecimen));

                        x.SetValue(typedSpecimen, elements.ToList());
                    }
                });
            }
        }

        private class TypeSpecification<T> : IRequestSpecification
        {
            public bool IsSatisfiedBy(object request)
            {
                var requestType = request as Type;
                if (requestType == null)
                    return false;

                return typeof(T).IsAssignableFrom(requestType);
            }
        }

Your generic solution was great!
I updated it to use Property Expressions for more type safe code and created a generic Customization. I ended up not using it, but I thought I would share it since I had already written it. :-)

Example. CashRegister has List with Receipts. Receipt has a back reference to CashRegister

public class CashRegister : EntityBase
{
    public List<Receipt> Receipts { get; set; }
}

public class Receipt : EntityBase
{
    public CashRegister CashRegister { get; set; }
}

Usage of Customization:
new BackReferenceCustomization<CashRegister, Receipt>(cashRegister => cashRegister.Receipts, receipt => receipt.CashRegister)

Customization:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using AutoFixture;
using AutoFixture.Kernel;

public class BackReferenceCustomization<TTypeWithList, TTypeWithBackReference> : ICustomization where TTypeWithList : class
{
    private readonly Expression<Func<TTypeWithList, List<TTypeWithBackReference>>> _collectionPropertyExpression;
    private readonly Expression<Func<TTypeWithBackReference, TTypeWithList>> _backReferencePropertyExpression;

    public BackReferenceCustomization(
        Expression<Func<TTypeWithList, List<TTypeWithBackReference>>> collectionPropertyExpression,
        Expression<Func<TTypeWithBackReference, TTypeWithList>> backReferencePropertyExpression)
    {
        _collectionPropertyExpression = collectionPropertyExpression;
        _backReferencePropertyExpression = backReferencePropertyExpression;
    }

    public void Customize(IFixture fixture)
    {
        fixture.Customize<TTypeWithBackReference>(c => c.Without(_backReferencePropertyExpression));
        fixture.Customizations.Add(
            new FilteringSpecimenBuilder(
                new Postprocessor(
                    new MethodInvoker(new ModestConstructorQuery()),
                    new CollectionBackReferenceFiller<TTypeWithList, TTypeWithBackReference>(_collectionPropertyExpression, _backReferencePropertyExpression)
                ),
                new TypeSpecification<TTypeWithList>()
            )
        );
    }
}

public class CollectionBackReferenceFiller<TTypeWithList, TTypeWithBackReference> : ISpecimenCommand where TTypeWithList : class
{
    private readonly Expression<Func<TTypeWithList, List<TTypeWithBackReference>>> _collectionPropertyExpression;
    private readonly Expression<Func<TTypeWithBackReference, TTypeWithList>> _backReferencePropertyExpression;

    public CollectionBackReferenceFiller(Expression<Func<TTypeWithList, List<TTypeWithBackReference>>> collectionPropertyExpression, Expression<Func<TTypeWithBackReference, TTypeWithList>> backReferencePropertyExpression)
    {
        _collectionPropertyExpression = collectionPropertyExpression;
        _backReferencePropertyExpression = backReferencePropertyExpression;
    }

    public void Execute(object specimen, ISpecimenContext context)
    {
        if (specimen == null)
            throw new ArgumentNullException(nameof(specimen));
        if (context == null)
            throw new ArgumentNullException(nameof(context));

        if (!(specimen is TTypeWithList typedSpecimen))
            throw new ArgumentException(
                "The specimen must be an instance of " + typeof(TTypeWithList).Name,
                nameof(specimen));

        var elements =
            ((IEnumerable<object>)context
                .Resolve(new MultipleRequest(typeof(TTypeWithBackReference))))
            .Cast<TTypeWithBackReference>().ToList();

        var collectionProperty = (PropertyInfo)((MemberExpression)_collectionPropertyExpression.Body).Member;
        collectionProperty.SetValue(typedSpecimen, elements);

        var backReferenceProperty = (PropertyInfo)((MemberExpression)_backReferencePropertyExpression.Body).Member;

        foreach (var element in elements)
        {
            backReferenceProperty.SetValue(element, typedSpecimen);
        }

        var otherProperties = typedSpecimen.GetType().GetProperties().Where(p => !p.Equals(collectionProperty) && p.SetMethod != null);
        foreach (var property in otherProperties)
        {
            property.SetValue(typedSpecimen, context.Resolve(property.PropertyType));
        }
    }
}

public class TypeSpecification<T> : IRequestSpecification
{
    public bool IsSatisfiedBy(object request)
    {
        var requestType = request as Type;
        if (requestType == null)
            return false;

        return typeof(T).IsAssignableFrom(requestType);
    }
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

JoshKeegan picture JoshKeegan  ·  6Comments

Ephasme picture Ephasme  ·  3Comments

tomasaschan picture tomasaschan  ·  3Comments

DeafLight picture DeafLight  ·  5Comments

ecampidoglio picture ecampidoglio  ·  7Comments